All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging
@ 2014-10-02  4:07 matt
  2014-10-02  4:07 ` [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers matt
                   ` (18 more replies)
  0 siblings, 19 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci

Sorry, the previous submission was damaged by my editor which purged the sign off lines from the patches,
this is a fixed version.

pci_fixup_irqs is the current method used in most arches to assign IRQs to
PCI devices. This has a number of flaws including it requiring an extra walk
of the PCI bus and most importantly not running for devices which are added
after boot time, this includes hot-added devices on boards that support this.

This patch set modifies the IRQ mapping and swizzling infrastructure
such that functions are registered by the boot code (instead of being
run directly by the boot code) and then run later in the enable_device
path such that it will apply to all devices and not only those inserted
at boot time.

This is cleaner as it unifies how each architecture allocates PCI IRQs as much
as possible (some arches were particularly resistant to these changes so some
work-arounds have been used or the change disabled completely).

The caveat here is that I have been forced to modify some architecture specific
code for various architectures which I cannot test due to not having such boards
available. The code seems correct and the changes in most cases are small and
trivial however I have not tested all the patches for rare arches.

NEW: Since the last version all changes and suggested bug fixes have been implemented
the patch-set has also been rebased onto the latest kernel version to ease merging.

Many Thanks,
Matthew

Note also that I have switched email addresses due to a change in employment
but I am indeed the same person who submitted the previous versions of this patch.

 arch/alpha/kernel/pci.c                 | 16 +++---
 arch/alpha/kernel/sys_nautilus.c        |  1 -
 arch/arm/kernel/bios32.c                | 13 +++--
 arch/cris/arch-v32/drivers/pci/bios.c   | 14 ++---
 arch/frv/mb93090-mb00/pci-frv.h         |  1 -
 arch/frv/mb93090-mb00/pci-irq.c         | 28 ++++++----
 arch/frv/mb93090-mb00/pci-vdk.c         |  1 -
 arch/ia64/pci/pci.c                     |  3 ++
 arch/m68k/platform/coldfire/pci.c       |  8 ++-
 arch/microblaze/pci/pci-common.c        | 10 ++--
 arch/mips/pci/pci.c                     |  9 +++-
 arch/mn10300/unit-asb2305/pci-asb2305.h |  5 +-
 arch/mn10300/unit-asb2305/pci-irq.c     | 25 ++-------
 arch/mn10300/unit-asb2305/pci.c         | 21 +++-----
 arch/parisc/kernel/pci.c                |  8 ++-
 arch/powerpc/kernel/pci-common.c        | 26 ++++-----
 arch/s390/pci/pci.c                     |  7 +++
 arch/sh/drivers/pci/fixups-cayman.c     |  2 +-
 arch/sh/drivers/pci/fixups-dreamcast.c  |  2 +-
 arch/sh/drivers/pci/fixups-r7780rp.c    |  2 +-
 arch/sh/drivers/pci/fixups-rts7751r2d.c |  6 +--
 arch/sh/drivers/pci/fixups-sdk7780.c    |  4 +-
 arch/sh/drivers/pci/fixups-se7751.c     |  2 +-
 arch/sh/drivers/pci/fixups-sh03.c       |  2 +-
 arch/sh/drivers/pci/fixups-snapgear.c   |  2 +-
 arch/sh/drivers/pci/fixups-titan.c      |  4 +-
 arch/sh/drivers/pci/pci.c               | 10 ++--
 arch/sh/drivers/pci/pcie-sh7786.c       |  2 +-
 arch/sparc/kernel/leon_pci.c            | 12 ++++-
 arch/sparc/kernel/pci.c                 | 21 ++++++--
 arch/tile/kernel/pci.c                  | 10 ++--
 arch/tile/kernel/pci_gx.c               | 10 ++--
 arch/unicore32/kernel/pci.c             | 11 ++--
 arch/x86/include/asm/pci_x86.h          |  7 +--
 arch/x86/kernel/x86_init.c              |  1 -
 arch/x86/pci/acpi.c                     |  5 +-
 arch/x86/pci/common.c                   |  2 -
 arch/x86/pci/irq.c                      | 94 ++++++++++++++++++---------------
 drivers/of/of_pci_irq.c                 |  2 +-
 drivers/pci/Makefile                    | 15 +-----
 drivers/pci/host-bridge.c               |  2 +-
 drivers/pci/pci.c                       |  5 +-
 drivers/pci/pci.h                       |  1 +
 drivers/pci/probe.c                     | 12 -----
 drivers/pci/setup-irq.c                 | 34 ++++++------
 include/linux/pci.h                     |  6 ++-
 46 files changed, 265 insertions(+), 219 deletions(-)



