aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-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 +