PCI: Place interrupt related code into irq.c
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Mon, 29 Jan 2024 11:36:54 +0000 (13:36 +0200)
committerBjorn Helgaas <bhelgaas@google.com>
Mon, 29 Jan 2024 23:01:31 +0000 (17:01 -0600)
Interrupt related code is spread into irq.c, pci.c, and setup-irq.c.
Group them into pre-existing irq.c.

Link: https://lore.kernel.org/r/20240129113655.3368-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
drivers/pci/Makefile
drivers/pci/irq.c
drivers/pci/pci-driver.c
drivers/pci/pci.c
drivers/pci/setup-irq.c [deleted file]

index cc8b4e01e29de5439c1671896d5dd53f77a3b9c4..54a7adf0bb88cfecdbf546ba5d97be957e232609 100644 (file)
@@ -5,7 +5,7 @@
 obj-$(CONFIG_PCI)              += access.o bus.o probe.o host-bridge.o \
                                   remove.o pci.o pci-driver.o search.o \
                                   pci-sysfs.o rom.o setup-res.o irq.o vpd.o \
-                                  setup-bus.o vc.o mmap.o setup-irq.o
+                                  setup-bus.o vc.o mmap.o
 
 obj-$(CONFIG_PCI)              += msi/
 obj-$(CONFIG_PCI)              += pcie/
index 0050e8f6814ed655ee06a87252ed468d22963722..4555630be9ecdf3d46b5ea1ebf90fe6861a00212 100644 (file)
@@ -8,9 +8,13 @@
 
 #include <linux/device.h>
 #include <linux/kernel.h>
+#include <linux/errno.h>
 #include <linux/export.h>
+#include <linux/interrupt.h>
 #include <linux/pci.h>
 