^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
@ 2014-10-02  4:07 ` matt
  2014-10-02 10:33   ` Liviu Dudau
  2014-10-14 17:15   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time matt
                   ` (17 subsequent siblings)
  18 siblings, 2 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>


These are the main infrastructure changes to allow the registration of
PCI IRQ assignment functions which can then be called during the device
enabling stage. This replaces the pre-initialisation of PCI IRQs at boot
time which caused limitations such as failing for devices which are
hot-plugged after the machine has booted and resulted in highly
fragmented PCI initialisation paths.

The pdev_assign_irq function becomes a centralised method of assigning
IRQs to PCI devices in a non platform specific way. The pci_host_bridge
structure has had some function pointers added to it where the boot code
can register the platform specific ways of assigning PCI IRQs to be used
to allow them to be used by pdev_assign_irq.

Some small adjustements have also been made to makefiles in order to
accomodate these changes.

Note this code completely obsolites the pci_fixup_irqs code path which
has thus been removed.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 drivers/of/of_pci_irq.c   |  2 +-
 drivers/pci/Makefile      | 15 ++-------------
 drivers/pci/host-bridge.c |  2 +-
 drivers/pci/pci.c         |  5 ++++-
 drivers/pci/pci.h         |  1 +
 drivers/pci/probe.c       | 12 ------------
 drivers/pci/setup-irq.c   | 34 ++++++++++++++++------------------
 include/linux/pci.h       |  6 ++++--
 8 files changed, 29 insertions(+), 48 deletions(-)

diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
index 1710d9d..205eb7a 100644
--- a/drivers/of/of_pci_irq.c
+++ b/drivers/of/of_pci_irq.c
@@ -97,7 +97,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_pci);
  * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
  *
  * @slot and @pin are unused, but included in the function so that this
- * function can be used directly as the map_irq callback to pci_fixup_irqs().
+ * function can be used directly as the map_irq callback to pdev_assign_irq().
  */
 int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
 {
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index e04fe2d..38c4cb0 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -4,7 +4,8 @@
 
 obj-y		+= 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
+			irq.o vpd.o setup-bus.o vc.o setup-irq.o
+
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
@@ -31,18 +32,6 @@ obj-$(CONFIG_PCI_ATS) += ats.o
 obj-$(CONFIG_PCI_IOV) += iov.o
 
 #
-# Some architectures use the generic PCI setup functions
-#
-obj-$(CONFIG_ALPHA) += setup-irq.o
-obj-$(CONFIG_ARM) += setup-irq.o
-obj-$(CONFIG_UNICORE32) += setup-irq.o
-obj-$(CONFIG_SUPERH) += setup-irq.o
-obj-$(CONFIG_MIPS) += setup-irq.o
-obj-$(CONFIG_TILE) += setup-irq.o
-obj-$(CONFIG_SPARC_LEON) += setup-irq.o
-obj-$(CONFIG_M68K) += setup-irq.o
-
-#
 # ACPI Related PCI FW Functions
 # ACPI _DSM provided firmware instance and string name
 #
diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
index 0e5f3c9..8ed186f 100644
--- a/drivers/pci/host-bridge.c
+++ b/drivers/pci/host-bridge.c
@@ -16,7 +16,7 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
 	return bus;
 }
 
-static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
+struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
 {
 	struct pci_bus *root_bus = find_pci_root_bus(bus);
 
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 2c9ac70..2dd28d9 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1192,11 +1192,15 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
 	struct pci_dev *bridge;
 	u16 cmd;
 	u8 pin;
+	struct pci_host_bridge *hbrg = find_pci_host_bridge(dev->bus);
 
 	err = pci_set_power_state(dev, PCI_D0);
 	if (err < 0 && err != -EIO)
 		return err;
 
+	pdev_assign_irq(dev, hbrg->swizzle_irq, hbrg->map_irq);
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+
 	bridge = pci_upstream_bridge(dev);
 	if (bridge)
 		pcie_aspm_powersave_config_link(bridge);
@@ -1209,7 +1213,6 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
 	if (dev->msi_enabled || dev->msix_enabled)
 		return 0;
 
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (pin) {
 		pci_read_config_word(dev, PCI_COMMAND, &cmd);
 		if (cmd & PCI_COMMAND_INTX_DISABLE)
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index 0601890..a6cf445 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -70,6 +70,7 @@ void pci_config_pm_runtime_put(struct pci_dev *dev);
 void pci_pm_init(struct pci_dev *dev);
 void pci_allocate_cap_save_buffers(struct pci_dev *dev);
 void pci_free_cap_save_buffers(struct pci_dev *dev);
+struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus);
 
 static inline void pci_wakeup_event(struct pci_dev *dev)
 {
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 4170113..314e9e3 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1719,18 +1719,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pci_scan_child_bus);
 
-/**
- * pcibios_root_bridge_prepare - Platform-specific host bridge setup.
- * @bridge: Host bridge to set up.
- *
- * Default empty implementation.  Replace with an architecture-specific setup
- * routine, if necessary.
- */
-int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
-{
-	return 0;
-}
-
 void __weak pcibios_add_bus(struct pci_bus *bus)
 {
 }
diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
index 4e2d595..203bf7e 100644
--- a/drivers/pci/setup-irq.c
+++ b/drivers/pci/setup-irq.c
@@ -22,13 +22,19 @@ void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 }
 
-static void pdev_fixup_irq(struct pci_dev *dev,
+void pdev_assign_irq(struct pci_dev *dev,
 			   u8 (*swizzle)(struct pci_dev *, u8 *),
-			   int (*map_irq)(const struct pci_dev *, u8, u8))
+			   int (*map_irq)(struct pci_dev *, u8, u8))
 {
-	u8 pin, slot;
+	u8 pin;
+	u8 slot = -1;
 	int irq = 0;
 
+	if (!map_irq) {
+		dev_dbg(&dev->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 'cos that slot is where the bridge is.   Each
@@ -40,28 +46,20 @@ static void pdev_fixup_irq(struct pci_dev *dev,
 	if (pin > 4)
 		pin = 1;
 
-	if (pin != 0) {
-		/* Follow the chain of bridges, swizzling as we go.  */
-		slot = (*swizzle)(dev, &pin);
+	if (pin) {
+		/* Follow the chain of bridges, swizzling as we go. */
+		if(swizzle)
+			slot = (*swizzle)(dev, &pin);
 
+		/* If a swizzling function is not used map_irq must ignore slot */
 		irq = (*map_irq)(dev, slot, pin);
 		if (irq == -1)
 			irq = 0;
 	}
-	dev->irq = irq;
-
-	dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq);
 
+	dev_dbg(&dev->dev, "assign irq: got %d\n", dev->irq);
+	dev->irq = irq;
 	/* Always tell the device, so the driver knows what is
 	   the real IRQ to use; the device does not use it. */
 	pcibios_update_irq(dev, irq);
 }
-
-void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
-		    int (*map_irq)(const struct pci_dev *, u8, u8))
-{
-	struct pci_dev *dev = NULL;
-
-	for_each_pci_dev(dev)
-		pdev_fixup_irq(dev, swizzle, map_irq);
-}
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 96453f9..5426d11 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -403,6 +403,8 @@ struct pci_host_bridge {
 	struct device dev;
 	struct pci_bus *bus;		/* root bus */
 	struct list_head windows;	/* pci_host_bridge_windows */
+	u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* platform irq swizzler */
+	int (*map_irq)(struct pci_dev *, u8, u8);
 	void (*release_fn)(struct pci_host_bridge *);
 	void *release_data;
 };
@@ -1064,8 +1066,8 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
 void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus);
 void pdev_enable_device(struct pci_dev *);
 int pci_enable_resources(struct pci_dev *, int mask);
-void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
-		    int (*)(const struct pci_dev *, u8, u8));
+void pdev_assign_irq(struct pci_dev *dev, u8 (*swizzle)(struct pci_dev *, u8 *),
+                     int (*map_irq)(struct pci_dev *, u8, u8));
 #define HAVE_PCI_REQ_REGIONS	2
 int __must_check pci_request_regions(struct pci_dev *, const char *);
 int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
  2014-10-02  4:07 ` [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers matt
@ 2014-10-02  4:07 ` matt
  2014-10-02 10:51   ` Liviu Dudau
  2014-10-14 18:11   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 03/18] Delayed arm " matt
                   ` (16 subsequent siblings)
  18 siblings, 2 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

The x86 architecture boot code currently traverses the PCI buses with
an extra pass in order to initialise the PCI device IRQs at boot, this
patch avoids this pass and defers the IRQ assignment untill device
enable time which also has the benefit that hot-plugged devices are
assigned IRQs without additional code.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/x86/include/asm/pci_x86.h |  7 ++--
 arch/x86/kernel/x86_init.c     |  1 -
 arch/x86/pci/acpi.c            |  5 ++-
 arch/x86/pci/common.c          |  2 -
 arch/x86/pci/irq.c             | 94 +++++++++++++++++++++++-------------------
 5 files changed, 59 insertions(+), 50 deletions(-)

diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
index fa1195d..16fd8e9 100644
--- a/arch/x86/include/asm/pci_x86.h
+++ b/arch/x86/include/asm/pci_x86.h
@@ -90,6 +90,7 @@ extern unsigned int pcibios_irq_mask;
 
 extern raw_spinlock_t pci_config_lock;
 
+extern int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
 extern int (*pcibios_enable_irq)(struct pci_dev *dev);
 extern void (*pcibios_disable_irq)(struct pci_dev *dev);
 
@@ -119,7 +120,7 @@ extern int __init pci_acpi_init(void);
 extern void __init pcibios_irq_init(void);
 extern int __init pcibios_init(void);
 extern int pci_legacy_init(void);
-extern void pcibios_fixup_irqs(void);
+extern int pcibios_fixup_irq(struct pci_dev *dev, u8 pin);
 
 /* pci-mmconfig.c */
 
@@ -200,9 +201,9 @@ static inline void mmio_config_writel(void __iomem *pos, u32 val)
 #  define x86_default_pci_init		pci_legacy_init
 # endif
 # define x86_default_pci_init_irq	pcibios_irq_init
-# define x86_default_pci_fixup_irqs	pcibios_fixup_irqs
+# define x86_default_pci_fixup_irq	pcibios_fixup_irq
 #else
 # define x86_default_pci_init		NULL
 # define x86_default_pci_init_irq	NULL
-# define x86_default_pci_fixup_irqs	NULL
+# define x86_default_pci_fixup_irq	NULL
 #endif
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index e48b674..064457f 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -81,7 +81,6 @@ struct x86_init_ops x86_init __initdata = {
 	.pci = {
 		.init			= x86_default_pci_init,
 		.init_irq		= x86_default_pci_init_irq,
-		.fixup_irqs		= x86_default_pci_fixup_irqs,
 	},
 };
 
diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
index cfd1b13..2c433f4 100644
--- a/arch/x86/pci/acpi.c
+++ b/arch/x86/pci/acpi.c
@@ -311,7 +311,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
 	} else if (orig_end != end) {
 		dev_info(&info->bridge->dev,
 			"host bridge window [%#llx-%#llx] "
-			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
+			"([%#llx-%#llx] ignored, not CPU addressable)\n",
 			start, orig_end, end + 1, orig_end);
 	}
 
@@ -571,6 +571,9 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 	struct pci_sysdata *sd = bridge->bus->sysdata;
 
 	ACPI_COMPANION_SET(&bridge->dev, sd->companion);
+
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pci_map_irq;
 	return 0;
 }
 
diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
index 059a76c..d4ed0b0 100644
--- a/arch/x86/pci/common.c
+++ b/arch/x86/pci/common.c
@@ -662,8 +662,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
 	if ((err = pci_enable_resources(dev, mask)) < 0)
 		return err;
 
-	if (!pci_dev_msi_enabled(dev))
-		return pcibios_enable_irq(dev);
 	return 0;
 }
 
diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
index eb500c2..33d323d 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -594,9 +594,9 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
 		return 1;
 	}
 
-	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN && 
-	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX) 
-	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && 
+	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN &&
+	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)
+	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
 	     device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)
 	||  (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN &&
 	     device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)
@@ -875,9 +875,8 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
 	return NULL;
 }
 
-static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
+static int pcibios_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
 {
-	u8 pin;
 	struct irq_info *info;
 	int i, pirq, newirq;
 	int irq = 0;
@@ -887,7 +886,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 	char *msg = NULL;
 
 	/* Find IRQ pin */
-	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
 	if (!pin) {
 		dev_dbg(&dev->dev, "no interrupt pin\n");
 		return 0;
@@ -1017,50 +1015,45 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
 					 irq, pci_name(dev2));
 		}
 	}
-	return 1;
+	/*
+	 * Due to the complicated platform specific behvaiour we cannot defer
+	 * assigning dev->irq to the caller but will return it anyway
+	 */
+	return dev->irq;
 }
 
-void __init pcibios_fixup_irqs(void)
+int pcibios_fixup_irq(struct pci_dev *dev, u8 pin)
 {
-	struct pci_dev *dev = NULL;
-	u8 pin;
-
+	int irq = dev->irq;
 	DBG(KERN_DEBUG "PCI: IRQ fixup\n");
-	for_each_pci_dev(dev) {
-		/*
-		 * If the BIOS has set an out of range IRQ number, just
-		 * ignore it.  Also keep track of which IRQ's are
-		 * already in use.
-		 */
-		if (dev->irq >= 16) {
-			dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
-			dev->irq = 0;
-		}
-		/*
-		 * If the IRQ is already assigned to a PCI device,
-		 * ignore its ISA use penalty
-		 */
-		if (pirq_penalty[dev->irq] >= 100 &&
-				pirq_penalty[dev->irq] < 100000)
-			pirq_penalty[dev->irq] = 0;
-		pirq_penalty[dev->irq]++;
+	/*
+	 * If the BIOS has set an out of range IRQ number, just
+	 * ignore it.  Also keep track of which IRQ's are
+	 * already in use.
+	 */
+	if (irq >= 16) {
+		dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", irq);
+		irq = 0;
 	}
+	/*
+	 * If the IRQ is already assigned to a PCI device,
+	 * ignore its ISA use penalty
+	 */
+	if (pirq_penalty[irq] >= 100 &&
+			pirq_penalty[irq] < 100000)
+		pirq_penalty[irq] = 0;
+	pirq_penalty[irq]++;
 
-	if (io_apic_assign_pci_irqs)
-		return;
+	if (io_apic_assign_pci_irqs || !pin)
+		return irq;
 
-	dev = NULL;
-	for_each_pci_dev(dev) {
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		if (!pin)
-			continue;
+	/*
+	 * Still no IRQ? Try to lookup one...
+	 */
+	if (!irq)
+		irq = pcibios_lookup_irq(dev, pin, 0);
 
-		/*
-		 * Still no IRQ? Try to lookup one...
-		 */
-		if (!dev->irq)
-			pcibios_lookup_irq(dev, 0);
-	}
+	return irq;
 }
 
 /*
@@ -1161,6 +1154,13 @@ void __init pcibios_irq_init(void)
 	}
 }
 
+int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pci_map_irq;
+	return 0;
+}
+
 static void pirq_penalize_isa_irq(int irq, int active)
 {
 	/*
@@ -1185,12 +1185,20 @@ void pcibios_penalize_isa_irq(int irq, int active)
 		pirq_penalize_isa_irq(irq, active);
 }
 
+int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	dev->irq = pcibios_fixup_irq(dev, pin);
+	if (pcibios_enable_irq(dev))
+		return -1;
+	return dev->irq;
+}
+
 static int pirq_enable_irq(struct pci_dev *dev)
 {
 	u8 pin = 0;
 
 	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-	if (pin && !pcibios_lookup_irq(dev, 1)) {
+	if (pin && !pcibios_lookup_irq(dev, pin, 1)) {
 		char *msg = "";
 
 		if (!io_apic_assign_pci_irqs && dev->irq)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 03/18] Delayed arm setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
  2014-10-02  4:07 ` [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers matt
  2014-10-02  4:07 ` [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:14   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 04/18] Delayed powerpc " matt
                   ` (15 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently PCI device IRQs under arm are initialised during the
pci_common_init_dev code path, this results in an extra sweep of the
PCI bus as well as causing PCI devices hot-plugged after boot to not
receive an IRQ.

This patch set defers this assignment untill the device enable phase
which prevents both these issues.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/arm/kernel/bios32.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
index 17a26c1..4dcf3f7 100644
--- a/arch/arm/kernel/bios32.c
+++ b/arch/arm/kernel/bios32.c
@@ -389,7 +389,7 @@ void pcibios_remove_bus(struct pci_bus *bus)
  * PCI standard swizzle is implemented on plug-in cards and Cardbus based
  * PCI extenders, so it can not be ignored.
  */
-static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
+u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
 {
 	struct pci_sys_data *sys = dev->sysdata;
 	int slot, oldpin = *pin;
@@ -409,7 +409,7 @@ static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
 /*
  * Map a slot/pin to an IRQ.
  */
-static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	struct pci_sys_data *sys = dev->sysdata;
 	int irq = -1;
@@ -424,6 +424,13 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 	return irq;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pcibios_swizzle;
+	bridge->map_irq = pcibios_map_irq;
+	return 0;
+}
+
 static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
 {
 	int ret;
@@ -523,8 +530,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
 	if (hw->postinit)
 		hw->postinit();
 
-	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
-
 	list_for_each_entry(sys, &head, node) {
 		struct pci_bus *bus = sys->bus;
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 04/18] Delayed powerpc setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (2 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 03/18] Delayed arm " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:20   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 05/18] Delayed sh " matt
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

The powerpc PCI init code is currently initialising PCI device IRQ during
the boot time pcibios phase. This results in devices which are connected
after boot time not being asigned IRQs which can cause various problems.

This patch as part of its set fixes this be moving the IRQ initialisation
into the PCI device enable code path so that it is run for boot time and
hot-plugged devices alike.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/powerpc/kernel/pci-common.c | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index b2814e2..a8be5a5 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -217,7 +217,7 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
  * If the interrupt is used, then gets the interrupt line from the
  * openfirmware and sets it in the pci_dev and pci_config line.
  */
-static int pci_read_irq_line(struct pci_dev *pci_dev)
+static int pci_read_irq_line(struct pci_dev *pci_dev, u8 pin)
 {
 	struct of_phandle_args oirq;
 	unsigned int virq;
@@ -229,7 +229,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
 #endif
 	/* Try to get a mapping from the device-tree */
 	if (of_irq_parse_pci(pci_dev, &oirq)) {
-		u8 line, pin;
+		u8 line;
 
 		/* If that fails, lets fallback to what is in the config
 		 * space and map that through the default controller. We
@@ -238,10 +238,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
 		 * either provide a proper interrupt tree or don't use this
 		 * function.
 		 */
-		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
-			return -1;
-		if (pin == 0)
-			return -1;
 		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
 		    line == 0xff || line == 0) {
 			return -1;
@@ -266,9 +262,16 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
 
 	pr_debug(" Mapped to linux irq %d\n", virq);
 
-	pci_dev->irq = virq;
+	return virq;
+}
 
-	return 0;
+int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	/* Read default IRQs and fixup if necessary */
+	int irq = pci_read_irq_line(dev, pin);
+	if (ppc_md.pci_irq_fixup)
+		ppc_md.pci_irq_fixup(dev);
+	return irq;
 }
 
 /*
@@ -766,6 +769,8 @@ int pci_proc_domain(struct pci_bus *bus)
 
 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pci_map_irq;
 	if (ppc_md.pcibios_root_bridge_prepare)
 		return ppc_md.pcibios_root_bridge_prepare(bridge);
 
@@ -968,11 +973,6 @@ static void pcibios_setup_device(struct pci_dev *dev)
 	/* Additional platform DMA/iommu setup */
 	if (ppc_md.pci_dma_dev_setup)
 		ppc_md.pci_dma_dev_setup(dev);
-
-	/* Read default IRQs and fixup if necessary */
-	pci_read_irq_line(dev);
-	if (ppc_md.pci_irq_fixup)
-		ppc_md.pci_irq_fixup(dev);
 }
 
 int pcibios_add_device(struct pci_dev *dev)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 05/18] Delayed sh setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (3 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 04/18] Delayed powerpc " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:25   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 06/18] Delayed alpha " matt
                   ` (13 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently platform specific PCI device IRQ assignment is run during
the boot code, this results in a wide array of differing code paths
and causes hot-plugged PCI devices to not be assigned IRQs, this
patch removes the boot time initialisation of such IRQs and instead
registers assignment functions to be run during the PCI device enable
plase.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/sh/drivers/pci/fixups-cayman.c     |  2 +-
 arch/sh/drivers/pci/fixups-dreamcast.c  |  2 +-
 arch/sh/drivers/pci/fixups-r7780rp.c    |  2 +-
 arch/sh/drivers/pci/fixups-rts7751r2d.c |  6 +++---
 arch/sh/drivers/pci/fixups-sdk7780.c    |  4 ++--
 arch/sh/drivers/pci/fixups-se7751.c     |  2 +-
 arch/sh/drivers/pci/fixups-sh03.c       |  2 +-
 arch/sh/drivers/pci/fixups-snapgear.c   |  2 +-
 arch/sh/drivers/pci/fixups-titan.c      |  4 ++--
 arch/sh/drivers/pci/pci.c               | 10 +++++++---
 arch/sh/drivers/pci/pcie-sh7786.c       |  2 +-
 11 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/arch/sh/drivers/pci/fixups-cayman.c b/arch/sh/drivers/pci/fixups-cayman.c
index edc2fb7..3246788 100644
--- a/arch/sh/drivers/pci/fixups-cayman.c
+++ b/arch/sh/drivers/pci/fixups-cayman.c
@@ -5,7 +5,7 @@
 #include <cpu/irq.h>
 #include "pci-sh5.h"
 
-int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int result = -1;
 
diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
index 1d1c5a2..9d597f7 100644
--- a/arch/sh/drivers/pci/fixups-dreamcast.c
+++ b/arch/sh/drivers/pci/fixups-dreamcast.c
@@ -76,7 +76,7 @@ static void gapspci_fixup_resources(struct pci_dev *dev)
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
 
-int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	/*
 	 * The interrupt routing semantics here are quite trivial.
diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
index 57ed3f0..2c9b58f 100644
--- a/arch/sh/drivers/pci/fixups-r7780rp.c
+++ b/arch/sh/drivers/pci/fixups-r7780rp.c
@@ -15,7 +15,7 @@
 #include <linux/sh_intc.h>
 #include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
 	return evt2irq(0xa20) + slot;
 }
diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
index eaddb56..358ac10 100644
--- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
+++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
@@ -20,18 +20,18 @@
 #define PCIMCR_MRSET_OFF	0xBFFFFFFF
 #define PCIMCR_RFSH_OFF		0xFFFFFFFB
 
-static u8 rts7751r2d_irq_tab[] __initdata = {
+static u8 rts7751r2d_irq_tab[] = {
 	IRQ_PCI_INTA,
 	IRQ_PCI_INTB,
 	IRQ_PCI_INTC,
 	IRQ_PCI_INTD,
 };
 
-static char lboxre2_irq_tab[] __initdata = {
+static char lboxre2_irq_tab[] = {
 	IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
 };
 
-int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
 	if (mach_is_lboxre2())
 		return lboxre2_irq_tab[slot];
diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c
index c0a015a..24e96df 100644
--- a/arch/sh/drivers/pci/fixups-sdk7780.c
+++ b/arch/sh/drivers/pci/fixups-sdk7780.c
@@ -22,7 +22,7 @@
 #define IRQ_INTD	evt2irq(0xa80)
 
 /* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
-static char sdk7780_irq_tab[4][16] __initdata = {
+static char sdk7780_irq_tab[4][16] = {
 	/* INTA */
 	{ IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1,
 	  -1, -1, -1, -1, -1, -1 },
@@ -37,7 +37,7 @@ static char sdk7780_irq_tab[4][16] __initdata = {
 	  -1, -1, -1 },
 };
 
-int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
        return sdk7780_irq_tab[pin-1][slot];
 }
diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
index 84a88ca..1cb8d0a 100644
--- a/arch/sh/drivers/pci/fixups-se7751.c
+++ b/arch/sh/drivers/pci/fixups-se7751.c
@@ -7,7 +7,7 @@
 #include <linux/sh_intc.h>
 #include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
 {
         switch (slot) {
         case 0: return evt2irq(0x3a0);
diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
index 16207be..55ac1ba 100644
--- a/arch/sh/drivers/pci/fixups-sh03.c
+++ b/arch/sh/drivers/pci/fixups-sh03.c
@@ -4,7 +4,7 @@
 #include <linux/pci.h>
 #include <linux/sh_intc.h>
 
-int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	int irq;
 
diff --git a/arch/sh/drivers/pci/fixups-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c
index 6e33ba4..a931e59 100644
--- a/arch/sh/drivers/pci/fixups-snapgear.c
+++ b/arch/sh/drivers/pci/fixups-snapgear.c
@@ -19,7 +19,7 @@
 #include <linux/sh_intc.h>
 #include "pci-sh4.h"
 
-int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
 	int irq = -1;
 
diff --git a/arch/sh/drivers/pci/fixups-titan.c b/arch/sh/drivers/pci/fixups-titan.c
index bd1addb..a9d563e 100644
--- a/arch/sh/drivers/pci/fixups-titan.c
+++ b/arch/sh/drivers/pci/fixups-titan.c
@@ -19,7 +19,7 @@
 #include <mach/titan.h>
 #include "pci-sh4.h"
 
-static char titan_irq_tab[] __initdata = {
+static char titan_irq_tab[] = {
 	TITAN_IRQ_WAN,
 	TITAN_IRQ_LAN,
 	TITAN_IRQ_MPCIA,
@@ -27,7 +27,7 @@ static char titan_irq_tab[] __initdata = {
 	TITAN_IRQ_USB,
 };
 
-int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
 	int irq = titan_irq_tab[slot];
 
diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
index 1bc09ee..718fae3 100644
--- a/arch/sh/drivers/pci/pci.c
+++ b/arch/sh/drivers/pci/pci.c
@@ -141,16 +141,20 @@ static int __init pcibios_init(void)
 	for (hose = hose_head; hose; hose = hose->next)
 		pcibios_scanbus(hose);
 
-	pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
-
 	dma_debug_add_bus(&pci_bus_type);
-
 	pci_initialized = 1;
 
 	return 0;
 }
 subsys_initcall(pcibios_init);
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = pcibios_map_platform_irq;
+	return 0;
+}
+
 /*
  *  Called after each bus is probed, but before its children
  *  are examined.
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index a162a7f..0167a73 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -467,7 +467,7 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
 	return 0;
 }
 
-int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
+int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
 {
         return evt2irq(0xae0);
 }
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 06/18] Delayed alpha setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (4 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 05/18] Delayed sh " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:27   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 07/18] Delayed cris " matt
                   ` (12 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

PCI IRQ initialisation is currently run during the boot code on alpha,
this has the issue that firstly an extra pass over the PCI bus is
required and second hot-plugged devices which are added after boot have
no way to be assigned an IRQ. This patch set fixes this by defering the
assignment of PCI IRQs untill device enable time which should solve
both of these issues.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/alpha/kernel/pci.c          | 16 ++++++++++------
 arch/alpha/kernel/sys_nautilus.c |  1 -
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
index 076c35c..338537c 100644
--- a/arch/alpha/kernel/pci.c
+++ b/arch/alpha/kernel/pci.c
@@ -28,7 +28,7 @@
 
 
 /*
- * Some string constants used by the various core logics. 
+ * Some string constants used by the various core logics.
  */
 
 const char *const pci_io_names[] = {
@@ -247,7 +247,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
 	if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
  		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
  		pci_read_bridge_bases(bus);
-	} 
+	}
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		pdev_save_srm_config(dev);
@@ -338,7 +338,7 @@ common_init_pci(void)
 		hose->need_domain_info = need_domain_info;
 		next_busno = bus->busn_res.end + 1;
 		/* Don't allow 8-bit bus number overflow inside the hose -
-		   reserve some space for bridges. */ 
+		   reserve some space for bridges. */
 		if (next_busno > 224) {
 			next_busno = 0;
 			need_domain_info = 1;
@@ -346,11 +346,15 @@ common_init_pci(void)
 	}
 
 	pcibios_claim_console_setup();
-
 	pci_assign_unassigned_resources();
-	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = alpha_mv.pci_swizzle;
+	bridge->map_irq = alpha_mv.pci_map_irq;
+	return 0;
+}
 
 struct pci_controller * __init
 alloc_pci_controller(void)
