PCI/sysfs: Explicitly show first MSI IRQ for 'irq'
authorBarry Song <song.bao.hua@hisilicon.com>
Wed, 25 Aug 2021 10:26:35 +0000 (18:26 +0800)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 18 Oct 2021 21:43:04 +0000 (16:43 -0500)
The sysfs "irq" file contains the legacy INTx IRQ.  Or, if the device has
MSI enabled, it contains the first MSI IRQ instead.

Previously this file showed the pci_dev.irq value directly.  But we'd
prefer to use pci_dev.irq only for the INTx IRQ and decouple that from any
MSI or MSI-X IRQs.

If the device has MSI enabled, explicitly look up and show the first MSI
IRQ in the sysfs "irq" file.  Otherwise, show the INTx IRQ.

This removes the requirement that msi_capability_init() set pci_dev.irq to
the first MSI IRQ when enabling MSI and pci_msi_shutdown() restore the INTx
IRQ when disabling MSI.

[bhelgaas: commit log]
Link: https://lore.kernel.org/r/20210825102636.52757-3-21cnbao@gmail.com
Signed-off-by: Barry Song <song.bao.hua@hisilicon.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/pci-sysfs.c

index 7fb5cd1..b50fe7c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/slab.h>
 #include <linux/vgaarb.h>
 #include <linux/pm_runtime.h>
+#include <linux/msi.h>
 #include <linux/of.h>
 #include "pci.h"
 
@@ -49,7 +50,28 @@ pci_config_attr(subsystem_vendor, "0x%04x\n");
 pci_config_attr(subsystem_device, "0x%04x\n");
 pci_config_attr(revision, "0x%02x\n");
 pci_config_attr(class, "0x%06x\n");
-pci_config_attr(irq, "%u\n");
+
+static ssize_t irq_show(struct device *dev,
+                       struct device_attribute *attr,
+                       char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+#ifdef CONFIG_PCI_MSI
+       /*
+        * For MSI, show the first MSI IRQ; for all other cases including
+        * MSI-X, show the legacy INTx IRQ.
+        */
+       if (pdev->msi_enabled) {
+               struct msi_desc *desc = first_pci_msi_entry(pdev);
+
+               return sysfs_emit(buf, "%u\n", desc->irq);
+       }
+#endif
+
+       return sysfs_emit(buf, "%u\n", pdev->irq);
+}
+static DEVICE_ATTR_RO(irq);
 
 static ssize_t broken_parity_status_show(struct device *dev,
                                         struct device_attribute *attr,