diff options
Diffstat (limited to 'drivers/pci/msi.c')
-rw-r--r-- | drivers/pci/msi.c | 96 |
1 files changed, 39 insertions, 57 deletions
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 955ab7990c5b..27a7e67ddfe4 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/init.h> | ||
14 | #include <linux/export.h> | 13 | #include <linux/export.h> |
15 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
16 | #include <linux/pci.h> | 15 | #include <linux/pci.h> |
@@ -544,22 +543,18 @@ static int populate_msi_sysfs(struct pci_dev *pdev) | |||
544 | if (!msi_attrs) | 543 | if (!msi_attrs) |
545 | return -ENOMEM; | 544 | return -ENOMEM; |
546 | list_for_each_entry(entry, &pdev->msi_list, list) { | 545 | list_for_each_entry(entry, &pdev->msi_list, list) { |
547 | char *name = kmalloc(20, GFP_KERNEL); | ||
548 | if (!name) | ||
549 | goto error_attrs; | ||
550 | |||
551 | msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); | 546 | msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL); |
552 | if (!msi_dev_attr) { | 547 | if (!msi_dev_attr) |
553 | kfree(name); | ||
554 | goto error_attrs; | 548 | goto error_attrs; |
555 | } | 549 | msi_attrs[count] = &msi_dev_attr->attr; |
556 | 550 | ||
557 | sprintf(name, "%d", entry->irq); | ||
558 | sysfs_attr_init(&msi_dev_attr->attr); | 551 | sysfs_attr_init(&msi_dev_attr->attr); |
559 | msi_dev_attr->attr.name = name; | 552 | msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d", |
553 | entry->irq); | ||
554 | if (!msi_dev_attr->attr.name) | ||
555 | goto error_attrs; | ||
560 | msi_dev_attr->attr.mode = S_IRUGO; | 556 | msi_dev_attr->attr.mode = S_IRUGO; |
561 | msi_dev_attr->show = msi_mode_show; | 557 | msi_dev_attr->show = msi_mode_show; |
562 | msi_attrs[count] = &msi_dev_attr->attr; | ||
563 | ++count; | 558 | ++count; |
564 | } | 559 | } |
565 | 560 | ||
@@ -883,50 +878,6 @@ int pci_msi_vec_count(struct pci_dev *dev) | |||
883 | } | 878 | } |
884 | EXPORT_SYMBOL(pci_msi_vec_count); | 879 | EXPORT_SYMBOL(pci_msi_vec_count); |
885 | 880 | ||
886 | /** | ||
887 | * pci_enable_msi_block - configure device's MSI capability structure | ||
888 | * @dev: device to configure | ||
889 | * @nvec: number of interrupts to configure | ||
890 | * | ||
891 | * Allocate IRQs for a device with the MSI capability. | ||
892 | * This function returns a negative errno if an error occurs. If it | ||
893 | * is unable to allocate the number of interrupts requested, it returns | ||
894 | * the number of interrupts it might be able to allocate. If it successfully | ||
895 | * allocates at least the number of interrupts requested, it returns 0 and | ||
896 | * updates the @dev's irq member to the lowest new interrupt number; the | ||
897 | * other interrupt numbers allocated to this device are consecutive. | ||
898 | */ | ||
899 | int pci_enable_msi_block(struct pci_dev *dev, int nvec) | ||
900 | { | ||
901 | int status, maxvec; | ||
902 | |||
903 | if (dev->current_state != PCI_D0) | ||
904 | return -EINVAL; | ||
905 | |||
906 | maxvec = pci_msi_vec_count(dev); | ||
907 | if (maxvec < 0) | ||
908 | return maxvec; | ||
909 | if (nvec > maxvec) | ||
910 | return maxvec; | ||
911 | |||
912 | status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); | ||
913 | if (status) | ||
914 | return status; | ||
915 | |||
916 | WARN_ON(!!dev->msi_enabled); | ||
917 | |||
918 | /* Check whether driver already requested MSI-X irqs */ | ||
919 | if (dev->msix_enabled) { | ||
920 | dev_info(&dev->dev, "can't enable MSI " | ||
921 | "(MSI-X already enabled)\n"); | ||
922 | return -EINVAL; | ||
923 | } | ||
924 | |||
925 | status = msi_capability_init(dev, nvec); | ||
926 | return status; | ||
927 | } | ||
928 | EXPORT_SYMBOL(pci_enable_msi_block); | ||
929 | |||
930 | void pci_msi_shutdown(struct pci_dev *dev) | 881 | void pci_msi_shutdown(struct pci_dev *dev) |
931 | { | 882 | { |
932 | struct msi_desc *desc; | 883 | struct msi_desc *desc; |
@@ -1132,14 +1083,45 @@ void pci_msi_init_pci_dev(struct pci_dev *dev) | |||
1132 | **/ | 1083 | **/ |
1133 | int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) | 1084 | int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec) |
1134 | { | 1085 | { |
1135 | int nvec = maxvec; | 1086 | int nvec; |
1136 | int rc; | 1087 | int rc; |
1137 | 1088 | ||
1089 | if (dev->current_state != PCI_D0) | ||
1090 | return -EINVAL; | ||
1091 | |||
1092 | WARN_ON(!!dev->msi_enabled); | ||
1093 | |||
1094 | /* Check whether driver already requested MSI-X irqs */ | ||
1095 | if (dev->msix_enabled) { | ||
1096 | dev_info(&dev->dev, | ||
1097 | "can't enable MSI (MSI-X already enabled)\n"); | ||
1098 | return -EINVAL; | ||
1099 | } | ||
1100 | |||
1138 | if (maxvec < minvec) | 1101 | if (maxvec < minvec) |
1139 | return -ERANGE; | 1102 | return -ERANGE; |
1140 | 1103 | ||
1104 | nvec = pci_msi_vec_count(dev); | ||
1105 | if (nvec < 0) | ||
1106 | return nvec; | ||
1107 | else if (nvec < minvec) | ||
1108 | return -EINVAL; | ||
1109 | else if (nvec > maxvec) | ||
1110 | nvec = maxvec; | ||
1111 | |||
1112 | do { | ||
1113 | rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI); | ||
1114 | if (rc < 0) { | ||
1115 | return rc; | ||
1116 | } else if (rc > 0) { | ||
1117 | if (rc < minvec) | ||
1118 | return -ENOSPC; | ||
1119 | nvec = rc; | ||
1120 | } | ||
1121 | } while (rc); | ||
1122 | |||
1141 | do { | 1123 | do { |
1142 | rc = pci_enable_msi_block(dev, nvec); | 1124 | rc = msi_capability_init(dev, nvec); |
1143 | if (rc < 0) { | 1125 | if (rc < 0) { |
1144 | return rc; | 1126 | return rc; |
1145 | } else if (rc > 0) { | 1127 | } else if (rc > 0) { |