@@ -387,7 +391,7 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
 
 	/* from hose or from bus.devfn */
 	if (which & IOBASE_FROM_HOSE) {
-		for(hose = hose_head; hose; hose = hose->next) 
+		for(hose = hose_head; hose; hose = hose->next)
 			if (hose->index == bus) break;
 		if (!hose) return -ENODEV;
 	} else {
diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
index 837c0fa..7fb4d51 100644
--- a/arch/alpha/kernel/sys_nautilus.c
+++ b/arch/alpha/kernel/sys_nautilus.c
@@ -252,7 +252,6 @@ nautilus_init_pci(void)
 	/* pci_common_swizzle() relies on bus->self being NULL
 	   for the root bus, so just clear it. */
 	bus->self = NULL;
-	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
 }
 
 /*
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 07/18] Delayed cris setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (5 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 06/18] Delayed alpha " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:34   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 08/18] Delayed frv " matt
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

PCI IRQs are currently configured to be enabled once at boot in a
dedicated pass. This means that PCI devices which are hot-plugged after
boot time will not be given an IRQ, this patch-set fixes this by
registering the assignment function to be called later in the device
enable path.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/cris/arch-v32/drivers/pci/bios.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
index 64a5fb9..d04ecc8 100644
--- a/arch/cris/arch-v32/drivers/pci/bios.c
+++ b/arch/cris/arch-v32/drivers/pci/bios.c
@@ -80,20 +80,16 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
 	return 0;
 }
 
-int pcibios_enable_irq(struct pci_dev *dev)
+int pcibios_enable_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	dev->irq = EXT_INTR_VECT;
 	return 0;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
-	int err;
-
-	if ((err = pcibios_enable_resources(dev, mask)) < 0)
-		return err;
-
-	if (!dev->msi_enabled)
-		pcibios_enable_irq(dev);
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pcibios_enable_irq;
 	return 0;
 }
+
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 08/18] Delayed frv setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (6 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 07/18] Delayed cris " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:37   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 09/18] Delayed m68k " matt
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

PCI IRQs are being assigned during the frv pcibios phase. This causes
devices which are not connected at boot but are later hot-plugged
to not receive an IRQ. This patch set causes the pcibios to instead
register an IRQ assignment function which is called during the enable
device path to apply to all devices.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/frv/mb93090-mb00/pci-frv.h |  1 -
 arch/frv/mb93090-mb00/pci-irq.c | 28 +++++++++++++++++-----------
 arch/frv/mb93090-mb00/pci-vdk.c |  1 -
 3 files changed, 17 insertions(+), 13 deletions(-)

diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h
index a7e487fe..492b56d 100644
--- a/arch/frv/mb93090-mb00/pci-frv.h
+++ b/arch/frv/mb93090-mb00/pci-frv.h
@@ -36,5 +36,4 @@ extern struct pci_ops *__nongpreldata pci_root_ops;
 extern unsigned int pcibios_irq_mask;
 
 void pcibios_irq_init(void);
-void pcibios_fixup_irqs(void);
 void pcibios_enable_irq(struct pci_dev *dev);
diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
index 1c35c93..3463e30 100644
--- a/arch/frv/mb93090-mb00/pci-irq.c
+++ b/arch/frv/mb93090-mb00/pci-irq.c
@@ -40,19 +40,25 @@ void __init pcibios_irq_init(void)
 {
 }
 
-void __init pcibios_fixup_irqs(void)
+int pcibios_map_irq(struct pci_dev *dev, uint8_t slot, uint8_t pin)
 {
-	struct pci_dev *dev = NULL;
-	uint8_t line, pin;
-
-	for_each_pci_dev(dev) {
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		if (pin) {
-			dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1];
-			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-		}
-		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
+	uint8_t line;
+	int irq;
+
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (pin) {
+		irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1];
+		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
 	}
+	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
+	return irq;
+}
+
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pcibios_map_irq;
+	return 0;
 }
 
 void pcibios_enable_irq(struct pci_dev *dev)
diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
index efa5d65..86657a7 100644
--- a/arch/frv/mb93090-mb00/pci-vdk.c
+++ b/arch/frv/mb93090-mb00/pci-vdk.c
@@ -386,7 +386,6 @@ int __init pcibios_init(void)
 	pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
 
 	pcibios_irq_init();
-	pcibios_fixup_irqs();
 	pcibios_resource_survey();
 
 	return 0;
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 09/18] Delayed m68k setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (7 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 08/18] Delayed frv " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:38   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 10/18] Delayed microblaze " matt
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently PCI IRQs are assigned during mcf_pci_init which is only run
at boot time, this causes devices which are connected after boot time
to not receive an IRQ, this patch set fixes this by registering an IRQ
assignment function to be run later at device enable time.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/m68k/platform/coldfire/pci.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/m68k/platform/coldfire/pci.c b/arch/m68k/platform/coldfire/pci.c
index df96792..058ca86 100644
--- a/arch/m68k/platform/coldfire/pci.c
+++ b/arch/m68k/platform/coldfire/pci.c
@@ -316,10 +316,16 @@ static int __init mcf_pci_init(void)
 	rootbus->resource[0] = &mcf_pci_io;
 	rootbus->resource[1] = &mcf_pci_mem;
 
-	pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
 	pci_bus_size_bridges(rootbus);
 	pci_bus_assign_resources(rootbus);
 	return 0;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = mcf_pci_map_irq;
+	return 0;
+}
+
 subsys_initcall(mcf_pci_init);
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 10/18] Delayed microblaze setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (8 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 09/18] Delayed m68k " matt
@ 2014-10-02  4:07 ` matt
  2014-10-02  4:07 ` [PATCH 11/18] Delayed mips " matt
                   ` (8 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently microblaze assigns PCI IRQs during the pcibios phase, this means
that devices connected after boot will not be assigned an IRQ, instead the
boot code now registers IRQ assignment functions to be called later by the
device enable code paths.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/microblaze/pci/pci-common.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/microblaze/pci/pci-common.c b/arch/microblaze/pci/pci-common.c
index 9037914..6843b34 100644
--- a/arch/microblaze/pci/pci-common.c
+++ b/arch/microblaze/pci/pci-common.c
@@ -850,12 +850,16 @@ void pcibios_setup_bus_devices(struct pci_bus *bus)
 		 * code and is needed by the DMA init
 		 */
 		set_dev_node(&dev->dev, pcibus_to_node(dev->bus));
-
-		/* Read default IRQs and fixup if necessary */
-		dev->irq = of_irq_parse_and_map_pci(dev, 0, 0);
 	}
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = of_irq_parse_and_map_pci;
+	return 0;
+}
+
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
 	/* When called from the generic PCI probe, read PCI<->PCI bridge
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 11/18] Delayed mips setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (9 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 10/18] Delayed microblaze " matt
@ 2014-10-02  4:07 ` matt
  2014-10-02  4:07 ` [PATCH 12/18] Delayed mn10300 " matt
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently mips PCI IRQs are assigned at boot, this creates an extra
pass over the PCI bus and causes hot-plugged devices which are not
present at boot to not be given IRQs, this patch set fixes this by
registering assignment functions which are then run later during the
device enable code path.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/mips/pci/pci.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c
index 1bf60b1..dc660a0 100644
--- a/arch/mips/pci/pci.c
+++ b/arch/mips/pci/pci.c
@@ -242,13 +242,18 @@ static int __init pcibios_init(void)
 	for (hose = hose_head; hose; hose = hose->next)
 		pcibios_scanbus(hose);
 
-	pci_fixup_irqs(pci_common_swizzle, pcibios_map_irq);
-
 	pci_initialized = 1;
 
 	return 0;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+       bridge->swizzle_irq = pci_common_swizzle;
+       bridge->map_irq = pcibios_map_irq;
+       return 0;
+}
+
 subsys_initcall(pcibios_init);
 
 static int pcibios_enable_resources(struct pci_dev *dev, int mask)
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 12/18] Delayed mn10300 setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (10 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 11/18] Delayed mips " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:46   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 13/18] Delayed sparc " matt
                   ` (6 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>


PCI IRQs are being asigned during pcibios_irq_init currently, this causes
a problem by which hot-plug devices connected after boot will not recieve
an IRQ, this patch-set fixes this by registering the IRQ assignment
functions at boot, to then be called later by the device enable code.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/mn10300/unit-asb2305/pci-asb2305.h |  5 +----
 arch/mn10300/unit-asb2305/pci-irq.c     | 25 +++++--------------------
 arch/mn10300/unit-asb2305/pci.c         | 21 ++++++++-------------
 3 files changed, 14 insertions(+), 37 deletions(-)

diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
index 9e17aca..fb520cf 100644
--- a/arch/mn10300/unit-asb2305/pci-asb2305.h
+++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
@@ -67,9 +67,6 @@ struct irq_routing_table {
 } __attribute__((packed));
 
 extern unsigned int pcibios_irq_mask;
-
-extern void pcibios_irq_init(void);
-extern void pcibios_fixup_irqs(void);
-extern void pcibios_enable_irq(struct pci_dev *dev);
+extern int pci_map_irq(struct pci_dev *, u8 slot, u8 pin);
 
 #endif /* PCI_ASB2305_H */
diff --git a/arch/mn10300/unit-asb2305/pci-irq.c b/arch/mn10300/unit-asb2305/pci-irq.c
index fcb28ce..5be6fea 100644
--- a/arch/mn10300/unit-asb2305/pci-irq.c
+++ b/arch/mn10300/unit-asb2305/pci-irq.c
@@ -20,27 +20,12 @@
 #include <asm/smp.h>
 #include "pci-asb2305.h"
 
-void __init pcibios_irq_init(void)
+int pci_map_irq(struct pci_dev *, u8 slot, u8 pin)
 {
-}
-
-void __init pcibios_fixup_irqs(void)
-{
-	struct pci_dev *dev = NULL;
-	u8 line, pin;
+	u8 line;
 
-	for_each_pci_dev(dev) {
-		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
-		if (pin) {
-			dev->irq = XIRQ1;
-			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
-					      dev->irq);
-		}
-		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
-	}
-}
-
-void pcibios_enable_irq(struct pci_dev *dev)
-{
+	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	dev->irq = XIRQ1;
 	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
+	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
 }
diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
index 6b4339f..22f8786 100644
--- a/arch/mn10300/unit-asb2305/pci.c
+++ b/arch/mn10300/unit-asb2305/pci.c
@@ -377,13 +377,18 @@ static int __init pcibios_init(void)
 	pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
 	pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
 	pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
-
-	pcibios_irq_init();
-	pcibios_fixup_irqs();
 	pcibios_resource_survey();
 	return 0;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pci_map_irq;
+	return 0;
+}
+
+
 arch_initcall(pcibios_init);
 
 char *__init pcibios_setup(char *str)
@@ -396,16 +401,6 @@ char *__init pcibios_setup(char *str)
 	return str;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
-{
-	int err;
-
-	err = pci_enable_resources(dev, mask);
-	if (err == 0)
-		pcibios_enable_irq(dev);
-	return err;
-}
-
 /*
  * disable the ethernet chipset
  */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 13/18] Delayed sparc setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (11 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 12/18] Delayed mn10300 " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:51   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 14/18] Delayed tile " matt
                   ` (5 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently sparc allocates PCI IRQs through several different methods
based on device. This is done during the boot stage and faces a draw-back
by which hot-plugged devices will not be allocated an IRQ, this is fixed
by registering IRQ allocation functions for later use during the device
enable path.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/sparc/kernel/leon_pci.c | 12 +++++++++++-
 arch/sparc/kernel/pci.c      | 21 +++++++++++++++++----
 2 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
index 899b720..1079eb7 100644
--- a/arch/sparc/kernel/leon_pci.c
+++ b/arch/sparc/kernel/leon_pci.c
@@ -13,6 +13,8 @@
 #include <asm/leon.h>
 #include <asm/leon_pci.h>
 
+int (*leon_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
+
 /* The LEON architecture does not rely on a BIOS or bootloader to setup
  * PCI for us. The Linux generic routines are used to setup resources,
  * reset values of configuration-space register settings are preserved.
@@ -36,7 +38,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 				     &resources);
 	if (root_bus) {
 		/* Setup IRQs of all devices using custom routines */
-		pci_fixup_irqs(pci_common_swizzle, info->map_irq);
+		leon_pci_map_irq = info->map_irq;
 
 		/* Assign devices with resources */
 		pci_assign_unassigned_resources();
@@ -45,6 +47,14 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
 	}
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = leon_pci_map_irq;
+	return 0;
+}
+
+
 void pcibios_fixup_bus(struct pci_bus *pbus)
 {
 	struct pci_dev *dev;
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index b36365f..7361c52 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -340,10 +340,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
 	} else {
 		dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
 		dev->rom_base_reg = PCI_ROM_ADDRESS;
-
-		dev->irq = sd->op->archdata.irqs[0];
-		if (dev->irq == 0xffffffff)
-			dev->irq = PCI_IRQ_NONE;
 	}
 
 	pci_parse_of_addrs(sd->op, node, dev);
@@ -356,6 +352,23 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
 	return dev;
 }
 
+int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	int irq;
+	struct platform_device *op = of_find_device_by_node(dev->sysdata);
+	irq = op->archdata.irqs[0];
+	if (irq == 0xffffffff)
+		irq = PCI_IRQ_NONE;
+	return irq;
+}
+
+int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pci_map_irq;
+	return 0;
+}
+
 static void apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
 {
 	u32 idx, first, last;
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 14/18] Delayed tile setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (12 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 13/18] Delayed sparc " matt
@ 2014-10-02  4:07 ` matt
  2014-10-02  4:07 ` [PATCH 15/18] Delayed unicore32 " matt
                   ` (4 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Currently pcibios_init is running pci_fixup_irqs in order to assign
IRQs to PCI devices, this is only done once at boot-time and causes
devices hot-plugged after boot time to not be allocated an IRQ.
This is fixed in this patch-set by delaying the allocation untill
device enable time by registering the function to be called later.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/tile/kernel/pci.c    | 10 +++++++---
 arch/tile/kernel/pci_gx.c | 10 +++++++---
 2 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/arch/tile/kernel/pci.c b/arch/tile/kernel/pci.c
index 1f80a88..6dc0bd8 100644
--- a/arch/tile/kernel/pci.c
+++ b/arch/tile/kernel/pci.c
@@ -313,9 +313,6 @@ int __init pcibios_init(void)
 		}
 	}
 
-	/* Do machine dependent PCI interrupt routing */
-	pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
-
 	/*
 	 * This comes from the generic Linux PCI driver.
 	 *
@@ -367,6 +364,13 @@ int __init pcibios_init(void)
 }
 subsys_initcall(pcibios_init);
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = tile_map_irq;
+	return 0;
+}
+
 /*
  * No bus fixups needed.
  */
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
index e39f9c5..7d1b5bf 100644
--- a/arch/tile/kernel/pci_gx.c
+++ b/arch/tile/kernel/pci_gx.c
@@ -893,9 +893,6 @@ int __init pcibios_init(void)
 		next_busno = bus->busn_res.end + 1;
 	}
 
-	/* Do machine dependent PCI interrupt routing */
-	pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
-
 	/*
 	 * This comes from the generic Linux PCI driver.
 	 *
@@ -1048,6 +1045,13 @@ alloc_mem_map_failed:
 }
 subsys_initcall(pcibios_init);
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = tile_map_irq;
+	return 0;
+}
+
 /* No bus fixups needed. */
 void pcibios_fixup_bus(struct pci_bus *bus)
 {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 15/18] Delayed unicore32 setup of PCI IRQs to bus scan time
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (13 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 14/18] Delayed tile " matt
@ 2014-10-02  4:07 ` matt
  2014-10-02  4:07 ` [PATCH 16/18] Disabled bus scan time PCI IRQ assignment on ia64 matt
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

PCI IRQs are currently assigned during pci_common_init, this is only run
at boot time so devices hot-plugged after boot will not be allocated an IRQ.
this is fixed here by defering the assignment untill the device enable code,
instead registering the function pointer at boot time.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/unicore32/kernel/pci.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/arch/unicore32/kernel/pci.c b/arch/unicore32/kernel/pci.c
index 374a055..6a9da80 100644
--- a/arch/unicore32/kernel/pci.c
+++ b/arch/unicore32/kernel/pci.c
@@ -101,7 +101,7 @@ void pci_puv3_preinit(void)
 	writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD);
 }
 
