diff options
Diffstat (limited to 'arch/powerpc/kernel')
| -rw-r--r-- | arch/powerpc/kernel/cpu_setup_fsl_booke.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/cputable.c | 22 | ||||
| -rw-r--r-- | arch/powerpc/kernel/crash_dump.c | 17 | ||||
| -rw-r--r-- | arch/powerpc/kernel/irq.c | 55 | ||||
| -rw-r--r-- | arch/powerpc/kernel/machine_kexec.c | 21 | ||||
| -rw-r--r-- | arch/powerpc/kernel/nvram_64.c | 31 | ||||
| -rw-r--r-- | arch/powerpc/kernel/pci_dn.c | 7 | ||||
| -rw-r--r-- | arch/powerpc/kernel/perf_event.c | 24 | ||||
| -rw-r--r-- | arch/powerpc/kernel/process.c | 4 | ||||
| -rw-r--r-- | arch/powerpc/kernel/prom.c | 2 | ||||
| -rw-r--r-- | arch/powerpc/kernel/ptrace.c | 15 | ||||
| -rw-r--r-- | arch/powerpc/kernel/rtasd.c | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/vdso.c | 6 |
13 files changed, 131 insertions, 78 deletions
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index 5c518ad3445c..913611105c1f 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S @@ -64,7 +64,7 @@ _GLOBAL(__setup_cpu_e500v2) bl __e500_icache_setup bl __e500_dcache_setup bl __setup_e500_ivors -#ifdef CONFIG_RAPIDIO +#ifdef CONFIG_FSL_RIO /* Ensure that RFXE is set */ mfspr r3,SPRN_HID1 oris r3,r3,HID1_RFXE@h diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e8e915ce3d8d..c9b68d07ac4f 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -1811,11 +1811,11 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_440A, .platform = "ppc440", }, - { /* 476 core */ - .pvr_mask = 0xffff0000, - .pvr_value = 0x11a50000, + { /* 476 DD2 core */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x11a52080, .cpu_name = "476", - .cpu_features = CPU_FTRS_47X, + .cpu_features = CPU_FTRS_47X | CPU_FTR_476_DD2, .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, .mmu_features = MMU_FTR_TYPE_47x | @@ -1839,6 +1839,20 @@ static struct cpu_spec __initdata cpu_specs[] = { .machine_check = machine_check_47x, .platform = "ppc470", }, + { /* 476 others */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x11a50000, + .cpu_name = "476", + .cpu_features = CPU_FTRS_47X, + .cpu_user_features = COMMON_USER_BOOKE | + PPC_FEATURE_HAS_FPU, + .mmu_features = MMU_FTR_TYPE_47x | + MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL, + .icache_bsize = 32, + .dcache_bsize = 128, + .machine_check = machine_check_47x, + .platform = "ppc470", + }, { /* default match */ .pvr_mask = 0x00000000, .pvr_value = 0x00000000, diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 0a2af50243cb..424afb6b8fba 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c @@ -28,9 +28,6 @@ #define DBG(fmt...) #endif -/* Stores the physical address of elf header of crash image. */ -unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX; - #ifndef CONFIG_RELOCATABLE void __init reserve_kdump_trampoline(void) { @@ -72,20 +69,6 @@ void __init setup_kdump_trampoline(void) } #endif /* CONFIG_RELOCATABLE */ -/* - * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by - * is_kdump_kernel() to determine if we are booting after a panic. Hence - * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. - */ -static int __init parse_elfcorehdr(char *p) -{ - if (p) - elfcorehdr_addr = memparse(p, &p); - - return 1; -} -__setup("elfcorehdr=", parse_elfcorehdr); - static int __init parse_savemaxmem(char *p) { if (p) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index ce557f6f00fc..0a5570338b96 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -237,6 +237,7 @@ int show_interrupts(struct seq_file *p, void *v) int i = *(loff_t *) v, j, prec; struct irqaction *action; struct irq_desc *desc; + struct irq_chip *chip; if (i > nr_irqs) return 0; @@ -270,8 +271,9 @@ int show_interrupts(struct seq_file *p, void *v) for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_irqs_cpu(i, j)); - if (desc->chip) - seq_printf(p, " %-16s", desc->chip->name); + chip = get_irq_desc_chip(desc); + if (chip) + seq_printf(p, " %-16s", chip->name); else seq_printf(p, " %-16s", "None"); seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge"); @@ -313,6 +315,8 @@ void fixup_irqs(const struct cpumask *map) alloc_cpumask_var(&mask, GFP_KERNEL); for_each_irq(irq) { + struct irq_chip *chip; + desc = irq_to_desc(irq); if (!desc) continue; @@ -320,13 +324,15 @@ void fixup_irqs(const struct cpumask *map) if (desc->status & IRQ_PER_CPU) continue; - cpumask_and(mask, desc->affinity, map); + chip = get_irq_desc_chip(desc); + + cpumask_and(mask, desc->irq_data.affinity, map); if (cpumask_any(mask) >= nr_cpu_ids) { printk("Breaking affinity for irq %i\n", irq); cpumask_copy(mask, map); } - if (desc->chip->set_affinity) - desc->chip->set_affinity(irq, mask); + if (chip->irq_set_affinity) + chip->irq_set_affinity(&desc->irq_data, mask, true); else if (desc->action && !(warned++)) printk("Cannot set affinity for irq %i\n", irq); } @@ -678,16 +684,15 @@ void irq_set_virq_count(unsigned int count) static int irq_setup_virq(struct irq_host *host, unsigned int virq, irq_hw_number_t hwirq) { - struct irq_desc *desc; + int res; - desc = irq_to_desc_alloc_node(virq, 0); - if (!desc) { + res = irq_alloc_desc_at(virq, 0); + if (res != virq) { pr_debug("irq: -> allocating desc failed\n"); goto error; } - /* Clear IRQ_NOREQUEST flag */ - desc->status &= ~IRQ_NOREQUEST; + irq_clear_status_flags(virq, IRQ_NOREQUEST); /* map it */ smp_wmb(); @@ -696,11 +701,13 @@ static int irq_setup_virq(struct irq_host *host, unsigned int virq, if (host->ops->map(host, virq, hwirq)) { pr_debug("irq: -> mapping failed, freeing\n"); - goto error; + goto errdesc; } return 0; +errdesc: + irq_free_descs(virq, 1); error: irq_free_virt(virq, 1); return -1; @@ -879,9 +886,9 @@ void irq_dispose_mapping(unsigned int virq) smp_mb(); irq_map[virq].hwirq = host->inval_irq; - /* Set some flags */ - irq_to_desc(virq)->status |= IRQ_NOREQUEST; + irq_set_status_flags(virq, IRQ_NOREQUEST); + irq_free_descs(virq, 1); /* Free it */ irq_free_virt(virq, 1); } @@ -1074,21 +1081,6 @@ void irq_free_virt(unsigned int virq, unsigned int count) int arch_early_irq_init(void) { - struct irq_desc *desc; - int i; - - for (i = 0; i < NR_IRQS; i++) { - desc = irq_to_desc(i); - if (desc) - desc->status |= IRQ_NOREQUEST; - } - - return 0; -} - -int arch_init_chip_data(struct irq_desc *desc, int node) -{ - desc->status |= IRQ_NOREQUEST; return 0; } @@ -1159,11 +1151,14 @@ static int virq_debug_show(struct seq_file *m, void *private) raw_spin_lock_irqsave(&desc->lock, flags); if (desc->action && desc->action->handler) { + struct irq_chip *chip; + seq_printf(m, "%5d ", i); seq_printf(m, "0x%05lx ", virq_to_hw(i)); - if (desc->chip && desc->chip->name) - p = desc->chip->name; + chip = get_irq_desc_chip(desc); + if (chip && chip->name) + p = chip->name; else p = none; seq_printf(m, "%-15s ", p); diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index a5f8672eeff3..bd1e1ff17b2d 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c @@ -26,20 +26,23 @@ void machine_kexec_mask_interrupts(void) { for_each_irq(i) { struct irq_desc *desc = irq_to_desc(i); + struct irq_chip *chip; - if (!desc || !desc->chip) + if (!desc) continue; - if (desc->chip->eoi && - desc->status & IRQ_INPROGRESS) - desc->chip->eoi(i); + chip = get_irq_desc_chip(desc); + if (!chip) + continue; + + if (chip->irq_eoi && desc->status & IRQ_INPROGRESS) + chip->irq_eoi(&desc->irq_data); - if (desc->chip->mask) - desc->chip->mask(i); + if (chip->irq_mask) + chip->irq_mask(&desc->irq_data); - if (desc->chip->disable && - !(desc->status & IRQ_DISABLED)) - desc->chip->disable(i); + if (chip->irq_disable && !(desc->status & IRQ_DISABLED)) + chip->irq_disable(&desc->irq_data); } } diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index bb12b3248f13..bec1e930ed73 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c @@ -237,22 +237,45 @@ static unsigned char __init nvram_checksum(struct nvram_header *p) return c_sum; } +/* + * Per the criteria passed via nvram_remove_partition(), should this + * partition be removed? 1=remove, 0=keep + */ +static int nvram_can_remove_partition(struct nvram_partition *part, + const char *name, int sig, const char *exceptions[]) +{ + if (part->header.signature != sig) + return 0; + if (name) { + if (strncmp(name, part->header.name, 12)) + return 0; + } else if (exceptions) { + const char **except; + for (except = exceptions; *except; except++) { + if (!strncmp(*except, part->header.name, 12)) + return 0; + } + } + return 1; +} + /** * nvram_remove_partition - Remove one or more partitions in nvram * @name: name of the partition to remove, or NULL for a * signature only match * @sig: signature of the partition(s) to remove + * @exceptions: When removing all partitions with a matching signature, + * leave these alone. */ -int __init nvram_remove_partition(const char *name, int sig) +int __init nvram_remove_partition(const char *name, int sig, + const char *exceptions[]) { struct nvram_partition *part, *prev, *tmp; int rc; list_for_each_entry(part, &nvram_partitions, partition) { - if (part->header.signature != sig) - continue; - if (name && strncmp(name, part->header.name, 12)) + if (!nvram_can_remove_partition(part, name, sig, exceptions)) continue; /* Make partition a free partition */ diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 29852688ceaa..d225d99fe39d 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c @@ -176,11 +176,14 @@ static void *is_devfn_node(struct device_node *dn, void *data) */ struct device_node *fetch_dev_dn(struct pci_dev *dev) { - struct device_node *orig_dn = dev->dev.of_node; + struct pci_controller *phb = dev->sysdata; struct device_node *dn; unsigned long searchval = (dev->bus->number << 8) | dev->devfn; - dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval); + if (WARN_ON(!phb)) + return NULL; + + dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval); if (dn) dev->dev.of_node = dn; return dn; diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index ab6f6beadb57..97e0ae414940 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c @@ -1269,6 +1269,28 @@ unsigned long perf_instruction_pointer(struct pt_regs *regs) return ip; } +static bool pmc_overflow(unsigned long val) +{ + if ((int)val < 0) + return true; + + /* + * Events on POWER7 can roll back if a speculative event doesn't + * eventually complete. Unfortunately in some rare cases they will + * raise a performance monitor exception. We need to catch this to + * ensure we reset the PMC. In all cases the PMC will be 256 or less + * cycles from overflow. + * + * We only do this if the first pass fails to find any overflowing + * PMCs because a user might set a period of less than 256 and we + * don't want to mistakenly reset them. + */ + if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256)) + return true; + + return false; +} + /* * Performance monitor interrupt stuff */ @@ -1316,7 +1338,7 @@ static void perf_event_interrupt(struct pt_regs *regs) if (is_limited_pmc(i + 1)) continue; val = read_pmc(i + 1); - if ((int)val < 0) + if (pmc_overflow(val)) write_pmc(i + 1, 0); } } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 8303a6c65ef7..f74f355a9617 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1218,11 +1218,11 @@ void __ppc64_runlatch_off(void) static struct kmem_cache *thread_info_cache; -struct thread_info *alloc_thread_info(struct task_struct *tsk) +struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node) { struct thread_info *ti; - ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL); + ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node); if (unlikely(ti == NULL)) return NULL; #ifdef CONFIG_DEBUG_STACK_USAGE diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 7185f0da7dc3..05b7139d6a27 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -97,7 +97,7 @@ static void __init move_device_tree(void) start = __pa(initial_boot_params); size = be32_to_cpu(initial_boot_params->totalsize); - if ((memory_limit && (start + size) > memory_limit) || + if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) || overlaps_crashkernel(start, size)) { p = __va(memblock_alloc(size, PAGE_SIZE)); memcpy(p, initial_boot_params, size); diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 906536998291..895b082f1e48 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -229,12 +229,16 @@ static int gpr_get(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, void *kbuf, void __user *ubuf) { - int ret; + int i, ret; if (target->thread.regs == NULL) return -EIO; - CHECK_FULL_REGS(target->thread.regs); + if (!FULL_REGS(target->thread.regs)) { + /* We have a partial register set. Fill 14-31 with bogus values */ + for (i = 14; i < 32; i++) + target->thread.regs->gpr[i] = NV_REG_POISON; + } ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, target->thread.regs, @@ -641,11 +645,16 @@ static int gpr32_get(struct task_struct *target, compat_ulong_t *k = kbuf; compat_ulong_t __user *u = ubuf; compat_ulong_t reg; + int i; if (target->thread.regs == NULL) return -EIO; - CHECK_FULL_REGS(target->thread.regs); + if (!FULL_REGS(target->thread.regs)) { + /* We have a partial register set. Fill 14-31 with bogus values */ + for (i = 14; i < 32; i++) + target->thread.regs->gpr[i] = NV_REG_POISON; + } pos /= sizeof(reg); count /= sizeof(reg); diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 049dbecb5dbc..7980ec0e1e1a 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c @@ -412,7 +412,8 @@ static void rtas_event_scan(struct work_struct *w) get_online_cpus(); - cpu = cpumask_next(smp_processor_id(), cpu_online_mask); + /* raw_ OK because just using CPU as starting point. */ + cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask); if (cpu >= nr_cpu_ids) { cpu = cpumask_first(cpu_online_mask); diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index fd8728729abc..142ab1008c3b 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -820,17 +820,17 @@ static int __init vdso_init(void) } arch_initcall(vdso_init); -int in_gate_area_no_task(unsigned long addr) +int in_gate_area_no_mm(unsigned long addr) { return 0; } -int in_gate_area(struct task_struct *task, unsigned long addr) +int in_gate_area(struct mm_struct *mm, unsigned long addr) { return 0; } -struct vm_area_struct *get_gate_vma(struct task_struct *tsk) +struct vm_area_struct *get_gate_vma(struct mm_struct *mm) { return NULL; } |
