[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