-static int __init pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int pci_puv3_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 	if (dev->bus->number == 0) {
 #ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
@@ -263,8 +263,6 @@ static int __init pci_common_init(void)
 	if (!puv3_bus)
 		panic("PCI: unable to scan bus!");
 
-	pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
-
 	if (!pci_has_flag(PCI_PROBE_ONLY)) {
 		/*
 		 * Size the bridge windows.
@@ -281,6 +279,13 @@ static int __init pci_common_init(void)
 }
 subsys_initcall(pci_common_init);
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = pci_common_swizzle;
+	bridge->map_irq = pci_puv3_map_irq;
+	return 0;
+}
+
 char * __init pcibios_setup(char *str)
 {
 	if (!strcmp(str, "debug")) {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 16/18] Disabled bus scan time PCI IRQ assignment on ia64
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (14 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 15/18] Delayed unicore32 " matt
@ 2014-10-02  4:07 ` matt
  2014-10-14 18:53   ` Bjorn Helgaas
  2014-10-02  4:07 ` [PATCH 17/18] Disabled bus scan time PCI IRQ assignment on parisc matt
                   ` (2 subsequent siblings)
  18 siblings, 1 reply; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Most of the architectures are switched to allocating IRQs at device_enable
time instead of boot time, however ia64 does not provide an easy way of
making that transition so the new code is disabled here on ia64.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/ia64/pci/pci.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
index 291a582..398d5d4 100644
--- a/arch/ia64/pci/pci.c
+++ b/arch/ia64/pci/pci.c
@@ -483,6 +483,9 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
 	struct pci_controller *controller = bridge->bus->sysdata;
 
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = NULL;
+
 	ACPI_COMPANION_SET(&bridge->dev, controller->companion);
 	return 0;
 }
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 17/18] Disabled bus scan time PCI IRQ assignment on parisc
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (15 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 16/18] Disabled bus scan time PCI IRQ assignment on ia64 matt
@ 2014-10-02  4:07 ` matt
  2014-10-02  4:07 ` [PATCH 18/18] Disabled bus scan time PCI IRQ assignment on s390 matt
  2015-01-31 14:56 ` [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging Bjorn Helgaas
  18 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Most of the architectures are switched to allocating IRQs at device_enable
time instead of boot time, however parisc does not provide an easy way of
making that transition so the new code is disabled here on parisc.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/parisc/kernel/pci.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/arch/parisc/kernel/pci.c b/arch/parisc/kernel/pci.c
index 64f2764..9654c69 100644
--- a/arch/parisc/kernel/pci.c
+++ b/arch/parisc/kernel/pci.c
@@ -105,7 +105,13 @@ PCI_PORT_OUT(b,  8)
 PCI_PORT_OUT(w, 16)
 PCI_PORT_OUT(l, 32)
 
-
+/* We do not support hot-add irq assignment */
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = NULL;
+	return 0;
+}
 
 /*
  * BIOS32 replacement.
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* [PATCH 18/18] Disabled bus scan time PCI IRQ assignment on s390
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (16 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 17/18] Disabled bus scan time PCI IRQ assignment on parisc matt
@ 2014-10-02  4:07 ` matt
  2015-01-31 14:56 ` [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging Bjorn Helgaas
  18 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  4:07 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

Most of the architectures are switched to allocating IRQs at device_enable
time instead of boot time, however s390 does not provide an easy way of
making that transition so the new code is disabled here on s390.

Signed-off-by: Matthew Minter <matt@masarand.com>

---
 arch/s390/pci/pci.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index 2fa7b14..720592f 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -434,6 +434,13 @@ out:
 	return rc;
 }
 
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
+{
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = NULL;
+	return 0;
+}
+
 void arch_teardown_msi_irqs(struct pci_dev *pdev)
 {
 	struct zpci_dev *zdev = get_zdev(pdev);
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers
  2014-10-02  4:07 ` [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers matt
@ 2014-10-02 10:33   ` Liviu Dudau
  2014-10-14 23:25     ` Bjorn Helgaas
  2014-10-14 17:15   ` Bjorn Helgaas
  1 sibling, 1 reply; 36+ messages in thread
From: Liviu Dudau @ 2014-10-02 10:33 UTC (permalink / raw)
  To: matt; +Cc: bhelgaas, linux-pci

On Thu, Oct 02, 2014 at 05:07:29AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 

Hi Matthew,

Some comments below:

> 
> These are the main infrastructure changes to allow the registration of
> PCI IRQ assignment functions which can then be called during the device
> enabling stage. This replaces the pre-initialisation of PCI IRQs at boot
> time which caused limitations such as failing for devices which are
> hot-plugged after the machine has booted and resulted in highly
> fragmented PCI initialisation paths.
> 
> The pdev_assign_irq function becomes a centralised method of assigning
> IRQs to PCI devices in a non platform specific way. The pci_host_bridge
> structure has had some function pointers added to it where the boot code
> can register the platform specific ways of assigning PCI IRQs to be used
> to allow them to be used by pdev_assign_irq.
> 
> Some small adjustements have also been made to makefiles in order to
> accomodate these changes.
> 
> Note this code completely obsolites the pci_fixup_irqs code path which

s/obsolites/obsoletes/

> has thus been removed.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  drivers/of/of_pci_irq.c   |  2 +-
>  drivers/pci/Makefile      | 15 ++-------------
>  drivers/pci/host-bridge.c |  2 +-
>  drivers/pci/pci.c         |  5 ++++-
>  drivers/pci/pci.h         |  1 +
>  drivers/pci/probe.c       | 12 ------------
>  drivers/pci/setup-irq.c   | 34 ++++++++++++++++------------------
>  include/linux/pci.h       |  6 ++++--
>  8 files changed, 29 insertions(+), 48 deletions(-)
> 
> diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
> index 1710d9d..205eb7a 100644
> --- a/drivers/of/of_pci_irq.c
> +++ b/drivers/of/of_pci_irq.c
> @@ -97,7 +97,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_pci);
>   * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
>   *
>   * @slot and @pin are unused, but included in the function so that this
> - * function can be used directly as the map_irq callback to pci_fixup_irqs().
> + * function can be used directly as the map_irq callback to pdev_assign_irq().
>   */
>  int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index e04fe2d..38c4cb0 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -4,7 +4,8 @@
>  
>  obj-y		+= 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
> +			irq.o vpd.o setup-bus.o vc.o setup-irq.o
> +
>  obj-$(CONFIG_PROC_FS) += proc.o
>  obj-$(CONFIG_SYSFS) += slot.o
>  
> @@ -31,18 +32,6 @@ obj-$(CONFIG_PCI_ATS) += ats.o
>  obj-$(CONFIG_PCI_IOV) += iov.o
>  
>  #
> -# Some architectures use the generic PCI setup functions
> -#
> -obj-$(CONFIG_ALPHA) += setup-irq.o
> -obj-$(CONFIG_ARM) += setup-irq.o
> -obj-$(CONFIG_UNICORE32) += setup-irq.o
> -obj-$(CONFIG_SUPERH) += setup-irq.o
> -obj-$(CONFIG_MIPS) += setup-irq.o
> -obj-$(CONFIG_TILE) += setup-irq.o
> -obj-$(CONFIG_SPARC_LEON) += setup-irq.o
> -obj-$(CONFIG_M68K) += setup-irq.o
> -
> -#
>  # ACPI Related PCI FW Functions
>  # ACPI _DSM provided firmware instance and string name
>  #
> diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
> index 0e5f3c9..8ed186f 100644
> --- a/drivers/pci/host-bridge.c
> +++ b/drivers/pci/host-bridge.c
> @@ -16,7 +16,7 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
>  	return bus;
>  }
>  
> -static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
> +struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)

When I did the same thing in one of the versions of my generic host bridge series,
Bjorn has mentioned that he would like the name to be changed to pci_xxxxx to
make clear that the function is now public.

>  {
>  	struct pci_bus *root_bus = find_pci_root_bus(bus);
>  
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 2c9ac70..2dd28d9 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1192,11 +1192,15 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
>  	struct pci_dev *bridge;
>  	u16 cmd;
>  	u8 pin;
> +	struct pci_host_bridge *hbrg = find_pci_host_bridge(dev->bus);
>  
>  	err = pci_set_power_state(dev, PCI_D0);
>  	if (err < 0 && err != -EIO)
>  		return err;
>  
> +	pdev_assign_irq(dev, hbrg->swizzle_irq, hbrg->map_irq);
> +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> +
>  	bridge = pci_upstream_bridge(dev);
>  	if (bridge)
>  		pcie_aspm_powersave_config_link(bridge);
> @@ -1209,7 +1213,6 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
>  	if (dev->msi_enabled || dev->msix_enabled)
>  		return 0;
>  
> -	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
>  	if (pin) {
>  		pci_read_config_word(dev, PCI_COMMAND, &cmd);
>  		if (cmd & PCI_COMMAND_INTX_DISABLE)
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 0601890..a6cf445 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -70,6 +70,7 @@ void pci_config_pm_runtime_put(struct pci_dev *dev);
>  void pci_pm_init(struct pci_dev *dev);
>  void pci_allocate_cap_save_buffers(struct pci_dev *dev);
>  void pci_free_cap_save_buffers(struct pci_dev *dev);
> +struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus);
>  
>  static inline void pci_wakeup_event(struct pci_dev *dev)
>  {
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 4170113..314e9e3 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1719,18 +1719,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
>  }
>  EXPORT_SYMBOL_GPL(pci_scan_child_bus);
>  
> -/**
> - * pcibios_root_bridge_prepare - Platform-specific host bridge setup.
> - * @bridge: Host bridge to set up.
> - *
> - * Default empty implementation.  Replace with an architecture-specific setup
> - * routine, if necessary.
> - */
> -int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> -{
> -	return 0;
> -}
> -

Any reason for removing this? It is meant for host bridge setup, I don't see how
it relates to your patchset.

>  void __weak pcibios_add_bus(struct pci_bus *bus)
>  {
>  }
> diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
> index 4e2d595..203bf7e 100644
> --- a/drivers/pci/setup-irq.c
> +++ b/drivers/pci/setup-irq.c
> @@ -22,13 +22,19 @@ void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
>  	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
>  }
>  
> -static void pdev_fixup_irq(struct pci_dev *dev,
> +void pdev_assign_irq(struct pci_dev *dev,
>  			   u8 (*swizzle)(struct pci_dev *, u8 *),
> -			   int (*map_irq)(const struct pci_dev *, u8, u8))
> +			   int (*map_irq)(struct pci_dev *, u8, u8))
>  {
> -	u8 pin, slot;
> +	u8 pin;
> +	u8 slot = -1;
>  	int irq = 0;
>  
> +	if (!map_irq) {
> +		dev_dbg(&dev->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 'cos that slot is where the bridge is.   Each
> @@ -40,28 +46,20 @@ static void pdev_fixup_irq(struct pci_dev *dev,
>  	if (pin > 4)
>  		pin = 1;
>  
> -	if (pin != 0) {
> -		/* Follow the chain of bridges, swizzling as we go.  */
> -		slot = (*swizzle)(dev, &pin);
> +	if (pin) {
> +		/* Follow the chain of bridges, swizzling as we go. */

Space adjustments in comments should be a separate patch. And if you care so much about
spaces ....

> +		if(swizzle)

how about adding one here?

> +			slot = (*swizzle)(dev, &pin);
>  
> +		/* If a swizzling function is not used map_irq must ignore slot */
>  		irq = (*map_irq)(dev, slot, pin);
>  		if (irq == -1)
>  			irq = 0;
>  	}
> -	dev->irq = irq;
> -
> -	dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq);
>  
> +	dev_dbg(&dev->dev, "assign irq: got %d\n", dev->irq);
> +	dev->irq = irq;
>  	/* Always tell the device, so the driver knows what is
>  	   the real IRQ to use; the device does not use it. */
>  	pcibios_update_irq(dev, irq);
>  }
> -
> -void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
> -		    int (*map_irq)(const struct pci_dev *, u8, u8))
> -{
> -	struct pci_dev *dev = NULL;
> -
> -	for_each_pci_dev(dev)
> -		pdev_fixup_irq(dev, swizzle, map_irq);
> -}
> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 96453f9..5426d11 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -403,6 +403,8 @@ struct pci_host_bridge {
>  	struct device dev;
>  	struct pci_bus *bus;		/* root bus */
>  	struct list_head windows;	/* pci_host_bridge_windows */
> +	u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* platform irq swizzler */
> +	int (*map_irq)(struct pci_dev *, u8, u8);

I think you should split this patch so that you first introduce the hooks and the
way to set them and after that you make the change from pdev_fixup_irq to pdev_assign_irq.

Best regards,
Liviu

>  	void (*release_fn)(struct pci_host_bridge *);
>  	void *release_data;
>  };
> @@ -1064,8 +1066,8 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
>  void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus);
>  void pdev_enable_device(struct pci_dev *);
>  int pci_enable_resources(struct pci_dev *, int mask);
> -void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
> -		    int (*)(const struct pci_dev *, u8, u8));
> +void pdev_assign_irq(struct pci_dev *dev, u8 (*swizzle)(struct pci_dev *, u8 *),
> +                     int (*map_irq)(struct pci_dev *, u8, u8));
>  #define HAVE_PCI_REQ_REGIONS	2
>  int __must_check pci_request_regions(struct pci_dev *, const char *);
>  int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time matt
@ 2014-10-02 10:51   ` Liviu Dudau
  2014-10-14 18:11   ` Bjorn Helgaas
  1 sibling, 0 replies; 36+ messages in thread
From: Liviu Dudau @ 2014-10-02 10:51 UTC (permalink / raw)
  To: matt; +Cc: bhelgaas, linux-pci

On Thu, Oct 02, 2014 at 05:07:30AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> The x86 architecture boot code currently traverses the PCI buses with
> an extra pass in order to initialise the PCI device IRQs at boot, this
> patch avoids this pass and defers the IRQ assignment untill device
> enable time which also has the benefit that hot-plugged devices are
> assigned IRQs without additional code.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/x86/include/asm/pci_x86.h |  7 ++--
>  arch/x86/kernel/x86_init.c     |  1 -
>  arch/x86/pci/acpi.c            |  5 ++-
>  arch/x86/pci/common.c          |  2 -
>  arch/x86/pci/irq.c             | 94 +++++++++++++++++++++++-------------------
>  5 files changed, 59 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
> index fa1195d..16fd8e9 100644
> --- a/arch/x86/include/asm/pci_x86.h
> +++ b/arch/x86/include/asm/pci_x86.h
> @@ -90,6 +90,7 @@ extern unsigned int pcibios_irq_mask;
>  
>  extern raw_spinlock_t pci_config_lock;
>  
> +extern int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
>  extern int (*pcibios_enable_irq)(struct pci_dev *dev);
>  extern void (*pcibios_disable_irq)(struct pci_dev *dev);
>  
> @@ -119,7 +120,7 @@ extern int __init pci_acpi_init(void);
>  extern void __init pcibios_irq_init(void);
>  extern int __init pcibios_init(void);
>  extern int pci_legacy_init(void);
> -extern void pcibios_fixup_irqs(void);
> +extern int pcibios_fixup_irq(struct pci_dev *dev, u8 pin);
>  
>  /* pci-mmconfig.c */
>  
> @@ -200,9 +201,9 @@ static inline void mmio_config_writel(void __iomem *pos, u32 val)
>  #  define x86_default_pci_init		pci_legacy_init
>  # endif
>  # define x86_default_pci_init_irq	pcibios_irq_init
> -# define x86_default_pci_fixup_irqs	pcibios_fixup_irqs
> +# define x86_default_pci_fixup_irq	pcibios_fixup_irq
>  #else
>  # define x86_default_pci_init		NULL
>  # define x86_default_pci_init_irq	NULL
> -# define x86_default_pci_fixup_irqs	NULL
> +# define x86_default_pci_fixup_irq	NULL
>  #endif
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index e48b674..064457f 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -81,7 +81,6 @@ struct x86_init_ops x86_init __initdata = {
>  	.pci = {
>  		.init			= x86_default_pci_init,
>  		.init_irq		= x86_default_pci_init_irq,
> -		.fixup_irqs		= x86_default_pci_fixup_irqs,
>  	},
>  };
>  
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index cfd1b13..2c433f4 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -311,7 +311,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
>  	} else if (orig_end != end) {
>  		dev_info(&info->bridge->dev,
>  			"host bridge window [%#llx-%#llx] "
> -			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
> +			"([%#llx-%#llx] ignored, not CPU addressable)\n",
>  			start, orig_end, end + 1, orig_end);
>  	}
>  
> @@ -571,6 +571,9 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)

Your previous patch removed the weak implementation of pcibios_root_bridge_prepare yet
you are adding it here in the arch specific code. Again, confused on what you
were trying to achieve by removing the __weak version. Should that not have by default
setup bridge->swizzle_irq and bridge->map_irq to some sane defaults and kept into drivers/pci?

>  	struct pci_sysdata *sd = bridge->bus->sysdata;
>  
>  	ACPI_COMPANION_SET(&bridge->dev, sd->companion);
> +
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;
>  	return 0;
>  }
>  
> diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
> index 059a76c..d4ed0b0 100644
> --- a/arch/x86/pci/common.c
> +++ b/arch/x86/pci/common.c
> @@ -662,8 +662,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
>  	if ((err = pci_enable_resources(dev, mask)) < 0)
>  		return err;
>  
> -	if (!pci_dev_msi_enabled(dev))
> -		return pcibios_enable_irq(dev);
>  	return 0;
>  }
>  
> diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
> index eb500c2..33d323d 100644
> --- a/arch/x86/pci/irq.c
> +++ b/arch/x86/pci/irq.c
> @@ -594,9 +594,9 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
>  		return 1;
>  	}
>  
> -	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN && 
> -	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX) 
> -	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && 
> +	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN &&
> +	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)
> +	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&

More indentation fixes?

>  	     device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)
>  	||  (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN &&
>  	     device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)
> @@ -875,9 +875,8 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
>  	return NULL;
>  }
>  
> -static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
> +static int pcibios_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
>  {
> -	u8 pin;
>  	struct irq_info *info;
>  	int i, pirq, newirq;
>  	int irq = 0;
> @@ -887,7 +886,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
>  	char *msg = NULL;
>  
>  	/* Find IRQ pin */
> -	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
>  	if (!pin) {
>  		dev_dbg(&dev->dev, "no interrupt pin\n");
>  		return 0;
> @@ -1017,50 +1015,45 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
>  					 irq, pci_name(dev2));
>  		}
>  	}
> -	return 1;
> +	/*
> +	 * Due to the complicated platform specific behvaiour we cannot defer

behaviour

> +	 * assigning dev->irq to the caller but will return it anyway
> +	 */

