[PATCH] pSeries - read irqs dynamically

John Rose johnrose at austin.ibm.com
Sat Jun 18 07:59:19 EST 2005


For I/O DLPAR to work properly, the kernel needs to allow for dynamic
assignment of the irq field of the pci_dev structure upon dynamic bus
addition.  This patch moves the assignment of that field from
pSeries_final_fixup() to pcibios_fixup_bus(), which enables dynamic
assignment for the children of a newly added bus.

Currently, pci_devs receive their irq numbers in one of two ways.  The
irq line is either read at boot for all pci_devs, or read by the rpaphp
module at slot enable time.  The latter is no longer sufficient for
DLPAR addition of slots that don't qualify as PCI-hotplug capable.
This solution handles the cases of boot and dynamic add.

Comments welcome.

Thanks-
John

Signed-off-by: John Rose <johnrose at austin.ibm.com>

diff -puN arch/ppc64/kernel/pSeries_pci.c~irq_dev_setup arch/ppc64/kernel/pSeries_pci.c
--- 2_6_linus/arch/ppc64/kernel/pSeries_pci.c~irq_dev_setup	2005-06-17 16:37:45.000000000 -0500
+++ 2_6_linus-johnrose/arch/ppc64/kernel/pSeries_pci.c	2005-06-17 16:37:45.000000000 -0500
@@ -48,8 +48,6 @@ static int write_pci_config;
 static int ibm_read_pci_config;
 static int ibm_write_pci_config;
 
-static int s7a_workaround;
-
 extern struct mpic *pSeries_mpic;
 
 static int config_access_valid(struct device_node *dn, int where)
@@ -227,6 +225,39 @@ static void python_countermeasures(struc
 	iounmap(chip_regs);
 }
 
+static int is_model_s7a(void)
+{
+	struct device_node *root;
+	char *model;
+	int rc = 0;
+
+	root = of_find_node_by_path("/");
+	if (root) {
+		model = get_property(root, "model", NULL);
+		if (model && !strcmp(model, "IBM,7013-S7A"))
+			 rc = 1;
+		of_node_put(root);
+	}
+
+	return rc;
+}
+
+void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		pci_read_irq_line(dev);
+		if (is_model_s7a()) {
+			if (dev->irq > 16) {
+				dev->irq -= 3;
+				pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
+					dev->irq);
+			}
+		}
+	}
+}
+
 void __init init_pci_config_tokens (void)
 {
 	read_pci_config = rtas_token("read-pci-config");
@@ -414,6 +445,7 @@ unsigned long __init find_and_init_phbs(
 		if (prop)
 			pci_assign_all_buses = *prop;
 	}
+	ppc_md.irq_bus_setup = pSeries_irq_bus_setup;
 
 	return 0;
 }
@@ -474,20 +506,6 @@ void pcibios_name_device(struct pci_dev 
 DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device);
 #endif
 
-static void check_s7a(void)
-{
-	struct device_node *root;
-	char *model;
-
-	root = of_find_node_by_path("/");
-	if (root) {
-		model = get_property(root, "model", NULL);
-		if (model && !strcmp(model, "IBM,7013-S7A"))
-			s7a_workaround = 1;
-		of_node_put(root);
-	}
-}
-
 /* RPA-specific bits for removing PHBs */
 int pcibios_remove_root_bus(struct pci_controller *phb)
 {
@@ -553,20 +571,6 @@ static void __init pSeries_request_regio
 
 void __init pSeries_final_fixup(void)
 {
-	struct pci_dev *dev = NULL;
-
-	check_s7a();
-
-	for_each_pci_dev(dev) {
-		pci_read_irq_line(dev);
-		if (s7a_workaround) {
-			if (dev->irq > 16) {
-				dev->irq -= 3;
-				pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
-			}
-		}
-	}
-
 	phbs_remap_io();
 	pSeries_request_regions();
 
diff -puN arch/ppc64/kernel/pci.c~irq_dev_setup arch/ppc64/kernel/pci.c
--- 2_6_linus/arch/ppc64/kernel/pci.c~irq_dev_setup	2005-06-17 16:37:45.000000000 -0500
+++ 2_6_linus-johnrose/arch/ppc64/kernel/pci.c	2005-06-17 16:37:45.000000000 -0500
@@ -902,6 +902,9 @@ void __devinit pcibios_fixup_bus(struct 
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		ppc_md.iommu_dev_setup(dev);
 
+	if (ppc_md.irq_bus_setup)
+		ppc_md.irq_bus_setup(bus);
+
 	if (!pci_probe_only)
 		return;
 
diff -puN include/asm-ppc64/machdep.h~irq_dev_setup include/asm-ppc64/machdep.h
--- 2_6_linus/include/asm-ppc64/machdep.h~irq_dev_setup	2005-06-17 16:37:45.000000000 -0500
+++ 2_6_linus-johnrose/include/asm-ppc64/machdep.h	2005-06-17 16:37:45.000000000 -0500
@@ -76,6 +76,7 @@ struct machdep_calls {
 	void		(*tce_flush)(struct iommu_table *tbl);
 	void		(*iommu_dev_setup)(struct pci_dev *dev);
 	void		(*iommu_bus_setup)(struct pci_bus *bus);
+	void		(*irq_bus_setup)(struct pci_bus *bus);
 
 	int		(*probe)(int platform);
 	void		(*setup_arch)(void);

_




More information about the Linuxppc64-dev mailing list