]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - drivers/pci/msi.c
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb...
[karo-tx-linux.git] / drivers / pci / msi.c
index 955ab7990c5bd7045f2bf896e6d4c65989176089..13f3d303727296821f25fde0b7acd22106a3fc3b 100644 (file)
@@ -10,7 +10,6 @@
 #include <linux/mm.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <linux/init.h>
 #include <linux/export.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
@@ -414,7 +413,7 @@ static void free_msi_irqs(struct pci_dev *dev)
        if (dev->msi_irq_groups) {
                sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups);
                msi_attrs = dev->msi_irq_groups[0]->attrs;
-               list_for_each_entry(entry, &dev->msi_list, list) {
+               while (msi_attrs[count]) {
                        dev_attr = container_of(msi_attrs[count],
                                                struct device_attribute, attr);
                        kfree(dev_attr->attr.name);
@@ -544,22 +543,18 @@ static int populate_msi_sysfs(struct pci_dev *pdev)
        if (!msi_attrs)
                return -ENOMEM;
        list_for_each_entry(entry, &pdev->msi_list, list) {
-               char *name = kmalloc(20, GFP_KERNEL);
-               if (!name)
-                       goto error_attrs;
-
                msi_dev_attr = kzalloc(sizeof(*msi_dev_attr), GFP_KERNEL);
-               if (!msi_dev_attr) {
-                       kfree(name);
+               if (!msi_dev_attr)
                        goto error_attrs;
-               }
+               msi_attrs[count] = &msi_dev_attr->attr;
 
-               sprintf(name, "%d", entry->irq);
                sysfs_attr_init(&msi_dev_attr->attr);
-               msi_dev_attr->attr.name = name;
+               msi_dev_attr->attr.name = kasprintf(GFP_KERNEL, "%d",
+                                                   entry->irq);
+               if (!msi_dev_attr->attr.name)
+                       goto error_attrs;
                msi_dev_attr->attr.mode = S_IRUGO;
                msi_dev_attr->show = msi_mode_show;
-               msi_attrs[count] = &msi_dev_attr->attr;
                ++count;
        }
 
@@ -883,50 +878,6 @@ int pci_msi_vec_count(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_msi_vec_count);
 
-/**
- * pci_enable_msi_block - configure device's MSI capability structure
- * @dev: device to configure
- * @nvec: number of interrupts to configure
- *
- * Allocate IRQs for a device with the MSI capability.
- * This function returns a negative errno if an error occurs.  If it
- * is unable to allocate the number of interrupts requested, it returns
- * the number of interrupts it might be able to allocate.  If it successfully
- * allocates at least the number of interrupts requested, it returns 0 and
- * updates the @dev's irq member to the lowest new interrupt number; the
- * other interrupt numbers allocated to this device are consecutive.
- */
-int pci_enable_msi_block(struct pci_dev *dev, int nvec)
-{
-       int status, maxvec;
-
-       if (dev->current_state != PCI_D0)
-               return -EINVAL;
-
-       maxvec = pci_msi_vec_count(dev);
-       if (maxvec < 0)
-               return maxvec;
-       if (nvec > maxvec)
-               return maxvec;
-
-       status = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
-       if (status)
-               return status;
-
-       WARN_ON(!!dev->msi_enabled);
-
-       /* Check whether driver already requested MSI-X irqs */
-       if (dev->msix_enabled) {
-               dev_info(&dev->dev, "can't enable MSI "
-                        "(MSI-X already enabled)\n");
-               return -EINVAL;
-       }
-
-       status = msi_capability_init(dev, nvec);
-       return status;
-}
-EXPORT_SYMBOL(pci_enable_msi_block);
-
 void pci_msi_shutdown(struct pci_dev *dev)
 {
        struct msi_desc *desc;
@@ -1029,8 +980,7 @@ int pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries, int nvec)
 
        /* Check whether driver already requested for MSI irq */
        if (dev->msi_enabled) {
-               dev_info(&dev->dev, "can't enable MSI-X "
-                      "(MSI IRQ already assigned)\n");
+               dev_info(&dev->dev, "can't enable MSI-X (MSI IRQ already assigned)\n");
                return -EINVAL;
        }
        status = msix_capability_init(dev, entries, nvec);
@@ -1132,14 +1082,45 @@ void pci_msi_init_pci_dev(struct pci_dev *dev)
  **/
 int pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec)
 {
-       int nvec = maxvec;
+       int nvec;
        int rc;
 
+       if (dev->current_state != PCI_D0)
+               return -EINVAL;
+
+       WARN_ON(!!dev->msi_enabled);
+
+       /* Check whether driver already requested MSI-X irqs */
+       if (dev->msix_enabled) {
+               dev_info(&dev->dev,
+                        "can't enable MSI (MSI-X already enabled)\n");
+               return -EINVAL;
+       }
+
        if (maxvec < minvec)
                return -ERANGE;
 
+       nvec = pci_msi_vec_count(dev);
+       if (nvec < 0)
+               return nvec;
+       else if (nvec < minvec)
+               return -EINVAL;
+       else if (nvec > maxvec)
+               nvec = maxvec;
+
+       do {
+               rc = pci_msi_check_device(dev, nvec, PCI_CAP_ID_MSI);
+               if (rc < 0) {
+                       return rc;
+               } else if (rc > 0) {
+                       if (rc < minvec)
+                               return -ENOSPC;
+                       nvec = rc;
+               }
+       } while (rc);
+
        do {
-               rc = pci_enable_msi_block(dev, nvec);
+               rc = msi_capability_init(dev, nvec);
                if (rc < 0) {
                        return rc;
                } else if (rc > 0) {