What? How is that sane?

> +	return dev->irq;

Beside the above comment, you are changing the behaviour of the function from previously
returning 0/1 depending on whether an irq has been found into returning 0/dev->irq. That
is unnecessary as you can extract the information anyway from dev, according to your
comment.

>  }
>  
> -void __init pcibios_fixup_irqs(void)
> +int pcibios_fixup_irq(struct pci_dev *dev, u8 pin)
>  {
> -	struct pci_dev *dev = NULL;
> -	u8 pin;
> -
> +	int irq = dev->irq;
>  	DBG(KERN_DEBUG "PCI: IRQ fixup\n");
> -	for_each_pci_dev(dev) {
> -		/*
> -		 * If the BIOS has set an out of range IRQ number, just
> -		 * ignore it.  Also keep track of which IRQ's are
> -		 * already in use.
> -		 */
> -		if (dev->irq >= 16) {
> -			dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
> -			dev->irq = 0;
> -		}
> -		/*
> -		 * If the IRQ is already assigned to a PCI device,
> -		 * ignore its ISA use penalty
> -		 */
> -		if (pirq_penalty[dev->irq] >= 100 &&
> -				pirq_penalty[dev->irq] < 100000)
> -			pirq_penalty[dev->irq] = 0;
> -		pirq_penalty[dev->irq]++;
> +	/*
> +	 * If the BIOS has set an out of range IRQ number, just
> +	 * ignore it.  Also keep track of which IRQ's are
> +	 * already in use.
> +	 */
> +	if (irq >= 16) {
> +		dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", irq);
> +		irq = 0;
>  	}
> +	/*
> +	 * If the IRQ is already assigned to a PCI device,
> +	 * ignore its ISA use penalty
> +	 */
> +	if (pirq_penalty[irq] >= 100 &&
> +			pirq_penalty[irq] < 100000)
> +		pirq_penalty[irq] = 0;
> +	pirq_penalty[irq]++;
>  
> -	if (io_apic_assign_pci_irqs)
> -		return;
> +	if (io_apic_assign_pci_irqs || !pin)
> +		return irq;
>  
> -	dev = NULL;
> -	for_each_pci_dev(dev) {
> -		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> -		if (!pin)
> -			continue;
> +	/*
> +	 * Still no IRQ? Try to lookup one...
> +	 */
> +	if (!irq)
> +		irq = pcibios_lookup_irq(dev, pin, 0);
>  
> -		/*
> -		 * Still no IRQ? Try to lookup one...
> -		 */
> -		if (!dev->irq)
> -			pcibios_lookup_irq(dev, 0);
> -	}
> +	return irq;
>  }
>  
>  /*
> @@ -1161,6 +1154,13 @@ void __init pcibios_irq_init(void)
>  	}
>  }
>  
> +int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;
> +	return 0;
> +}

Like I've mentioned above, you already have a non-weak version in arch/x86/pci/acpi.c,
why do you provide a week one here?

Best regards,
Liviu

> +
>  static void pirq_penalize_isa_irq(int irq, int active)
>  {
>  	/*
> @@ -1185,12 +1185,20 @@ void pcibios_penalize_isa_irq(int irq, int active)
>  		pirq_penalize_isa_irq(irq, active);
>  }
>  
> +int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	dev->irq = pcibios_fixup_irq(dev, pin);
> +	if (pcibios_enable_irq(dev))
> +		return -1;
> +	return dev->irq;
> +}
> +
>  static int pirq_enable_irq(struct pci_dev *dev)
>  {
>  	u8 pin = 0;
>  
>  	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> -	if (pin && !pcibios_lookup_irq(dev, 1)) {
> +	if (pin && !pcibios_lookup_irq(dev, pin, 1)) {
>  		char *msg = "";
>  
>  		if (!io_apic_assign_pci_irqs && dev->irq)
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pci" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

-- 
====================
| I would like to |
| fix the world,  |
| but they're not |
| giving me the   |
 \ source code!  /
  ---------------
    ¯\_(ツ)_/¯


^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers
  2014-10-02  4:07 ` [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers matt
  2014-10-02 10:33   ` Liviu Dudau
@ 2014-10-14 17:15   ` Bjorn Helgaas
  1 sibling, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 17:15 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

I like the overall idea here and I think this will be a major improvement.
But we need to tweak a few procedural things to integrate it cleanly.

On Thu, Oct 02, 2014 at 05:07:29AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>

Please run "git log --oneline --no-merges drivers/pci" and follow the
style there for subject lines, i.e.,

  PCI: Add ...

For the patches that touch things outside drivers/pci, e.g., the
architecture patches, run git log on those as well and try to do something
consistent with previous patch descriptions.

> These are the main infrastructure changes to allow the registration of
> PCI IRQ assignment functions which can then be called during the device
> enabling stage. This replaces the pre-initialisation of PCI IRQs at boot
> time which caused limitations such as failing for devices which are
> hot-plugged after the machine has booted and resulted in highly
> fragmented PCI initialisation paths.
> 
> The pdev_assign_irq function becomes a centralised method of assigning
> IRQs to PCI devices in a non platform specific way. The pci_host_bridge
> structure has had some function pointers added to it where the boot code
> can register the platform specific ways of assigning PCI IRQs to be used
> to allow them to be used by pdev_assign_irq.
> 
> Some small adjustements have also been made to makefiles in order to
> accomodate these changes.
> 
> Note this code completely obsolites the pci_fixup_irqs code path which
> has thus been removed.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  drivers/of/of_pci_irq.c   |  2 +-
>  drivers/pci/Makefile      | 15 ++-------------
>  drivers/pci/host-bridge.c |  2 +-
>  drivers/pci/pci.c         |  5 ++++-
>  drivers/pci/pci.h         |  1 +
>  drivers/pci/probe.c       | 12 ------------
>  drivers/pci/setup-irq.c   | 34 ++++++++++++++++------------------
>  include/linux/pci.h       |  6 ++++--
>  8 files changed, 29 insertions(+), 48 deletions(-)

There's a lot going on in this first patch.  I'd like to split it up so
it's easier to see where the critical changes are.  For example, I think it
is safe to build setup-irq.o for all arches, even if they don't actually
use it, so the makefile changes could be split out.  Similarly for the
change to make find_pci_host_bridge() non-static.

> diff --git a/drivers/of/of_pci_irq.c b/drivers/of/of_pci_irq.c
> index 1710d9d..205eb7a 100644
> --- a/drivers/of/of_pci_irq.c
> +++ b/drivers/of/of_pci_irq.c
> @@ -97,7 +97,7 @@ EXPORT_SYMBOL_GPL(of_irq_parse_pci);
>   * @pin: PCI irq pin number; passed when used as map_irq callback. Unused
>   *
>   * @slot and @pin are unused, but included in the function so that this
> - * function can be used directly as the map_irq callback to pci_fixup_irqs().
> + * function can be used directly as the map_irq callback to pdev_assign_irq().
>   */
>  int of_irq_parse_and_map_pci(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
> diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
> index e04fe2d..38c4cb0 100644
> --- a/drivers/pci/Makefile
> +++ b/drivers/pci/Makefile
> @@ -4,7 +4,8 @@
>  
>  obj-y		+= 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
> +			irq.o vpd.o setup-bus.o vc.o setup-irq.o
> +
>  obj-$(CONFIG_PROC_FS) += proc.o
>  obj-$(CONFIG_SYSFS) += slot.o
>  
> @@ -31,18 +32,6 @@ obj-$(CONFIG_PCI_ATS) += ats.o
>  obj-$(CONFIG_PCI_IOV) += iov.o
>  
>  #
> -# Some architectures use the generic PCI setup functions
> -#
> -obj-$(CONFIG_ALPHA) += setup-irq.o
> -obj-$(CONFIG_ARM) += setup-irq.o
> -obj-$(CONFIG_UNICORE32) += setup-irq.o
> -obj-$(CONFIG_SUPERH) += setup-irq.o
> -obj-$(CONFIG_MIPS) += setup-irq.o
> -obj-$(CONFIG_TILE) += setup-irq.o
> -obj-$(CONFIG_SPARC_LEON) += setup-irq.o
> -obj-$(CONFIG_M68K) += setup-irq.o
> -
> -#
>  # ACPI Related PCI FW Functions
>  # ACPI _DSM provided firmware instance and string name
>  #
> diff --git a/drivers/pci/host-bridge.c b/drivers/pci/host-bridge.c
> index 0e5f3c9..8ed186f 100644
> --- a/drivers/pci/host-bridge.c
> +++ b/drivers/pci/host-bridge.c
> @@ -16,7 +16,7 @@ static struct pci_bus *find_pci_root_bus(struct pci_bus *bus)
>  	return bus;
>  }
>  
> -static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
> +struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
>  {
>  	struct pci_bus *root_bus = find_pci_root_bus(bus);
>  
> diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
> index 2c9ac70..2dd28d9 100644
> --- a/drivers/pci/pci.c
> +++ b/drivers/pci/pci.c
> @@ -1192,11 +1192,15 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
>  	struct pci_dev *bridge;
>  	u16 cmd;
>  	u8 pin;
> +	struct pci_host_bridge *hbrg = find_pci_host_bridge(dev->bus);
>  
>  	err = pci_set_power_state(dev, PCI_D0);
>  	if (err < 0 && err != -EIO)
>  		return err;
>  
> +	pdev_assign_irq(dev, hbrg->swizzle_irq, hbrg->map_irq);

We don't need the host bridge for anything else here, so why not just look
it up inside pdev_assign_irq()?

> +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> +
>  	bridge = pci_upstream_bridge(dev);
>  	if (bridge)
>  		pcie_aspm_powersave_config_link(bridge);
> @@ -1209,7 +1213,6 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
>  	if (dev->msi_enabled || dev->msix_enabled)
>  		return 0;
>  
> -	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
>  	if (pin) {
>  		pci_read_config_word(dev, PCI_COMMAND, &cmd);
>  		if (cmd & PCI_COMMAND_INTX_DISABLE)
> diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
> index 0601890..a6cf445 100644
> --- a/drivers/pci/pci.h
> +++ b/drivers/pci/pci.h
> @@ -70,6 +70,7 @@ void pci_config_pm_runtime_put(struct pci_dev *dev);
>  void pci_pm_init(struct pci_dev *dev);
>  void pci_allocate_cap_save_buffers(struct pci_dev *dev);
>  void pci_free_cap_save_buffers(struct pci_dev *dev);
> +struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus);
>  
>  static inline void pci_wakeup_event(struct pci_dev *dev)
>  {
> diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
> index 4170113..314e9e3 100644
> --- a/drivers/pci/probe.c
> +++ b/drivers/pci/probe.c
> @@ -1719,18 +1719,6 @@ unsigned int pci_scan_child_bus(struct pci_bus *bus)
>  }
>  EXPORT_SYMBOL_GPL(pci_scan_child_bus);
>  
> -/**
> - * pcibios_root_bridge_prepare - Platform-specific host bridge setup.
> - * @bridge: Host bridge to set up.
> - *
> - * Default empty implementation.  Replace with an architecture-specific setup
> - * routine, if necessary.
> - */
> -int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> -{
> -	return 0;
> -}

We can't just remove this, because it will cause link failures for any arch
that doesn't supply its own implementation of
pcibios_root_bridge_prepare().  Future patches add such implementations,
but the tree should build and work correctly after every patch.  That is
required for bisectability.

If your intent is that every arch must supply its own
pcibios_root_bridge_prepare(), you should 

  - keep the __weak version here,
  - add a non-weak version for every arch,
  - then finally remove this __weak default version at the end.

> -
>  void __weak pcibios_add_bus(struct pci_bus *bus)
>  {
>  }
> diff --git a/drivers/pci/setup-irq.c b/drivers/pci/setup-irq.c
> index 4e2d595..203bf7e 100644
> --- a/drivers/pci/setup-irq.c
> +++ b/drivers/pci/setup-irq.c
> @@ -22,13 +22,19 @@ void __weak pcibios_update_irq(struct pci_dev *dev, int irq)
>  	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
>  }
>  
> -static void pdev_fixup_irq(struct pci_dev *dev,
> +void pdev_assign_irq(struct pci_dev *dev,
>  			   u8 (*swizzle)(struct pci_dev *, u8 *),
> -			   int (*map_irq)(const struct pci_dev *, u8, u8))
> +			   int (*map_irq)(struct pci_dev *, u8, u8))
>  {
> -	u8 pin, slot;
> +	u8 pin;
> +	u8 slot = -1;
>  	int irq = 0;
>  
> +	if (!map_irq) {
> +		dev_dbg(&dev->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 'cos that slot is where the bridge is.   Each
> @@ -40,28 +46,20 @@ static void pdev_fixup_irq(struct pci_dev *dev,
>  	if (pin > 4)
>  		pin = 1;
>  
> -	if (pin != 0) {
> -		/* Follow the chain of bridges, swizzling as we go.  */
> -		slot = (*swizzle)(dev, &pin);
> +	if (pin) {
> +		/* Follow the chain of bridges, swizzling as we go. */
> +		if(swizzle)
> +			slot = (*swizzle)(dev, &pin);
>  
> +		/* If a swizzling function is not used map_irq must ignore slot */
>  		irq = (*map_irq)(dev, slot, pin);
>  		if (irq == -1)
>  			irq = 0;
>  	}
> -	dev->irq = irq;
> -
> -	dev_dbg(&dev->dev, "fixup irq: got %d\n", dev->irq);
>  
> +	dev_dbg(&dev->dev, "assign irq: got %d\n", dev->irq);
> +	dev->irq = irq;
>  	/* Always tell the device, so the driver knows what is
>  	   the real IRQ to use; the device does not use it. */
>  	pcibios_update_irq(dev, irq);
>  }
> -
> -void pci_fixup_irqs(u8 (*swizzle)(struct pci_dev *, u8 *),
> -		    int (*map_irq)(const struct pci_dev *, u8, u8))
> -{
> -	struct pci_dev *dev = NULL;
> -
> -	for_each_pci_dev(dev)
> -		pdev_fixup_irq(dev, swizzle, map_irq);
> -}

This removes pci_fixup_irqs(), which is still used (at this point) by many
architectures.  I see that you remove those uses in later patches, but that
means the tree is broken in the interim, so it's not bisectable.

I think you're going to have to build up the new assign-IRQ-at-enable-time
path while leaving the old path intact, in such a way that the new path
does nothing until an arch is converted to use it.  Then when you convert
each arch to the new strategy, you can remove its use of the old path.
After all arches are converted and there are no users of the old path, you
can remove it completely.

> diff --git a/include/linux/pci.h b/include/linux/pci.h
> index 96453f9..5426d11 100644
> --- a/include/linux/pci.h
> +++ b/include/linux/pci.h
> @@ -403,6 +403,8 @@ struct pci_host_bridge {
>  	struct device dev;
>  	struct pci_bus *bus;		/* root bus */
>  	struct list_head windows;	/* pci_host_bridge_windows */
> +	u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* platform irq swizzler */
> +	int (*map_irq)(struct pci_dev *, u8, u8);
>  	void (*release_fn)(struct pci_host_bridge *);
>  	void *release_data;
>  };
> @@ -1064,8 +1066,8 @@ void pci_assign_unassigned_bus_resources(struct pci_bus *bus);
>  void pci_assign_unassigned_root_bus_resources(struct pci_bus *bus);
>  void pdev_enable_device(struct pci_dev *);
>  int pci_enable_resources(struct pci_dev *, int mask);
> -void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
> -		    int (*)(const struct pci_dev *, u8, u8));
> +void pdev_assign_irq(struct pci_dev *dev, u8 (*swizzle)(struct pci_dev *, u8 *),

For things exported via include/linux/pci.h, I think we should use names
prefixed by "pci_", not "pdev_".

> +                     int (*map_irq)(struct pci_dev *, u8, u8));
>  #define HAVE_PCI_REQ_REGIONS	2
>  int __must_check pci_request_regions(struct pci_dev *, const char *);
>  int __must_check pci_request_regions_exclusive(struct pci_dev *, const char *);

Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time matt
  2014-10-02 10:51   ` Liviu Dudau
@ 2014-10-14 18:11   ` Bjorn Helgaas
  1 sibling, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:11 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:30AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> The x86 architecture boot code currently traverses the PCI buses with
> an extra pass in order to initialise the PCI device IRQs at boot, this
> patch avoids this pass and defers the IRQ assignment untill device
> enable time which also has the benefit that hot-plugged devices are
> assigned IRQs without additional code.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/x86/include/asm/pci_x86.h |  7 ++--
>  arch/x86/kernel/x86_init.c     |  1 -
>  arch/x86/pci/acpi.c            |  5 ++-
>  arch/x86/pci/common.c          |  2 -
>  arch/x86/pci/irq.c             | 94 +++++++++++++++++++++++-------------------
>  5 files changed, 59 insertions(+), 50 deletions(-)
> 
> diff --git a/arch/x86/include/asm/pci_x86.h b/arch/x86/include/asm/pci_x86.h
> index fa1195d..16fd8e9 100644
> --- a/arch/x86/include/asm/pci_x86.h
> +++ b/arch/x86/include/asm/pci_x86.h
> @@ -90,6 +90,7 @@ extern unsigned int pcibios_irq_mask;
>  
>  extern raw_spinlock_t pci_config_lock;
>  
> +extern int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin);
>  extern int (*pcibios_enable_irq)(struct pci_dev *dev);
>  extern void (*pcibios_disable_irq)(struct pci_dev *dev);
>  
> @@ -119,7 +120,7 @@ extern int __init pci_acpi_init(void);
>  extern void __init pcibios_irq_init(void);
>  extern int __init pcibios_init(void);
>  extern int pci_legacy_init(void);
> -extern void pcibios_fixup_irqs(void);
> +extern int pcibios_fixup_irq(struct pci_dev *dev, u8 pin);
>  
>  /* pci-mmconfig.c */
>  
> @@ -200,9 +201,9 @@ static inline void mmio_config_writel(void __iomem *pos, u32 val)
>  #  define x86_default_pci_init		pci_legacy_init
>  # endif
>  # define x86_default_pci_init_irq	pcibios_irq_init
> -# define x86_default_pci_fixup_irqs	pcibios_fixup_irqs
> +# define x86_default_pci_fixup_irq	pcibios_fixup_irq
>  #else
>  # define x86_default_pci_init		NULL
>  # define x86_default_pci_init_irq	NULL
> -# define x86_default_pci_fixup_irqs	NULL
> +# define x86_default_pci_fixup_irq	NULL
>  #endif
> diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
> index e48b674..064457f 100644
> --- a/arch/x86/kernel/x86_init.c
> +++ b/arch/x86/kernel/x86_init.c
> @@ -81,7 +81,6 @@ struct x86_init_ops x86_init __initdata = {
>  	.pci = {
>  		.init			= x86_default_pci_init,
>  		.init_irq		= x86_default_pci_init_irq,
> -		.fixup_irqs		= x86_default_pci_fixup_irqs,
>  	},
>  };
>  
> diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c
> index cfd1b13..2c433f4 100644
> --- a/arch/x86/pci/acpi.c
> +++ b/arch/x86/pci/acpi.c
> @@ -311,7 +311,7 @@ static acpi_status setup_resource(struct acpi_resource *acpi_res, void *data)
>  	} else if (orig_end != end) {
>  		dev_info(&info->bridge->dev,
>  			"host bridge window [%#llx-%#llx] "
> -			"([%#llx-%#llx] ignored, not CPU addressable)\n", 
> +			"([%#llx-%#llx] ignored, not CPU addressable)\n",

This and the similar whitespace fixes below are out of scope for this
patch.  This patch series should have the minimal set of IRQ changes you
need, and whitespace changes can be done later.  This makes the series
easier to review and to backport.

>  			start, orig_end, end + 1, orig_end);
>  	}
>  
> @@ -571,6 +571,9 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>  	struct pci_sysdata *sd = bridge->bus->sysdata;
>  
>  	ACPI_COMPANION_SET(&bridge->dev, sd->companion);
> +
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;
>  	return 0;
>  }
>  
> diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c
> index 059a76c..d4ed0b0 100644
> --- a/arch/x86/pci/common.c
> +++ b/arch/x86/pci/common.c
> @@ -662,8 +662,6 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
>  	if ((err = pci_enable_resources(dev, mask)) < 0)
>  		return err;
>  
> -	if (!pci_dev_msi_enabled(dev))
> -		return pcibios_enable_irq(dev);
>  	return 0;
>  }
>  
> diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c
> index eb500c2..33d323d 100644
> --- a/arch/x86/pci/irq.c
> +++ b/arch/x86/pci/irq.c
> @@ -594,9 +594,9 @@ static __init int intel_router_probe(struct irq_router *r, struct pci_dev *route
>  		return 1;
>  	}
>  
> -	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN && 
> -	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX) 
> -	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && 
> +	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN &&
> +	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)
> +	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN &&
>  	     device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)
>  	||  (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN &&
>  	     device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)
> @@ -875,9 +875,8 @@ static struct irq_info *pirq_get_info(struct pci_dev *dev)
>  	return NULL;
>  }
>  
> -static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
> +static int pcibios_lookup_irq(struct pci_dev *dev, u8 pin, int assign)
>  {
> -	u8 pin;
>  	struct irq_info *info;
>  	int i, pirq, newirq;
>  	int irq = 0;
> @@ -887,7 +886,6 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
>  	char *msg = NULL;
>  
>  	/* Find IRQ pin */
> -	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
>  	if (!pin) {
>  		dev_dbg(&dev->dev, "no interrupt pin\n");
>  		return 0;
> @@ -1017,50 +1015,45 @@ static int pcibios_lookup_irq(struct pci_dev *dev, int assign)
>  					 irq, pci_name(dev2));
>  		}
>  	}
> -	return 1;
> +	/*
> +	 * Due to the complicated platform specific behvaiour we cannot defer
> +	 * assigning dev->irq to the caller but will return it anyway
> +	 */
> +	return dev->irq;
>  }
>  
> -void __init pcibios_fixup_irqs(void)
> +int pcibios_fixup_irq(struct pci_dev *dev, u8 pin)
>  {
> -	struct pci_dev *dev = NULL;
> -	u8 pin;
> -
> +	int irq = dev->irq;
>  	DBG(KERN_DEBUG "PCI: IRQ fixup\n");
> -	for_each_pci_dev(dev) {
> -		/*
> -		 * If the BIOS has set an out of range IRQ number, just
> -		 * ignore it.  Also keep track of which IRQ's are
> -		 * already in use.
> -		 */
> -		if (dev->irq >= 16) {
> -			dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", dev->irq);
> -			dev->irq = 0;
> -		}
> -		/*
> -		 * If the IRQ is already assigned to a PCI device,
> -		 * ignore its ISA use penalty
> -		 */
> -		if (pirq_penalty[dev->irq] >= 100 &&
> -				pirq_penalty[dev->irq] < 100000)
> -			pirq_penalty[dev->irq] = 0;
> -		pirq_penalty[dev->irq]++;
> +	/*
> +	 * If the BIOS has set an out of range IRQ number, just
> +	 * ignore it.  Also keep track of which IRQ's are
> +	 * already in use.
> +	 */
> +	if (irq >= 16) {
> +		dev_dbg(&dev->dev, "ignoring bogus IRQ %d\n", irq);
> +		irq = 0;
>  	}
> +	/*
> +	 * If the IRQ is already assigned to a PCI device,
> +	 * ignore its ISA use penalty
> +	 */
> +	if (pirq_penalty[irq] >= 100 &&
> +			pirq_penalty[irq] < 100000)
> +		pirq_penalty[irq] = 0;
> +	pirq_penalty[irq]++;
>  
> -	if (io_apic_assign_pci_irqs)
> -		return;
> +	if (io_apic_assign_pci_irqs || !pin)
> +		return irq;
>  
> -	dev = NULL;
> -	for_each_pci_dev(dev) {
> -		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> -		if (!pin)
> -			continue;
> +	/*
> +	 * Still no IRQ? Try to lookup one...
> +	 */
> +	if (!irq)
> +		irq = pcibios_lookup_irq(dev, pin, 0);
>  
> -		/*
> -		 * Still no IRQ? Try to lookup one...
> -		 */
> -		if (!dev->irq)
> -			pcibios_lookup_irq(dev, 0);
> -	}
> +	return irq;
>  }
>  
>  /*
> @@ -1161,6 +1154,13 @@ void __init pcibios_irq_init(void)
>  	}
>  }
>  
> +int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;
> +	return 0;
> +}

It's confusing to have two pcibios_root_bridge_prepare() definitions for
one architecture, especially since one is weak and the other is not, and
they contain duplicated code.  I think the only practical way to use __weak
is to have a single default weak version in the entire kernel.  If we have
more than one, e.g., this one and the one in drivers/pci/probe.c, we can't
really tell which version will be used because it depends on link order.

I think it'd be better to just move the arch/x86/pci/acpi.c implementation
to here so it's always compiled.  It can still use ACPI_COMPANION_SET(),
since there's a stub for that even when CONFIG_ACPI is not set.

Moving pcibios_root_bridge_prepare() can be its own separate patch since
it's trivial and can be done independently.  Then you can add the setting
of ->map_irq in this patch.  Setting ->swizzle_irq is optional since it
defaults to NULL anyway.

> +
>  static void pirq_penalize_isa_irq(int irq, int active)
>  {
>  	/*
> @@ -1185,12 +1185,20 @@ void pcibios_penalize_isa_irq(int irq, int active)
>  		pirq_penalize_isa_irq(irq, active);
>  }
>  
> +int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	dev->irq = pcibios_fixup_irq(dev, pin);
> +	if (pcibios_enable_irq(dev))
> +		return -1;
> +	return dev->irq;
> +}
> +
>  static int pirq_enable_irq(struct pci_dev *dev)
>  {
>  	u8 pin = 0;
>  
>  	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> -	if (pin && !pcibios_lookup_irq(dev, 1)) {
> +	if (pin && !pcibios_lookup_irq(dev, pin, 1)) {

This change (passing in "pin" instead of reading it again inside
pcibios_lookup_irq()) can also be done separately in a small,
obviously-correct patch.  Splitting it out will make the essential
parts of *this* patch more obvious.

>  		char *msg = "";
>  
>  		if (!io_apic_assign_pci_irqs && dev->irq)
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 03/18] Delayed arm setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 03/18] Delayed arm " matt
@ 2014-10-14 18:14   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:14 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:31AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> Currently PCI device IRQs under arm are initialised during the
> pci_common_init_dev code path, this results in an extra sweep of the
> PCI bus as well as causing PCI devices hot-plugged after boot to not
> receive an IRQ.
> 
> This patch set defers this assignment untill the device enable phase
> which prevents both these issues.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/arm/kernel/bios32.c | 13 +++++++++----
>  1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/arch/arm/kernel/bios32.c b/arch/arm/kernel/bios32.c
> index 17a26c1..4dcf3f7 100644
> --- a/arch/arm/kernel/bios32.c
> +++ b/arch/arm/kernel/bios32.c
> @@ -389,7 +389,7 @@ void pcibios_remove_bus(struct pci_bus *bus)
>   * PCI standard swizzle is implemented on plug-in cards and Cardbus based
>   * PCI extenders, so it can not be ignored.
>   */
> -static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
> +u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)

