aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/msi.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-01-28 14:56:37 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2007-02-07 18:50:08 -0500
commitf7feaca77d6ad6bcfcc88ac54e3188970448d6fe (patch)
tree3002076ed2b6ab497b3b90232ff11b08de2eca5d /drivers/pci/msi.c
parent5b912c108c8b1fcecbfe13d6d9a183db97b682d3 (diff)
msi: Make MSI useable more architectures
The arch hooks arch_setup_msi_irq and arch_teardown_msi_irq are now responsible for allocating and freeing the linux irq in addition to setting up the the linux irq to work with the interrupt. arch_setup_msi_irq now takes a pci_device and a msi_desc and returns an irq. With this change in place this code should be useable by all platforms except those that won't let the OS touch the hardware like ppc RTAS. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Acked-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r--drivers/pci/msi.c80
1 files changed, 22 insertions, 58 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 52c253c5ad3d..68555c11f556 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -192,37 +192,6 @@ static struct msi_desc* alloc_msi_entry(void)
192 return entry; 192 return entry;
193} 193}
194 194
195static int create_msi_irq(void)
196{
197 struct msi_desc *entry;
198 int irq;
199
200 entry = alloc_msi_entry();
201 if (!entry)
202 return -ENOMEM;
203
204 irq = create_irq();
205 if (irq < 0) {
206 kmem_cache_free(msi_cachep, entry);
207 return -EBUSY;
208 }
209
210 set_irq_msi(irq, entry);
211
212 return irq;
213}
214
215static void destroy_msi_irq(unsigned int irq)
216{
217 struct msi_desc *entry;
218
219 entry = get_irq_msi(irq);
220 set_irq_chip(irq, NULL);
221 set_irq_msi(irq, NULL);
222 destroy_irq(irq);
223 kmem_cache_free(msi_cachep, entry);
224}
225
226static void enable_msi_mode(struct pci_dev *dev, int pos, int type) 195static void enable_msi_mode(struct pci_dev *dev, int pos, int type)
227{ 196{
228 u16 control; 197 u16 control;
@@ -438,7 +407,6 @@ void pci_restore_msi_state(struct pci_dev *dev)
438 **/ 407 **/
439static int msi_capability_init(struct pci_dev *dev) 408static int msi_capability_init(struct pci_dev *dev)
440{ 409{
441 int status;
442 struct msi_desc *entry; 410 struct msi_desc *entry;
443 int pos, irq; 411 int pos, irq;
444 u16 control; 412 u16 control;
@@ -446,13 +414,10 @@ static int msi_capability_init(struct pci_dev *dev)
446 pos = pci_find_capability(dev, PCI_CAP_ID_MSI); 414 pos = pci_find_capability(dev, PCI_CAP_ID_MSI);
447 pci_read_config_word(dev, msi_control_reg(pos), &control); 415 pci_read_config_word(dev, msi_control_reg(pos), &control);
448 /* MSI Entry Initialization */ 416 /* MSI Entry Initialization */
449 irq = create_msi_irq(); 417 entry = alloc_msi_entry();
450 if (irq < 0) 418 if (!entry)
451 return irq; 419 return -ENOMEM;
452 420
453 entry = get_irq_msi(irq);
454 entry->link.head = irq;
455 entry->link.tail = irq;
456 entry->msi_attrib.type = PCI_CAP_ID_MSI; 421 entry->msi_attrib.type = PCI_CAP_ID_MSI;
457 entry->msi_attrib.is_64 = is_64bit_address(control); 422 entry->msi_attrib.is_64 = is_64bit_address(control);
458 entry->msi_attrib.entry_nr = 0; 423 entry->msi_attrib.entry_nr = 0;
@@ -478,14 +443,16 @@ static int msi_capability_init(struct pci_dev *dev)
478 maskbits); 443 maskbits);
479 } 444 }
480 /* Configure MSI capability structure */ 445 /* Configure MSI capability structure */
481 status = arch_setup_msi_irq(irq, dev); 446 irq = arch_setup_msi_irq(dev, entry);
482 if (status < 0) { 447 if (irq < 0) {
483 destroy_msi_irq(irq); 448 kmem_cache_free(msi_cachep, entry);
484 return status; 449 return irq;
485 } 450 }
486 451 entry->link.head = irq;
452 entry->link.tail = irq;
487 dev->first_msi_irq = irq; 453 dev->first_msi_irq = irq;
488 set_irq_msi(irq, entry); 454 set_irq_msi(irq, entry);
455
489 /* Set MSI enabled bits */ 456 /* Set MSI enabled bits */
490 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI); 457 enable_msi_mode(dev, pos, PCI_CAP_ID_MSI);
491 458
@@ -507,7 +474,6 @@ static int msix_capability_init(struct pci_dev *dev,
507 struct msix_entry *entries, int nvec) 474 struct msix_entry *entries, int nvec)
508{ 475{
509 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL; 476 struct msi_desc *head = NULL, *tail = NULL, *entry = NULL;
510 int status;
511 int irq, pos, i, j, nr_entries, temp = 0; 477 int irq, pos, i, j, nr_entries, temp = 0;
512 unsigned long phys_addr; 478 unsigned long phys_addr;
513 u32 table_offset; 479 u32 table_offset;
@@ -530,13 +496,11 @@ static int msix_capability_init(struct pci_dev *dev,
530 496
531 /* MSI-X Table Initialization */ 497 /* MSI-X Table Initialization */
532 for (i = 0; i < nvec; i++) { 498 for (i = 0; i < nvec; i++) {
533 irq = create_msi_irq(); 499 entry = alloc_msi_entry();
534 if (irq < 0) 500 if (!entry)
535 break; 501 break;
536 502
537 entry = get_irq_msi(irq);
538 j = entries[i].entry; 503 j = entries[i].entry;
539 entries[i].vector = irq;
540 entry->msi_attrib.type = PCI_CAP_ID_MSIX; 504 entry->msi_attrib.type = PCI_CAP_ID_MSIX;
541 entry->msi_attrib.is_64 = 1; 505 entry->msi_attrib.is_64 = 1;
542 entry->msi_attrib.entry_nr = j; 506 entry->msi_attrib.entry_nr = j;
@@ -545,6 +509,14 @@ static int msix_capability_init(struct pci_dev *dev,
545 entry->msi_attrib.pos = pos; 509 entry->msi_attrib.pos = pos;
546 entry->dev = dev; 510 entry->dev = dev;
547 entry->mask_base = base; 511 entry->mask_base = base;
512
513 /* Configure MSI-X capability structure */
514 irq = arch_setup_msi_irq(dev, entry);
515 if (irq < 0) {
516 kmem_cache_free(msi_cachep, entry);
517 break;
518 }
519 entries[i].vector = irq;
548 if (!head) { 520 if (!head) {
549 entry->link.head = irq; 521 entry->link.head = irq;
550 entry->link.tail = irq; 522 entry->link.tail = irq;
@@ -557,12 +529,6 @@ static int msix_capability_init(struct pci_dev *dev,
557 } 529 }
558 temp = irq; 530 temp = irq;
559 tail = entry; 531 tail = entry;
560 /* Configure MSI-X capability structure */
561 status = arch_setup_msi_irq(irq, dev);
562 if (status < 0) {
563 destroy_msi_irq(irq);
564 break;
565 }
566 532
567 set_irq_msi(irq, entry); 533 set_irq_msi(irq, entry);
568 } 534 }
@@ -706,8 +672,6 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
706 int head, entry_nr, type; 672 int head, entry_nr, type;
707 void __iomem *base; 673 void __iomem *base;
708 674
709 arch_teardown_msi_irq(irq);
710
711 entry = get_irq_msi(irq); 675 entry = get_irq_msi(irq);
712 if (!entry || entry->dev != dev) { 676 if (!entry || entry->dev != dev) {
713 return -EINVAL; 677 return -EINVAL;
@@ -718,9 +682,9 @@ static int msi_free_irq(struct pci_dev* dev, int irq)
718 base = entry->mask_base; 682 base = entry->mask_base;
719 get_irq_msi(entry->link.head)->link.tail = entry->link.tail; 683 get_irq_msi(entry->link.head)->link.tail = entry->link.tail;
720 get_irq_msi(entry->link.tail)->link.head = entry->link.head; 684 get_irq_msi(entry->link.tail)->link.head = entry->link.head;
721 entry->dev = NULL;
722 685
723 destroy_msi_irq(irq); 686 arch_teardown_msi_irq(irq);
687 kmem_cache_free(msi_cachep, entry);
724 688
725 if (type == PCI_CAP_ID_MSIX) { 689 if (type == PCI_CAP_ID_MSIX) {
726 writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE + 690 writel(1, base + entry_nr * PCI_MSIX_ENTRY_SIZE +