aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Rose <johnrose@austin.ibm.com>2005-06-23 03:09:54 -0400
committerPaul Mackerras <paulus@samba.org>2005-06-23 03:09:54 -0400
commitdad32bbf43b496bcd32a83f73a1e7fd0a02cfd3e (patch)
tree4be484d37e792c95815c74dda3b6d4968a979cfe
parent8f586b2243198194240626fd9695da5564ffa7ee (diff)
[PATCH] pSeries - read irqs dynamically
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. Signed-off-by: John Rose <johnrose@austin.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/ppc64/kernel/pSeries_pci.c35
-rw-r--r--arch/ppc64/kernel/pSeries_setup.c3
-rw-r--r--arch/ppc64/kernel/pci.c3
-rw-r--r--arch/ppc64/kernel/pci.h6
-rw-r--r--include/asm-ppc64/machdep.h1
5 files changed, 30 insertions, 18 deletions
diff --git a/arch/ppc64/kernel/pSeries_pci.c b/arch/ppc64/kernel/pSeries_pci.c
index dfa6d3d3e9f0..1f5f141fb7a1 100644
--- a/arch/ppc64/kernel/pSeries_pci.c
+++ b/arch/ppc64/kernel/pSeries_pci.c
@@ -32,7 +32,7 @@
32 32
33#include "pci.h" 33#include "pci.h"
34 34
35static int __initdata s7a_workaround; 35static int __initdata s7a_workaround = -1;
36 36
37#if 0 37#if 0
38void pcibios_name_device(struct pci_dev *dev) 38void pcibios_name_device(struct pci_dev *dev)
@@ -65,6 +65,7 @@ static void __init check_s7a(void)
65 struct device_node *root; 65 struct device_node *root;
66 char *model; 66 char *model;
67 67
68 s7a_workaround = 0;
68 root = of_find_node_by_path("/"); 69 root = of_find_node_by_path("/");
69 if (root) { 70 if (root) {
70 model = get_property(root, "model", NULL); 71 model = get_property(root, "model", NULL);
@@ -74,6 +75,24 @@ static void __init check_s7a(void)
74 } 75 }
75} 76}
76 77
78void __devinit pSeries_irq_bus_setup(struct pci_bus *bus)
79{
80 struct pci_dev *dev;
81
82 if (s7a_workaround < 0)
83 check_s7a();
84 list_for_each_entry(dev, &bus->devices, bus_list) {
85 pci_read_irq_line(dev);
86 if (s7a_workaround) {
87 if (dev->irq > 16) {
88 dev->irq -= 3;
89 pci_write_config_byte(dev, PCI_INTERRUPT_LINE,
90 dev->irq);
91 }
92 }
93 }
94}
95
77static void __init pSeries_request_regions(void) 96static void __init pSeries_request_regions(void)
78{ 97{
79 if (!isa_io_base) 98 if (!isa_io_base)
@@ -89,20 +108,6 @@ static void __init pSeries_request_regions(void)
89 108
90void __init pSeries_final_fixup(void) 109void __init pSeries_final_fixup(void)
91{ 110{
92 struct pci_dev *dev = NULL;
93
94 check_s7a();
95
96 for_each_pci_dev(dev) {
97 pci_read_irq_line(dev);
98 if (s7a_workaround) {
99 if (dev->irq > 16) {
100 dev->irq -= 3;
101 pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
102 }
103 }
104 }
105
106 phbs_remap_io(); 111 phbs_remap_io();
107 pSeries_request_regions(); 112 pSeries_request_regions();
108 113
diff --git a/arch/ppc64/kernel/pSeries_setup.c b/arch/ppc64/kernel/pSeries_setup.c
index 41e6de2c9158..f2b41243342c 100644
--- a/arch/ppc64/kernel/pSeries_setup.c
+++ b/arch/ppc64/kernel/pSeries_setup.c
@@ -71,8 +71,6 @@
71#define DBG(fmt...) 71#define DBG(fmt...)
72#endif 72#endif
73 73
74extern void pSeries_final_fixup(void);
75
76extern void find_udbg_vterm(void); 74extern void find_udbg_vterm(void);
77extern void system_reset_fwnmi(void); /* from head.S */ 75extern void system_reset_fwnmi(void); /* from head.S */
78extern void machine_check_fwnmi(void); /* from head.S */ 76extern void machine_check_fwnmi(void); /* from head.S */
@@ -425,6 +423,7 @@ struct machdep_calls __initdata pSeries_md = {
425 .get_cpuinfo = pSeries_get_cpuinfo, 423 .get_cpuinfo = pSeries_get_cpuinfo,
426 .log_error = pSeries_log_error, 424 .log_error = pSeries_log_error,
427 .pcibios_fixup = pSeries_final_fixup, 425 .pcibios_fixup = pSeries_final_fixup,
426 .irq_bus_setup = pSeries_irq_bus_setup,
428 .restart = rtas_restart, 427 .restart = rtas_restart,
429 .power_off = rtas_power_off, 428 .power_off = rtas_power_off,
430 .halt = rtas_halt, 429 .halt = rtas_halt,
diff --git a/arch/ppc64/kernel/pci.c b/arch/ppc64/kernel/pci.c
index 2bf0513f3eca..580676f87d23 100644
--- a/arch/ppc64/kernel/pci.c
+++ b/arch/ppc64/kernel/pci.c
@@ -902,6 +902,9 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus)
902 list_for_each_entry(dev, &bus->devices, bus_list) 902 list_for_each_entry(dev, &bus->devices, bus_list)
903 ppc_md.iommu_dev_setup(dev); 903 ppc_md.iommu_dev_setup(dev);
904 904
905 if (ppc_md.irq_bus_setup)
906 ppc_md.irq_bus_setup(bus);
907
905 if (!pci_probe_only) 908 if (!pci_probe_only)
906 return; 909 return;
907 910
diff --git a/arch/ppc64/kernel/pci.h b/arch/ppc64/kernel/pci.h
index 0fd7d849aa77..26be78b13af1 100644
--- a/arch/ppc64/kernel/pci.h
+++ b/arch/ppc64/kernel/pci.h
@@ -40,10 +40,14 @@ struct device_node *fetch_dev_dn(struct pci_dev *dev);
40void pci_addr_cache_insert_device(struct pci_dev *dev); 40void pci_addr_cache_insert_device(struct pci_dev *dev);
41void pci_addr_cache_remove_device(struct pci_dev *dev); 41void pci_addr_cache_remove_device(struct pci_dev *dev);
42 42
43/* From pSeries_pci.h */ 43/* From rtas_pci.h */
44void init_pci_config_tokens (void); 44void init_pci_config_tokens (void);
45unsigned long get_phb_buid (struct device_node *); 45unsigned long get_phb_buid (struct device_node *);
46 46
47/* From pSeries_pci.h */
48extern void pSeries_final_fixup(void);
49extern void pSeries_irq_bus_setup(struct pci_bus *bus);
50
47extern unsigned long pci_probe_only; 51extern unsigned long pci_probe_only;
48extern unsigned long pci_assign_all_buses; 52extern unsigned long pci_assign_all_buses;
49extern int pci_read_irq_line(struct pci_dev *pci_dev); 53extern int pci_read_irq_line(struct pci_dev *pci_dev);
diff --git a/include/asm-ppc64/machdep.h b/include/asm-ppc64/machdep.h
index 5d3cd9d042e2..553b2ea23bed 100644
--- a/include/asm-ppc64/machdep.h
+++ b/include/asm-ppc64/machdep.h
@@ -76,6 +76,7 @@ struct machdep_calls {
76 void (*tce_flush)(struct iommu_table *tbl); 76 void (*tce_flush)(struct iommu_table *tbl);
77 void (*iommu_dev_setup)(struct pci_dev *dev); 77 void (*iommu_dev_setup)(struct pci_dev *dev);
78 void (*iommu_bus_setup)(struct pci_bus *bus); 78 void (*iommu_bus_setup)(struct pci_bus *bus);
79 void (*irq_bus_setup)(struct pci_bus *bus);
79 80
80 int (*probe)(int platform); 81 int (*probe)(int platform);
81 void (*setup_arch)(void); 82 void (*setup_arch)(void);