I don't think there's anything in this patch that requires
pcibios_swizzle() or pcibios_map_irq() to be non-static.

>  {
>  	struct pci_sys_data *sys = dev->sysdata;
>  	int slot, oldpin = *pin;
> @@ -409,7 +409,7 @@ static u8 pcibios_swizzle(struct pci_dev *dev, u8 *pin)
>  /*
>   * Map a slot/pin to an IRQ.
>   */
> -static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	struct pci_sys_data *sys = dev->sysdata;
>  	int irq = -1;
> @@ -424,6 +424,13 @@ static int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  	return irq;
>  }
>  
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = pcibios_swizzle;
> +	bridge->map_irq = pcibios_map_irq;
> +	return 0;
> +}
> +
>  static int pcibios_init_resources(int busnr, struct pci_sys_data *sys)
>  {
>  	int ret;
> @@ -523,8 +530,6 @@ void pci_common_init_dev(struct device *parent, struct hw_pci *hw)
>  	if (hw->postinit)
>  		hw->postinit();
>  
> -	pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
> -
>  	list_for_each_entry(sys, &head, node) {
>  		struct pci_bus *bus = sys->bus;
>  
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 04/18] Delayed powerpc setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 04/18] Delayed powerpc " matt
@ 2014-10-14 18:20   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:20 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:32AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> The powerpc PCI init code is currently initialising PCI device IRQ during
> the boot time pcibios phase. This results in devices which are connected
> after boot time not being asigned IRQs which can cause various problems.
> 
> This patch as part of its set fixes this be moving the IRQ initialisation
> into the PCI device enable code path so that it is run for boot time and
> hot-plugged devices alike.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/powerpc/kernel/pci-common.c | 26 +++++++++++++-------------
>  1 file changed, 13 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> index b2814e2..a8be5a5 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -217,7 +217,7 @@ struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node)
>   * If the interrupt is used, then gets the interrupt line from the
>   * openfirmware and sets it in the pci_dev and pci_config line.
>   */
> -static int pci_read_irq_line(struct pci_dev *pci_dev)
> +static int pci_read_irq_line(struct pci_dev *pci_dev, u8 pin)
>  {
>  	struct of_phandle_args oirq;
>  	unsigned int virq;
> @@ -229,7 +229,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
>  #endif
>  	/* Try to get a mapping from the device-tree */
>  	if (of_irq_parse_pci(pci_dev, &oirq)) {
> -		u8 line, pin;
> +		u8 line;
>  
>  		/* If that fails, lets fallback to what is in the config
>  		 * space and map that through the default controller. We
> @@ -238,10 +238,6 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
>  		 * either provide a proper interrupt tree or don't use this
>  		 * function.
>  		 */
> -		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &pin))
> -			return -1;
> -		if (pin == 0)
> -			return -1;
>  		if (pci_read_config_byte(pci_dev, PCI_INTERRUPT_LINE, &line) ||
>  		    line == 0xff || line == 0) {
>  			return -1;
> @@ -266,9 +262,16 @@ static int pci_read_irq_line(struct pci_dev *pci_dev)
>  
>  	pr_debug(" Mapped to linux irq %d\n", virq);
>  
> -	pci_dev->irq = virq;
> +	return virq;
> +}
>  
> -	return 0;
> +int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)

Should be static.

> +{
> +	/* Read default IRQs and fixup if necessary */
> +	int irq = pci_read_irq_line(dev, pin);
> +	if (ppc_md.pci_irq_fixup)
> +		ppc_md.pci_irq_fixup(dev);
> +	return irq;

The .pci_irq_fixup() can change dev->irq, so wouldn't you want to return
dev->irq, not irq, here?  Otherwise, pdev_assign_irq() (the caller of
pci_map_irq()) will overwrite the dev->irq value set by the fixup.

>  }
>  
>  /*
> @@ -766,6 +769,8 @@ int pci_proc_domain(struct pci_bus *bus)
>  
>  int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>  {
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;
>  	if (ppc_md.pcibios_root_bridge_prepare)
>  		return ppc_md.pcibios_root_bridge_prepare(bridge);
>  
> @@ -968,11 +973,6 @@ static void pcibios_setup_device(struct pci_dev *dev)
>  	/* Additional platform DMA/iommu setup */
>  	if (ppc_md.pci_dma_dev_setup)
>  		ppc_md.pci_dma_dev_setup(dev);
> -
> -	/* Read default IRQs and fixup if necessary */
> -	pci_read_irq_line(dev);
> -	if (ppc_md.pci_irq_fixup)
> -		ppc_md.pci_irq_fixup(dev);
>  }
>  
>  int pcibios_add_device(struct pci_dev *dev)
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 05/18] Delayed sh setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 05/18] Delayed sh " matt
@ 2014-10-14 18:25   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:25 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:33AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> Currently platform specific PCI device IRQ assignment is run during
> the boot code, this results in a wide array of differing code paths
> and causes hot-plugged PCI devices to not be assigned IRQs, this
> patch removes the boot time initialisation of such IRQs and instead
> registers assignment functions to be run during the PCI device enable
> plase.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/sh/drivers/pci/fixups-cayman.c     |  2 +-
>  arch/sh/drivers/pci/fixups-dreamcast.c  |  2 +-
>  arch/sh/drivers/pci/fixups-r7780rp.c    |  2 +-
>  arch/sh/drivers/pci/fixups-rts7751r2d.c |  6 +++---
>  arch/sh/drivers/pci/fixups-sdk7780.c    |  4 ++--
>  arch/sh/drivers/pci/fixups-se7751.c     |  2 +-
>  arch/sh/drivers/pci/fixups-sh03.c       |  2 +-
>  arch/sh/drivers/pci/fixups-snapgear.c   |  2 +-
>  arch/sh/drivers/pci/fixups-titan.c      |  4 ++--
>  arch/sh/drivers/pci/pci.c               | 10 +++++++---
>  arch/sh/drivers/pci/pcie-sh7786.c       |  2 +-
>  11 files changed, 21 insertions(+), 17 deletions(-)
> 
> diff --git a/arch/sh/drivers/pci/fixups-cayman.c b/arch/sh/drivers/pci/fixups-cayman.c
> index edc2fb7..3246788 100644
> --- a/arch/sh/drivers/pci/fixups-cayman.c
> +++ b/arch/sh/drivers/pci/fixups-cayman.c
> @@ -5,7 +5,7 @@
>  #include <cpu/irq.h>
>  #include "pci-sh5.h"
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)

