diff options
author | Gavin Shan <shangw@linux.vnet.ibm.com> | 2013-04-04 12:54:33 -0400 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-04-23 11:50:30 -0400 |
commit | 520fe9dc1b07827d795578037ffd11190767e448 (patch) | |
tree | 342c8a662221606456d33a397d2d11e027d57b97 | |
parent | f465136d7287538cabdcdbf8deb24f99a9f855e4 (diff) |
PCI: Use cached MSI-X cap while enabling MSI-X
The patch uses the cached MSI-X capability offset in
pci_dev instead of reading it from config space when enabling
MSI-X interrupts.
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
-rw-r--r-- | drivers/pci/msi.c | 36 |
1 files changed, 16 insertions, 20 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 0138550dc806..79d9d045a1b8 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -598,14 +598,14 @@ static int msi_capability_init(struct pci_dev *dev, int nvec) | |||
598 | return 0; | 598 | return 0; |
599 | } | 599 | } |
600 | 600 | ||
601 | static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, | 601 | static void __iomem *msix_map_region(struct pci_dev *dev, unsigned nr_entries) |
602 | unsigned nr_entries) | ||
603 | { | 602 | { |
604 | resource_size_t phys_addr; | 603 | resource_size_t phys_addr; |
605 | u32 table_offset; | 604 | u32 table_offset; |
606 | u8 bir; | 605 | u8 bir; |
607 | 606 | ||
608 | pci_read_config_dword(dev, msix_table_offset_reg(pos), &table_offset); | 607 | pci_read_config_dword(dev, |
608 | msix_table_offset_reg(dev->msix_cap), &table_offset); | ||
609 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); | 609 | bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK); |
610 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; | 610 | table_offset &= ~PCI_MSIX_FLAGS_BIRMASK; |
611 | phys_addr = pci_resource_start(dev, bir) + table_offset; | 611 | phys_addr = pci_resource_start(dev, bir) + table_offset; |
@@ -613,9 +613,8 @@ static void __iomem *msix_map_region(struct pci_dev *dev, unsigned pos, | |||
613 | return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); | 613 | return ioremap_nocache(phys_addr, nr_entries * PCI_MSIX_ENTRY_SIZE); |
614 | } | 614 | } |
615 | 615 | ||
616 | static int msix_setup_entries(struct pci_dev *dev, unsigned pos, | 616 | static int msix_setup_entries(struct pci_dev *dev, void __iomem *base, |
617 | void __iomem *base, struct msix_entry *entries, | 617 | struct msix_entry *entries, int nvec) |
618 | int nvec) | ||
619 | { | 618 | { |
620 | struct msi_desc *entry; | 619 | struct msi_desc *entry; |
621 | int i; | 620 | int i; |
@@ -635,7 +634,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos, | |||
635 | entry->msi_attrib.is_64 = 1; | 634 | entry->msi_attrib.is_64 = 1; |
636 | entry->msi_attrib.entry_nr = entries[i].entry; | 635 | entry->msi_attrib.entry_nr = entries[i].entry; |
637 | entry->msi_attrib.default_irq = dev->irq; | 636 | entry->msi_attrib.default_irq = dev->irq; |
638 | entry->msi_attrib.pos = pos; | 637 | entry->msi_attrib.pos = dev->msix_cap; |
639 | entry->mask_base = base; | 638 | entry->mask_base = base; |
640 | 639 | ||
641 | list_add_tail(&entry->list, &dev->msi_list); | 640 | list_add_tail(&entry->list, &dev->msi_list); |
@@ -645,7 +644,7 @@ static int msix_setup_entries(struct pci_dev *dev, unsigned pos, | |||
645 | } | 644 | } |
646 | 645 | ||
647 | static void msix_program_entries(struct pci_dev *dev, | 646 | static void msix_program_entries(struct pci_dev *dev, |
648 | struct msix_entry *entries) | 647 | struct msix_entry *entries) |
649 | { | 648 | { |
650 | struct msi_desc *entry; | 649 | struct msi_desc *entry; |
651 | int i = 0; | 650 | int i = 0; |
@@ -675,23 +674,22 @@ static void msix_program_entries(struct pci_dev *dev, | |||
675 | static int msix_capability_init(struct pci_dev *dev, | 674 | static int msix_capability_init(struct pci_dev *dev, |
676 | struct msix_entry *entries, int nvec) | 675 | struct msix_entry *entries, int nvec) |
677 | { | 676 | { |
678 | int pos, ret; | 677 | int ret; |
679 | u16 control; | 678 | u16 control; |
680 | void __iomem *base; | 679 | void __iomem *base; |
681 | 680 | ||
682 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 681 | pci_read_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, &control); |
683 | pci_read_config_word(dev, pos + PCI_MSIX_FLAGS, &control); | ||
684 | 682 | ||
685 | /* Ensure MSI-X is disabled while it is set up */ | 683 | /* Ensure MSI-X is disabled while it is set up */ |
686 | control &= ~PCI_MSIX_FLAGS_ENABLE; | 684 | control &= ~PCI_MSIX_FLAGS_ENABLE; |
687 | pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); | 685 | pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); |
688 | 686 | ||
689 | /* Request & Map MSI-X table region */ | 687 | /* Request & Map MSI-X table region */ |
690 | base = msix_map_region(dev, pos, multi_msix_capable(control)); | 688 | base = msix_map_region(dev, multi_msix_capable(control)); |
691 | if (!base) | 689 | if (!base) |
692 | return -ENOMEM; | 690 | return -ENOMEM; |
693 | 691 | ||
694 | ret = msix_setup_entries(dev, pos, base, entries, nvec); | 692 | ret = msix_setup_entries(dev, base, entries, nvec); |
695 | if (ret) | 693 | if (ret) |
696 | return ret; | 694 | return ret; |
697 | 695 | ||
@@ -705,7 +703,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
705 | * interrupts coming in before they're fully set up. | 703 | * interrupts coming in before they're fully set up. |
706 | */ | 704 | */ |
707 | control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE; | 705 | control |= PCI_MSIX_FLAGS_MASKALL | PCI_MSIX_FLAGS_ENABLE; |
708 | pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); | 706 | pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); |
709 | 707 | ||
710 | msix_program_entries(dev, entries); | 708 | msix_program_entries(dev, entries); |
711 | 709 | ||
@@ -720,7 +718,7 @@ static int msix_capability_init(struct pci_dev *dev, | |||
720 | dev->msix_enabled = 1; | 718 | dev->msix_enabled = 1; |
721 | 719 | ||
722 | control &= ~PCI_MSIX_FLAGS_MASKALL; | 720 | control &= ~PCI_MSIX_FLAGS_MASKALL; |
723 | pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control); | 721 | pci_write_config_word(dev, dev->msix_cap + PCI_MSIX_FLAGS, control); |
724 | 722 | ||
725 | return 0; | 723 | return 0; |
726 | 724 | ||
@@ -906,14 +904,12 @@ EXPORT_SYMBOL(pci_disable_msi); | |||
906 | */ | 904 | */ |
907 | int pci_msix_table_size(struct pci_dev *dev) | 905 | int pci_msix_table_size(struct pci_dev *dev) |
908 | { | 906 | { |
909 | int pos; | ||
910 | u16 control; | 907 | u16 control; |
911 | 908 | ||
912 | pos = pci_find_capability(dev, PCI_CAP_ID_MSIX); | 909 | if (!dev->msix_cap) |
913 | if (!pos) | ||
914 | return 0; | 910 | return 0; |
915 | 911 | ||
916 | pci_read_config_word(dev, msi_control_reg(pos), &control); | 912 | pci_read_config_word(dev, msi_control_reg(dev->msix_cap), &control); |
917 | return multi_msix_capable(control); | 913 | return multi_msix_capable(control); |
918 | } | 914 | } |
919 | 915 | ||