Merge branch 'x86-acpi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[firefly-linux-kernel-4.4.55.git] / drivers / pci / msi.c
index 337e16ab4a92ba3cde34b53b220b61d9191b4658..5099636a6e5f65782ea87fbb9c25a0aeeeed282e 100644 (file)
@@ -86,6 +86,31 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
 }
 #endif
 
+#ifndef arch_restore_msi_irqs
+# define arch_restore_msi_irqs default_restore_msi_irqs
+# define HAVE_DEFAULT_MSI_RESTORE_IRQS
+#endif
+
+#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
+void default_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+       struct msi_desc *entry;
+
+       entry = NULL;
+       if (dev->msix_enabled) {
+               list_for_each_entry(entry, &dev->msi_list, list) {
+                       if (irq == entry->irq)
+                               break;
+               }
+       } else if (dev->msi_enabled)  {
+               entry = irq_get_msi_desc(irq);
+       }
+
+       if (entry)
+               write_msi_msg(irq, &entry->msg);
+}
+#endif
+
 static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
 {
        u16 control;
@@ -182,6 +207,8 @@ static void msix_mask_irq(struct msi_desc *desc, u32 flag)
        desc->masked = __msix_mask_irq(desc, flag);
 }
 
+#ifdef CONFIG_GENERIC_HARDIRQS
+
 static void msi_set_mask_bit(struct irq_data *data, u32 flag)
 {
        struct msi_desc *desc = irq_data_get_msi(data);
@@ -205,6 +232,8 @@ void unmask_msi_irq(struct irq_data *data)
        msi_set_mask_bit(data, 0);
 }
 
+#endif /* CONFIG_GENERIC_HARDIRQS */
+
 void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
        BUG_ON(entry->dev->current_state != PCI_D0);
@@ -312,8 +341,10 @@ static void free_msi_irqs(struct pci_dev *dev)
                if (!entry->irq)
                        continue;
                nvec = 1 << entry->msi_attrib.multiple;
+#ifdef CONFIG_GENERIC_HARDIRQS
                for (i = 0; i < nvec; i++)
                        BUG_ON(irq_has_action(entry->irq + i));
+#endif
        }
 
        arch_teardown_msi_irqs(dev);
@@ -323,8 +354,18 @@ static void free_msi_irqs(struct pci_dev *dev)
                        if (list_is_last(&entry->list, &dev->msi_list))
                                iounmap(entry->mask_base);
                }
-               kobject_del(&entry->kobj);
-               kobject_put(&entry->kobj);
+
+               /*
+                * Its possible that we get into this path
+                * When populate_msi_sysfs fails, which means the entries
+                * were not registered with sysfs.  In that case don't
+                * unregister them.
+                */
+               if (entry->kobj.parent) {
+                       kobject_del(&entry->kobj);
+                       kobject_put(&entry->kobj);
+               }
+
                list_del(&entry->list);
                kfree(entry);
        }
@@ -362,7 +403,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
 
        pci_intx_for_msi(dev, 0);
        msi_set_enable(dev, pos, 0);
-       write_msi_msg(dev->irq, &entry->msg);
+       arch_restore_msi_irqs(dev, dev->irq);
 
        pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
        msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
@@ -390,7 +431,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
        pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
 
        list_for_each_entry(entry, &dev->msi_list, list) {
-               write_msi_msg(entry->irq, &entry->msg);
+               arch_restore_msi_irqs(dev, entry->irq);
                msix_mask_irq(entry, entry->masked);
        }