Most of this patch is just removing "__init".  Can you split it into two:
one that removes the __init annotations, and another that adds the
pcibios_root_bridge_prepare() definition?  Then the first will be obviously
correct (it should always be safe to remove the __init optimization), and
the second will be smaller and contain only the interesting part.

>  {
>  	int result = -1;
>  
> diff --git a/arch/sh/drivers/pci/fixups-dreamcast.c b/arch/sh/drivers/pci/fixups-dreamcast.c
> index 1d1c5a2..9d597f7 100644
> --- a/arch/sh/drivers/pci/fixups-dreamcast.c
> +++ b/arch/sh/drivers/pci/fixups-dreamcast.c
> @@ -76,7 +76,7 @@ static void gapspci_fixup_resources(struct pci_dev *dev)
>  }
>  DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, gapspci_fixup_resources);
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	/*
>  	 * The interrupt routing semantics here are quite trivial.
> diff --git a/arch/sh/drivers/pci/fixups-r7780rp.c b/arch/sh/drivers/pci/fixups-r7780rp.c
> index 57ed3f0..2c9b58f 100644
> --- a/arch/sh/drivers/pci/fixups-r7780rp.c
> +++ b/arch/sh/drivers/pci/fixups-r7780rp.c
> @@ -15,7 +15,7 @@
>  #include <linux/sh_intc.h>
>  #include "pci-sh4.h"
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
>  {
>  	return evt2irq(0xa20) + slot;
>  }
> diff --git a/arch/sh/drivers/pci/fixups-rts7751r2d.c b/arch/sh/drivers/pci/fixups-rts7751r2d.c
> index eaddb56..358ac10 100644
> --- a/arch/sh/drivers/pci/fixups-rts7751r2d.c
> +++ b/arch/sh/drivers/pci/fixups-rts7751r2d.c
> @@ -20,18 +20,18 @@
>  #define PCIMCR_MRSET_OFF	0xBFFFFFFF
>  #define PCIMCR_RFSH_OFF		0xFFFFFFFB
>  
> -static u8 rts7751r2d_irq_tab[] __initdata = {
> +static u8 rts7751r2d_irq_tab[] = {
>  	IRQ_PCI_INTA,
>  	IRQ_PCI_INTB,
>  	IRQ_PCI_INTC,
>  	IRQ_PCI_INTD,
>  };
>  
> -static char lboxre2_irq_tab[] __initdata = {
> +static char lboxre2_irq_tab[] = {
>  	IRQ_ETH0, IRQ_ETH1, IRQ_INTA, IRQ_INTD,
>  };
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
>  {
>  	if (mach_is_lboxre2())
>  		return lboxre2_irq_tab[slot];
> diff --git a/arch/sh/drivers/pci/fixups-sdk7780.c b/arch/sh/drivers/pci/fixups-sdk7780.c
> index c0a015a..24e96df 100644
> --- a/arch/sh/drivers/pci/fixups-sdk7780.c
> +++ b/arch/sh/drivers/pci/fixups-sdk7780.c
> @@ -22,7 +22,7 @@
>  #define IRQ_INTD	evt2irq(0xa80)
>  
>  /* IDSEL [16][17][18][19][20][21][22][23][24][25][26][27][28][29][30][31] */
> -static char sdk7780_irq_tab[4][16] __initdata = {
> +static char sdk7780_irq_tab[4][16] = {
>  	/* INTA */
>  	{ IRQ_INTA, IRQ_INTD, IRQ_INTC, IRQ_INTD, -1, -1, -1, -1, -1, -1,
>  	  -1, -1, -1, -1, -1, -1 },
> @@ -37,7 +37,7 @@ static char sdk7780_irq_tab[4][16] __initdata = {
>  	  -1, -1, -1 },
>  };
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
>  {
>         return sdk7780_irq_tab[pin-1][slot];
>  }
> diff --git a/arch/sh/drivers/pci/fixups-se7751.c b/arch/sh/drivers/pci/fixups-se7751.c
> index 84a88ca..1cb8d0a 100644
> --- a/arch/sh/drivers/pci/fixups-se7751.c
> +++ b/arch/sh/drivers/pci/fixups-se7751.c
> @@ -7,7 +7,7 @@
>  #include <linux/sh_intc.h>
>  #include "pci-sh4.h"
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *, u8 slot, u8 pin)
>  {
>          switch (slot) {
>          case 0: return evt2irq(0x3a0);
> diff --git a/arch/sh/drivers/pci/fixups-sh03.c b/arch/sh/drivers/pci/fixups-sh03.c
> index 16207be..55ac1ba 100644
> --- a/arch/sh/drivers/pci/fixups-sh03.c
> +++ b/arch/sh/drivers/pci/fixups-sh03.c
> @@ -4,7 +4,7 @@
>  #include <linux/pci.h>
>  #include <linux/sh_intc.h>
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	int irq;
>  
> diff --git a/arch/sh/drivers/pci/fixups-snapgear.c b/arch/sh/drivers/pci/fixups-snapgear.c
> index 6e33ba4..a931e59 100644
> --- a/arch/sh/drivers/pci/fixups-snapgear.c
> +++ b/arch/sh/drivers/pci/fixups-snapgear.c
> @@ -19,7 +19,7 @@
>  #include <linux/sh_intc.h>
>  #include "pci-sh4.h"
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
>  {
>  	int irq = -1;
>  
> diff --git a/arch/sh/drivers/pci/fixups-titan.c b/arch/sh/drivers/pci/fixups-titan.c
> index bd1addb..a9d563e 100644
> --- a/arch/sh/drivers/pci/fixups-titan.c
> +++ b/arch/sh/drivers/pci/fixups-titan.c
> @@ -19,7 +19,7 @@
>  #include <mach/titan.h>
>  #include "pci-sh4.h"
>  
> -static char titan_irq_tab[] __initdata = {
> +static char titan_irq_tab[] = {
>  	TITAN_IRQ_WAN,
>  	TITAN_IRQ_LAN,
>  	TITAN_IRQ_MPCIA,
> @@ -27,7 +27,7 @@ static char titan_irq_tab[] __initdata = {
>  	TITAN_IRQ_USB,
>  };
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
>  {
>  	int irq = titan_irq_tab[slot];
>  
> diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c
> index 1bc09ee..718fae3 100644
> --- a/arch/sh/drivers/pci/pci.c
> +++ b/arch/sh/drivers/pci/pci.c
> @@ -141,16 +141,20 @@ static int __init pcibios_init(void)
>  	for (hose = hose_head; hose; hose = hose->next)
>  		pcibios_scanbus(hose);
>  
> -	pci_fixup_irqs(pci_common_swizzle, pcibios_map_platform_irq);
> -
>  	dma_debug_add_bus(&pci_bus_type);
> -
>  	pci_initialized = 1;
>  
>  	return 0;
>  }
>  subsys_initcall(pcibios_init);
>  
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = pci_common_swizzle;
> +	bridge->map_irq = pcibios_map_platform_irq;
> +	return 0;
> +}
> +
>  /*
>   *  Called after each bus is probed, but before its children
>   *  are examined.
> diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
> index a162a7f..0167a73 100644
> --- a/arch/sh/drivers/pci/pcie-sh7786.c
> +++ b/arch/sh/drivers/pci/pcie-sh7786.c
> @@ -467,7 +467,7 @@ static int __init pcie_init(struct sh7786_pcie_port *port)
>  	return 0;
>  }
>  
> -int __init pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
> +int pcibios_map_platform_irq(const struct pci_dev *pdev, u8 slot, u8 pin)
>  {
>          return evt2irq(0xae0);
>  }
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 06/18] Delayed alpha setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 06/18] Delayed alpha " matt
@ 2014-10-14 18:27   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:27 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:34AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> PCI IRQ initialisation is currently run during the boot code on alpha,
> this has the issue that firstly an extra pass over the PCI bus is
> required and second hot-plugged devices which are added after boot have
> no way to be assigned an IRQ. This patch set fixes this by defering the
> assignment of PCI IRQs untill device enable time which should solve
> both of these issues.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/alpha/kernel/pci.c          | 16 ++++++++++------
>  arch/alpha/kernel/sys_nautilus.c |  1 -
>  2 files changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c
> index 076c35c..338537c 100644
> --- a/arch/alpha/kernel/pci.c
> +++ b/arch/alpha/kernel/pci.c
> @@ -28,7 +28,7 @@
>  
>  
>  /*
> - * Some string constants used by the various core logics. 
> + * Some string constants used by the various core logics.
>   */
>  
>  const char *const pci_io_names[] = {
> @@ -247,7 +247,7 @@ void pcibios_fixup_bus(struct pci_bus *bus)
>  	if (pci_has_flag(PCI_PROBE_ONLY) && dev &&
>   		   (dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
>   		pci_read_bridge_bases(bus);
> -	} 
> +	}
>  
>  	list_for_each_entry(dev, &bus->devices, bus_list) {
>  		pdev_save_srm_config(dev);
> @@ -338,7 +338,7 @@ common_init_pci(void)
>  		hose->need_domain_info = need_domain_info;
>  		next_busno = bus->busn_res.end + 1;
>  		/* Don't allow 8-bit bus number overflow inside the hose -
> -		   reserve some space for bridges. */ 
> +		   reserve some space for bridges. */

Extraneous whitespace changes above.

>  		if (next_busno > 224) {
>  			next_busno = 0;
>  			need_domain_info = 1;
> @@ -346,11 +346,15 @@ common_init_pci(void)
>  	}
>  
>  	pcibios_claim_console_setup();
> -
>  	pci_assign_unassigned_resources();
> -	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
>  }
>  
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = alpha_mv.pci_swizzle;
> +	bridge->map_irq = alpha_mv.pci_map_irq;
> +	return 0;
> +}
>  
>  struct pci_controller * __init
>  alloc_pci_controller(void)
> @@ -387,7 +391,7 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
>  
>  	/* from hose or from bus.devfn */
>  	if (which & IOBASE_FROM_HOSE) {
> -		for(hose = hose_head; hose; hose = hose->next) 
> +		for(hose = hose_head; hose; hose = hose->next)

Extraneous whitespace change.  If you fix this in a separate patch, also
add a space after "for".

>  			if (hose->index == bus) break;
>  		if (!hose) return -ENODEV;
>  	} else {
> diff --git a/arch/alpha/kernel/sys_nautilus.c b/arch/alpha/kernel/sys_nautilus.c
> index 837c0fa..7fb4d51 100644
> --- a/arch/alpha/kernel/sys_nautilus.c
> +++ b/arch/alpha/kernel/sys_nautilus.c
> @@ -252,7 +252,6 @@ nautilus_init_pci(void)
>  	/* pci_common_swizzle() relies on bus->self being NULL
>  	   for the root bus, so just clear it. */
>  	bus->self = NULL;
> -	pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
>  }
>  
>  /*
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 07/18] Delayed cris setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 07/18] Delayed cris " matt
@ 2014-10-14 18:34   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:34 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:35AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> PCI IRQs are currently configured to be enabled once at boot in a
> dedicated pass. This means that PCI devices which are hot-plugged after
> boot time will not be given an IRQ, this patch-set fixes this by
> registering the assignment function to be called later in the device
> enable path.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/cris/arch-v32/drivers/pci/bios.c | 14 +++++---------
>  1 file changed, 5 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
> index 64a5fb9..d04ecc8 100644
> --- a/arch/cris/arch-v32/drivers/pci/bios.c
> +++ b/arch/cris/arch-v32/drivers/pci/bios.c
> @@ -80,20 +80,16 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
>  	return 0;
>  }
>  
> -int pcibios_enable_irq(struct pci_dev *dev)
> +int pcibios_enable_irq(struct pci_dev *dev, u8 slot, u8 pin)
>  {
>  	dev->irq = EXT_INTR_VECT;
>  	return 0;
>  }
>  
> -int pcibios_enable_device(struct pci_dev *dev, int mask)
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>  {
> -	int err;
> -
> -	if ((err = pcibios_enable_resources(dev, mask)) < 0)
> -		return err;

If I understand correctly, this means we'd now use the default
pcibios_enable_device() from drivers/pci/pci.c, which uses
pci_enable_resources(), instead of cris's pcibios_enable_resources().

That's a good thing that we should do someday, but it's out of scope for
this series because they *are* different, and we need to evaluate whether
it's safe to use the default version instead of the cris version.  Also, I
think this patch leaves the cris pcibios_enable_resources() unused.

> -
> -	if (!dev->msi_enabled)
> -		pcibios_enable_irq(dev);
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pcibios_enable_irq;
>  	return 0;
>  }
> +
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 08/18] Delayed frv setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 08/18] Delayed frv " matt
@ 2014-10-14 18:37   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:37 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:36AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> PCI IRQs are being assigned during the frv pcibios phase. This causes
> devices which are not connected at boot but are later hot-plugged
> to not receive an IRQ. This patch set causes the pcibios to instead
> register an IRQ assignment function which is called during the enable
> device path to apply to all devices.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/frv/mb93090-mb00/pci-frv.h |  1 -
>  arch/frv/mb93090-mb00/pci-irq.c | 28 +++++++++++++++++-----------
>  arch/frv/mb93090-mb00/pci-vdk.c |  1 -
>  3 files changed, 17 insertions(+), 13 deletions(-)
> 
> diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h
> index a7e487fe..492b56d 100644
> --- a/arch/frv/mb93090-mb00/pci-frv.h
> +++ b/arch/frv/mb93090-mb00/pci-frv.h
> @@ -36,5 +36,4 @@ extern struct pci_ops *__nongpreldata pci_root_ops;
>  extern unsigned int pcibios_irq_mask;
>  
>  void pcibios_irq_init(void);
> -void pcibios_fixup_irqs(void);
>  void pcibios_enable_irq(struct pci_dev *dev);
> diff --git a/arch/frv/mb93090-mb00/pci-irq.c b/arch/frv/mb93090-mb00/pci-irq.c
> index 1c35c93..3463e30 100644
> --- a/arch/frv/mb93090-mb00/pci-irq.c
> +++ b/arch/frv/mb93090-mb00/pci-irq.c
> @@ -40,19 +40,25 @@ void __init pcibios_irq_init(void)
>  {
>  }
>  
> -void __init pcibios_fixup_irqs(void)
> +int pcibios_map_irq(struct pci_dev *dev, uint8_t slot, uint8_t pin)
>  {
> -	struct pci_dev *dev = NULL;
> -	uint8_t line, pin;
> -
> -	for_each_pci_dev(dev) {
> -		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> -		if (pin) {
> -			dev->irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1];
> -			pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
> -		}
> -		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
> +	uint8_t line;
> +	int irq;
> +
> +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);

Doesn't your common code always read PCI_INTERRUPT_PIN and pass it in, so
you wouldn't need to read it again here?

> +	if (pin) {
> +		irq = pci_bus0_irq_routing[PCI_SLOT(dev->devfn)][pin - 1];
> +		pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
>  	}
> +	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
> +	return irq;
> +}
> +
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pcibios_map_irq;
> +	return 0;
>  }
>  
>  void pcibios_enable_irq(struct pci_dev *dev)
> diff --git a/arch/frv/mb93090-mb00/pci-vdk.c b/arch/frv/mb93090-mb00/pci-vdk.c
> index efa5d65..86657a7 100644
> --- a/arch/frv/mb93090-mb00/pci-vdk.c
> +++ b/arch/frv/mb93090-mb00/pci-vdk.c
> @@ -386,7 +386,6 @@ int __init pcibios_init(void)
>  	pci_scan_root_bus(NULL, 0, pci_root_ops, NULL, &resources);
>  
>  	pcibios_irq_init();
> -	pcibios_fixup_irqs();
>  	pcibios_resource_survey();
>  
>  	return 0;
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 09/18] Delayed m68k setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 09/18] Delayed m68k " matt
@ 2014-10-14 18:38   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:38 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:37AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> Currently PCI IRQs are assigned during mcf_pci_init which is only run
> at boot time, this causes devices which are connected after boot time
> to not receive an IRQ, this patch set fixes this by registering an IRQ
> assignment function to be run later at device enable time.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/m68k/platform/coldfire/pci.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/m68k/platform/coldfire/pci.c b/arch/m68k/platform/coldfire/pci.c
> index df96792..058ca86 100644
> --- a/arch/m68k/platform/coldfire/pci.c
> +++ b/arch/m68k/platform/coldfire/pci.c
> @@ -316,10 +316,16 @@ static int __init mcf_pci_init(void)
>  	rootbus->resource[0] = &mcf_pci_io;
>  	rootbus->resource[1] = &mcf_pci_mem;
>  
> -	pci_fixup_irqs(pci_common_swizzle, mcf_pci_map_irq);
>  	pci_bus_size_bridges(rootbus);
>  	pci_bus_assign_resources(rootbus);
>  	return 0;
>  }
>  
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = pci_common_swizzle;
> +	bridge->map_irq = mcf_pci_map_irq;
> +	return 0;
> +}
> +
>  subsys_initcall(mcf_pci_init);
> -- 
> 2.1.0
> 

Awesome, very nice and simple!

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 12/18] Delayed mn10300 setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 12/18] Delayed mn10300 " matt
@ 2014-10-14 18:46   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:46 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:40AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> 
> PCI IRQs are being asigned during pcibios_irq_init currently, this causes
> a problem by which hot-plug devices connected after boot will not recieve
> an IRQ, this patch-set fixes this by registering the IRQ assignment
> functions at boot, to then be called later by the device enable code.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/mn10300/unit-asb2305/pci-asb2305.h |  5 +----
>  arch/mn10300/unit-asb2305/pci-irq.c     | 25 +++++--------------------
>  arch/mn10300/unit-asb2305/pci.c         | 21 ++++++++-------------
>  3 files changed, 14 insertions(+), 37 deletions(-)
> 
> diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h
> index 9e17aca..fb520cf 100644
> --- a/arch/mn10300/unit-asb2305/pci-asb2305.h
> +++ b/arch/mn10300/unit-asb2305/pci-asb2305.h
> @@ -67,9 +67,6 @@ struct irq_routing_table {
>  } __attribute__((packed));
>  
>  extern unsigned int pcibios_irq_mask;
> -
> -extern void pcibios_irq_init(void);
> -extern void pcibios_fixup_irqs(void);
> -extern void pcibios_enable_irq(struct pci_dev *dev);
> +extern int pci_map_irq(struct pci_dev *, u8 slot, u8 pin);
>  
>  #endif /* PCI_ASB2305_H */
> diff --git a/arch/mn10300/unit-asb2305/pci-irq.c b/arch/mn10300/unit-asb2305/pci-irq.c
> index fcb28ce..5be6fea 100644
> --- a/arch/mn10300/unit-asb2305/pci-irq.c
> +++ b/arch/mn10300/unit-asb2305/pci-irq.c
> @@ -20,27 +20,12 @@
>  #include <asm/smp.h>
>  #include "pci-asb2305.h"
>  
> -void __init pcibios_irq_init(void)
> +int pci_map_irq(struct pci_dev *, u8 slot, u8 pin)
>  {
> -}
> -
> -void __init pcibios_fixup_irqs(void)
> -{
> -	struct pci_dev *dev = NULL;
> -	u8 line, pin;
> +	u8 line;
>  
> -	for_each_pci_dev(dev) {
> -		pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> -		if (pin) {
> -			dev->irq = XIRQ1;
> -			pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
> -					      dev->irq);
> -		}
> -		pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
> -	}
> -}
> -
> -void pcibios_enable_irq(struct pci_dev *dev)
> -{
> +	pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
> +	dev->irq = XIRQ1;
>  	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
> +	pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &line);
>  }
> diff --git a/arch/mn10300/unit-asb2305/pci.c b/arch/mn10300/unit-asb2305/pci.c
> index 6b4339f..22f8786 100644
> --- a/arch/mn10300/unit-asb2305/pci.c
> +++ b/arch/mn10300/unit-asb2305/pci.c
> @@ -377,13 +377,18 @@ static int __init pcibios_init(void)
>  	pci_add_resource_offset(&resources, &pci_ioport_resource, io_offset);
>  	pci_add_resource_offset(&resources, &pci_iomem_resource, mem_offset);
>  	pci_scan_root_bus(NULL, 0, &pci_direct_ampci, NULL, &resources);
> -
> -	pcibios_irq_init();
> -	pcibios_fixup_irqs();
>  	pcibios_resource_survey();
>  	return 0;
>  }
>  
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;

I would lean toward omitting the "= NULL" initializations here and
elsewhere, because it will make git grep and cscope searches for
swizzle_irq more useful because they will show only the arches that
actually need it.  But it's fine either way.

> +	return 0;
> +}
> +
> +
>  arch_initcall(pcibios_init);
>  
>  char *__init pcibios_setup(char *str)
> @@ -396,16 +401,6 @@ char *__init pcibios_setup(char *str)
>  	return str;
>  }
>  
> -int pcibios_enable_device(struct pci_dev *dev, int mask)
> -{
> -	int err;
> -
> -	err = pci_enable_resources(dev, mask);
> -	if (err == 0)
> -		pcibios_enable_irq(dev);
> -	return err;

I would personally do this as two patches -- one that does the IRQ change,
and a second that drops the pcibios_enable_device() implementation because
it is now the same as the default one in drivers/pci/pci.c.  That way it's
clear that there really two logical changes happening here and reviewers
can easily verify that the two pcibios_enable_device() implementations are
identical.

> -}
> -
>  /*
>   * disable the ethernet chipset
>   */
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 13/18] Delayed sparc setup of PCI IRQs to bus scan time
  2014-10-02  4:07 ` [PATCH 13/18] Delayed sparc " matt
@ 2014-10-14 18:51   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:51 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:41AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> Currently sparc allocates PCI IRQs through several different methods
> based on device. This is done during the boot stage and faces a draw-back
> by which hot-plugged devices will not be allocated an IRQ, this is fixed
> by registering IRQ allocation functions for later use during the device
> enable path.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/sparc/kernel/leon_pci.c | 12 +++++++++++-
>  arch/sparc/kernel/pci.c      | 21 +++++++++++++++++----
>  2 files changed, 28 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/sparc/kernel/leon_pci.c b/arch/sparc/kernel/leon_pci.c
> index 899b720..1079eb7 100644
> --- a/arch/sparc/kernel/leon_pci.c
> +++ b/arch/sparc/kernel/leon_pci.c
> @@ -13,6 +13,8 @@
>  #include <asm/leon.h>
>  #include <asm/leon_pci.h>
>  
> +int (*leon_pci_map_irq)(const struct pci_dev *dev, u8 slot, u8 pin);
> +
>  /* The LEON architecture does not rely on a BIOS or bootloader to setup
>   * PCI for us. The Linux generic routines are used to setup resources,
>   * reset values of configuration-space register settings are preserved.
> @@ -36,7 +38,7 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
>  				     &resources);
>  	if (root_bus) {
>  		/* Setup IRQs of all devices using custom routines */
> -		pci_fixup_irqs(pci_common_swizzle, info->map_irq);
> +		leon_pci_map_irq = info->map_irq;
>  
>  		/* Assign devices with resources */
>  		pci_assign_unassigned_resources();
> @@ -45,6 +47,14 @@ void leon_pci_init(struct platform_device *ofdev, struct leon_pci_info *info)
>  	}
>  }
>  
> +int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
> +{
> +	bridge->swizzle_irq = pci_common_swizzle;
> +	bridge->map_irq = leon_pci_map_irq;
> +	return 0;
> +}
> +
> +
>  void pcibios_fixup_bus(struct pci_bus *pbus)
>  {
>  	struct pci_dev *dev;
> diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
> index b36365f..7361c52 100644
> --- a/arch/sparc/kernel/pci.c
> +++ b/arch/sparc/kernel/pci.c
> @@ -340,10 +340,6 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
>  	} else {
>  		dev->hdr_type = PCI_HEADER_TYPE_NORMAL;
>  		dev->rom_base_reg = PCI_ROM_ADDRESS;
> -
> -		dev->irq = sd->op->archdata.irqs[0];
> -		if (dev->irq == 0xffffffff)
> -			dev->irq = PCI_IRQ_NONE;
>  	}
>  
>  	pci_parse_of_addrs(sd->op, node, dev);
> @@ -356,6 +352,23 @@ static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm,
>  	return dev;
>  }
>  
> +int pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
> +{
> +	int irq;
> +	struct platform_device *op = of_find_device_by_node(dev->sysdata);

Add a blank line here.

> +	irq = op->archdata.irqs[0];
> +	if (irq == 0xffffffff)
> +		irq = PCI_IRQ_NONE;
> +	return irq;
> +}
> +
> +int __weak pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)

Shouldn't be weak.  I see why you're doing it, since you added a non-weak
version in leon_pci.c, but without leon_pci.c, we'll have two weak versions
(this one and the one in drivers/pci/probe.c), and it's not clear which one
will be used.  Maybe keep this implementation (non-weak), and make a global
map_irq pointer that defaults to pci_map_irq() and leon_pci.c would
override that?

> +{
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = pci_map_irq;
> +	return 0;
> +}
> +
>  static void apb_calc_first_last(u8 map, u32 *first_p, u32 *last_p)
>  {
>  	u32 idx, first, last;
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 16/18] Disabled bus scan time PCI IRQ assignment on ia64
  2014-10-02  4:07 ` [PATCH 16/18] Disabled bus scan time PCI IRQ assignment on ia64 matt
