diff options
Diffstat (limited to 'arch/powerpc/platforms')
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-ioda.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/eeh-powernv.c | 57 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 21 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/dlpar.c | 22 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hotplug-cpu.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 11 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/pseries.h | 3 |
8 files changed, 98 insertions, 24 deletions
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index 426814a2ede3..eba9cb10619c 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -373,7 +373,7 @@ static int ioda_eeh_get_pe_state(struct eeh_pe *pe) | |||
373 | * moving forward, we have to return operational | 373 | * moving forward, we have to return operational |
374 | * state during PE reset. | 374 | * state during PE reset. |
375 | */ | 375 | */ |
376 | if (pe->state & EEH_PE_RESET) { | 376 | if (pe->state & EEH_PE_CFG_BLOCKED) { |
377 | result = (EEH_STATE_MMIO_ACTIVE | | 377 | result = (EEH_STATE_MMIO_ACTIVE | |
378 | EEH_STATE_DMA_ACTIVE | | 378 | EEH_STATE_DMA_ACTIVE | |
379 | EEH_STATE_MMIO_ENABLED | | 379 | EEH_STATE_MMIO_ENABLED | |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 3e89cbf55885..1d19e7917d7f 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
@@ -169,6 +169,26 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
169 | } | 169 | } |
170 | 170 | ||
171 | /* | 171 | /* |
172 | * If the PE contains any one of following adapters, the | ||
173 | * PCI config space can't be accessed when dumping EEH log. | ||
174 | * Otherwise, we will run into fenced PHB caused by shortage | ||
175 | * of outbound credits in the adapter. The PCI config access | ||
176 | * should be blocked until PE reset. MMIO access is dropped | ||
177 | * by hardware certainly. In order to drop PCI config requests, | ||
178 | * one more flag (EEH_PE_CFG_RESTRICTED) is introduced, which | ||
179 | * will be checked in the backend for PE state retrival. If | ||
180 | * the PE becomes frozen for the first time and the flag has | ||
181 | * been set for the PE, we will set EEH_PE_CFG_BLOCKED for | ||
182 | * that PE to block its config space. | ||
183 | * | ||
184 | * Broadcom Austin 4-ports NICs (14e4:1657) | ||
185 | * Broadcom Shiner 2-ports 10G NICs (14e4:168e) | ||
186 | */ | ||
187 | if ((dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x1657) || | ||
188 | (dev->vendor == PCI_VENDOR_ID_BROADCOM && dev->device == 0x168e)) | ||
189 | edev->pe->state |= EEH_PE_CFG_RESTRICTED; | ||
190 | |||
191 | /* | ||
172 | * Cache the PE primary bus, which can't be fetched when | 192 | * Cache the PE primary bus, which can't be fetched when |
173 | * full hotplug is in progress. In that case, all child | 193 | * full hotplug is in progress. In that case, all child |
174 | * PCI devices of the PE are expected to be removed prior | 194 | * PCI devices of the PE are expected to be removed prior |
@@ -383,6 +403,39 @@ static int powernv_eeh_err_inject(struct eeh_pe *pe, int type, int func, | |||
383 | return ret; | 403 | return ret; |
384 | } | 404 | } |
385 | 405 | ||
406 | static inline bool powernv_eeh_cfg_blocked(struct device_node *dn) | ||
407 | { | ||
408 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); | ||
409 | |||
410 | if (!edev || !edev->pe) | ||
411 | return false; | ||
412 | |||
413 | if (edev->pe->state & EEH_PE_CFG_BLOCKED) | ||
414 | return true; | ||
415 | |||
416 | return false; | ||
417 | } | ||
418 | |||
419 | static int powernv_eeh_read_config(struct device_node *dn, | ||
420 | int where, int size, u32 *val) | ||
421 | { | ||
422 | if (powernv_eeh_cfg_blocked(dn)) { | ||
423 | *val = 0xFFFFFFFF; | ||
424 | return PCIBIOS_SET_FAILED; | ||
425 | } | ||
426 | |||
427 | return pnv_pci_cfg_read(dn, where, size, val); | ||
428 | } | ||
429 | |||
430 | static int powernv_eeh_write_config(struct device_node *dn, | ||
431 | int where, int size, u32 val) | ||
432 | { | ||
433 | if (powernv_eeh_cfg_blocked(dn)) | ||
434 | return PCIBIOS_SET_FAILED; | ||
435 | |||
436 | return pnv_pci_cfg_write(dn, where, size, val); | ||
437 | } | ||
438 | |||
386 | /** | 439 | /** |
387 | * powernv_eeh_next_error - Retrieve next EEH error to handle | 440 | * powernv_eeh_next_error - Retrieve next EEH error to handle |
388 | * @pe: Affected PE | 441 | * @pe: Affected PE |
@@ -440,8 +493,8 @@ static struct eeh_ops powernv_eeh_ops = { | |||
440 | .get_log = powernv_eeh_get_log, | 493 | .get_log = powernv_eeh_get_log, |
441 | .configure_bridge = powernv_eeh_configure_bridge, | 494 | .configure_bridge = powernv_eeh_configure_bridge, |
442 | .err_inject = powernv_eeh_err_inject, | 495 | .err_inject = powernv_eeh_err_inject, |
443 | .read_config = pnv_pci_cfg_read, | 496 | .read_config = powernv_eeh_read_config, |
444 | .write_config = pnv_pci_cfg_write, | 497 | .write_config = powernv_eeh_write_config, |
445 | .next_error = powernv_eeh_next_error, | 498 | .next_error = powernv_eeh_next_error, |
446 | .restore_config = powernv_eeh_restore_config | 499 | .restore_config = powernv_eeh_restore_config |
447 | }; | 500 | }; |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index b642b0562f5a..d019b081df9d 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -194,6 +194,27 @@ static int __init opal_register_exception_handlers(void) | |||
194 | * fwnmi area at 0x7000 to provide the glue space to OPAL | 194 | * fwnmi area at 0x7000 to provide the glue space to OPAL |
195 | */ | 195 | */ |
196 | glue = 0x7000; | 196 | glue = 0x7000; |
197 | |||
198 | /* | ||
199 | * Check if we are running on newer firmware that exports | ||
200 | * OPAL_HANDLE_HMI token. If yes, then don't ask OPAL to patch | ||
201 | * the HMI interrupt and we catch it directly in Linux. | ||
202 | * | ||
203 | * For older firmware (i.e currently released POWER8 System Firmware | ||
204 | * as of today <= SV810_087), we fallback to old behavior and let OPAL | ||
205 | * patch the HMI vector and handle it inside OPAL firmware. | ||
206 | * | ||
207 | * For newer firmware (in development/yet to be released) we will | ||
208 | * start catching/handling HMI directly in Linux. | ||
209 | */ | ||
210 | if (!opal_check_token(OPAL_HANDLE_HMI)) { | ||
211 | pr_info("opal: Old firmware detected, OPAL handles HMIs.\n"); | ||
212 | opal_register_exception_handler( | ||
213 | OPAL_HYPERVISOR_MAINTENANCE_HANDLER, | ||
214 | 0, glue); | ||
215 | glue += 128; | ||
216 | } | ||
217 | |||
197 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); | 218 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); |
198 | #endif | 219 | #endif |
199 | 220 | ||
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index b3ca77ddf36d..b2187d0068b8 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -505,7 +505,7 @@ static bool pnv_pci_cfg_check(struct pci_controller *hose, | |||
505 | edev = of_node_to_eeh_dev(dn); | 505 | edev = of_node_to_eeh_dev(dn); |
506 | if (edev) { | 506 | if (edev) { |
507 | if (edev->pe && | 507 | if (edev->pe && |
508 | (edev->pe->state & EEH_PE_RESET)) | 508 | (edev->pe->state & EEH_PE_CFG_BLOCKED)) |
509 | return false; | 509 | return false; |
510 | 510 | ||
511 | if (edev->mode & EEH_DEV_REMOVED) | 511 | if (edev->mode & EEH_DEV_REMOVED) |
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index fdf01b660d59..6ad83bd11fe2 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -25,11 +25,11 @@ | |||
25 | #include <asm/rtas.h> | 25 | #include <asm/rtas.h> |
26 | 26 | ||
27 | struct cc_workarea { | 27 | struct cc_workarea { |
28 | u32 drc_index; | 28 | __be32 drc_index; |
29 | u32 zero; | 29 | __be32 zero; |
30 | u32 name_offset; | 30 | __be32 name_offset; |
31 | u32 prop_length; | 31 | __be32 prop_length; |
32 | u32 prop_offset; | 32 | __be32 prop_offset; |
33 | }; | 33 | }; |
34 | 34 | ||
35 | void dlpar_free_cc_property(struct property *prop) | 35 | void dlpar_free_cc_property(struct property *prop) |
@@ -49,11 +49,11 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) | |||
49 | if (!prop) | 49 | if (!prop) |
50 | return NULL; | 50 | return NULL; |
51 | 51 | ||
52 | name = (char *)ccwa + ccwa->name_offset; | 52 | name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); |
53 | prop->name = kstrdup(name, GFP_KERNEL); | 53 | prop->name = kstrdup(name, GFP_KERNEL); |
54 | 54 | ||
55 | prop->length = ccwa->prop_length; | 55 | prop->length = be32_to_cpu(ccwa->prop_length); |
56 | value = (char *)ccwa + ccwa->prop_offset; | 56 | value = (char *)ccwa + be32_to_cpu(ccwa->prop_offset); |
57 | prop->value = kmemdup(value, prop->length, GFP_KERNEL); | 57 | prop->value = kmemdup(value, prop->length, GFP_KERNEL); |
58 | if (!prop->value) { | 58 | if (!prop->value) { |
59 | dlpar_free_cc_property(prop); | 59 | dlpar_free_cc_property(prop); |
@@ -79,7 +79,7 @@ static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa, | |||
79 | if (!dn) | 79 | if (!dn) |
80 | return NULL; | 80 | return NULL; |
81 | 81 | ||
82 | name = (char *)ccwa + ccwa->name_offset; | 82 | name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); |
83 | dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name); | 83 | dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name); |
84 | if (!dn->full_name) { | 84 | if (!dn->full_name) { |
85 | kfree(dn); | 85 | kfree(dn); |
@@ -126,7 +126,7 @@ void dlpar_free_cc_nodes(struct device_node *dn) | |||
126 | #define CALL_AGAIN -2 | 126 | #define CALL_AGAIN -2 |
127 | #define ERR_CFG_USE -9003 | 127 | #define ERR_CFG_USE -9003 |
128 | 128 | ||
129 | struct device_node *dlpar_configure_connector(u32 drc_index, | 129 | struct device_node *dlpar_configure_connector(__be32 drc_index, |
130 | struct device_node *parent) | 130 | struct device_node *parent) |
131 | { | 131 | { |
132 | struct device_node *dn; | 132 | struct device_node *dn; |
@@ -414,7 +414,7 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | |||
414 | if (!parent) | 414 | if (!parent) |
415 | return -ENODEV; | 415 | return -ENODEV; |
416 | 416 | ||
417 | dn = dlpar_configure_connector(drc_index, parent); | 417 | dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent); |
418 | if (!dn) | 418 | if (!dn) |
419 | return -EINVAL; | 419 | return -EINVAL; |
420 | 420 | ||
diff --git a/arch/powerpc/platforms/pseries/hotplug-cpu.c b/arch/powerpc/platforms/pseries/hotplug-cpu.c index b174fa751d26..5c375f93c669 100644 --- a/arch/powerpc/platforms/pseries/hotplug-cpu.c +++ b/arch/powerpc/platforms/pseries/hotplug-cpu.c | |||
@@ -247,7 +247,7 @@ static int pseries_add_processor(struct device_node *np) | |||
247 | unsigned int cpu; | 247 | unsigned int cpu; |
248 | cpumask_var_t candidate_mask, tmp; | 248 | cpumask_var_t candidate_mask, tmp; |
249 | int err = -ENOSPC, len, nthreads, i; | 249 | int err = -ENOSPC, len, nthreads, i; |
250 | const u32 *intserv; | 250 | const __be32 *intserv; |
251 | 251 | ||
252 | intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); | 252 | intserv = of_get_property(np, "ibm,ppc-interrupt-server#s", &len); |
253 | if (!intserv) | 253 | if (!intserv) |
@@ -293,7 +293,7 @@ static int pseries_add_processor(struct device_node *np) | |||
293 | for_each_cpu(cpu, tmp) { | 293 | for_each_cpu(cpu, tmp) { |
294 | BUG_ON(cpu_present(cpu)); | 294 | BUG_ON(cpu_present(cpu)); |
295 | set_cpu_present(cpu, true); | 295 | set_cpu_present(cpu, true); |
296 | set_hard_smp_processor_id(cpu, *intserv++); | 296 | set_hard_smp_processor_id(cpu, be32_to_cpu(*intserv++)); |
297 | } | 297 | } |
298 | err = 0; | 298 | err = 0; |
299 | out_unlock: | 299 | out_unlock: |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index de1ec54a2a57..e32e00976a94 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <linux/memblock.h> | 31 | #include <linux/memblock.h> |
32 | #include <linux/spinlock.h> | 32 | #include <linux/spinlock.h> |
33 | #include <linux/sched.h> /* for show_stack */ | ||
34 | #include <linux/string.h> | 33 | #include <linux/string.h> |
35 | #include <linux/pci.h> | 34 | #include <linux/pci.h> |
36 | #include <linux/dma-mapping.h> | 35 | #include <linux/dma-mapping.h> |
@@ -168,7 +167,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
168 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); | 167 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); |
169 | printk("\ttcenum = 0x%llx\n", (u64)tcenum); | 168 | printk("\ttcenum = 0x%llx\n", (u64)tcenum); |
170 | printk("\ttce val = 0x%llx\n", tce ); | 169 | printk("\ttce val = 0x%llx\n", tce ); |
171 | show_stack(current, (unsigned long *)__get_SP()); | 170 | dump_stack(); |
172 | } | 171 | } |
173 | 172 | ||
174 | tcenum++; | 173 | tcenum++; |
@@ -257,7 +256,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
257 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); | 256 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); |
258 | printk("\tnpages = 0x%llx\n", (u64)npages); | 257 | printk("\tnpages = 0x%llx\n", (u64)npages); |
259 | printk("\ttce[0] val = 0x%llx\n", tcep[0]); | 258 | printk("\ttce[0] val = 0x%llx\n", tcep[0]); |
260 | show_stack(current, (unsigned long *)__get_SP()); | 259 | dump_stack(); |
261 | } | 260 | } |
262 | return ret; | 261 | return ret; |
263 | } | 262 | } |
@@ -273,7 +272,7 @@ static void tce_free_pSeriesLP(struct iommu_table *tbl, long tcenum, long npages | |||
273 | printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc); | 272 | printk("tce_free_pSeriesLP: plpar_tce_put failed. rc=%lld\n", rc); |
274 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); | 273 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); |
275 | printk("\ttcenum = 0x%llx\n", (u64)tcenum); | 274 | printk("\ttcenum = 0x%llx\n", (u64)tcenum); |
276 | show_stack(current, (unsigned long *)__get_SP()); | 275 | dump_stack(); |
277 | } | 276 | } |
278 | 277 | ||
279 | tcenum++; | 278 | tcenum++; |
@@ -292,7 +291,7 @@ static void tce_freemulti_pSeriesLP(struct iommu_table *tbl, long tcenum, long n | |||
292 | printk("\trc = %lld\n", rc); | 291 | printk("\trc = %lld\n", rc); |
293 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); | 292 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); |
294 | printk("\tnpages = 0x%llx\n", (u64)npages); | 293 | printk("\tnpages = 0x%llx\n", (u64)npages); |
295 | show_stack(current, (unsigned long *)__get_SP()); | 294 | dump_stack(); |
296 | } | 295 | } |
297 | } | 296 | } |
298 | 297 | ||
@@ -307,7 +306,7 @@ static unsigned long tce_get_pSeriesLP(struct iommu_table *tbl, long tcenum) | |||
307 | printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc); | 306 | printk("tce_get_pSeriesLP: plpar_tce_get failed. rc=%lld\n", rc); |
308 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); | 307 | printk("\tindex = 0x%llx\n", (u64)tbl->it_index); |
309 | printk("\ttcenum = 0x%llx\n", (u64)tcenum); | 308 | printk("\ttcenum = 0x%llx\n", (u64)tcenum); |
310 | show_stack(current, (unsigned long *)__get_SP()); | 309 | dump_stack(); |
311 | } | 310 | } |
312 | 311 | ||
313 | return tce_ret; | 312 | return tce_ret; |
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 361add62abf1..1796c5438cc6 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -56,7 +56,8 @@ extern void hvc_vio_init_early(void); | |||
56 | /* Dynamic logical Partitioning/Mobility */ | 56 | /* Dynamic logical Partitioning/Mobility */ |
57 | extern void dlpar_free_cc_nodes(struct device_node *); | 57 | extern void dlpar_free_cc_nodes(struct device_node *); |
58 | extern void dlpar_free_cc_property(struct property *); | 58 | extern void dlpar_free_cc_property(struct property *); |
59 | extern struct device_node *dlpar_configure_connector(u32, struct device_node *); | 59 | extern struct device_node *dlpar_configure_connector(__be32, |
60 | struct device_node *); | ||
60 | extern int dlpar_attach_node(struct device_node *); | 61 | extern int dlpar_attach_node(struct device_node *); |
61 | extern int dlpar_detach_node(struct device_node *); | 62 | extern int dlpar_detach_node(struct device_node *); |
62 | 63 | ||