diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/pci/msi.c | 59 |
1 files changed, 36 insertions, 23 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index ce08d0bffe08..14159cf7d38e 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -447,6 +447,37 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, | |||
447 | return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); | 447 | return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); |
448 | } | 448 | } |
449 | 449 | ||
450 | static int msix_setup_entries(struct pci_dev *dev, unsigned pos, | ||
451 | void __iomem *base, struct msix_entry *entries, | ||
452 | int nvec) | ||
453 | { | ||
454 | struct msi_desc *entry; | ||
455 | int i; | ||
456 | |||
457 | for (i = 0; i < nvec; i++) { | ||
458 | entry = alloc_msi_entry(dev); | ||
459 | if (!entry) { | ||
460 | if (!i) | ||
461 | iounmap(base); | ||
462 | else | ||
463 | free_msi_irqs(dev); | ||
464 | /* No enough memory. Don't try again */ | ||
465 | return -ENOMEM; | ||
466 | } | ||
467 | |||
468 | entry->msi_attrib.is_msix = 1; | ||
469 | entry->msi_attrib.is_64 = 1; | ||
470 | entry->msi_attrib.entry_nr = entries[i].entry; | ||
471 | entry->msi_attrib.default_irq = dev->irq; | ||
472 | entry->msi_attrib.pos = pos; | ||
473 | entry->mask_base = base; | ||
474 | |||
475 | list_add_tail(&entry->list, &dev->msi_list); | ||
476 | } | ||
477 | |||
478 | return 0; | ||
479 | } | ||
480 | |||
450 | static void msix_program_entries(struct pci_dev *dev, | 481 | static void msix_program_entries(struct pci_dev *dev, |
451 | struct msix_entry *entries) | 482 | struct msix_entry *entries) |
452 | { | 483 | { |
@@ -478,8 +509,7 @@ static void msix_program_entries(struct pci_dev *dev, | |||
478 | static int msix_capability_init(struct pci_dev *dev, | 509 | static int msix_capability_init(struct pci_dev *dev, |
479 | struct msix_entry *entries, int nvec) | 510 | struct msix_entry *entries, int nvec) |
480 | { | 511 | { |
481 | struct msi_desc *entry; | 512 | int pos, ret; |
482 | int pos, i, j, ret; | ||
483 | u16 control; | 513 | u16 control; |
484 | void __iomem *base; | 514 | void __iomem *base; |
485 | 515 | ||
@@ -495,27 +525,9 @@ static int msix_capability_init(struct pci_dev *dev, | |||
495 | if (!base) | 525 | if (!base) |
496 | return -ENOMEM; | 526 | return -ENOMEM; |
497 | 527 | ||
498 | for (i = 0; i < nvec; i++) { | 528 | ret = msix_setup_entries(dev, pos, base, entries, nvec); |
499 | entry = alloc_msi_entry(dev); | 529 | if (ret) |
500 | if (!entry) { | 530 | return ret; |
501 | if (!i) | ||
502 | iounmap(base); | ||
503 | else | ||
504 | free_msi_irqs(dev); | ||
505 | /* No enough memory. Don't try again */ | ||
506 | return -ENOMEM; | ||
507 | } | ||
508 | |||
509 | j = entries[i].entry; | ||
510 | entry->msi_attrib.is_msix = 1; | ||
511 | entry->msi_attrib.is_64 = 1; | ||
512 | entry->msi_attrib.entry_nr = j; | ||
513 | entry->msi_attrib.default_irq = dev->irq; | ||
514 | entry->msi_attrib.pos = pos; | ||
515 | entry->mask_base = base; | ||
516 | |||
517 | list_add_tail(&entry->list, &dev->msi_list); | ||
518 | } | ||
519 | 531 | ||
520 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); | 532 | ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); |
521 | if (ret) | 533 | if (ret) |
@@ -546,6 +558,7 @@ error: | |||
546 | * If we had some success, report the number of irqs | 558 | * If we had some success, report the number of irqs |
547 | * we succeeded in setting up. | 559 | * we succeeded in setting up. |
548 | */ | 560 | */ |
561 | struct msi_desc *entry; | ||
549 | int avail = 0; | 562 | int avail = 0; |
550 | 563 | ||
551 | list_for_each_entry(entry, &dev->msi_list, list) { | 564 | list_for_each_entry(entry, &dev->msi_list, list) { |