@ 2014-10-14 18:53   ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 18:53 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:44AM +0100, matt@masarand.com wrote:
> From: Matthew Minter <matt@masarand.com>
> 
> Most of the architectures are switched to allocating IRQs at device_enable
> time instead of boot time, however ia64 does not provide an easy way of
> making that transition so the new code is disabled here on ia64.
> 
> Signed-off-by: Matthew Minter <matt@masarand.com>
> 
> ---
>  arch/ia64/pci/pci.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/arch/ia64/pci/pci.c b/arch/ia64/pci/pci.c
> index 291a582..398d5d4 100644
> --- a/arch/ia64/pci/pci.c
> +++ b/arch/ia64/pci/pci.c
> @@ -483,6 +483,9 @@ int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
>  {
>  	struct pci_controller *controller = bridge->bus->sysdata;
>  
> +	bridge->swizzle_irq = NULL;
> +	bridge->map_irq = NULL;

Since ->swizzle_irq and ->map_irq default to NULL anyway, isn't this a
no-op?

>  	ACPI_COMPANION_SET(&bridge->dev, controller->companion);
>  	return 0;
>  }
> -- 
> 2.1.0
> 

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers
  2014-10-02 10:33   ` Liviu Dudau
@ 2014-10-14 23:25     ` Bjorn Helgaas
  0 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2014-10-14 23:25 UTC (permalink / raw)
  To: Liviu Dudau; +Cc: matt, linux-pci

On Thu, Oct 02, 2014 at 11:33:15AM +0100, Liviu Dudau wrote:
> On Thu, Oct 02, 2014 at 05:07:29AM +0100, matt@masarand.com wrote:
> > From: Matthew Minter <matt@masarand.com>
> > 
> 
> Hi Matthew,
> 
> Some comments below:

Hi Liviu,

Thank you very much for reviewing this!  Sorry that I didn't notice your
comments until later (mutt email-reading snafu on my end), so I duplicated
some of your thoughts.  This was just out of my ignorance, not because I'm
taking issue with your comments.

> > -static struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
> > +struct pci_host_bridge *find_pci_host_bridge(struct pci_bus *bus)
> 
> When I did the same thing in one of the versions of my generic host bridge series,
> Bjorn has mentioned that he would like the name to be changed to pci_xxxxx to
> make clear that the function is now public.

This particular one is not a big deal to me because it's in
drivers/pci/pci.h, which is really only for use inside the PCI core.  It's
when we expose things in include/linux/pci.h, and especially when we export
things for use by modules, that I think we should be careful to use a
consistent namespace.

Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* Re: [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging
  2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
                   ` (17 preceding siblings ...)
  2014-10-02  4:07 ` [PATCH 18/18] Disabled bus scan time PCI IRQ assignment on s390 matt
@ 2015-01-31 14:56 ` Bjorn Helgaas
  18 siblings, 0 replies; 36+ messages in thread
From: Bjorn Helgaas @ 2015-01-31 14:56 UTC (permalink / raw)
  To: matt; +Cc: linux-pci

On Thu, Oct 02, 2014 at 05:07:28AM +0100, matt@masarand.com wrote:
> Sorry, the previous submission was damaged by my editor which purged the sign off lines from the patches,
> this is a fixed version.
> 
> pci_fixup_irqs is the current method used in most arches to assign IRQs to
> PCI devices. This has a number of flaws including it requiring an extra walk
> of the PCI bus and most importantly not running for devices which are added
> after boot time, this includes hot-added devices on boards that support this.
> 
> This patch set modifies the IRQ mapping and swizzling infrastructure
> such that functions are registered by the boot code (instead of being
> run directly by the boot code) and then run later in the enable_device
> path such that it will apply to all devices and not only those inserted
> at boot time.
> 
> This is cleaner as it unifies how each architecture allocates PCI IRQs as much
> as possible (some arches were particularly resistant to these changes so some
> work-arounds have been used or the change disabled completely).
> 
> The caveat here is that I have been forced to modify some architecture specific
> code for various architectures which I cannot test due to not having such boards
> available. The code seems correct and the changes in most cases are small and
> trivial however I have not tested all the patches for rare arches.
> 
> NEW: Since the last version all changes and suggested bug fixes have been implemented
> the patch-set has also been rebased onto the latest kernel version to ease merging.

Hi Matthew,

I'm not sure where we are with this.  This has a lot of good fixes that I'd
like to merge, but I think there were some comments that needed to be
addressed.  But I might have missed something, so I'm just checking to see
if I accidentally dropped the ball.

Bjorn

^ permalink raw reply	[flat|nested] 36+ messages in thread

* [PATCH 07/18] Delayed cris setup of PCI IRQs to bus scan time
  2014-10-02  3:50 matt
@ 2014-10-02  3:50 ` matt
  0 siblings, 0 replies; 36+ messages in thread
From: matt @ 2014-10-02  3:50 UTC (permalink / raw)
  To: bhelgaas; +Cc: linux-pci, Matthew Minter

From: Matthew Minter <matt@masarand.com>

PCI IRQs are currently configured to be enabled once at boot in a
dedicated pass. This means that PCI devices which are hot-plugged after
boot time will not be given an IRQ, this patch-set fixes this by
registering the assignment function to be called later in the device
enable path.

---
 arch/cris/arch-v32/drivers/pci/bios.c | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/arch/cris/arch-v32/drivers/pci/bios.c b/arch/cris/arch-v32/drivers/pci/bios.c
index 64a5fb9..d04ecc8 100644
--- a/arch/cris/arch-v32/drivers/pci/bios.c
+++ b/arch/cris/arch-v32/drivers/pci/bios.c
@@ -80,20 +80,16 @@ int pcibios_enable_resources(struct pci_dev *dev, int mask)
 	return 0;
 }
 
-int pcibios_enable_irq(struct pci_dev *dev)
+int pcibios_enable_irq(struct pci_dev *dev, u8 slot, u8 pin)
 {
 	dev->irq = EXT_INTR_VECT;
 	return 0;
 }
 
-int pcibios_enable_device(struct pci_dev *dev, int mask)
+int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
 {
-	int err;
-
-	if ((err = pcibios_enable_resources(dev, mask)) < 0)
-		return err;
-
-	if (!dev->msi_enabled)
-		pcibios_enable_irq(dev);
+	bridge->swizzle_irq = NULL;
+	bridge->map_irq = pcibios_enable_irq;
 	return 0;
 }
+
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 36+ messages in thread

end of thread, other threads:[~2015-01-31 14:56 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-02  4:07 [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging matt
2014-10-02  4:07 ` [PATCH 01/18] Added way to register deferred PCI IRQ assignment handlers matt
2014-10-02 10:33   ` Liviu Dudau
2014-10-14 23:25     ` Bjorn Helgaas
2014-10-14 17:15   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time matt
2014-10-02 10:51   ` Liviu Dudau
2014-10-14 18:11   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 03/18] Delayed arm " matt
2014-10-14 18:14   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 04/18] Delayed powerpc " matt
2014-10-14 18:20   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 05/18] Delayed sh " matt
2014-10-14 18:25   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 06/18] Delayed alpha " matt
2014-10-14 18:27   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 07/18] Delayed cris " matt
2014-10-14 18:34   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 08/18] Delayed frv " matt
2014-10-14 18:37   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 09/18] Delayed m68k " matt
2014-10-14 18:38   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 10/18] Delayed microblaze " matt
2014-10-02  4:07 ` [PATCH 11/18] Delayed mips " matt
2014-10-02  4:07 ` [PATCH 12/18] Delayed mn10300 " matt
2014-10-14 18:46   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 13/18] Delayed sparc " matt
2014-10-14 18:51   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 14/18] Delayed tile " matt
2014-10-02  4:07 ` [PATCH 15/18] Delayed unicore32 " matt
2014-10-02  4:07 ` [PATCH 16/18] Disabled bus scan time PCI IRQ assignment on ia64 matt
2014-10-14 18:53   ` Bjorn Helgaas
2014-10-02  4:07 ` [PATCH 17/18] Disabled bus scan time PCI IRQ assignment on parisc matt
2014-10-02  4:07 ` [PATCH 18/18] Disabled bus scan time PCI IRQ assignment on s390 matt
2015-01-31 14:56 ` [PATCH V3] Delay allocation of PCI device IRQs from boot time until bus scan time to fix PCI hotplugging Bjorn Helgaas
  -- strict thread matches above, loose matches on Subject: below --
2014-10-02  3:50 matt
2014-10-02  3:50 ` [PATCH 07/18] Delayed cris setup of PCI IRQs to bus scan time matt

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.