linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: matt@masarand.com
To: bhelgaas@google.com
Cc: linux-pci@vger.kernel.org, Matthew Minter <matt@masarand.com>
Subject: [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time
Date: Thu,  2 Oct 2014 05:07:30 +0100	[thread overview]
Message-ID: <1412222866-21068-3-git-send-email-matt@masarand.com> (raw)
In-Reply-To: <1412222866-21068-1-git-send-email-matt@masarand.com>

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


  parent reply	other threads:[~2014-10-02  4:08 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` matt [this message]
2014-10-02 10:51   ` [PATCH 02/18] Delayed x86 setup of PCI IRQs to bus scan time 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 02/18] Delayed x86 setup of PCI IRQs to bus scan time matt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1412222866-21068-3-git-send-email-matt@masarand.com \
    --to=matt@masarand.com \
    --cc=bhelgaas@google.com \
    --cc=linux-pci@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).