diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/Makefile | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 19 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_cache.c | 5 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_driver.c | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh_sysfs.c | 87 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 17 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pci_dlpar.c | 9 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/plpar_wrappers.h | 15 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pseries.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 53 |
12 files changed, 177 insertions, 42 deletions
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index ae1fc92dc1c9..992ba6753cf2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -8,7 +8,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | |||
8 | obj-$(CONFIG_SMP) += smp.o | 8 | obj-$(CONFIG_SMP) += smp.o |
9 | obj-$(CONFIG_XICS) += xics.o | 9 | obj-$(CONFIG_XICS) += xics.o |
10 | obj-$(CONFIG_SCANLOG) += scanlog.o | 10 | obj-$(CONFIG_SCANLOG) += scanlog.o |
11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o | 11 | obj-$(CONFIG_EEH) += eeh.o eeh_cache.o eeh_driver.o eeh_event.o eeh_sysfs.o |
12 | obj-$(CONFIG_KEXEC) += kexec.o | 12 | obj-$(CONFIG_KEXEC) += kexec.o |
13 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o | 13 | obj-$(CONFIG_PCI) += pci.o pci_dlpar.o |
14 | obj-$(CONFIG_PCI_MSI) += msi.o | 14 | obj-$(CONFIG_PCI_MSI) += msi.o |
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 5f3e6d8659fe..b8770395013d 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c | |||
@@ -1,6 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * eeh.c | 2 | * eeh.c |
3 | * Copyright (C) 2001 Dave Engebretsen & Todd Inglett IBM Corporation | 3 | * Copyright IBM Corporation 2001, 2005, 2006 |
4 | * Copyright Dave Engebretsen & Todd Inglett 2001 | ||
5 | * Copyright Linas Vepstas 2005, 2006 | ||
4 | * | 6 | * |
5 | * This program is free software; you can redistribute it and/or modify | 7 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by | 8 | * it under the terms of the GNU General Public License as published by |
@@ -15,6 +17,8 @@ | |||
15 | * You should have received a copy of the GNU General Public License | 17 | * You should have received a copy of the GNU General Public License |
16 | * along with this program; if not, write to the Free Software | 18 | * along with this program; if not, write to the Free Software |
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
20 | * | ||
21 | * Please address comments and feedback to Linas Vepstas <linas@austin.ibm.com> | ||
18 | */ | 22 | */ |
19 | 23 | ||
20 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
@@ -117,7 +121,6 @@ static unsigned long no_cfg_addr; | |||
117 | static unsigned long ignored_check; | 121 | static unsigned long ignored_check; |
118 | static unsigned long total_mmio_ffs; | 122 | static unsigned long total_mmio_ffs; |
119 | static unsigned long false_positives; | 123 | static unsigned long false_positives; |
120 | static unsigned long ignored_failures; | ||
121 | static unsigned long slot_resets; | 124 | static unsigned long slot_resets; |
122 | 125 | ||
123 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) | 126 | #define IS_BRIDGE(class_code) (((class_code)<<16) == PCI_BASE_CLASS_BRIDGE) |
@@ -505,6 +508,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
505 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", | 508 | printk(KERN_WARNING "EEH: read_slot_reset_state() failed; rc=%d dn=%s\n", |
506 | ret, dn->full_name); | 509 | ret, dn->full_name); |
507 | false_positives++; | 510 | false_positives++; |
511 | pdn->eeh_false_positives ++; | ||
508 | rc = 0; | 512 | rc = 0; |
509 | goto dn_unlock; | 513 | goto dn_unlock; |
510 | } | 514 | } |
@@ -513,6 +517,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
513 | * they are empty when they don't have children. */ | 517 | * they are empty when they don't have children. */ |
514 | if ((rets[0] == 5) && (dn->child == NULL)) { | 518 | if ((rets[0] == 5) && (dn->child == NULL)) { |
515 | false_positives++; | 519 | false_positives++; |
520 | pdn->eeh_false_positives ++; | ||
516 | rc = 0; | 521 | rc = 0; |
517 | goto dn_unlock; | 522 | goto dn_unlock; |
518 | } | 523 | } |
@@ -522,6 +527,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
522 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", | 527 | printk(KERN_WARNING "EEH: event on unsupported device, rc=%d dn=%s\n", |
523 | ret, dn->full_name); | 528 | ret, dn->full_name); |
524 | false_positives++; | 529 | false_positives++; |
530 | pdn->eeh_false_positives ++; | ||
525 | rc = 0; | 531 | rc = 0; |
526 | goto dn_unlock; | 532 | goto dn_unlock; |
527 | } | 533 | } |
@@ -529,6 +535,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) | |||
529 | /* If not the kind of error we know about, punt. */ | 535 | /* If not the kind of error we know about, punt. */ |
530 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { | 536 | if (rets[0] != 1 && rets[0] != 2 && rets[0] != 4 && rets[0] != 5) { |
531 | false_positives++; | 537 | false_positives++; |
538 | pdn->eeh_false_positives ++; | ||
532 | rc = 0; | 539 | rc = 0; |
533 | goto dn_unlock; | 540 | goto dn_unlock; |
534 | } | 541 | } |
@@ -921,6 +928,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data) | |||
921 | pdn->eeh_mode = 0; | 928 | pdn->eeh_mode = 0; |
922 | pdn->eeh_check_count = 0; | 929 | pdn->eeh_check_count = 0; |
923 | pdn->eeh_freeze_count = 0; | 930 | pdn->eeh_freeze_count = 0; |
931 | pdn->eeh_false_positives = 0; | ||
924 | 932 | ||
925 | if (status && strcmp(status, "ok") != 0) | 933 | if (status && strcmp(status, "ok") != 0) |
926 | return NULL; /* ignore devices with bad status */ | 934 | return NULL; /* ignore devices with bad status */ |
@@ -1139,7 +1147,8 @@ static void eeh_add_device_late(struct pci_dev *dev) | |||
1139 | pdn = PCI_DN(dn); | 1147 | pdn = PCI_DN(dn); |
1140 | pdn->pcidev = dev; | 1148 | pdn->pcidev = dev; |
1141 | 1149 | ||
1142 | pci_addr_cache_insert_device (dev); | 1150 | pci_addr_cache_insert_device(dev); |
1151 | eeh_sysfs_add_device(dev); | ||
1143 | } | 1152 | } |
1144 | 1153 | ||
1145 | void eeh_add_device_tree_late(struct pci_bus *bus) | 1154 | void eeh_add_device_tree_late(struct pci_bus *bus) |
@@ -1178,6 +1187,7 @@ static void eeh_remove_device(struct pci_dev *dev) | |||
1178 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); | 1187 | printk(KERN_DEBUG "EEH: remove device %s\n", pci_name(dev)); |
1179 | #endif | 1188 | #endif |
1180 | pci_addr_cache_remove_device(dev); | 1189 | pci_addr_cache_remove_device(dev); |
1190 | eeh_sysfs_remove_device(dev); | ||
1181 | 1191 | ||
1182 | dn = pci_device_to_OF_node(dev); | 1192 | dn = pci_device_to_OF_node(dev); |
1183 | if (PCI_DN(dn)->pcidev) { | 1193 | if (PCI_DN(dn)->pcidev) { |
@@ -1214,11 +1224,10 @@ static int proc_eeh_show(struct seq_file *m, void *v) | |||
1214 | "check not wanted=%ld\n" | 1224 | "check not wanted=%ld\n" |
1215 | "eeh_total_mmio_ffs=%ld\n" | 1225 | "eeh_total_mmio_ffs=%ld\n" |
1216 | "eeh_false_positives=%ld\n" | 1226 | "eeh_false_positives=%ld\n" |
1217 | "eeh_ignored_failures=%ld\n" | ||
1218 | "eeh_slot_resets=%ld\n", | 1227 | "eeh_slot_resets=%ld\n", |
1219 | no_device, no_dn, no_cfg_addr, | 1228 | no_device, no_dn, no_cfg_addr, |
1220 | ignored_check, total_mmio_ffs, | 1229 | ignored_check, total_mmio_ffs, |
1221 | false_positives, ignored_failures, | 1230 | false_positives, |
1222 | slot_resets); | 1231 | slot_resets); |
1223 | } | 1232 | } |
1224 | 1233 | ||
diff --git a/arch/powerpc/platforms/pseries/eeh_cache.c b/arch/powerpc/platforms/pseries/eeh_cache.c index f2bae04424f8..e49c815eae23 100644 --- a/arch/powerpc/platforms/pseries/eeh_cache.c +++ b/arch/powerpc/platforms/pseries/eeh_cache.c | |||
@@ -2,7 +2,8 @@ | |||
2 | * eeh_cache.c | 2 | * eeh_cache.c |
3 | * PCI address cache; allows the lookup of PCI devices based on I/O address | 3 | * PCI address cache; allows the lookup of PCI devices based on I/O address |
4 | * | 4 | * |
5 | * Copyright (C) 2004 Linas Vepstas <linas@austin.ibm.com> IBM Corporation | 5 | * Copyright IBM Corporation 2004 |
6 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2004 | ||
6 | * | 7 | * |
7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
8 | * it under the terms of the GNU General Public License as published by | 9 | * it under the terms of the GNU General Public License as published by |
@@ -295,6 +296,8 @@ void __init pci_addr_cache_build(void) | |||
295 | continue; | 296 | continue; |
296 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ | 297 | pci_dev_get (dev); /* matching put is in eeh_remove_device() */ |
297 | PCI_DN(dn)->pcidev = dev; | 298 | PCI_DN(dn)->pcidev = dev; |
299 | |||
300 | eeh_sysfs_add_device(dev); | ||
298 | } | 301 | } |
299 | 302 | ||
300 | #ifdef DEBUG | 303 | #ifdef DEBUG |
diff --git a/arch/powerpc/platforms/pseries/eeh_driver.c b/arch/powerpc/platforms/pseries/eeh_driver.c index 161a5844ab6c..15e015ef6865 100644 --- a/arch/powerpc/platforms/pseries/eeh_driver.c +++ b/arch/powerpc/platforms/pseries/eeh_driver.c | |||
@@ -1,6 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * PCI Error Recovery Driver for RPA-compliant PPC64 platform. | 2 | * PCI Error Recovery Driver for RPA-compliant PPC64 platform. |
3 | * Copyright (C) 2004, 2005 Linas Vepstas <linas@linas.org> | 3 | * Copyright IBM Corp. 2004 2005 |
4 | * Copyright Linas Vepstas <linas@linas.org> 2004, 2005 | ||
4 | * | 5 | * |
5 | * All rights reserved. | 6 | * All rights reserved. |
6 | * | 7 | * |
@@ -19,8 +20,7 @@ | |||
19 | * along with this program; if not, write to the Free Software | 20 | * along with this program; if not, write to the Free Software |
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
21 | * | 22 | * |
22 | * Send feedback to <linas@us.ibm.com> | 23 | * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com> |
23 | * | ||
24 | */ | 24 | */ |
25 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
diff --git a/arch/powerpc/platforms/pseries/eeh_sysfs.c b/arch/powerpc/platforms/pseries/eeh_sysfs.c new file mode 100644 index 000000000000..15e13b568904 --- /dev/null +++ b/arch/powerpc/platforms/pseries/eeh_sysfs.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Sysfs entries for PCI Error Recovery for PAPR-compliant platform. | ||
3 | * Copyright IBM Corporation 2007 | ||
4 | * Copyright Linas Vepstas <linas@austin.ibm.com> 2007 | ||
5 | * | ||
6 | * All rights reserved. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License as published by | ||
10 | * the Free Software Foundation; either version 2 of the License, or (at | ||
11 | * your option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, but | ||
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
16 | * NON INFRINGEMENT. See the GNU General Public License for more | ||
17 | * details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | * | ||
23 | * Send comments and feedback to Linas Vepstas <linas@austin.ibm.com> | ||
24 | */ | ||
25 | #include <linux/pci.h> | ||
26 | #include <asm/ppc-pci.h> | ||
27 | #include <asm/pci-bridge.h> | ||
28 | #include <linux/kobject.h> | ||
29 | |||
30 | /** | ||
31 | * EEH_SHOW_ATTR -- create sysfs entry for eeh statistic | ||
32 | * @_name: name of file in sysfs directory | ||
33 | * @_memb: name of member in struct pci_dn to access | ||
34 | * @_format: printf format for display | ||
35 | * | ||
36 | * All of the attributes look very similar, so just | ||
37 | * auto-gen a cut-n-paste routine to display them. | ||
38 | */ | ||
39 | #define EEH_SHOW_ATTR(_name,_memb,_format) \ | ||
40 | static ssize_t eeh_show_##_name(struct device *dev, \ | ||
41 | struct device_attribute *attr, char *buf) \ | ||
42 | { \ | ||
43 | struct pci_dev *pdev = to_pci_dev(dev); \ | ||
44 | struct device_node *dn = pci_device_to_OF_node(pdev); \ | ||
45 | struct pci_dn *pdn; \ | ||
46 | \ | ||
47 | if (!dn || PCI_DN(dn) == NULL) \ | ||
48 | return 0; \ | ||
49 | \ | ||
50 | pdn = PCI_DN(dn); \ | ||
51 | return sprintf(buf, _format "\n", pdn->_memb); \ | ||
52 | } \ | ||
53 | static DEVICE_ATTR(_name, S_IRUGO, eeh_show_##_name, NULL); | ||
54 | |||
55 | |||
56 | EEH_SHOW_ATTR(eeh_mode, eeh_mode, "0x%x"); | ||
57 | EEH_SHOW_ATTR(eeh_config_addr, eeh_config_addr, "0x%x"); | ||
58 | EEH_SHOW_ATTR(eeh_pe_config_addr, eeh_pe_config_addr, "0x%x"); | ||
59 | EEH_SHOW_ATTR(eeh_check_count, eeh_check_count, "%d"); | ||
60 | EEH_SHOW_ATTR(eeh_freeze_count, eeh_freeze_count, "%d"); | ||
61 | EEH_SHOW_ATTR(eeh_false_positives, eeh_false_positives, "%d"); | ||
62 | |||
63 | void eeh_sysfs_add_device(struct pci_dev *pdev) | ||
64 | { | ||
65 | int rc=0; | ||
66 | |||
67 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_mode); | ||
68 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_config_addr); | ||
69 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | ||
70 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_check_count); | ||
71 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_false_positives); | ||
72 | rc += device_create_file(&pdev->dev, &dev_attr_eeh_freeze_count); | ||
73 | |||
74 | if (rc) | ||
75 | printk(KERN_WARNING "EEH: Unable to create sysfs entries\n"); | ||
76 | } | ||
77 | |||
78 | void eeh_sysfs_remove_device(struct pci_dev *pdev) | ||
79 | { | ||
80 | device_remove_file(&pdev->dev, &dev_attr_eeh_mode); | ||
81 | device_remove_file(&pdev->dev, &dev_attr_eeh_config_addr); | ||
82 | device_remove_file(&pdev->dev, &dev_attr_eeh_pe_config_addr); | ||
83 | device_remove_file(&pdev->dev, &dev_attr_eeh_check_count); | ||
84 | device_remove_file(&pdev->dev, &dev_attr_eeh_false_positives); | ||
85 | device_remove_file(&pdev->dev, &dev_attr_eeh_freeze_count); | ||
86 | } | ||
87 | |||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 362dfbc260a6..8cc6eeeaae2f 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -373,12 +373,23 @@ static void pSeries_lpar_hptab_clear(void) | |||
373 | { | 373 | { |
374 | unsigned long size_bytes = 1UL << ppc64_pft_size; | 374 | unsigned long size_bytes = 1UL << ppc64_pft_size; |
375 | unsigned long hpte_count = size_bytes >> 4; | 375 | unsigned long hpte_count = size_bytes >> 4; |
376 | unsigned long dummy1, dummy2; | 376 | unsigned long dummy1, dummy2, dword0; |
377 | long lpar_rc; | ||
377 | int i; | 378 | int i; |
378 | 379 | ||
379 | /* TODO: Use bulk call */ | 380 | /* TODO: Use bulk call */ |
380 | for (i = 0; i < hpte_count; i++) | 381 | for (i = 0; i < hpte_count; i++) { |
381 | plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); | 382 | /* dont remove HPTEs with VRMA mappings */ |
383 | lpar_rc = plpar_pte_remove_raw(H_ANDCOND, i, HPTE_V_1TB_SEG, | ||
384 | &dummy1, &dummy2); | ||
385 | if (lpar_rc == H_NOT_FOUND) { | ||
386 | lpar_rc = plpar_pte_read_raw(0, i, &dword0, &dummy1); | ||
387 | if (!lpar_rc && ((dword0 & HPTE_V_VRMA_MASK) | ||
388 | != HPTE_V_VRMA_MASK)) | ||
389 | /* Can be hpte for 1TB Seg. So remove it */ | ||
390 | plpar_pte_remove_raw(0, i, 0, &dummy1, &dummy2); | ||
391 | } | ||
392 | } | ||
382 | } | 393 | } |
383 | 394 | ||
384 | /* | 395 | /* |
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index ffaf6c5c517b..47f0e0857f0e 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -110,8 +110,6 @@ pcibios_fixup_new_pci_devices(struct pci_bus *bus, int fix_bus) | |||
110 | } | 110 | } |
111 | } | 111 | } |
112 | } | 112 | } |
113 | |||
114 | eeh_add_device_tree_late(bus); | ||
115 | } | 113 | } |
116 | EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); | 114 | EXPORT_SYMBOL_GPL(pcibios_fixup_new_pci_devices); |
117 | 115 | ||
@@ -139,6 +137,8 @@ pcibios_pci_config_bridge(struct pci_dev *dev) | |||
139 | 137 | ||
140 | /* Make the discovered devices available */ | 138 | /* Make the discovered devices available */ |
141 | pci_bus_add_devices(child_bus); | 139 | pci_bus_add_devices(child_bus); |
140 | |||
141 | eeh_add_device_tree_late(child_bus); | ||
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | 144 | ||
@@ -171,6 +171,7 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
171 | if (!list_empty(&bus->devices)) { | 171 | if (!list_empty(&bus->devices)) { |
172 | pcibios_fixup_new_pci_devices(bus, 0); | 172 | pcibios_fixup_new_pci_devices(bus, 0); |
173 | pci_bus_add_devices(bus); | 173 | pci_bus_add_devices(bus); |
174 | eeh_add_device_tree_late(bus); | ||
174 | } | 175 | } |
175 | } else if (mode == PCI_PROBE_NORMAL) { | 176 | } else if (mode == PCI_PROBE_NORMAL) { |
176 | /* use legacy probe */ | 177 | /* use legacy probe */ |
@@ -179,6 +180,7 @@ pcibios_add_pci_devices(struct pci_bus * bus) | |||
179 | if (num) { | 180 | if (num) { |
180 | pcibios_fixup_new_pci_devices(bus, 1); | 181 | pcibios_fixup_new_pci_devices(bus, 1); |
181 | pci_bus_add_devices(bus); | 182 | pci_bus_add_devices(bus); |
183 | eeh_add_device_tree_late(bus); | ||
182 | } | 184 | } |
183 | 185 | ||
184 | list_for_each_entry(dev, &bus->devices, bus_list) | 186 | list_for_each_entry(dev, &bus->devices, bus_list) |
@@ -200,8 +202,6 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
200 | rtas_setup_phb(phb); | 202 | rtas_setup_phb(phb); |
201 | pci_process_bridge_OF_ranges(phb, dn, 0); | 203 | pci_process_bridge_OF_ranges(phb, dn, 0); |
202 | 204 | ||
203 | pci_setup_phb_io_dynamic(phb, primary); | ||
204 | |||
205 | pci_devs_phb_init_dynamic(phb); | 205 | pci_devs_phb_init_dynamic(phb); |
206 | 206 | ||
207 | if (dn->child) | 207 | if (dn->child) |
@@ -210,6 +210,7 @@ struct pci_controller * __devinit init_phb_dynamic(struct device_node *dn) | |||
210 | scan_phb(phb); | 210 | scan_phb(phb); |
211 | pcibios_fixup_new_pci_devices(phb->bus, 0); | 211 | pcibios_fixup_new_pci_devices(phb->bus, 0); |
212 | pci_bus_add_devices(phb->bus); | 212 | pci_bus_add_devices(phb->bus); |
213 | eeh_add_device_tree_late(phb->bus); | ||
213 | 214 | ||
214 | return phb; | 215 | return phb; |
215 | } | 216 | } |
diff --git a/arch/powerpc/platforms/pseries/plpar_wrappers.h b/arch/powerpc/platforms/pseries/plpar_wrappers.h index 2e4d10c9eea8..d003c80fa31d 100644 --- a/arch/powerpc/platforms/pseries/plpar_wrappers.h +++ b/arch/powerpc/platforms/pseries/plpar_wrappers.h | |||
@@ -108,6 +108,21 @@ static inline long plpar_pte_read(unsigned long flags, unsigned long ptex, | |||
108 | return rc; | 108 | return rc; |
109 | } | 109 | } |
110 | 110 | ||
111 | /* plpar_pte_read_raw can be called in real mode. It calls plpar_hcall_raw */ | ||
112 | static inline long plpar_pte_read_raw(unsigned long flags, unsigned long ptex, | ||
113 | unsigned long *old_pteh_ret, unsigned long *old_ptel_ret) | ||
114 | { | ||
115 | long rc; | ||
116 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
117 | |||
118 | rc = plpar_hcall_raw(H_READ, retbuf, flags, ptex); | ||
119 | |||
120 | *old_pteh_ret = retbuf[0]; | ||
121 | *old_ptel_ret = retbuf[1]; | ||
122 | |||
123 | return rc; | ||
124 | } | ||
125 | |||
111 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, | 126 | static inline long plpar_pte_protect(unsigned long flags, unsigned long ptex, |
112 | unsigned long avpn) | 127 | unsigned long avpn) |
113 | { | 128 | { |
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 2729d559fd91..61e19f78b923 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -33,6 +33,8 @@ static inline void setup_kexec_cpu_down_xics(void) { } | |||
33 | static inline void setup_kexec_cpu_down_mpic(void) { } | 33 | static inline void setup_kexec_cpu_down_mpic(void) { } |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | extern void pSeries_final_fixup(void); | ||
37 | |||
36 | /* Poweron flag used for enabling auto ups restart */ | 38 | /* Poweron flag used for enabling auto ups restart */ |
37 | extern unsigned long rtas_poweron_auto; | 39 | extern unsigned long rtas_poweron_auto; |
38 | 40 | ||
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 5aa97aff3391..c02f8742c54d 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -123,7 +123,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist | |||
123 | strcpy(np->full_name, path); | 123 | strcpy(np->full_name, path); |
124 | 124 | ||
125 | np->properties = proplist; | 125 | np->properties = proplist; |
126 | OF_MARK_DYNAMIC(np); | 126 | of_node_set_flag(np, OF_DYNAMIC); |
127 | kref_init(&np->kref); | 127 | kref_init(&np->kref); |
128 | 128 | ||
129 | np->parent = derive_parent(path); | 129 | np->parent = derive_parent(path); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index 470db6efaeb6..de6c2efd0479 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -399,6 +399,7 @@ static void pseries_dedicated_idle_sleep(void) | |||
399 | * a good time to find other work to dispatch. | 399 | * a good time to find other work to dispatch. |
400 | */ | 400 | */ |
401 | get_lppaca()->idle = 1; | 401 | get_lppaca()->idle = 1; |
402 | get_lppaca()->donate_dedicated_cpu = 1; | ||
402 | 403 | ||
403 | /* | 404 | /* |
404 | * We come in with interrupts disabled, and need_resched() | 405 | * We come in with interrupts disabled, and need_resched() |
@@ -431,6 +432,7 @@ static void pseries_dedicated_idle_sleep(void) | |||
431 | 432 | ||
432 | out: | 433 | out: |
433 | HMT_medium(); | 434 | HMT_medium(); |
435 | get_lppaca()->donate_dedicated_cpu = 0; | ||
434 | get_lppaca()->idle = 0; | 436 | get_lppaca()->idle = 0; |
435 | } | 437 | } |
436 | 438 | ||
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index f1df942072bb..5bd90a7eb763 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -156,9 +156,9 @@ static inline void lpar_qirr_info(int n_cpu , u8 value) | |||
156 | 156 | ||
157 | 157 | ||
158 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
159 | static int get_irq_server(unsigned int virq) | 159 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
160 | { | 160 | { |
161 | unsigned int server; | 161 | int server; |
162 | /* For the moment only implement delivery to all cpus or one cpu */ | 162 | /* For the moment only implement delivery to all cpus or one cpu */ |
163 | cpumask_t cpumask = irq_desc[virq].affinity; | 163 | cpumask_t cpumask = irq_desc[virq].affinity; |
164 | cpumask_t tmp = CPU_MASK_NONE; | 164 | cpumask_t tmp = CPU_MASK_NONE; |
@@ -166,22 +166,25 @@ static int get_irq_server(unsigned int virq) | |||
166 | if (!distribute_irqs) | 166 | if (!distribute_irqs) |
167 | return default_server; | 167 | return default_server; |
168 | 168 | ||
169 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 169 | if (!cpus_equal(cpumask, CPU_MASK_ALL)) { |
170 | server = default_distrib_server; | ||
171 | } else { | ||
172 | cpus_and(tmp, cpu_online_map, cpumask); | 170 | cpus_and(tmp, cpu_online_map, cpumask); |
173 | 171 | ||
174 | if (cpus_empty(tmp)) | 172 | server = first_cpu(tmp); |
175 | server = default_distrib_server; | 173 | |
176 | else | 174 | if (server < NR_CPUS) |
177 | server = get_hard_smp_processor_id(first_cpu(tmp)); | 175 | return get_hard_smp_processor_id(server); |
176 | |||
177 | if (strict_check) | ||
178 | return -1; | ||
178 | } | 179 | } |
179 | 180 | ||
180 | return server; | 181 | if (cpus_equal(cpu_online_map, cpu_present_map)) |
182 | return default_distrib_server; | ||
181 | 183 | ||
184 | return default_server; | ||
182 | } | 185 | } |
183 | #else | 186 | #else |
184 | static int get_irq_server(unsigned int virq) | 187 | static int get_irq_server(unsigned int virq, unsigned int strict_check) |
185 | { | 188 | { |
186 | return default_server; | 189 | return default_server; |
187 | } | 190 | } |
@@ -192,7 +195,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
192 | { | 195 | { |
193 | unsigned int irq; | 196 | unsigned int irq; |
194 | int call_status; | 197 | int call_status; |
195 | unsigned int server; | 198 | int server; |
196 | 199 | ||
197 | pr_debug("xics: unmask virq %d\n", virq); | 200 | pr_debug("xics: unmask virq %d\n", virq); |
198 | 201 | ||
@@ -201,7 +204,7 @@ static void xics_unmask_irq(unsigned int virq) | |||
201 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 204 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
202 | return; | 205 | return; |
203 | 206 | ||
204 | server = get_irq_server(virq); | 207 | server = get_irq_server(virq, 0); |
205 | 208 | ||
206 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, | 209 | call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server, |
207 | DEFAULT_PRIORITY); | 210 | DEFAULT_PRIORITY); |
@@ -398,8 +401,7 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
398 | unsigned int irq; | 401 | unsigned int irq; |
399 | int status; | 402 | int status; |
400 | int xics_status[2]; | 403 | int xics_status[2]; |
401 | unsigned long newmask; | 404 | int irq_server; |
402 | cpumask_t tmp = CPU_MASK_NONE; | ||
403 | 405 | ||
404 | irq = (unsigned int)irq_map[virq].hwirq; | 406 | irq = (unsigned int)irq_map[virq].hwirq; |
405 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) | 407 | if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS) |
@@ -413,18 +415,21 @@ static void xics_set_affinity(unsigned int virq, cpumask_t cpumask) | |||
413 | return; | 415 | return; |
414 | } | 416 | } |
415 | 417 | ||
416 | /* For the moment only implement delivery to all cpus or one cpu */ | 418 | /* |
417 | if (cpus_equal(cpumask, CPU_MASK_ALL)) { | 419 | * For the moment only implement delivery to all cpus or one cpu. |
418 | newmask = default_distrib_server; | 420 | * Get current irq_server for the given irq |
419 | } else { | 421 | */ |
420 | cpus_and(tmp, cpu_online_map, cpumask); | 422 | irq_server = get_irq_server(irq, 1); |
421 | if (cpus_empty(tmp)) | 423 | if (irq_server == -1) { |
422 | return; | 424 | char cpulist[128]; |
423 | newmask = get_hard_smp_processor_id(first_cpu(tmp)); | 425 | cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); |
426 | printk(KERN_WARNING "xics_set_affinity: No online cpus in " | ||
427 | "the mask %s for irq %d\n", cpulist, virq); | ||
428 | return; | ||
424 | } | 429 | } |
425 | 430 | ||
426 | status = rtas_call(ibm_set_xive, 3, 1, NULL, | 431 | status = rtas_call(ibm_set_xive, 3, 1, NULL, |
427 | irq, newmask, xics_status[1]); | 432 | irq, irq_server, xics_status[1]); |
428 | 433 | ||
429 | if (status) { | 434 | if (status) { |
430 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " | 435 | printk(KERN_ERR "xics_set_affinity: irq=%u ibm,set-xive " |