aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 19:54:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-12-28 19:54:33 -0500
commit3c92ec8ae91ecf59d88c798301833d7cf83f2179 (patch)
tree08a38cd3523c42bd49882f17cd501fd879e7ca1c /arch/powerpc/platforms/pseries
parentc4c9f0183b7c4e97836e8fecbb67898b06c47e78 (diff)
parentca9153a3a2a7556d091dfe080e42b0e67881fff6 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (144 commits) powerpc/44x: Support 16K/64K base page sizes on 44x powerpc: Force memory size to be a multiple of PAGE_SIZE powerpc/32: Wire up the trampoline code for kdump powerpc/32: Add the ability for a classic ppc kernel to be loaded at 32M powerpc/32: Allow __ioremap on RAM addresses for kdump kernel powerpc/32: Setup OF properties for kdump powerpc/32/kdump: Implement crash_setup_regs() using ppc_save_regs() powerpc: Prepare xmon_save_regs for use with kdump powerpc: Remove default kexec/crash_kernel ops assignments powerpc: Make default kexec/crash_kernel ops implicit powerpc: Setup OF properties for ppc32 kexec powerpc/pseries: Fix cpu hotplug powerpc: Fix KVM build on ppc440 powerpc/cell: add QPACE as a separate Cell platform powerpc/cell: fix build breakage with CONFIG_SPUFS disabled powerpc/mpc5200: fix error paths in PSC UART probe function powerpc/mpc5200: add rts/cts handling in PSC UART driver powerpc/mpc5200: Make PSC UART driver update serial errors counters powerpc/mpc5200: Remove obsolete code from mpc5200 MDIO driver powerpc/mpc5200: Add MDMA/UDMA support to MPC5200 ATA driver ... Fix trivial conflict in drivers/char/Makefile as per Paul's directions
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r--arch/powerpc/platforms/pseries/Kconfig2
-rw-r--r--arch/powerpc/platforms/pseries/cmm.c29
-rw-r--r--arch/powerpc/platforms/pseries/eeh.c44
-rw-r--r--arch/powerpc/platforms/pseries/hotplug-cpu.c2
-rw-r--r--arch/powerpc/platforms/pseries/pci_dlpar.c163
-rw-r--r--arch/powerpc/platforms/pseries/phyp_dump.c5
-rw-r--r--arch/powerpc/platforms/pseries/xics.c43
7 files changed, 174 insertions, 114 deletions
diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig
index 97619fd51e39..ddc2a307cd50 100644
--- a/arch/powerpc/platforms/pseries/Kconfig
+++ b/arch/powerpc/platforms/pseries/Kconfig
@@ -54,7 +54,7 @@ config PPC_SMLPAR
54 54
55config CMM 55config CMM
56 tristate "Collaborative memory management" 56 tristate "Collaborative memory management"
57 depends on PPC_SMLPAR 57 depends on PPC_SMLPAR && !CRASH_DUMP
58 default y 58 default y
59 help 59 help
60 Select this option, if you want to enable the kernel interface 60 Select this option, if you want to enable the kernel interface
diff --git a/arch/powerpc/platforms/pseries/cmm.c b/arch/powerpc/platforms/pseries/cmm.c
index 5cd4d2761620..6567439fe78d 100644
--- a/arch/powerpc/platforms/pseries/cmm.c
+++ b/arch/powerpc/platforms/pseries/cmm.c
@@ -28,6 +28,7 @@
28#include <linux/kthread.h> 28#include <linux/kthread.h>
29#include <linux/module.h> 29#include <linux/module.h>
30#include <linux/oom.h> 30#include <linux/oom.h>
31#include <linux/reboot.h>
31#include <linux/sched.h> 32#include <linux/sched.h>
32#include <linux/stringify.h> 33#include <linux/stringify.h>
33#include <linux/swap.h> 34#include <linux/swap.h>
@@ -384,6 +385,26 @@ static void cmm_unregister_sysfs(struct sys_device *sysdev)
384} 385}
385 386
386/** 387/**
388 * cmm_reboot_notifier - Make sure pages are not still marked as "loaned"
389 *
390 **/
391static int cmm_reboot_notifier(struct notifier_block *nb,
392 unsigned long action, void *unused)
393{
394 if (action == SYS_RESTART) {
395 if (cmm_thread_ptr)
396 kthread_stop(cmm_thread_ptr);
397 cmm_thread_ptr = NULL;
398 cmm_free_pages(loaned_pages);
399 }
400 return NOTIFY_DONE;
401}
402
403static struct notifier_block cmm_reboot_nb = {
404 .notifier_call = cmm_reboot_notifier,
405};
406
407/**
387 * cmm_init - Module initialization 408 * cmm_init - Module initialization
388 * 409 *
389 * Return value: 410 * Return value:
@@ -399,9 +420,12 @@ static int cmm_init(void)
399 if ((rc = register_oom_notifier(&cmm_oom_nb)) < 0) 420 if ((rc = register_oom_notifier(&cmm_oom_nb)) < 0)
400 return rc; 421 return rc;
401 422
402 if ((rc = cmm_sysfs_register(&cmm_sysdev))) 423 if ((rc = register_reboot_notifier(&cmm_reboot_nb)))
403 goto out_oom_notifier; 424 goto out_oom_notifier;
404 425
426 if ((rc = cmm_sysfs_register(&cmm_sysdev)))
427 goto out_reboot_notifier;
428
405 if (cmm_disabled) 429 if (cmm_disabled)
406 return rc; 430 return rc;
407 431
@@ -415,6 +439,8 @@ static int cmm_init(void)
415 439
416out_unregister_sysfs: 440out_unregister_sysfs:
417 cmm_unregister_sysfs(&cmm_sysdev); 441 cmm_unregister_sysfs(&cmm_sysdev);
442out_reboot_notifier:
443 unregister_reboot_notifier(&cmm_reboot_nb);
418out_oom_notifier: 444out_oom_notifier:
419 unregister_oom_notifier(&cmm_oom_nb); 445 unregister_oom_notifier(&cmm_oom_nb);
420 return rc; 446 return rc;
@@ -431,6 +457,7 @@ static void cmm_exit(void)
431 if (cmm_thread_ptr) 457 if (cmm_thread_ptr)
432 kthread_stop(cmm_thread_ptr); 458 kthread_stop(cmm_thread_ptr);
433 unregister_oom_notifier(&cmm_oom_nb); 459 unregister_oom_notifier(&cmm_oom_nb);
460 unregister_reboot_notifier(&cmm_reboot_nb);
434 cmm_free_pages(loaned_pages); 461 cmm_free_pages(loaned_pages);
435 cmm_unregister_sysfs(&cmm_sysdev); 462 cmm_unregister_sysfs(&cmm_sysdev);
436} 463}
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c
index 54816d75b578..989d6462c154 100644
--- a/arch/powerpc/platforms/pseries/eeh.c
+++ b/arch/powerpc/platforms/pseries/eeh.c
@@ -21,6 +21,8 @@
21 * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com> 21 * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com>
22 */ 22 */
23 23
24#undef DEBUG
25
24#include <linux/delay.h> 26#include <linux/delay.h>
25#include <linux/init.h> 27#include <linux/init.h>
26#include <linux/list.h> 28#include <linux/list.h>
@@ -488,10 +490,8 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
488 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) || 490 if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
489 pdn->eeh_mode & EEH_MODE_NOCHECK) { 491 pdn->eeh_mode & EEH_MODE_NOCHECK) {
490 ignored_check++; 492 ignored_check++;
491#ifdef DEBUG 493 pr_debug("EEH: Ignored check (%x) for %s %s\n",
492 printk ("EEH:ignored check (%x) for %s %s\n", 494 pdn->eeh_mode, pci_name (dev), dn->full_name);
493 pdn->eeh_mode, pci_name (dev), dn->full_name);
494#endif
495 return 0; 495 return 0;
496 } 496 }
497 497
@@ -1014,10 +1014,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
1014 eeh_subsystem_enabled = 1; 1014 eeh_subsystem_enabled = 1;
1015 pdn->eeh_mode |= EEH_MODE_SUPPORTED; 1015 pdn->eeh_mode |= EEH_MODE_SUPPORTED;
1016 1016
1017#ifdef DEBUG 1017 pr_debug("EEH: %s: eeh enabled, config=%x pe_config=%x\n",
1018 printk(KERN_DEBUG "EEH: %s: eeh enabled, config=%x pe_config=%x\n", 1018 dn->full_name, pdn->eeh_config_addr,
1019 dn->full_name, pdn->eeh_config_addr, pdn->eeh_pe_config_addr); 1019 pdn->eeh_pe_config_addr);
1020#endif
1021 } else { 1020 } else {
1022 1021
1023 /* This device doesn't support EEH, but it may have an 1022 /* This device doesn't support EEH, but it may have an
@@ -1161,13 +1160,17 @@ static void eeh_add_device_late(struct pci_dev *dev)
1161 if (!dev || !eeh_subsystem_enabled) 1160 if (!dev || !eeh_subsystem_enabled)
1162 return; 1161 return;
1163 1162
1164#ifdef DEBUG 1163 pr_debug("EEH: Adding device %s\n", pci_name(dev));
1165 printk(KERN_DEBUG "EEH: adding device %s\n", pci_name(dev));
1166#endif
1167 1164
1168 pci_dev_get (dev);
1169 dn = pci_device_to_OF_node(dev); 1165 dn = pci_device_to_OF_node(dev);
1170 pdn = PCI_DN(dn); 1166 pdn = PCI_DN(dn);
1167 if (pdn->pcidev == dev) {
1168 pr_debug("EEH: Already referenced !\n");
1169 return;
1170 }
1171 WARN_ON(pdn->pcidev);
1172
1173 pci_dev_get (dev);
1171 pdn->pcidev = dev; 1174 pdn->pcidev = dev;
1172 1175
1173 pci_addr_cache_insert_device(dev); 1176 pci_addr_cache_insert_device(dev);
@@ -1206,17 +1209,18 @@ static void eeh_remove_device(struct pci_dev *dev)
1206 return; 1209 return;
1207 1210
1208 /* Unregister the device with the EEH/PCI address search system */ 1211 /* Unregister the device with the EEH/PCI address search system */
1209#ifdef DEBUG 1212 pr_debug("EEH: Removing device %s\n", pci_name(dev));
1210 printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev));
1211#endif
1212 pci_addr_cache_remove_device(dev);
1213 eeh_sysfs_remove_device(dev);
1214 1213
1215 dn = pci_device_to_OF_node(dev); 1214 dn = pci_device_to_OF_node(dev);
1216 if (PCI_DN(dn)->pcidev) { 1215 if (PCI_DN(dn)->pcidev == NULL) {
1217 PCI_DN(dn)->pcidev = NULL; 1216 pr_debug("EEH: Not referenced !\n");
1218 pci_dev_put (dev); 1217 return;
1219 } 1218 }
1219 PCI_DN(dn)->pcidev = NULL;
1220 pci_dev_put (dev);
1221
1222 pci_addr_cache_remove_device(dev);
1223 eeh_sysfs_remove_device(dev);
1220} 1224}
1221 1225
1222void eeh_remove_bus_device(struct pci_dev *dev) 1226void eeh_remove_bus_device(struct pci_dev *dev)
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c
index 1f032483c026..a20ead87153d 100644
--- a/arch/powerpc/platforms/pseries/hotplug-cpu.c
+++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c
@@ -116,7 +116,7 @@ static void pseries_cpu_die(unsigned int cpu)
116 cpu_status = query_cpu_stopped(pcpu); 116 cpu_status = query_cpu_stopped(pcpu);
117 if (cpu_status == 0 || cpu_status == -1) 117 if (cpu_status == 0 || cpu_status == -1)
118 break; 118 break;
119 msleep(200); 119 cpu_relax();
120 } 120 }
121 if (cpu_status != 0) { 121 if (cpu_status != 0) {
122 printk("Querying DEAD? cpu %i (%i) shows %i\n", 122 printk("Querying DEAD? cpu %i (%i) shows %i\n",
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c
index 7190493e9bdc..5e1ed3d60ee5 100644
--- a/arch/powerpc/platforms/pseries/pci_dlpar.c
+++ b/arch/powerpc/platforms/pseries/pci_dlpar.c
@@ -25,6 +25,8 @@
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 */ 26 */
27 27
28#undef DEBUG
29
28#include <linux/pci.h> 30#include <linux/pci.h>
29#include <asm/pci-bridge.h> 31#include <asm/pci-bridge.h>
30#include <asm/ppc-pci.h> 32#include <asm/ppc-pci.h>
@@ -69,74 +71,25 @@ EXPORT_SYMBOL_GPL(pcibios_find_pci_bus);
69 * Remove all of the PCI devices under this bus both from the 71 * Remove all of the PCI devices under this bus both from the
70 * linux pci device tree, and from the powerpc EEH address cache. 72 * linux pci device tree, and from the powerpc EEH address cache.
71 */ 73 */
72void 74void pcibios_remove_pci_devices(struct pci_bus *bus)
73pcibios_remove_pci_devices(struct pci_bus *bus)
74{ 75{
75 struct pci_dev *dev, *tmp; 76 struct pci_dev *dev, *tmp;
77 struct pci_bus *child_bus;
78
79 /* First go down child busses */
80 list_for_each_entry(child_bus, &bus->children, node)
81 pcibios_remove_pci_devices(child_bus);
76 82
83 pr_debug("PCI: Removing devices on bus %04x:%02x\n",
84 pci_domain_nr(bus), bus->number);
77 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { 85 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
86 pr_debug(" * Removing %s...\n", pci_name(dev));
78 eeh_remove_bus_device(dev); 87 eeh_remove_bus_device(dev);
79 pci_remove_bus_device(dev); 88 pci_remove_bus_device(dev);
80 } 89 }
81} 90}
82EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices); 91EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
83 92
84/* Must be called before pci_bus_add_devices */
85void
86pcibios_fixup_new_pci_devices(struct pci_bus *bus)
87{
88 struct pci_dev *dev;
89
90 list_for_each_entry(dev, &bus->devices, bus_list) {
91 /* Skip already-added devices */
92 if (!dev->is_added) {
93 int i;
94
95 /* Fill device archdata and setup iommu table */
96 pcibios_setup_new_device(dev);
97
98 pci_read_irq_line(dev);
99 for (i = 0; i < PCI_NUM_RESOURCES; i++) {
100 struct resource *r = &dev->resource[i];
101
102 if (r->parent || !r->start || !r->flags)
103 continue;
104 pci_claim_resource(dev, i);
105 }
106 }
107 }
108}
109EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices);
110
111static int
112pcibios_pci_config_bridge(struct pci_dev *dev)
113{
114 u8 sec_busno;
115 struct pci_bus *child_bus;
116
117 /* Get busno of downstream bus */
118 pci_read_config_byte(dev, PCI_SECONDARY_BUS, &sec_busno);
119
120 /* Add to children of PCI bridge dev->bus */
121 child_bus = pci_add_new_bus(dev->bus, dev, sec_busno);
122 if (!child_bus) {
123 printk (KERN_ERR "%s: could not add second bus\n", __func__);
124 return -EIO;
125 }
126 sprintf(child_bus->name, "PCI Bus #%02x", child_bus->number);
127
128 pci_scan_child_bus(child_bus);
129
130 /* Fixup new pci devices */
131 pcibios_fixup_new_pci_devices(child_bus);
132
133 /* Make the discovered devices available */
134 pci_bus_add_devices(child_bus);
135
136 eeh_add_device_tree_late(child_bus);
137 return 0;
138}
139
140/** 93/**
141 * pcibios_add_pci_devices - adds new pci devices to bus 94 * pcibios_add_pci_devices - adds new pci devices to bus
142 * 95 *
@@ -147,10 +100,9 @@ pcibios_pci_config_bridge(struct pci_dev *dev)
147 * is how this routine differs from other, similar pcibios 100 * is how this routine differs from other, similar pcibios
148 * routines.) 101 * routines.)
149 */ 102 */
150void 103void pcibios_add_pci_devices(struct pci_bus * bus)
151pcibios_add_pci_devices(struct pci_bus * bus)
152{ 104{
153 int slotno, num, mode; 105 int slotno, num, mode, pass, max;
154 struct pci_dev *dev; 106 struct pci_dev *dev;
155 struct device_node *dn = pci_bus_to_OF_node(bus); 107 struct device_node *dn = pci_bus_to_OF_node(bus);
156 108
@@ -162,26 +114,23 @@ pcibios_add_pci_devices(struct pci_bus * bus)
162 114
163 if (mode == PCI_PROBE_DEVTREE) { 115 if (mode == PCI_PROBE_DEVTREE) {
164 /* use ofdt-based probe */ 116 /* use ofdt-based probe */
165 of_scan_bus(dn, bus); 117 of_rescan_bus(dn, bus);
166 if (!list_empty(&bus->devices)) {
167 pcibios_fixup_new_pci_devices(bus);
168 pci_bus_add_devices(bus);
169 eeh_add_device_tree_late(bus);
170 }
171 } else if (mode == PCI_PROBE_NORMAL) { 118 } else if (mode == PCI_PROBE_NORMAL) {
172 /* use legacy probe */ 119 /* use legacy probe */
173 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn); 120 slotno = PCI_SLOT(PCI_DN(dn->child)->devfn);
174 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0)); 121 num = pci_scan_slot(bus, PCI_DEVFN(slotno, 0));
175 if (num) { 122 if (!num)
176 pcibios_fixup_new_pci_devices(bus); 123 return;
177 pci_bus_add_devices(bus); 124 pcibios_setup_bus_devices(bus);
178 eeh_add_device_tree_late(bus); 125 max = bus->secondary;
126 for (pass=0; pass < 2; pass++)
127 list_for_each_entry(dev, &bus->devices, bus_list) {
128 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE ||
129 dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
130 max = pci_scan_bridge(bus, dev, max, pass);
179 } 131 }
180
181 list_for_each_entry(dev, &bus->devices, bus_list)
182 if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
183 pcibios_pci_config_bridge(dev);
184 } 132 }
133 pcibios_finish_adding_to_bus(bus);
185} 134}
186EXPORT_SYMBOL_GPL(pcibios_add_pci_devices); 135EXPORT_SYMBOL_GPL(pcibios_add_pci_devices);
187 136
@@ -190,6 +139,8 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
190 struct pci_controller *phb; 139 struct pci_controller *phb;
191 int primary; 140 int primary;
192 141
142 pr_debug("PCI: Initializing new hotplug PHB %s\n", dn->full_name);
143
193 primary = list_empty(&hose_list); 144 primary = list_empty(&hose_list);
194 phb = pcibios_alloc_controller(dn); 145 phb = pcibios_alloc_controller(dn);
195 if (!phb) 146 if (!phb)
@@ -203,11 +154,59 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn)
203 eeh_add_device_tree_early(dn); 154 eeh_add_device_tree_early(dn);
204 155
205 scan_phb(phb); 156 scan_phb(phb);
206 pcibios_allocate_bus_resources(phb->bus); 157 pcibios_finish_adding_to_bus(phb->bus);
207 pcibios_fixup_new_pci_devices(phb->bus);
208 pci_bus_add_devices(phb->bus);
209 eeh_add_device_tree_late(phb->bus);
210 158
211 return phb; 159 return phb;
212} 160}
213EXPORT_SYMBOL_GPL(init_phb_dynamic); 161EXPORT_SYMBOL_GPL(init_phb_dynamic);
162
163/* RPA-specific bits for removing PHBs */
164int remove_phb_dynamic(struct pci_controller *phb)
165{
166 struct pci_bus *b = phb->bus;
167 struct resource *res;
168 int rc, i;
169
170 pr_debug("PCI: Removing PHB %04x:%02x... \n",
171 pci_domain_nr(b), b->number);
172
173 /* We cannot to remove a root bus that has children */
174 if (!(list_empty(&b->children) && list_empty(&b->devices)))
175 return -EBUSY;
176
177 /* We -know- there aren't any child devices anymore at this stage
178 * and thus, we can safely unmap the IO space as it's not in use
179 */
180 res = &phb->io_resource;
181 if (res->flags & IORESOURCE_IO) {
182 rc = pcibios_unmap_io_space(b);
183 if (rc) {
184 printk(KERN_ERR "%s: failed to unmap IO on bus %s\n",
185 __func__, b->name);
186 return 1;
187 }
188 }
189
190 /* Unregister the bridge device from sysfs and remove the PCI bus */
191 device_unregister(b->bridge);
192 phb->bus = NULL;
193 pci_remove_bus(b);
194
195 /* Now release the IO resource */
196 if (res->flags & IORESOURCE_IO)
197 release_resource(res);
198
199 /* Release memory resources */
200 for (i = 0; i < 3; ++i) {
201 res = &phb->mem_resources[i];
202 if (!(res->flags & IORESOURCE_MEM))
203 continue;
204 release_resource(res);
205 }
206
207 /* Free pci_controller data structure */
208 pcibios_free_controller(phb);
209
210 return 0;
211}
212EXPORT_SYMBOL_GPL(remove_phb_dynamic);
diff --git a/arch/powerpc/platforms/pseries/phyp_dump.c b/arch/powerpc/platforms/pseries/phyp_dump.c
index edbc012c2ebc..6cf35cd8d0b5 100644
--- a/arch/powerpc/platforms/pseries/phyp_dump.c
+++ b/arch/powerpc/platforms/pseries/phyp_dump.c
@@ -130,6 +130,9 @@ static unsigned long init_dump_header(struct phyp_dump_header *ph)
130static void print_dump_header(const struct phyp_dump_header *ph) 130static void print_dump_header(const struct phyp_dump_header *ph)
131{ 131{
132#ifdef DEBUG 132#ifdef DEBUG
133 if (ph == NULL)
134 return;
135
133 printk(KERN_INFO "dump header:\n"); 136 printk(KERN_INFO "dump header:\n");
134 /* setup some ph->sections required */ 137 /* setup some ph->sections required */
135 printk(KERN_INFO "version = %d\n", ph->version); 138 printk(KERN_INFO "version = %d\n", ph->version);
@@ -411,6 +414,8 @@ static int __init phyp_dump_setup(void)
411 of_node_put(rtas); 414 of_node_put(rtas);
412 } 415 }
413 416
417 ibm_configure_kernel_dump = rtas_token("ibm,configure-kernel-dump");
418
414 print_dump_header(dump_header); 419 print_dump_header(dump_header);
415 dump_area_length = init_dump_header(&phdr); 420 dump_area_length = init_dump_header(&phdr);
416 /* align down */ 421 /* align down */
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index e1904774a70f..f7a69021b7bf 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -579,7 +579,7 @@ static void xics_update_irq_servers(void)
579 int i, j; 579 int i, j;
580 struct device_node *np; 580 struct device_node *np;
581 u32 ilen; 581 u32 ilen;
582 const u32 *ireg, *isize; 582 const u32 *ireg;
583 u32 hcpuid; 583 u32 hcpuid;
584 584
585 /* Find the server numbers for the boot cpu. */ 585 /* Find the server numbers for the boot cpu. */
@@ -607,11 +607,6 @@ static void xics_update_irq_servers(void)
607 } 607 }
608 } 608 }
609 609
610 /* get the bit size of server numbers */
611 isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
612 if (isize)
613 interrupt_server_size = *isize;
614
615 of_node_put(np); 610 of_node_put(np);
616} 611}
617 612
@@ -682,6 +677,7 @@ void __init xics_init_IRQ(void)
682 struct device_node *np; 677 struct device_node *np;
683 u32 indx = 0; 678 u32 indx = 0;
684 int found = 0; 679 int found = 0;
680 const u32 *isize;
685 681
686 ppc64_boot_msg(0x20, "XICS Init"); 682 ppc64_boot_msg(0x20, "XICS Init");
687 683
@@ -701,6 +697,26 @@ void __init xics_init_IRQ(void)
701 if (found == 0) 697 if (found == 0)
702 return; 698 return;
703 699
700 /* get the bit size of server numbers */
701 found = 0;
702
703 for_each_compatible_node(np, NULL, "ibm,ppc-xics") {
704 isize = of_get_property(np, "ibm,interrupt-server#-size", NULL);
705
706 if (!isize)
707 continue;
708
709 if (!found) {
710 interrupt_server_size = *isize;
711 found = 1;
712 } else if (*isize != interrupt_server_size) {
713 printk(KERN_WARNING "XICS: "
714 "mismatched ibm,interrupt-server#-size\n");
715 interrupt_server_size = max(*isize,
716 interrupt_server_size);
717 }
718 }
719
704 xics_update_irq_servers(); 720 xics_update_irq_servers();
705 xics_init_host(); 721 xics_init_host();
706 722
@@ -728,9 +744,18 @@ static void xics_set_cpu_priority(unsigned char cppr)
728/* Have the calling processor join or leave the specified global queue */ 744/* Have the calling processor join or leave the specified global queue */
729static void xics_set_cpu_giq(unsigned int gserver, unsigned int join) 745static void xics_set_cpu_giq(unsigned int gserver, unsigned int join)
730{ 746{
731 int status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, 747 int index;
732 (1UL << interrupt_server_size) - 1 - gserver, join); 748 int status;
733 WARN_ON(status < 0); 749
750 if (!rtas_indicator_present(GLOBAL_INTERRUPT_QUEUE, NULL))
751 return;
752
753 index = (1UL << interrupt_server_size) - 1 - gserver;
754
755 status = rtas_set_indicator_fast(GLOBAL_INTERRUPT_QUEUE, index, join);
756
757 WARN(status < 0, "set-indicator(%d, %d, %u) returned %d\n",
758 GLOBAL_INTERRUPT_QUEUE, index, join, status);
734} 759}
735 760
736void xics_setup_cpu(void) 761void xics_setup_cpu(void)