diff options
Diffstat (limited to 'arch/powerpc/platforms/pseries')
-rw-r--r-- | arch/powerpc/platforms/pseries/eeh.c | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/firmware.c | 1 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/hotplug-memory.c | 117 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/iommu.c | 15 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/kexec.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/lpar.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/ras.c | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/reconfig.c | 38 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/rtasd.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/setup.c | 4 | ||||
-rw-r--r-- | arch/powerpc/platforms/pseries/xics.c | 6 |
11 files changed, 145 insertions, 62 deletions
diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 6f544ba4b37..c027f0a70a0 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -812,6 +812,7 @@ int rtas_set_slot_reset(struct pci_dn *pdn) static inline void __restore_bars (struct pci_dn *pdn) { int i; + u32 cmd; if (NULL==pdn->phb) return; for (i=4; i<10; i++) { @@ -832,6 +833,19 @@ static inline void __restore_bars (struct pci_dn *pdn) /* max latency, min grant, interrupt pin and line */ rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]); + + /* Restore PERR & SERR bits, some devices require it, + don't touch the other command bits */ + rtas_read_config(pdn, PCI_COMMAND, 4, &cmd); + if (pdn->config_space[1] & PCI_COMMAND_PARITY) + cmd |= PCI_COMMAND_PARITY; + else + cmd &= ~PCI_COMMAND_PARITY; + if (pdn->config_space[1] & PCI_COMMAND_SERR) + cmd |= PCI_COMMAND_SERR; + else + cmd &= ~PCI_COMMAND_SERR; + rtas_write_config(pdn, PCI_COMMAND, 4, cmd); } /** diff --git a/arch/powerpc/platforms/pseries/firmware.c b/arch/powerpc/platforms/pseries/firmware.c index 9d3a40f4597..5a707da3f5c 100644 --- a/arch/powerpc/platforms/pseries/firmware.c +++ b/arch/powerpc/platforms/pseries/firmware.c @@ -26,6 +26,7 @@ #include <asm/prom.h> #include <asm/udbg.h> +#include "pseries.h" typedef struct { unsigned long val; diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 3c5727dd5aa..a1a368dd2d9 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -15,34 +15,13 @@ #include <asm/machdep.h> #include <asm/pSeries_reconfig.h> -static int pseries_remove_memory(struct device_node *np) +static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size) { - const char *type; - const unsigned int *my_index; - const unsigned int *regs; - u64 start_pfn, start; + unsigned long start, start_pfn; struct zone *zone; - int ret = -EINVAL; - - /* - * Check to see if we are actually removing memory - */ - type = of_get_property(np, "device_type", NULL); - if (type == NULL || strcmp(type, "memory") != 0) - return 0; + int ret; - /* - * Find the memory index and size of the removing section - */ - my_index = of_get_property(np, "ibm,my-drc-index", NULL); - if (!my_index) - return ret; - - regs = of_get_property(np, "reg", NULL); - if (!regs) - return ret; - - start_pfn = section_nr_to_pfn(*my_index & 0xffff); + start_pfn = base >> PFN_SECTION_SHIFT; zone = page_zone(pfn_to_page(start_pfn)); /* @@ -54,56 +33,111 @@ static int pseries_remove_memory(struct device_node *np) * to sysfs "state" file and we can't remove sysfs entries * while writing to it. So we have to defer it to here. */ - ret = __remove_pages(zone, start_pfn, regs[3] >> PAGE_SHIFT); + ret = __remove_pages(zone, start_pfn, lmb_size >> PAGE_SHIFT); if (ret) return ret; /* * Update memory regions for memory remove */ - lmb_remove(start_pfn << PAGE_SHIFT, regs[3]); + lmb_remove(base, lmb_size); /* * Remove htab bolted mappings for this section of memory */ - start = (unsigned long)__va(start_pfn << PAGE_SHIFT); - ret = remove_section_mapping(start, start + regs[3]); + start = (unsigned long)__va(base); + ret = remove_section_mapping(start, start + lmb_size); return ret; } -static int pseries_add_memory(struct device_node *np) +static int pseries_remove_memory(struct device_node *np) { const char *type; - const unsigned int *my_index; const unsigned int *regs; - u64 start_pfn; + unsigned long base; + unsigned int lmb_size; int ret = -EINVAL; /* - * Check to see if we are actually adding memory + * Check to see if we are actually removing memory */ type = of_get_property(np, "device_type", NULL); if (type == NULL || strcmp(type, "memory") != 0) return 0; /* - * Find the memory index and size of the added section + * Find the bae address and size of the lmb */ - my_index = of_get_property(np, "ibm,my-drc-index", NULL); - if (!my_index) + regs = of_get_property(np, "reg", NULL); + if (!regs) return ret; + base = *(unsigned long *)regs; + lmb_size = regs[3]; + + ret = pseries_remove_lmb(base, lmb_size); + return ret; +} + +static int pseries_add_memory(struct device_node *np) +{ + const char *type; + const unsigned int *regs; + unsigned long base; + unsigned int lmb_size; + int ret = -EINVAL; + + /* + * Check to see if we are actually adding memory + */ + type = of_get_property(np, "device_type", NULL); + if (type == NULL || strcmp(type, "memory") != 0) + return 0; + + /* + * Find the base and size of the lmb + */ regs = of_get_property(np, "reg", NULL); if (!regs) return ret; - start_pfn = section_nr_to_pfn(*my_index & 0xffff); + base = *(unsigned long *)regs; + lmb_size = regs[3]; /* * Update memory region to represent the memory add */ - lmb_add(start_pfn << PAGE_SHIFT, regs[3]); - return 0; + ret = lmb_add(base, lmb_size); + return (ret < 0) ? -EINVAL : 0; +} + +static int pseries_drconf_memory(unsigned long *base, unsigned int action) +{ + struct device_node *np; + const unsigned long *lmb_size; + int rc; + + np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); + if (!np) + return -EINVAL; + + lmb_size = of_get_property(np, "ibm,lmb-size", NULL); + if (!lmb_size) { + of_node_put(np); + return -EINVAL; + } + + if (action == PSERIES_DRCONF_MEM_ADD) { + rc = lmb_add(*base, *lmb_size); + rc = (rc < 0) ? -EINVAL : 0; + } else if (action == PSERIES_DRCONF_MEM_REMOVE) { + rc = pseries_remove_lmb(*base, *lmb_size); + } else { + rc = -EINVAL; + } + + of_node_put(np); + return rc; } static int pseries_memory_notifier(struct notifier_block *nb, @@ -120,6 +154,11 @@ static int pseries_memory_notifier(struct notifier_block *nb, if (pseries_remove_memory(node)) err = NOTIFY_BAD; break; + case PSERIES_DRCONF_MEM_ADD: + case PSERIES_DRCONF_MEM_REMOVE: + if (pseries_drconf_memory(node, action)) + err = NOTIFY_BAD; + break; default: err = NOTIFY_DONE; break; diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 176f1f39d2d..9a12908510f 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c @@ -135,9 +135,10 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, u64 rpn; long l, limit; - if (npages == 1) - return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, - direction); + if (npages == 1) { + tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, direction); + return; + } tcep = __get_cpu_var(tce_page); @@ -147,9 +148,11 @@ static void tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, if (!tcep) { tcep = (u64 *)__get_free_page(GFP_ATOMIC); /* If allocation fails, fall back to the loop implementation */ - if (!tcep) - return tce_build_pSeriesLP(tbl, tcenum, npages, - uaddr, direction); + if (!tcep) { + tce_build_pSeriesLP(tbl, tcenum, npages, uaddr, + direction); + return; + } __get_cpu_var(tce_page) = tcep; } diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index e9dd5fe081c..53cbd53d874 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c @@ -70,4 +70,4 @@ static int __init pseries_kexec_setup(void) return 0; } -__initcall(pseries_kexec_setup); +machine_device_initcall(pseries, pseries_kexec_setup); diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 2cbaedb17f3..52a80e5840e 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -52,7 +52,7 @@ EXPORT_SYMBOL(plpar_hcall_norets); extern void pSeries_find_serial_port(void); -int vtermno; /* virtual terminal# for udbg */ +static int vtermno; /* virtual terminal# for udbg */ #define __ALIGNED__ __attribute__((__aligned__(sizeof(long)))) static void udbg_hvsi_putc(char c) @@ -305,7 +305,7 @@ static long pSeries_lpar_hpte_insert(unsigned long hpte_group, flags = 0; /* Make pHyp happy */ - if (rflags & (_PAGE_GUARDED|_PAGE_NO_CACHE)) + if ((rflags & _PAGE_NO_CACHE) & !(rflags & _PAGE_WRITETHRU)) hpte_r &= ~_PAGE_COHERENT; lpar_rc = plpar_pte_enter(flags, hpte_group, hpte_v, hpte_r, &slot); diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 2b548afd100..d20b96e22c2 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -55,7 +55,7 @@ static unsigned char ras_log_buf[RTAS_ERROR_LOG_MAX]; static DEFINE_SPINLOCK(ras_log_buf_lock); -char mce_data_buf[RTAS_ERROR_LOG_MAX]; +static char mce_data_buf[RTAS_ERROR_LOG_MAX]; static int ras_get_sensor_state_token; static int ras_check_exception_token; diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 75769aae41d..7637bd38c79 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -365,7 +365,7 @@ static char *parse_node(char *buf, size_t bufsize, struct device_node **npp) *buf = '\0'; buf++; - handle = simple_strtoul(handle_str, NULL, 10); + handle = simple_strtoul(handle_str, NULL, 0); *npp = of_find_node_by_phandle(handle); return buf; @@ -422,8 +422,8 @@ static int do_update_property(char *buf, size_t bufsize) { struct device_node *np; unsigned char *value; - char *name, *end; - int length; + char *name, *end, *next_prop; + int rc, length; struct property *newprop, *oldprop; buf = parse_node(buf, bufsize, &np); end = buf + bufsize; @@ -431,7 +431,8 @@ static int do_update_property(char *buf, size_t bufsize) if (!np) return -ENODEV; - if (parse_next_property(buf, end, &name, &length, &value) == NULL) + next_prop = parse_next_property(buf, end, &name, &length, &value); + if (!next_prop) return -EINVAL; newprop = new_property(name, length, value, NULL); @@ -442,7 +443,34 @@ static int do_update_property(char *buf, size_t bufsize) if (!oldprop) return -ENODEV; - return prom_update_property(np, newprop, oldprop); + rc = prom_update_property(np, newprop, oldprop); + if (rc) + return rc; + + /* For memory under the ibm,dynamic-reconfiguration-memory node + * of the device tree, adding and removing memory is just an update + * to the ibm,dynamic-memory property instead of adding/removing a + * memory node in the device tree. For these cases we still need to + * involve the notifier chain. + */ + if (!strcmp(name, "ibm,dynamic-memory")) { + int action; + + next_prop = parse_next_property(next_prop, end, &name, + &length, &value); + if (!next_prop) + return -EINVAL; + + if (!strcmp(name, "add")) + action = PSERIES_DRCONF_MEM_ADD; + else + action = PSERIES_DRCONF_MEM_REMOVE; + + blocking_notifier_call_chain(&pSeries_reconfig_chain, + action, value); + } + + return 0; } /** diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index 7d3e2b0bd4d..c9ffd8c225f 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -32,7 +32,7 @@ static DEFINE_SPINLOCK(rtasd_log_lock); -DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); +static DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait); static char *rtas_log_buf; static unsigned long rtas_log_start; @@ -329,7 +329,7 @@ static unsigned int rtas_log_poll(struct file *file, poll_table * wait) return 0; } -const struct file_operations proc_rtas_log_operations = { +static const struct file_operations proc_rtas_log_operations = { .read = rtas_log_read, .poll = rtas_log_poll, .open = rtas_log_open, diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f5d29f5b13c..90beb444e1d 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c @@ -109,7 +109,7 @@ static void __init fwnmi_init(void) fwnmi_active = 1; } -void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc) +static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc) { unsigned int cascade_irq = i8259_irq(); if (cascade_irq != NO_IRQ) @@ -482,7 +482,7 @@ static int pSeries_pci_probe_mode(struct pci_bus *bus) * possible with power button press. If ibm,power-off-ups token is used * it will allow auto poweron after power is restored. */ -void pSeries_power_off(void) +static void pSeries_power_off(void) { int rc; int rtas_poweroff_ups_token = rtas_token("ibm,power-off-ups"); diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index ebebc28fe89..0fc830f576f 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c @@ -383,13 +383,11 @@ static irqreturn_t xics_ipi_dispatch(int cpu) mb(); smp_message_recv(PPC_MSG_RESCHEDULE); } -#if 0 - if (test_and_clear_bit(PPC_MSG_MIGRATE_TASK, + if (test_and_clear_bit(PPC_MSG_CALL_FUNC_SINGLE, &xics_ipi_message[cpu].value)) { mb(); - smp_message_recv(PPC_MSG_MIGRATE_TASK); + smp_message_recv(PPC_MSG_CALL_FUNC_SINGLE); } -#endif #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC) if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, &xics_ipi_message[cpu].value)) { |