+#include "pci.h"
+
 /**
  * pci_request_irq - allocate an interrupt line for a PCI device
  * @dev:       PCI device to operate on
@@ -74,3 +78,203 @@ void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id)
        kfree(free_irq(pci_irq_vector(dev, nr), dev_id));
 }
 EXPORT_SYMBOL(pci_free_irq);
+
+/**
+ * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
+ * @dev: the PCI device
+ * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
+ *
+ * Perform INTx swizzling for a device behind one level of bridge.  This is
+ * required by section 9.1 of the PCI-to-PCI bridge specification for devices
+ * behind bridges on add-in cards.  For devices with ARI enabled, the slot
+ * number is always 0 (see the Implementation Note in section 2.2.8.1 of
+ * the PCI Express Base Specification, Revision 2.1)
+ */
+u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin)
+{
+       int slot;
+
+       if (pci_ari_enabled(dev->bus))
+               slot = 0;
+       else
+               slot = PCI_SLOT(dev->devfn);
+
+       return (((pin - 1) + slot) % 4) + 1;
+}
+
+int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
+{
+       u8 pin;
+
+       pin = dev->pin;
+       if (!pin)
+               return -1;
+
+       while (!pci_is_root_bus(dev->bus)) {
+               pin = pci_swizzle_interrupt_pin(dev, pin);
+               dev = dev->bus->self;
+       }
+       *bridge = dev;
+       return pin;
+}
+
+/**
+ * pci_common_swizzle - swizzle INTx all the way to root bridge
+ * @dev: the PCI device
+ * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD)
+ *
+ * Perform INTx swizzling for a device.  This traverses through all PCI-to-PCI
+ * bridges all the way up to a PCI root bus.
+ */
+u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+       u8 pin = *pinp;
+
+       while (!pci_is_root_bus(dev->bus)) {
+               pin = pci_swizzle_interrupt_pin(dev, pin);
+               dev = dev->bus->self;
+       }
+       *pinp = pin;
+       return PCI_SLOT(dev->devfn);
+}
+EXPORT_SYMBOL_GPL(pci_common_swizzle);
+
+void pci_assign_irq(struct pci_dev *dev)
+{
+       u8 pin;
+       u8 slot = -1;
+       int irq = 0;
+       struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
+
+       if (!(hbrg->map_irq)) {
+               pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
+               return;
+       }
+
+       /*
+        * If this device is not on the primary bus, we need to figure out
+        * which interrupt pin it will come in on. We know which slot it
+        * will come in on because that slot is where the bridge is. Each
+        * time the interrupt line passes through a PCI-PCI bridge we must
+        * apply the swizzle function.
+        */
+       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+       /* Cope with illegal. */
+       if (pin > 4)
+               pin = 1;
+
+       if (pin) {
+               /* Follow the chain of bridges, swizzling as we go. */
+               if (hbrg->swizzle_irq)
+                       slot = (*(hbrg->swizzle_irq))(dev, &pin);
+
+               /*
+                * If a swizzling function is not used, map_irq() must
+                * ignore slot.
+                */
+               irq = (*(hbrg->map_irq))(dev, slot, pin);
+               if (irq == -1)
+                       irq = 0;
+       }
+       dev->irq = irq;
+
+       pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
+
+       /*
+        * Always tell the device, so the driver knows what is the real IRQ
+        * to use; the device does not use it.
+        */
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
+{
+       struct pci_bus *bus = dev->bus;
+       bool mask_updated = true;
+       u32 cmd_status_dword;
+       u16 origcmd, newcmd;
+       unsigned long flags;
+       bool irq_pending;
+
+       /*
+        * We do a single dword read to retrieve both command and status.
+        * Document assumptions that make this possible.
+        */
+       BUILD_BUG_ON(PCI_COMMAND % 4);
+       BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
+
+       raw_spin_lock_irqsave(&pci_lock, flags);
+
+       bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
+
+       irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
+
+       /*
+        * Check interrupt status register to see whether our device
+        * triggered the interrupt (when masking) or the next IRQ is
+        * already pending (when unmasking).
+        */
+       if (mask != irq_pending) {
+               mask_updated = false;
+               goto done;
+       }
+
+       origcmd = cmd_status_dword;
+       newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
+       if (mask)
+               newcmd |= PCI_COMMAND_INTX_DISABLE;
+       if (newcmd != origcmd)
+               bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
+
+done:
+       raw_spin_unlock_irqrestore(&pci_lock, flags);
+
+       return mask_updated;
+}
+
+/**
+ * pci_check_and_mask_intx - mask INTx on pending interrupt
+ * @dev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, mask it and return
+ * true in that case. False is returned if no interrupt was pending.
+ */
+bool pci_check_and_mask_intx(struct pci_dev *dev)
+{
+       return pci_check_and_set_intx_mask(dev, true);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
+
+/**
+ * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending
+ * @dev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, unmask it if not and
+ * return true. False is returned and the mask remains active if there was
+ * still an interrupt pending.
+ */
+bool pci_check_and_unmask_intx(struct pci_dev *dev)
+{
+       return pci_check_and_set_intx_mask(dev, false);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
+
+/**
+ * pcibios_penalize_isa_irq - penalize an ISA IRQ
+ * @irq: ISA IRQ to penalize
+ * @active: IRQ active or not
+ *
+ * Permits the platform to provide architecture-specific functionality when
+ * penalizing ISA IRQs. This is the default implementation. Architecture
+ * implementations can override this.
+ */
+void __weak pcibios_penalize_isa_irq(int irq, int active) {}
+
+int __weak pcibios_alloc_irq(struct pci_dev *dev)
+{
+       return 0;
+}
+
+void __weak pcibios_free_irq(struct pci_dev *dev)
+{
+}
index 51ec9e7e784f0e3a82134a05b114abe5be90d07c..ec838f2e892e38d69b54956a08c0e3424f45ab11 100644 (file)
@@ -419,15 +419,6 @@ static int __pci_device_probe(struct pci_driver *drv, struct pci_dev *pci_dev)
        return error;
 }
 
-int __weak pcibios_alloc_irq(struct pci_dev *dev)
-{
-       return 0;
-}
-
-void __weak pcibios_free_irq(struct pci_dev *dev)
-{
-}
-
 #ifdef CONFIG_PCI_IOV
 static inline bool pci_device_can_probe(struct pci_dev *pdev)
 {
index d8f11a078924c1336326456b0e3f37f7b0e66df9..75388584e60d9b5f5fa7d2c6207b2ce30b46cd38 100644 (file)
@@ -24,7 +24,6 @@
 #include <linux/log2.h>
 #include <linux/logic_pio.h>
 #include <linux/pm_wakeup.h>
-#include <linux/interrupt.h>
 #include <linux/device.h>
 #include <linux/pm_runtime.h>
 #include <linux/pci_hotplug.h>
@@ -2292,17 +2291,6 @@ void __weak pcibios_release_device(struct pci_dev *dev) {}
  */
 void __weak pcibios_disable_device(struct pci_dev *dev) {}
 
-/**
- * pcibios_penalize_isa_irq - penalize an ISA IRQ
- * @irq: ISA IRQ to penalize
- * @active: IRQ active or not
- *
- * Permits the platform to provide architecture-specific functionality when
- * penalizing ISA IRQs. This is the default implementation. Architecture
- * implementations can override this.
- */
-void __weak pcibios_penalize_isa_irq(int irq, int active) {}
-
 static void do_pci_disable_device(struct pci_dev *dev)
 {
        u16 pci_command;
@@ -3964,66 +3952,6 @@ int pci_enable_atomic_ops_to_root(struct pci_dev *dev, u32 cap_mask)
 }
 EXPORT_SYMBOL(pci_enable_atomic_ops_to_root);
 
-/**
- * pci_swizzle_interrupt_pin - swizzle INTx for device behind bridge
- * @dev: the PCI device
- * @pin: the INTx pin (1=INTA, 2=INTB, 3=INTC, 4=INTD)
- *
- * Perform INTx swizzling for a device behind one level of bridge.  This is
- * required by section 9.1 of the PCI-to-PCI bridge specification for devices
- * behind bridges on add-in cards.  For devices with ARI enabled, the slot
- * number is always 0 (see the Implementation Note in section 2.2.8.1 of
- * the PCI Express Base Specification, Revision 2.1)
- */
-u8 pci_swizzle_interrupt_pin(const struct pci_dev *dev, u8 pin)
-{
-       int slot;
-
-       if (pci_ari_enabled(dev->bus))
-               slot = 0;
-       else
-               slot = PCI_SLOT(dev->devfn);
-
-       return (((pin - 1) + slot) % 4) + 1;
-}
-
-int pci_get_interrupt_pin(struct pci_dev *dev, struct pci_dev **bridge)
-{
-       u8 pin;
-
-       pin = dev->pin;
-       if (!pin)
-               return -1;
-
-       while (!pci_is_root_bus(dev->bus)) {
-               pin = pci_swizzle_interrupt_pin(dev, pin);
-               dev = dev->bus->self;
-       }
-       *bridge = dev;
-       return pin;
-}
-
-/**
- * pci_common_swizzle - swizzle INTx all the way to root bridge
- * @dev: the PCI device
- * @pinp: pointer to the INTx pin value (1=INTA, 2=INTB, 3=INTD, 4=INTD)
- *
- * Perform INTx swizzling for a device.  This traverses through all PCI-to-PCI
- * bridges all the way up to a PCI root bus.
- */
-u8 pci_common_swizzle(struct pci_dev *dev, u8 *pinp)
-{
-       u8 pin = *pinp;
-
-       while (!pci_is_root_bus(dev->bus)) {
-               pin = pci_swizzle_interrupt_pin(dev, pin);
-               dev = dev->bus->self;
-       }
-       *pinp = pin;
-       return PCI_SLOT(dev->devfn);
-}
-EXPORT_SYMBOL_GPL(pci_common_swizzle);
-
 /**
  * pci_release_region - Release a PCI bar
  * @pdev: PCI device whose resources were previously reserved by
@@ -4737,78 +4665,6 @@ void pci_intx(struct pci_dev *pdev, int enable)
 }
 EXPORT_SYMBOL_GPL(pci_intx);
 
-static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
-{
-       struct pci_bus *bus = dev->bus;
-       bool mask_updated = true;
-       u32 cmd_status_dword;
-       u16 origcmd, newcmd;
-       unsigned long flags;
-       bool irq_pending;
-
-       /*
-        * We do a single dword read to retrieve both command and status.
-        * Document assumptions that make this possible.
-        */
-       BUILD_BUG_ON(PCI_COMMAND % 4);
-       BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
-
-       raw_spin_lock_irqsave(&pci_lock, flags);
-
-       bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
-
-       irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
-
-       /*
-        * Check interrupt status register to see whether our device
-        * triggered the interrupt (when masking) or the next IRQ is
-        * already pending (when unmasking).
-        */
-       if (mask != irq_pending) {
-               mask_updated = false;
-               goto done;
-       }
-
-       origcmd = cmd_status_dword;
-       newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
-       if (mask)
-               newcmd |= PCI_COMMAND_INTX_DISABLE;
-       if (newcmd != origcmd)
-               bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
-
-done:
-       raw_spin_unlock_irqrestore(&pci_lock, flags);
-
-       return mask_updated;
-}
-
-/**
- * pci_check_and_mask_intx - mask INTx on pending interrupt
- * @dev: the PCI device to operate on
- *
- * Check if the device dev has its INTx line asserted, mask it and return
- * true in that case. False is returned if no interrupt was pending.
- */
-bool pci_check_and_mask_intx(struct pci_dev *dev)
-{
-       return pci_check_and_set_intx_mask(dev, true);
-}
-EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
-
-/**
- * pci_check_and_unmask_intx - unmask INTx if no interrupt is pending
- * @dev: the PCI device to operate on
- *
- * Check if the device dev has its INTx line asserted, unmask it if not and
- * return true. False is returned and the mask remains active if there was
- * still an interrupt pending.
- */
-bool pci_check_and_unmask_intx(struct pci_dev *dev)
-{
-       return pci_check_and_set_intx_mask(dev, false);
-}
-EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
-
 /**
  * pci_wait_for_pending_transaction - wait for pending transaction
  * @dev: the PCI device to operate on
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
deleted file mode 100644 (file)
index cc7d26b..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Support routines for initializing a PCI subsystem
- *
- * Extruded from code written by
- *      Dave Rusling (david.rusling@reo.mts.dec.com)
- *      David Mosberger (davidm@cs.arizona.edu)
- *     David Miller (davem@redhat.com)
- */
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/cache.h>
-#include "pci.h"
-
-void pci_assign_irq(struct pci_dev *dev)
-{
-       u8 pin;
-       u8 slot = -1;
-       int irq = 0;
-       struct pci_host_bridge *hbrg = pci_find_host_bridge(dev->bus);
-
-       if (!(hbrg->map_irq)) {
-               pci_dbg(dev, "runtime IRQ mapping not provided by arch\n");
-               return;
-       }
-
-       /*
-        * If this device is not on the primary bus, we need to figure out
-        * which interrupt pin it will come in on. We know which slot it
-        * will come in on because that slot is where the bridge is. Each
-        * time the interrupt line passes through a PCI-PCI bridge we must
-        * apply the swizzle function.
-        */
-       pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-       /* Cope with illegal. */
-       if (pin > 4)
-               pin = 1;
-
-       if (pin) {
-               /* Follow the chain of bridges, swizzling as we go. */
-               if (hbrg->swizzle_irq)
-                       slot = (*(hbrg->swizzle_irq))(dev, &pin);
-
-               /*
-                * If a swizzling function is not used, map_irq() must
-                * ignore slot.
-                */
-               irq = (*(hbrg->map_irq))(dev, slot, pin);
-               if (irq == -1)
-                       irq = 0;
-       }
-       dev->irq = irq;
-
-       pci_dbg(dev, "assign IRQ: got %d\n", dev->irq);
-
-       /*
-        * Always tell the device, so the driver knows what is the real IRQ
-        * to use; the device does not use it.
-        */
-       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
-}