diff options
Diffstat (limited to 'arch/powerpc/kernel')
72 files changed, 1068 insertions, 789 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index ff2940548929..7ee84968087b 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -13,7 +13,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/signal.h> #include <linux/sched.h> #include <linux/kernel.h> diff --git a/arch/powerpc/kernel/binfmt_elf32.c b/arch/powerpc/kernel/binfmt_elf32.c index 8ad6b0f33651..5cb58757e1b1 100644 --- a/arch/powerpc/kernel/binfmt_elf32.c +++ b/arch/powerpc/kernel/binfmt_elf32.c @@ -19,7 +19,6 @@ #include <asm/processor.h> #include <linux/module.h> -#include <linux/config.h> #include <linux/elfcore.h> #include <linux/compat.h> diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 6223d39177cb..f4e5e14ee2b6 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c @@ -3,7 +3,6 @@ * * Benjamin Herrenschmidt <benh@kernel.crashing.org> */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> @@ -112,7 +111,7 @@ void __init btext_setup_display(int width, int height, int depth, int pitch, logicalDisplayBase = (unsigned char *)address; dispDeviceBase = (unsigned char *)address; dispDeviceRowBytes = pitch; - dispDeviceDepth = depth; + dispDeviceDepth = depth == 15 ? 16 : depth; dispDeviceRect[0] = dispDeviceRect[1] = 0; dispDeviceRect[2] = width; dispDeviceRect[3] = height; @@ -161,20 +160,28 @@ int btext_initialize(struct device_node *np) unsigned long address = 0; u32 *prop; - prop = (u32 *)get_property(np, "width", NULL); + prop = (u32 *)get_property(np, "linux,bootx-width", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "width", NULL); if (prop == NULL) return -EINVAL; width = *prop; - prop = (u32 *)get_property(np, "height", NULL); + prop = (u32 *)get_property(np, "linux,bootx-height", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "height", NULL); if (prop == NULL) return -EINVAL; height = *prop; - prop = (u32 *)get_property(np, "depth", NULL); + prop = (u32 *)get_property(np, "linux,bootx-depth", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "depth", NULL); if (prop == NULL) return -EINVAL; depth = *prop; pitch = width * ((depth + 7) / 8); - prop = (u32 *)get_property(np, "linebytes", NULL); + prop = (u32 *)get_property(np, "linux,bootx-linebytes", NULL); + if (prop == NULL) + prop = (u32 *)get_property(np, "linebytes", NULL); if (prop) pitch = *prop; if (pitch == 1) @@ -195,7 +202,7 @@ int btext_initialize(struct device_node *np) g_max_loc_Y = height / 16; dispDeviceBase = (unsigned char *)address; dispDeviceRowBytes = pitch; - dispDeviceDepth = depth; + dispDeviceDepth = depth == 15 ? 16 : depth; dispDeviceRect[0] = dispDeviceRect[1] = 0; dispDeviceRect[2] = width; dispDeviceRect[3] = height; diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 365381fcb27c..8b4a4ee85eca 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S @@ -9,7 +9,6 @@ * */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/cputable.h> diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index 1fc863261003..f69af2c5d7b3 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S @@ -9,7 +9,6 @@ * */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/cputable.h> diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index abf7d42a8b07..272e43622fd6 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c @@ -10,7 +10,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/string.h> #include <linux/sched.h> #include <linux/threads.h> diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 8866fd26c6b9..c03e829fee3c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -19,7 +19,6 @@ * */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/sys.h> #include <linux/threads.h> diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 221062c960c9..54d9f5cdaab4 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -18,7 +18,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/errno.h> #include <asm/unistd.h> #include <asm/processor.h> diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 0bfe9061720a..1679a70bbcad 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c @@ -13,7 +13,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/module.h> #include <asm/firmware.h> diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 01f71200c603..7e2c9fe44ac1 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S @@ -9,7 +9,6 @@ * */ -#include <linux/config.h> #include <asm/reg.h> #include <asm/page.h> #include <asm/mmu.h> diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index b25b25902d15..d88e182e40b3 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S @@ -22,7 +22,6 @@ * */ -#include <linux/config.h> #include <asm/reg.h> #include <asm/page.h> #include <asm/mmu.h> diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 47c7fa148c9a..accb39d49911 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S @@ -28,7 +28,6 @@ * option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/mmu.h> diff --git a/arch/powerpc/kernel/head_4xx.S b/arch/powerpc/kernel/head_4xx.S index 2590e97f5539..adc7f8097cd4 100644 --- a/arch/powerpc/kernel/head_4xx.S +++ b/arch/powerpc/kernel/head_4xx.S @@ -31,7 +31,6 @@ * */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/mmu.h> diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 8cfd040d1f50..e16eb2a33173 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -21,7 +21,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <asm/reg.h> #include <asm/page.h> diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 28941f5ce673..901be47a02a9 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -19,7 +19,6 @@ * */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> #include <asm/mmu.h> diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index dd86bbed7627..66877bdfe0b7 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S @@ -30,7 +30,6 @@ * option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <asm/processor.h> #include <asm/page.h> diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index e47d40ac6f39..97ddc02a3d42 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -323,13 +323,11 @@ int ibmebus_request_irq(struct ibmebus_dev *dev, unsigned long irq_flags, const char * devname, void *dev_id) { - unsigned int irq = virt_irq_create_mapping(ist); + unsigned int irq = irq_create_mapping(NULL, ist, 0); if (irq == NO_IRQ) return -EINVAL; - irq = irq_offset_up(irq); - return request_irq(irq, handler, irq_flags, devname, dev_id); } @@ -337,12 +335,9 @@ EXPORT_SYMBOL(ibmebus_request_irq); void ibmebus_free_irq(struct ibmebus_dev *dev, u32 ist, void *dev_id) { - unsigned int irq = virt_irq_create_mapping(ist); + unsigned int irq = irq_find_mapping(NULL, ist); - irq = irq_offset_up(irq); free_irq(irq, dev_id); - - return; } EXPORT_SYMBOL(ibmebus_free_irq); diff --git a/arch/powerpc/kernel/idle.c b/arch/powerpc/kernel/idle.c index d491052c8e0c..4180c3998b39 100644 --- a/arch/powerpc/kernel/idle.c +++ b/arch/powerpc/kernel/idle.c @@ -19,7 +19,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/kernel.h> #include <linux/smp.h> diff --git a/arch/powerpc/kernel/idle_6xx.S b/arch/powerpc/kernel/idle_6xx.S index b45fa0e37212..01bcd52bbf8e 100644 --- a/arch/powerpc/kernel/idle_6xx.S +++ b/arch/powerpc/kernel/idle_6xx.S @@ -13,7 +13,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <asm/reg.h> #include <asm/page.h> diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S index d85c7c938eed..30de81da7b40 100644 --- a/arch/powerpc/kernel/idle_power4.S +++ b/arch/powerpc/kernel/idle_power4.S @@ -7,7 +7,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/threads.h> #include <asm/processor.h> #include <asm/page.h> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 3d677ac99659..ba0694071728 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c @@ -23,7 +23,6 @@ */ -#include <linux/config.h> #include <linux/init.h> #include <linux/types.h> #include <linux/slab.h> diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 24f6050aa4ab..8cf987809c66 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -29,6 +29,8 @@ * to reduce code space and undefined function references. */ +#undef DEBUG + #include <linux/module.h> #include <linux/threads.h> #include <linux/kernel_stat.h> @@ -38,7 +40,6 @@ #include <linux/ioport.h> #include <linux/interrupt.h> #include <linux/timex.h> -#include <linux/config.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/delay.h> @@ -47,7 +48,10 @@ #include <linux/cpumask.h> #include <linux/profile.h> #include <linux/bitops.h> -#include <linux/pci.h> +#include <linux/list.h> +#include <linux/radix-tree.h> +#include <linux/mutex.h> +#include <linux/bootmem.h> #include <asm/uaccess.h> #include <asm/system.h> @@ -58,39 +62,38 @@ #include <asm/prom.h> #include <asm/ptrace.h> #include <asm/machdep.h> +#include <asm/udbg.h> #ifdef CONFIG_PPC_ISERIES #include <asm/paca.h> #endif int __irq_offset_value; -#ifdef CONFIG_PPC32 -EXPORT_SYMBOL(__irq_offset_value); -#endif - static int ppc_spurious_interrupts; #ifdef CONFIG_PPC32 -#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) +EXPORT_SYMBOL(__irq_offset_value); +atomic_t ppc_n_lost_interrupts; +#ifndef CONFIG_PPC_MERGE +#define NR_MASK_WORDS ((NR_IRQS + 31) / 32) unsigned long ppc_cached_irq_mask[NR_MASK_WORDS]; -atomic_t ppc_n_lost_interrupts; +#endif #ifdef CONFIG_TAU_INT extern int tau_initialized; extern int tau_interrupts(int); #endif +#endif /* CONFIG_PPC32 */ #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_MERGE) extern atomic_t ipi_recv; extern atomic_t ipi_sent; #endif -#endif /* CONFIG_PPC32 */ #ifdef CONFIG_PPC64 EXPORT_SYMBOL(irq_desc); int distribute_irqs = 1; -u64 ppc64_interrupt_controller; #endif /* CONFIG_PPC64 */ int show_interrupts(struct seq_file *p, void *v) @@ -183,7 +186,7 @@ void fixup_irqs(cpumask_t map) void do_IRQ(struct pt_regs *regs) { - int irq; + unsigned int irq; #ifdef CONFIG_IRQSTACKS struct thread_info *curtp, *irqtp; #endif @@ -214,22 +217,26 @@ void do_IRQ(struct pt_regs *regs) */ irq = ppc_md.get_irq(regs); - if (irq >= 0) { + if (irq != NO_IRQ && irq != NO_IRQ_IGNORE) { #ifdef CONFIG_IRQSTACKS /* Switch to the irq stack to handle this */ curtp = current_thread_info(); irqtp = hardirq_ctx[smp_processor_id()]; if (curtp != irqtp) { + struct irq_desc *desc = irq_desc + irq; + void *handler = desc->handle_irq; + if (handler == NULL) + handler = &__do_IRQ; irqtp->task = curtp->task; irqtp->flags = 0; - call___do_IRQ(irq, regs, irqtp); + call_handle_irq(irq, desc, regs, irqtp, handler); irqtp->task = NULL; if (irqtp->flags) set_bits(irqtp->flags, &curtp->flags); } else #endif - __do_IRQ(irq, regs); - } else if (irq != -2) + generic_handle_irq(irq, regs); + } else if (irq != NO_IRQ_IGNORE) /* That's not SMP safe ... but who cares ? */ ppc_spurious_interrupts++; @@ -246,196 +253,562 @@ void do_IRQ(struct pt_regs *regs) void __init init_IRQ(void) { + ppc_md.init_IRQ(); #ifdef CONFIG_PPC64 - static int once = 0; + irq_ctx_init(); +#endif +} + + +#ifdef CONFIG_IRQSTACKS +struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; +struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; + +void irq_ctx_init(void) +{ + struct thread_info *tp; + int i; + + for_each_possible_cpu(i) { + memset((void *)softirq_ctx[i], 0, THREAD_SIZE); + tp = softirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = SOFTIRQ_OFFSET; + + memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); + tp = hardirq_ctx[i]; + tp->cpu = i; + tp->preempt_count = HARDIRQ_OFFSET; + } +} + +static inline void do_softirq_onstack(void) +{ + struct thread_info *curtp, *irqtp; + + curtp = current_thread_info(); + irqtp = softirq_ctx[smp_processor_id()]; + irqtp->task = curtp->task; + call_do_softirq(irqtp); + irqtp->task = NULL; +} - if (once) +#else +#define do_softirq_onstack() __do_softirq() +#endif /* CONFIG_IRQSTACKS */ + +void do_softirq(void) +{ + unsigned long flags; + + if (in_interrupt()) return; - once++; + local_irq_save(flags); -#endif - ppc_md.init_IRQ(); -#ifdef CONFIG_PPC64 - irq_ctx_init(); -#endif + if (local_softirq_pending()) + do_softirq_onstack(); + + local_irq_restore(flags); } +EXPORT_SYMBOL(do_softirq); + -#ifdef CONFIG_PPC64 /* - * Virtual IRQ mapping code, used on systems with XICS interrupt controllers. + * IRQ controller and virtual interrupts */ -#define UNDEFINED_IRQ 0xffffffff -unsigned int virt_irq_to_real_map[NR_IRQS]; +#ifdef CONFIG_PPC_MERGE -/* - * Don't use virtual irqs 0, 1, 2 for devices. - * The pcnet32 driver considers interrupt numbers < 2 to be invalid, - * and 2 is the XICS IPI interrupt. - * We limit virtual irqs to __irq_offet_value less than virt_irq_max so - * that when we offset them we don't end up with an interrupt - * number >= virt_irq_max. - */ -#define MIN_VIRT_IRQ 3 +static LIST_HEAD(irq_hosts); +static spinlock_t irq_big_lock = SPIN_LOCK_UNLOCKED; -unsigned int virt_irq_max; -static unsigned int max_virt_irq; -static unsigned int nr_virt_irqs; +struct irq_map_entry irq_map[NR_IRQS]; +static unsigned int irq_virq_count = NR_IRQS; +static struct irq_host *irq_default_host; -void -virt_irq_init(void) +struct irq_host *irq_alloc_host(unsigned int revmap_type, + unsigned int revmap_arg, + struct irq_host_ops *ops, + irq_hw_number_t inval_irq) { - int i; + struct irq_host *host; + unsigned int size = sizeof(struct irq_host); + unsigned int i; + unsigned int *rmap; + unsigned long flags; - if ((virt_irq_max == 0) || (virt_irq_max > (NR_IRQS - 1))) - virt_irq_max = NR_IRQS - 1; - max_virt_irq = virt_irq_max - __irq_offset_value; - nr_virt_irqs = max_virt_irq - MIN_VIRT_IRQ + 1; + /* Allocate structure and revmap table if using linear mapping */ + if (revmap_type == IRQ_HOST_MAP_LINEAR) + size += revmap_arg * sizeof(unsigned int); + if (mem_init_done) + host = kzalloc(size, GFP_KERNEL); + else { + host = alloc_bootmem(size); + if (host) + memset(host, 0, size); + } + if (host == NULL) + return NULL; - for (i = 0; i < NR_IRQS; i++) - virt_irq_to_real_map[i] = UNDEFINED_IRQ; + /* Fill structure */ + host->revmap_type = revmap_type; + host->inval_irq = inval_irq; + host->ops = ops; + + spin_lock_irqsave(&irq_big_lock, flags); + + /* If it's a legacy controller, check for duplicates and + * mark it as allocated (we use irq 0 host pointer for that + */ + if (revmap_type == IRQ_HOST_MAP_LEGACY) { + if (irq_map[0].host != NULL) { + spin_unlock_irqrestore(&irq_big_lock, flags); + /* If we are early boot, we can't free the structure, + * too bad... + * this will be fixed once slab is made available early + * instead of the current cruft + */ + if (mem_init_done) + kfree(host); + return NULL; + } + irq_map[0].host = host; + } + + list_add(&host->link, &irq_hosts); + spin_unlock_irqrestore(&irq_big_lock, flags); + + /* Additional setups per revmap type */ + switch(revmap_type) { + case IRQ_HOST_MAP_LEGACY: + /* 0 is always the invalid number for legacy */ + host->inval_irq = 0; + /* setup us as the host for all legacy interrupts */ + for (i = 1; i < NUM_ISA_INTERRUPTS; i++) { + irq_map[i].hwirq = 0; + smp_wmb(); + irq_map[i].host = host; + smp_wmb(); + + /* Clear some flags */ + get_irq_desc(i)->status + &= ~(IRQ_NOREQUEST | IRQ_LEVEL); + + /* Legacy flags are left to default at this point, + * one can then use irq_create_mapping() to + * explicitely change them + */ + ops->map(host, i, i, 0); + } + break; + case IRQ_HOST_MAP_LINEAR: + rmap = (unsigned int *)(host + 1); + for (i = 0; i < revmap_arg; i++) + rmap[i] = IRQ_NONE; + host->revmap_data.linear.size = revmap_arg; + smp_wmb(); + host->revmap_data.linear.revmap = rmap; + break; + default: + break; + } + + pr_debug("irq: Allocated host of type %d @0x%p\n", revmap_type, host); + + return host; } -/* Create a mapping for a real_irq if it doesn't already exist. - * Return the virtual irq as a convenience. - */ -int virt_irq_create_mapping(unsigned int real_irq) +struct irq_host *irq_find_host(struct device_node *node) { - unsigned int virq, first_virq; - static int warned; + struct irq_host *h, *found = NULL; + unsigned long flags; + + /* We might want to match the legacy controller last since + * it might potentially be set to match all interrupts in + * the absence of a device node. This isn't a problem so far + * yet though... + */ + spin_lock_irqsave(&irq_big_lock, flags); + list_for_each_entry(h, &irq_hosts, link) + if (h->ops->match == NULL || h->ops->match(h, node)) { + found = h; + break; + } + spin_unlock_irqrestore(&irq_big_lock, flags); + return found; +} +EXPORT_SYMBOL_GPL(irq_find_host); + +void irq_set_default_host(struct irq_host *host) +{ + pr_debug("irq: Default host set to @0x%p\n", host); + + irq_default_host = host; +} - if (ppc64_interrupt_controller == IC_OPEN_PIC) - return real_irq; /* no mapping for openpic (for now) */ +void irq_set_virq_count(unsigned int count) +{ + pr_debug("irq: Trying to set virq count to %d\n", count); - if (ppc64_interrupt_controller == IC_CELL_PIC) - return real_irq; /* no mapping for iic either */ + BUG_ON(count < NUM_ISA_INTERRUPTS); + if (count < NR_IRQS) + irq_virq_count = count; +} - /* don't map interrupts < MIN_VIRT_IRQ */ - if (real_irq < MIN_VIRT_IRQ) { - virt_irq_to_real_map[real_irq] = real_irq; - return real_irq; +unsigned int irq_create_mapping(struct irq_host *host, + irq_hw_number_t hwirq, + unsigned int flags) +{ + unsigned int virq, hint; + + pr_debug("irq: irq_create_mapping(0x%p, 0x%lx, 0x%x)\n", + host, hwirq, flags); + + /* Look for default host if nececssary */ + if (host == NULL) + host = irq_default_host; + if (host == NULL) { + printk(KERN_WARNING "irq_create_mapping called for" + " NULL host, hwirq=%lx\n", hwirq); + WARN_ON(1); + return NO_IRQ; } + pr_debug("irq: -> using host @%p\n", host); - /* map to a number between MIN_VIRT_IRQ and max_virt_irq */ - virq = real_irq; - if (virq > max_virt_irq) - virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ; - - /* search for this number or a free slot */ - first_virq = virq; - while (virt_irq_to_real_map[virq] != UNDEFINED_IRQ) { - if (virt_irq_to_real_map[virq] == real_irq) - return virq; - if (++virq > max_virt_irq) - virq = MIN_VIRT_IRQ; - if (virq == first_virq) - goto nospace; /* oops, no free slots */ + /* Check if mapping already exist, if it does, call + * host->ops->map() to update the flags + */ + virq = irq_find_mapping(host, hwirq); + if (virq != IRQ_NONE) { + pr_debug("irq: -> existing mapping on virq %d\n", virq); + host->ops->map(host, virq, hwirq, flags); + return virq; + } + + /* Get a virtual interrupt number */ + if (host->revmap_type == IRQ_HOST_MAP_LEGACY) { + /* Handle legacy */ + virq = (unsigned int)hwirq; + if (virq == 0 || virq >= NUM_ISA_INTERRUPTS) + return NO_IRQ; + return virq; + } else { + /* Allocate a virtual interrupt number */ + hint = hwirq % irq_virq_count; + virq = irq_alloc_virt(host, 1, hint); + if (virq == NO_IRQ) { + pr_debug("irq: -> virq allocation failed\n"); + return NO_IRQ; + } } + pr_debug("irq: -> obtained virq %d\n", virq); - virt_irq_to_real_map[virq] = real_irq; + /* Clear some flags */ + get_irq_desc(virq)->status &= ~(IRQ_NOREQUEST | IRQ_LEVEL); + + /* map it */ + if (host->ops->map(host, virq, hwirq, flags)) { + pr_debug("irq: -> mapping failed, freeing\n"); + irq_free_virt(virq, 1); + return NO_IRQ; + } + smp_wmb(); + irq_map[virq].hwirq = hwirq; + smp_mb(); return virq; +} +EXPORT_SYMBOL_GPL(irq_create_mapping); - nospace: - if (!warned) { - printk(KERN_CRIT "Interrupt table is full\n"); - printk(KERN_CRIT "Increase virt_irq_max (currently %d) " - "in your kernel sources and rebuild.\n", virt_irq_max); - warned = 1; +extern unsigned int irq_create_of_mapping(struct device_node *controller, + u32 *intspec, unsigned int intsize) +{ + struct irq_host *host; + irq_hw_number_t hwirq; + unsigned int flags = IRQ_TYPE_NONE; + + if (controller == NULL) + host = irq_default_host; + else + host = irq_find_host(controller); + if (host == NULL) + return NO_IRQ; + + /* If host has no translation, then we assume interrupt line */ + if (host->ops->xlate == NULL) + hwirq = intspec[0]; + else { + if (host->ops->xlate(host, controller, intspec, intsize, + &hwirq, &flags)) + return NO_IRQ; } - return NO_IRQ; + + return irq_create_mapping(host, hwirq, flags); } +EXPORT_SYMBOL_GPL(irq_create_of_mapping); -/* - * In most cases will get a hit on the very first slot checked in the - * virt_irq_to_real_map. Only when there are a large number of - * IRQs will this be expensive. - */ -unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) +unsigned int irq_of_parse_and_map(struct device_node *dev, int index) { - unsigned int virq; - unsigned int first_virq; + struct of_irq oirq; - virq = real_irq; + if (of_irq_map_one(dev, index, &oirq)) + return NO_IRQ; - if (virq > max_virt_irq) - virq = (virq % nr_virt_irqs) + MIN_VIRT_IRQ; + return irq_create_of_mapping(oirq.controller, oirq.specifier, + oirq.size); +} +EXPORT_SYMBOL_GPL(irq_of_parse_and_map); - first_virq = virq; +void irq_dispose_mapping(unsigned int virq) +{ + struct irq_host *host = irq_map[virq].host; + irq_hw_number_t hwirq; + unsigned long flags; - do { - if (virt_irq_to_real_map[virq] == real_irq) - return virq; + WARN_ON (host == NULL); + if (host == NULL) + return; - virq++; + /* Never unmap legacy interrupts */ + if (host->revmap_type == IRQ_HOST_MAP_LEGACY) + return; - if (virq >= max_virt_irq) - virq = 0; + /* remove chip and handler */ + set_irq_chip_and_handler(virq, NULL, NULL); + + /* Make sure it's completed */ + synchronize_irq(virq); + + /* Tell the PIC about it */ + if (host->ops->unmap) + host->ops->unmap(host, virq); + smp_mb(); + + /* Clear reverse map */ + hwirq = irq_map[virq].hwirq; + switch(host->revmap_type) { + case IRQ_HOST_MAP_LINEAR: + if (hwirq < host->revmap_data.linear.size) + host->revmap_data.linear.revmap[hwirq] = IRQ_NONE; + break; + case IRQ_HOST_MAP_TREE: + /* Check if radix tree allocated yet */ + if (host->revmap_data.tree.gfp_mask == 0) + break; + /* XXX radix tree not safe ! remove lock whem it becomes safe + * and use some RCU sync to make sure everything is ok before we + * can re-use that map entry + */ + spin_lock_irqsave(&irq_big_lock, flags); + radix_tree_delete(&host->revmap_data.tree, hwirq); + spin_unlock_irqrestore(&irq_big_lock, flags); + break; + } - } while (first_virq != virq); + /* Destroy map */ + smp_mb(); + irq_map[virq].hwirq = host->inval_irq; - return NO_IRQ; + /* Set some flags */ + get_irq_desc(virq)->status |= IRQ_NOREQUEST; + /* Free it */ + irq_free_virt(virq, 1); } -#endif /* CONFIG_PPC64 */ +EXPORT_SYMBOL_GPL(irq_dispose_mapping); -#ifdef CONFIG_IRQSTACKS -struct thread_info *softirq_ctx[NR_CPUS] __read_mostly; -struct thread_info *hardirq_ctx[NR_CPUS] __read_mostly; +unsigned int irq_find_mapping(struct irq_host *host, + irq_hw_number_t hwirq) +{ + unsigned int i; + unsigned int hint = hwirq % irq_virq_count; + + /* Look for default host if nececssary */ + if (host == NULL) + host = irq_default_host; + if (host == NULL) + return NO_IRQ; + + /* legacy -> bail early */ + if (host->revmap_type == IRQ_HOST_MAP_LEGACY) + return hwirq; + + /* Slow path does a linear search of the map */ + if (hint < NUM_ISA_INTERRUPTS) + hint = NUM_ISA_INTERRUPTS; + i = hint; + do { + if (irq_map[i].host == host && + irq_map[i].hwirq == hwirq) + return i; + i++; + if (i >= irq_virq_count) + i = NUM_ISA_INTERRUPTS; + } while(i != hint); + return NO_IRQ; +} +EXPORT_SYMBOL_GPL(irq_find_mapping); -void irq_ctx_init(void) + +unsigned int irq_radix_revmap(struct irq_host *host, + irq_hw_number_t hwirq) { - struct thread_info *tp; - int i; + struct radix_tree_root *tree; + struct irq_map_entry *ptr; + unsigned int virq; + unsigned long flags; - for_each_possible_cpu(i) { - memset((void *)softirq_ctx[i], 0, THREAD_SIZE); - tp = softirq_ctx[i]; - tp->cpu = i; - tp->preempt_count = SOFTIRQ_OFFSET; + WARN_ON(host->revmap_type != IRQ_HOST_MAP_TREE); - memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); - tp = hardirq_ctx[i]; - tp->cpu = i; - tp->preempt_count = HARDIRQ_OFFSET; + /* Check if the radix tree exist yet. We test the value of + * the gfp_mask for that. Sneaky but saves another int in the + * structure. If not, we fallback to slow mode + */ + tree = &host->revmap_data.tree; + if (tree->gfp_mask == 0) + return irq_find_mapping(host, hwirq); + + /* XXX Current radix trees are NOT SMP safe !!! Remove that lock + * when that is fixed (when Nick's patch gets in + */ + spin_lock_irqsave(&irq_big_lock, flags); + + /* Now try to resolve */ + ptr = radix_tree_lookup(tree, hwirq); + /* Found it, return */ + if (ptr) { + virq = ptr - irq_map; + goto bail; } + + /* If not there, try to insert it */ + virq = irq_find_mapping(host, hwirq); + if (virq != NO_IRQ) + radix_tree_insert(tree, virq, &irq_map[virq]); + bail: + spin_unlock_irqrestore(&irq_big_lock, flags); + return virq; } -static inline void do_softirq_onstack(void) +unsigned int irq_linear_revmap(struct irq_host *host, + irq_hw_number_t hwirq) { - struct thread_info *curtp, *irqtp; + unsigned int *revmap; - curtp = current_thread_info(); - irqtp = softirq_ctx[smp_processor_id()]; - irqtp->task = curtp->task; - call_do_softirq(irqtp); - irqtp->task = NULL; + WARN_ON(host->revmap_type != IRQ_HOST_MAP_LINEAR); + + /* Check revmap bounds */ + if (unlikely(hwirq >= host->revmap_data.linear.size)) + return irq_find_mapping(host, hwirq); + + /* Check if revmap was allocated */ + revmap = host->revmap_data.linear.revmap; + if (unlikely(revmap == NULL)) + return irq_find_mapping(host, hwirq); + + /* Fill up revmap with slow path if no mapping found */ + if (unlikely(revmap[hwirq] == NO_IRQ)) + revmap[hwirq] = irq_find_mapping(host, hwirq); + + return revmap[hwirq]; } -#else -#define do_softirq_onstack() __do_softirq() -#endif /* CONFIG_IRQSTACKS */ +unsigned int irq_alloc_virt(struct irq_host *host, + unsigned int count, + unsigned int hint) +{ + unsigned long flags; + unsigned int i, j, found = NO_IRQ; + unsigned int limit = irq_virq_count - count; -void do_softirq(void) + if (count == 0 || count > (irq_virq_count - NUM_ISA_INTERRUPTS)) + return NO_IRQ; + + spin_lock_irqsave(&irq_big_lock, flags); + + /* Use hint for 1 interrupt if any */ + if (count == 1 && hint >= NUM_ISA_INTERRUPTS && + hint < irq_virq_count && irq_map[hint].host == NULL) { + found = hint; + goto hint_found; + } + + /* Look for count consecutive numbers in the allocatable + * (non-legacy) space + */ + for (i = NUM_ISA_INTERRUPTS; i <= limit; ) { + for (j = i; j < (i + count); j++) + if (irq_map[j].host != NULL) { + i = j + 1; + continue; + } + found = i; + break; + } + if (found == NO_IRQ) { + spin_unlock_irqrestore(&irq_big_lock, flags); + return NO_IRQ; + } + hint_found: + for (i = found; i < (found + count); i++) { + irq_map[i].hwirq = host->inval_irq; + smp_wmb(); + irq_map[i].host = host; + } + spin_unlock_irqrestore(&irq_big_lock, flags); + return found; +} + +void irq_free_virt(unsigned int virq, unsigned int count) { unsigned long flags; + unsigned int i; - if (in_interrupt()) - return; + WARN_ON (virq < NUM_ISA_INTERRUPTS); + WARN_ON (count == 0 || (virq + count) > irq_virq_count); - local_irq_save(flags); + spin_lock_irqsave(&irq_big_lock, flags); + for (i = virq; i < (virq + count); i++) { + struct irq_host *host; - if (local_softirq_pending()) { - account_system_vtime(current); - local_bh_disable(); - do_softirq_onstack(); - account_system_vtime(current); - __local_bh_enable(); + if (i < NUM_ISA_INTERRUPTS || + (virq + count) > irq_virq_count) + continue; + + host = irq_map[i].host; + irq_map[i].hwirq = host->inval_irq; + smp_wmb(); + irq_map[i].host = NULL; } + spin_unlock_irqrestore(&irq_big_lock, flags); +} - local_irq_restore(flags); +void irq_early_init(void) +{ + unsigned int i; + + for (i = 0; i < NR_IRQS; i++) + get_irq_desc(i)->status |= IRQ_NOREQUEST; } -EXPORT_SYMBOL(do_softirq); + +/* We need to create the radix trees late */ +static int irq_late_init(void) +{ + struct irq_host *h; + unsigned long flags; + + spin_lock_irqsave(&irq_big_lock, flags); + list_for_each_entry(h, &irq_hosts, link) { + if (h->revmap_type == IRQ_HOST_MAP_TREE) + INIT_RADIX_TREE(&h->revmap_data.tree, GFP_ATOMIC); + } + spin_unlock_irqrestore(&irq_big_lock, flags); + + return 0; +} +arch_initcall(irq_late_init); + +#endif /* CONFIG_PPC_MERGE */ #ifdef CONFIG_PCI_MSI int pci_enable_msi(struct pci_dev * pdev) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index f78866367b70..9f0898c89759 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -26,7 +26,6 @@ * for PPC64 */ -#include <linux/config.h> #include <linux/kprobes.h> #include <linux/ptrace.h> #include <linux/preempt.h> diff --git a/arch/powerpc/kernel/l2cr_6xx.S b/arch/powerpc/kernel/l2cr_6xx.S index d7f4e982b539..858f28ac8a06 100644 --- a/arch/powerpc/kernel/l2cr_6xx.S +++ b/arch/powerpc/kernel/l2cr_6xx.S @@ -40,7 +40,6 @@ Author: Terry Greeniaus (tgree@phys.ualberta.ca) Please e-mail updates to this file to me, thanks! */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/cputable.h> #include <asm/ppc_asm.h> diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 3a9b78d03542..7e98e778b52f 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/serial.h> #include <linux/serial_8250.h> @@ -29,6 +28,7 @@ static struct legacy_serial_info { struct device_node *np; unsigned int speed; unsigned int clock; + int irq_check_parent; phys_addr_t taddr; } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; static unsigned int legacy_serial_count; @@ -37,7 +37,7 @@ static int legacy_serial_console = -1; static int __init add_legacy_port(struct device_node *np, int want_index, int iotype, phys_addr_t base, phys_addr_t taddr, unsigned long irq, - upf_t flags) + upf_t flags, int irq_check_parent) { u32 *clk, *spd, clock = BASE_BAUD * 16; int index; @@ -69,7 +69,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index, if (legacy_serial_infos[index].np != 0) { /* if we still have some room, move it, else override */ if (legacy_serial_count < MAX_LEGACY_SERIAL_PORTS) { - printk(KERN_INFO "Moved legacy port %d -> %d\n", + printk(KERN_DEBUG "Moved legacy port %d -> %d\n", index, legacy_serial_count); legacy_serial_ports[legacy_serial_count] = legacy_serial_ports[index]; @@ -77,7 +77,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index, legacy_serial_infos[index]; legacy_serial_count++; } else { - printk(KERN_INFO "Replacing legacy port %d\n", index); + printk(KERN_DEBUG "Replacing legacy port %d\n", index); } } @@ -96,10 +96,11 @@ static int __init add_legacy_port(struct device_node *np, int want_index, legacy_serial_infos[index].np = of_node_get(np); legacy_serial_infos[index].clock = clock; legacy_serial_infos[index].speed = spd ? *spd : 0; + legacy_serial_infos[index].irq_check_parent = irq_check_parent; - printk(KERN_INFO "Found legacy serial port %d for %s\n", + printk(KERN_DEBUG "Found legacy serial port %d for %s\n", index, np->full_name); - printk(KERN_INFO " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n", + printk(KERN_DEBUG " %s=%llx, taddr=%llx, irq=%lx, clk=%d, speed=%d\n", (iotype == UPIO_PORT) ? "port" : "mem", (unsigned long long)base, (unsigned long long)taddr, irq, legacy_serial_ports[index].uartclk, @@ -127,11 +128,13 @@ static int __init add_legacy_soc_port(struct device_node *np, return -1; addr = of_translate_address(soc_dev, addrp); + if (addr == OF_BAD_ADDR) + return -1; /* Add port, irq will be dealt with later. We passed a translated * IO port value. It will be fixed up later along with the irq */ - return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags); + return add_legacy_port(np, -1, UPIO_MEM, addr, addr, NO_IRQ, flags, 0); } static int __init add_legacy_isa_port(struct device_node *np, @@ -142,6 +145,8 @@ static int __init add_legacy_isa_port(struct device_node *np, int index = -1; phys_addr_t taddr; + DBG(" -> add_legacy_isa_port(%s)\n", np->full_name); + /* Get the ISA port number */ reg = (u32 *)get_property(np, "reg", NULL); if (reg == NULL) @@ -162,9 +167,12 @@ static int __init add_legacy_isa_port(struct device_node *np, /* Translate ISA address */ taddr = of_translate_address(np, reg); + if (taddr == OF_BAD_ADDR) + return -1; /* Add port, irq will be dealt with later */ - return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, NO_IRQ, UPF_BOOT_AUTOCONF); + return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, + NO_IRQ, UPF_BOOT_AUTOCONF, 0); } @@ -177,6 +185,8 @@ static int __init add_legacy_pci_port(struct device_node *np, unsigned int flags; int iotype, index = -1, lindex = 0; + DBG(" -> add_legacy_pci_port(%s)\n", np->full_name); + /* We only support ports that have a clock frequency properly * encoded in the device-tree (that is have an fcode). Anything * else can't be used that early and will be normally probed by @@ -195,6 +205,8 @@ static int __init add_legacy_pci_port(struct device_node *np, /* We only support BAR 0 for now */ iotype = (flags & IORESOURCE_MEM) ? UPIO_MEM : UPIO_PORT; addr = of_translate_address(pci_dev, addrp); + if (addr == OF_BAD_ADDR) + return -1; /* Set the IO base to the same as the translated address for MMIO, * or to the domain local IO base for PIO (it will be fixed up later) @@ -232,7 +244,8 @@ static int __init add_legacy_pci_port(struct device_node *np, /* Add port, irq will be dealt with later. We passed a translated * IO port value. It will be fixed up later along with the irq */ - return add_legacy_port(np, index, iotype, base, addr, NO_IRQ, UPF_BOOT_AUTOCONF); + return add_legacy_port(np, index, iotype, base, addr, NO_IRQ, + UPF_BOOT_AUTOCONF, np != pci_dev); } #endif @@ -363,27 +376,22 @@ static void __init fixup_port_irq(int index, struct device_node *np, struct plat_serial8250_port *port) { + unsigned int virq; + DBG("fixup_port_irq(%d)\n", index); - /* Check for interrupts in that node */ - if (np->n_intrs > 0) { - port->irq = np->intrs[0].line; - DBG(" port %d (%s), irq=%d\n", - index, np->full_name, port->irq); - return; + virq = irq_of_parse_and_map(np, 0); + if (virq == NO_IRQ && legacy_serial_infos[index].irq_check_parent) { + np = of_get_parent(np); + if (np == NULL) + return; + virq = irq_of_parse_and_map(np, 0); + of_node_put(np); } - - /* Check for interrupts in the parent */ - np = of_get_parent(np); - if (np == NULL) + if (virq == NO_IRQ) return; - if (np->n_intrs > 0) { - port->irq = np->intrs[0].line; - DBG(" port %d (%s), irq=%d\n", - index, np->full_name, port->irq); - } - of_node_put(np); + port->irq = virq; } static void __init fixup_port_pio(int index, diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 73edc3c16137..23f34daa044a 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -18,7 +18,6 @@ * keyword - value pairs that specify the configuration of the partition. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/types.h> #include <linux/errno.h> diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index c74774e2175d..58758d883361 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -16,7 +16,6 @@ * */ -#include <linux/config.h> #include <linux/sys.h> #include <asm/unistd.h> #include <asm/errno.h> diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 580891cb8ccb..bfb407fc1aa1 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -14,7 +14,6 @@ * */ -#include <linux/config.h> #include <linux/sys.h> #include <asm/unistd.h> #include <asm/errno.h> @@ -52,12 +51,14 @@ _GLOBAL(call_do_softirq) mtlr r0 blr -_GLOBAL(call___do_IRQ) +_GLOBAL(call_handle_irq) + ld r8,0(r7) mflr r0 std r0,16(r1) - stdu r1,THREAD_SIZE-112(r5) - mr r1,r5 - bl .__do_IRQ + mtctr r8 + stdu r1,THREAD_SIZE-112(r6) + mr r1,r6 + bctrl ld r1,0(r1) ld r0,16(r1) mtlr r0 diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 9feeeef5a875..3262b73a3a68 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/string.h> #include <linux/kernel.h> #include <linux/init.h> diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index a0bb354c1c08..c68741fed14b 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c @@ -7,7 +7,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/types.h> #include <linux/threads.h> #include <linux/module.h> diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 8474355a1a4f..898dae8ab6d9 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -2,7 +2,6 @@ * Common pmac/prep/chrp pci routines. -- Cort */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/delay.h> @@ -1405,6 +1404,43 @@ pcibios_update_irq(struct pci_dev *dev, int irq) /* XXX FIXME - update OF device tree node interrupt property */ } +#ifdef CONFIG_PPC_MERGE +/* XXX This is a copy of the ppc64 version. This is temporary until we start + * merging the 2 PCI layers + */ +/* + * Reads the interrupt pin to determine if interrupt is use by card. + * If the interrupt is used, then gets the interrupt line from the + * openfirmware and sets it in the pci_dev and pci_config line. + */ +int pci_read_irq_line(struct pci_dev *pci_dev) +{ + struct of_irq oirq; + unsigned int virq; + + DBG("Try to map irq for %s...\n", pci_name(pci_dev)); + + if (of_irq_map_pci(pci_dev, &oirq)) { + DBG(" -> failed !\n"); + return -1; + } + + DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.controller->full_name); + + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); + if(virq == NO_IRQ) { + DBG(" -> failed to map !\n"); + return -1; + } + pci_dev->irq = virq; + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq); + + return 0; +} +EXPORT_SYMBOL(pci_read_irq_line); +#endif /* CONFIG_PPC_MERGE */ + int pcibios_enable_device(struct pci_dev *dev, int mask) { u16 cmd, old_cmd; diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 286aa52aae33..efc0b5559ee0 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -13,7 +13,6 @@ #undef DEBUG -#include <linux/config.h> #include <linux/kernel.h> #include <linux/pci.h> #include <linux/string.h> @@ -399,12 +398,8 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, } else { dev->hdr_type = PCI_HEADER_TYPE_NORMAL; dev->rom_base_reg = PCI_ROM_ADDRESS; + /* Maybe do a default OF mapping here */ dev->irq = NO_IRQ; - if (node->n_intrs > 0) { - dev->irq = node->intrs[0].line; - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, - dev->irq); - } } pci_parse_of_addrs(node, dev); @@ -1289,23 +1284,26 @@ EXPORT_SYMBOL(pcibios_fixup_bus); */ int pci_read_irq_line(struct pci_dev *pci_dev) { - u8 intpin; - struct device_node *node; - - pci_read_config_byte(pci_dev, PCI_INTERRUPT_PIN, &intpin); - if (intpin == 0) - return 0; + struct of_irq oirq; + unsigned int virq; - node = pci_device_to_OF_node(pci_dev); - if (node == NULL) - return -1; + DBG("Try to map irq for %s...\n", pci_name(pci_dev)); - if (node->n_intrs == 0) + if (of_irq_map_pci(pci_dev, &oirq)) { + DBG(" -> failed !\n"); return -1; + } - pci_dev->irq = node->intrs[0].line; + DBG(" -> got one, spec %d cells (0x%08x...) on %s\n", + oirq.size, oirq.specifier[0], oirq.controller->full_name); - pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, pci_dev->irq); + virq = irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); + if(virq == NO_IRQ) { + DBG(" -> failed to map !\n"); + return -1; + } + pci_dev->irq = virq; + pci_write_config_byte(pci_dev, PCI_INTERRUPT_LINE, virq); return 0; } diff --git a/arch/powerpc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c index 32455dfcc36b..bdc3977a7b06 100644 --- a/arch/powerpc/kernel/perfmon_fsl_booke.c +++ b/arch/powerpc/kernel/perfmon_fsl_booke.c @@ -21,7 +21,6 @@ #include <linux/user.h> #include <linux/a.out.h> #include <linux/interrupt.h> -#include <linux/config.h> #include <linux/init.h> #include <linux/module.h> #include <linux/prctl.h> diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c index e6fb194fe537..a0a2efadeabf 100644 --- a/arch/powerpc/kernel/pmc.c +++ b/arch/powerpc/kernel/pmc.c @@ -12,7 +12,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/spinlock.h> #include <linux/module.h> diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 4b052ae5dc34..e3b80f71748e 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/module.h> #include <linux/threads.h> #include <linux/smp.h> diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 2ab8f2be911e..f598cb519539 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -16,7 +16,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <linux/config.h> #include <linux/init.h> #include <linux/mm.h> #include <linux/proc_fs.h> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index e4732459c485..a127a1e3c097 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -14,7 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 320c913435cd..a1787ffb6319 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -16,7 +16,6 @@ #undef DEBUG #include <stdarg.h> -#include <linux/config.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> @@ -31,6 +30,7 @@ #include <linux/module.h> #include <linux/kexec.h> #include <linux/debugfs.h> +#include <linux/irq.h> #include <asm/prom.h> #include <asm/rtas.h> @@ -87,424 +87,6 @@ static DEFINE_RWLOCK(devtree_lock); /* export that to outside world */ struct device_node *of_chosen; -struct device_node *dflt_interrupt_controller; -int num_interrupt_controllers; - -/* - * Wrapper for allocating memory for various data that needs to be - * attached to device nodes as they are processed at boot or when - * added to the device tree later (e.g. DLPAR). At boot there is - * already a region reserved so we just increment *mem_start by size; - * otherwise we call kmalloc. - */ -static void * prom_alloc(unsigned long size, unsigned long *mem_start) -{ - unsigned long tmp; - - if (!mem_start) - return kmalloc(size, GFP_KERNEL); - - tmp = *mem_start; - *mem_start += size; - return (void *)tmp; -} - -/* - * Find the device_node with a given phandle. - */ -static struct device_node * find_phandle(phandle ph) -{ - struct device_node *np; - - for (np = allnodes; np != 0; np = np->allnext) - if (np->linux_phandle == ph) - return np; - return NULL; -} - -/* - * Find the interrupt parent of a node. - */ -static struct device_node * __devinit intr_parent(struct device_node *p) -{ - phandle *parp; - - parp = (phandle *) get_property(p, "interrupt-parent", NULL); - if (parp == NULL) - return p->parent; - p = find_phandle(*parp); - if (p != NULL) - return p; - /* - * On a powermac booted with BootX, we don't get to know the - * phandles for any nodes, so find_phandle will return NULL. - * Fortunately these machines only have one interrupt controller - * so there isn't in fact any ambiguity. -- paulus - */ - if (num_interrupt_controllers == 1) - p = dflt_interrupt_controller; - return p; -} - -/* - * Find out the size of each entry of the interrupts property - * for a node. - */ -int __devinit prom_n_intr_cells(struct device_node *np) -{ - struct device_node *p; - unsigned int *icp; - - for (p = np; (p = intr_parent(p)) != NULL; ) { - icp = (unsigned int *) - get_property(p, "#interrupt-cells", NULL); - if (icp != NULL) - return *icp; - if (get_property(p, "interrupt-controller", NULL) != NULL - || get_property(p, "interrupt-map", NULL) != NULL) { - printk("oops, node %s doesn't have #interrupt-cells\n", - p->full_name); - return 1; - } - } -#ifdef DEBUG_IRQ - printk("prom_n_intr_cells failed for %s\n", np->full_name); -#endif - return 1; -} - -/* - * Map an interrupt from a device up to the platform interrupt - * descriptor. - */ -static int __devinit map_interrupt(unsigned int **irq, struct device_node **ictrler, - struct device_node *np, unsigned int *ints, - int nintrc) -{ - struct device_node *p, *ipar; - unsigned int *imap, *imask, *ip; - int i, imaplen, match; - int newintrc = 0, newaddrc = 0; - unsigned int *reg; - int naddrc; - - reg = (unsigned int *) get_property(np, "reg", NULL); - naddrc = prom_n_addr_cells(np); - p = intr_parent(np); - while (p != NULL) { - if (get_property(p, "interrupt-controller", NULL) != NULL) - /* this node is an interrupt controller, stop here */ - break; - imap = (unsigned int *) - get_property(p, "interrupt-map", &imaplen); - if (imap == NULL) { - p = intr_parent(p); - continue; - } - imask = (unsigned int *) - get_property(p, "interrupt-map-mask", NULL); - if (imask == NULL) { - printk("oops, %s has interrupt-map but no mask\n", - p->full_name); - return 0; - } - imaplen /= sizeof(unsigned int); - match = 0; - ipar = NULL; - while (imaplen > 0 && !match) { - /* check the child-interrupt field */ - match = 1; - for (i = 0; i < naddrc && match; ++i) - match = ((reg[i] ^ imap[i]) & imask[i]) == 0; - for (; i < naddrc + nintrc && match; ++i) - match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; - imap += naddrc + nintrc; - imaplen -= naddrc + nintrc; - /* grab the interrupt parent */ - ipar = find_phandle((phandle) *imap++); - --imaplen; - if (ipar == NULL && num_interrupt_controllers == 1) - /* cope with BootX not giving us phandles */ - ipar = dflt_interrupt_controller; - if (ipar == NULL) { - printk("oops, no int parent %x in map of %s\n", - imap[-1], p->full_name); - return 0; - } - /* find the parent's # addr and intr cells */ - ip = (unsigned int *) - get_property(ipar, "#interrupt-cells", NULL); - if (ip == NULL) { - printk("oops, no #interrupt-cells on %s\n", - ipar->full_name); - return 0; - } - newintrc = *ip; - ip = (unsigned int *) - get_property(ipar, "#address-cells", NULL); - newaddrc = (ip == NULL)? 0: *ip; - imap += newaddrc + newintrc; - imaplen -= newaddrc + newintrc; - } - if (imaplen < 0) { - printk("oops, error decoding int-map on %s, len=%d\n", - p->full_name, imaplen); - return 0; - } - if (!match) { -#ifdef DEBUG_IRQ - printk("oops, no match in %s int-map for %s\n", - p->full_name, np->full_name); -#endif - return 0; - } - p = ipar; - naddrc = newaddrc; - nintrc = newintrc; - ints = imap - nintrc; - reg = ints - naddrc; - } - if (p == NULL) { -#ifdef DEBUG_IRQ - printk("hmmm, int tree for %s doesn't have ctrler\n", - np->full_name); -#endif - return 0; - } - *irq = ints; - *ictrler = p; - return nintrc; -} - -static unsigned char map_isa_senses[4] = { - IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, - IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE, - IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE, - IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE -}; - -static unsigned char map_mpic_senses[4] = { - IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE, - IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, - /* 2 seems to be used for the 8259 cascade... */ - IRQ_SENSE_LEVEL | IRQ_POLARITY_POSITIVE, - IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE, -}; - -static int __devinit finish_node_interrupts(struct device_node *np, - unsigned long *mem_start, - int measure_only) -{ - unsigned int *ints; - int intlen, intrcells, intrcount; - int i, j, n, sense; - unsigned int *irq, virq; - struct device_node *ic; - int trace = 0; - - //#define TRACE(fmt...) do { if (trace) { printk(fmt); mdelay(1000); } } while(0) -#define TRACE(fmt...) - - if (!strcmp(np->name, "smu-doorbell")) - trace = 1; - - TRACE("Finishing SMU doorbell ! num_interrupt_controllers = %d\n", - num_interrupt_controllers); - - if (num_interrupt_controllers == 0) { - /* - * Old machines just have a list of interrupt numbers - * and no interrupt-controller nodes. - */ - ints = (unsigned int *) get_property(np, "AAPL,interrupts", - &intlen); - /* XXX old interpret_pci_props looked in parent too */ - /* XXX old interpret_macio_props looked for interrupts - before AAPL,interrupts */ - if (ints == NULL) - ints = (unsigned int *) get_property(np, "interrupts", - &intlen); - if (ints == NULL) - return 0; - - np->n_intrs = intlen / sizeof(unsigned int); - np->intrs = prom_alloc(np->n_intrs * sizeof(np->intrs[0]), - mem_start); - if (!np->intrs) - return -ENOMEM; - if (measure_only) - return 0; - - for (i = 0; i < np->n_intrs; ++i) { - np->intrs[i].line = *ints++; - np->intrs[i].sense = IRQ_SENSE_LEVEL - | IRQ_POLARITY_NEGATIVE; - } - return 0; - } - - ints = (unsigned int *) get_property(np, "interrupts", &intlen); - TRACE("ints=%p, intlen=%d\n", ints, intlen); - if (ints == NULL) - return 0; - intrcells = prom_n_intr_cells(np); - intlen /= intrcells * sizeof(unsigned int); - TRACE("intrcells=%d, new intlen=%d\n", intrcells, intlen); - np->intrs = prom_alloc(intlen * sizeof(*(np->intrs)), mem_start); - if (!np->intrs) - return -ENOMEM; - - if (measure_only) - return 0; - - intrcount = 0; - for (i = 0; i < intlen; ++i, ints += intrcells) { - n = map_interrupt(&irq, &ic, np, ints, intrcells); - TRACE("map, irq=%d, ic=%p, n=%d\n", irq, ic, n); - if (n <= 0) - continue; - - /* don't map IRQ numbers under a cascaded 8259 controller */ - if (ic && device_is_compatible(ic, "chrp,iic")) { - np->intrs[intrcount].line = irq[0]; - sense = (n > 1)? (irq[1] & 3): 3; - np->intrs[intrcount].sense = map_isa_senses[sense]; - } else { - virq = virt_irq_create_mapping(irq[0]); - TRACE("virq=%d\n", virq); -#ifdef CONFIG_PPC64 - if (virq == NO_IRQ) { - printk(KERN_CRIT "Could not allocate interrupt" - " number for %s\n", np->full_name); - continue; - } -#endif - np->intrs[intrcount].line = irq_offset_up(virq); - sense = (n > 1)? (irq[1] & 3): 1; - - /* Apple uses bits in there in a different way, let's - * only keep the real sense bit on macs - */ - if (machine_is(powermac)) - sense &= 0x1; - np->intrs[intrcount].sense = map_mpic_senses[sense]; - } - -#ifdef CONFIG_PPC64 - /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ - if (machine_is(powermac) && ic && ic->parent) { - char *name = get_property(ic->parent, "name", NULL); - if (name && !strcmp(name, "u3")) - np->intrs[intrcount].line += 128; - else if (!(name && (!strcmp(name, "mac-io") || - !strcmp(name, "u4")))) - /* ignore other cascaded controllers, such as - the k2-sata-root */ - break; - } -#endif /* CONFIG_PPC64 */ - if (n > 2) { - printk("hmmm, got %d intr cells for %s:", n, - np->full_name); - for (j = 0; j < n; ++j) - printk(" %d", irq[j]); - printk("\n"); - } - ++intrcount; - } - np->n_intrs = intrcount; - - return 0; -} - -static int __devinit finish_node(struct device_node *np, - unsigned long *mem_start, - int measure_only) -{ - struct device_node *child; - int rc = 0; - - rc = finish_node_interrupts(np, mem_start, measure_only); - if (rc) - goto out; - - for (child = np->child; child != NULL; child = child->sibling) { - rc = finish_node(child, mem_start, measure_only); - if (rc) - goto out; - } -out: - return rc; -} - -static void __init scan_interrupt_controllers(void) -{ - struct device_node *np; - int n = 0; - char *name, *ic; - int iclen; - - for (np = allnodes; np != NULL; np = np->allnext) { - ic = get_property(np, "interrupt-controller", &iclen); - name = get_property(np, "name", NULL); - /* checking iclen makes sure we don't get a false - match on /chosen.interrupt_controller */ - if ((name != NULL - && strcmp(name, "interrupt-controller") == 0) - || (ic != NULL && iclen == 0 - && strcmp(name, "AppleKiwi"))) { - if (n == 0) - dflt_interrupt_controller = np; - ++n; - } - } - num_interrupt_controllers = n; -} - -/** - * finish_device_tree is called once things are running normally - * (i.e. with text and data mapped to the address they were linked at). - * It traverses the device tree and fills in some of the additional, - * fields in each node like {n_}addrs and {n_}intrs, the virt interrupt - * mapping is also initialized at this point. - */ -void __init finish_device_tree(void) -{ - unsigned long start, end, size = 0; - - DBG(" -> finish_device_tree\n"); - -#ifdef CONFIG_PPC64 - /* Initialize virtual IRQ map */ - virt_irq_init(); -#endif - scan_interrupt_controllers(); - - /* - * Finish device-tree (pre-parsing some properties etc...) - * We do this in 2 passes. One with "measure_only" set, which - * will only measure the amount of memory needed, then we can - * allocate that memory, and call finish_node again. However, - * we must be careful as most routines will fail nowadays when - * prom_alloc() returns 0, so we must make sure our first pass - * doesn't start at 0. We pre-initialize size to 16 for that - * reason and then remove those additional 16 bytes - */ - size = 16; - finish_node(allnodes, &size, 1); - size -= 16; - - if (0 == size) - end = start = 0; - else - end = start = (unsigned long)__va(lmb_alloc(size, 128)); - - finish_node(allnodes, &end, 0); - BUG_ON(end != start + size); - - DBG(" <- finish_device_tree\n"); -} - static inline char *find_flat_dt_string(u32 offset) { return ((char *)initial_boot_params) + @@ -1390,27 +972,6 @@ prom_n_size_cells(struct device_node* np) EXPORT_SYMBOL(prom_n_size_cells); /** - * Work out the sense (active-low level / active-high edge) - * of each interrupt from the device tree. - */ -void __init prom_get_irq_senses(unsigned char *senses, int off, int max) -{ - struct device_node *np; - int i, j; - - /* default to level-triggered */ - memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, max - off); - - for (np = allnodes; np != 0; np = np->allnext) { - for (j = 0; j < np->n_intrs; j++) { - i = np->intrs[j].line; - if (i >= off && i < max) - senses[i-off] = np->intrs[j].sense; - } - } -} - -/** * Construct and return a list of the device_nodes with a given name. */ struct device_node *find_devices(const char *name) @@ -1809,7 +1370,6 @@ static void of_node_release(struct kref *kref) node->deadprops = NULL; } } - kfree(node->intrs); kfree(node->full_name); kfree(node->data); kfree(node); @@ -1882,13 +1442,7 @@ void of_detach_node(const struct device_node *np) #ifdef CONFIG_PPC_PSERIES /* * Fix up the uninitialized fields in a new device node: - * name, type, n_addrs, addrs, n_intrs, intrs, and pci-specific fields - * - * A lot of boot-time code is duplicated here, because functions such - * as finish_node_interrupts, interpret_pci_props, etc. cannot use the - * slab allocator. - * - * This should probably be split up into smaller chunks. + * name, type and pci-specific fields */ static int of_finish_dynamic_node(struct device_node *node) @@ -1929,8 +1483,6 @@ static int prom_reconfig_notifier(struct notifier_block *nb, switch (action) { case PSERIES_RECONFIG_ADD: err = of_finish_dynamic_node(node); - if (!err) - finish_node(node, NULL, 0); if (err < 0) { printk(KERN_ERR "finish_node returned %d\n", err); err = NOTIFY_BAD; @@ -1976,8 +1528,7 @@ struct property *of_find_property(struct device_node *np, const char *name, * Find a property with a given name for a given node * and return the value. */ -unsigned char *get_property(struct device_node *np, const char *name, - int *lenp) +void *get_property(struct device_node *np, const char *name, int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 8c28eb0cbdac..ebd501a59abd 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c @@ -16,7 +16,6 @@ #undef DEBUG_PROM #include <stdarg.h> -#include <linux/config.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/init.h> @@ -988,7 +987,7 @@ static void reserve_mem(u64 base, u64 size) } /* - * Initialize memory allocation mecanism, parse "memory" nodes and + * Initialize memory allocation mechanism, parse "memory" nodes and * obtain that way the top of memory and RMO to setup out local allocator */ static void __init prom_init_mem(void) @@ -1991,12 +1990,22 @@ static void __init flatten_device_tree(void) static void __init fixup_device_tree_maple(void) { phandle isa; + u32 rloc = 0x01002000; /* IO space; PCI device = 4 */ u32 isa_ranges[6]; - - isa = call_prom("finddevice", 1, 1, ADDR("/ht@0/isa@4")); + char *name; + + name = "/ht@0/isa@4"; + isa = call_prom("finddevice", 1, 1, ADDR(name)); + if (!PHANDLE_VALID(isa)) { + name = "/ht@0/isa@6"; + isa = call_prom("finddevice", 1, 1, ADDR(name)); + rloc = 0x01003000; /* IO space; PCI device = 6 */ + } if (!PHANDLE_VALID(isa)) return; + if (prom_getproplen(isa, "ranges") != 12) + return; if (prom_getprop(isa, "ranges", isa_ranges, sizeof(isa_ranges)) == PROM_ERROR) return; @@ -2006,15 +2015,15 @@ static void __init fixup_device_tree_maple(void) isa_ranges[2] != 0x00010000) return; - prom_printf("fixing up bogus ISA range on Maple...\n"); + prom_printf("Fixing up bogus ISA range on Maple/Apache...\n"); isa_ranges[0] = 0x1; isa_ranges[1] = 0x0; - isa_ranges[2] = 0x01002000; /* IO space; PCI device = 4 */ + isa_ranges[2] = rloc; isa_ranges[3] = 0x0; isa_ranges[4] = 0x0; isa_ranges[5] = 0x00010000; - prom_setprop(isa, "/ht@0/isa@4", "ranges", + prom_setprop(isa, name, "ranges", isa_ranges, sizeof(isa_ranges)); } #else diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 45df420383cc..21009b1f7869 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c @@ -38,14 +38,6 @@ static void of_dump_addr(const char *s, u32 *addr, int na) static void of_dump_addr(const char *s, u32 *addr, int na) { } #endif -/* Read a big address */ -static inline u64 of_read_addr(u32 *cell, int size) -{ - u64 r = 0; - while (size--) - r = (r << 32) | *(cell++); - return r; -} /* Callbacks for bus specific translators */ struct of_bus { @@ -77,9 +69,9 @@ static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) { u64 cp, s, da; - cp = of_read_addr(range, na); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr, na); + cp = of_read_number(range, na); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr, na); DBG("OF: default map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); @@ -91,7 +83,7 @@ static u64 of_bus_default_map(u32 *addr, u32 *range, int na, int ns, int pna) static int of_bus_default_translate(u32 *addr, u64 offset, int na) { - u64 a = of_read_addr(addr, na); + u64 a = of_read_number(addr, na); memset(addr, 0, na * 4); a += offset; if (na > 1) @@ -135,9 +127,9 @@ static u64 of_bus_pci_map(u32 *addr, u32 *range, int na, int ns, int pna) return OF_BAD_ADDR; /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); DBG("OF: PCI map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); @@ -195,9 +187,9 @@ static u64 of_bus_isa_map(u32 *addr, u32 *range, int na, int ns, int pna) return OF_BAD_ADDR; /* Read address values, skipping high cell */ - cp = of_read_addr(range + 1, na - 1); - s = of_read_addr(range + na + pna, ns); - da = of_read_addr(addr + 1, na - 1); + cp = of_read_number(range + 1, na - 1); + s = of_read_number(range + na + pna, ns); + da = of_read_number(addr + 1, na - 1); DBG("OF: ISA map, cp="PRu64", s="PRu64", da="PRu64"\n", cp, s, da); @@ -295,7 +287,7 @@ static int of_translate_one(struct device_node *parent, struct of_bus *bus, */ ranges = (u32 *)get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) { - offset = of_read_addr(addr, na); + offset = of_read_number(addr, na); memset(addr, 0, pna * 4); DBG("OF: no ranges, 1:1 translation\n"); goto finish; @@ -378,7 +370,7 @@ u64 of_translate_address(struct device_node *dev, u32 *in_addr) /* If root, we have finished */ if (parent == NULL) { DBG("OF: reached root node\n"); - result = of_read_addr(addr, na); + result = of_read_number(addr, na); break; } @@ -442,7 +434,7 @@ u32 *of_get_address(struct device_node *dev, int index, u64 *size, for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) if (i == index) { if (size) - *size = of_read_addr(prop + na, ns); + *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; @@ -484,7 +476,7 @@ u32 *of_get_pci_address(struct device_node *dev, int bar_no, u64 *size, for (i = 0; psize >= onesize; psize -= onesize, prop += onesize, i++) if ((prop[0] & 0xff) == ((bar_no * 4) + PCI_BASE_ADDRESS_0)) { if (size) - *size = of_read_addr(prop + na, ns); + *size = of_read_number(prop + na, ns); if (flags) *flags = bus->get_flags(prop); return prop; @@ -565,11 +557,414 @@ void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, prop = get_property(dn, "#address-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); - *phys = of_read_addr(dma_window, cells); + *phys = of_read_number(dma_window, cells); dma_window += cells; prop = get_property(dn, "ibm,#dma-size-cells", NULL); cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); - *size = of_read_addr(dma_window, cells); + *size = of_read_number(dma_window, cells); +} + +/* + * Interrupt remapper + */ + +static unsigned int of_irq_workarounds; +static struct device_node *of_irq_dflt_pic; + +static struct device_node *of_irq_find_parent(struct device_node *child) +{ + struct device_node *p; + phandle *parp; + + if (!of_node_get(child)) + return NULL; + + do { + parp = (phandle *)get_property(child, "interrupt-parent", NULL); + if (parp == NULL) + p = of_get_parent(child); + else { + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + p = of_node_get(of_irq_dflt_pic); + else + p = of_find_node_by_phandle(*parp); + } + of_node_put(child); + child = p; + } while (p && get_property(p, "#interrupt-cells", NULL) == NULL); + + return p; +} + +static u8 of_irq_pci_swizzle(u8 slot, u8 pin) +{ + return (((pin - 1) + slot) % 4) + 1; } + +/* This doesn't need to be called if you don't have any special workaround + * flags to pass + */ +void of_irq_map_init(unsigned int flags) +{ + of_irq_workarounds = flags; + + /* OldWorld, don't bother looking at other things */ + if (flags & OF_IMAP_OLDWORLD_MAC) + return; + + /* If we don't have phandles, let's try to locate a default interrupt + * controller (happens when booting with BootX). We do a first match + * here, hopefully, that only ever happens on machines with one + * controller. + */ + if (flags & OF_IMAP_NO_PHANDLE) { + struct device_node *np; + + for(np = NULL; (np = of_find_all_nodes(np)) != NULL;) { + if (get_property(np, "interrupt-controller", NULL) + == NULL) + continue; + /* Skip /chosen/interrupt-controller */ + if (strcmp(np->name, "chosen") == 0) + continue; + /* It seems like at least one person on this planet wants + * to use BootX on a machine with an AppleKiwi controller + * which happens to pretend to be an interrupt + * controller too. + */ + if (strcmp(np->name, "AppleKiwi") == 0) + continue; + /* I think we found one ! */ + of_irq_dflt_pic = np; + break; + } + } + +} + +int of_irq_map_raw(struct device_node *parent, u32 *intspec, u32 *addr, + struct of_irq *out_irq) +{ + struct device_node *ipar, *tnode, *old = NULL, *newpar = NULL; + u32 *tmp, *imap, *imask; + u32 intsize = 1, addrsize, newintsize = 0, newaddrsize = 0; + int imaplen, match, i; + + ipar = of_node_get(parent); + + /* First get the #interrupt-cells property of the current cursor + * that tells us how to interpret the passed-in intspec. If there + * is none, we are nice and just walk up the tree + */ + do { + tmp = (u32 *)get_property(ipar, "#interrupt-cells", NULL); + if (tmp != NULL) { + intsize = *tmp; + break; + } + tnode = ipar; + ipar = of_irq_find_parent(ipar); + of_node_put(tnode); + } while (ipar); + if (ipar == NULL) { + DBG(" -> no parent found !\n"); + goto fail; + } + + DBG("of_irq_map_raw: ipar=%s, size=%d\n", ipar->full_name, intsize); + + /* Look for this #address-cells. We have to implement the old linux + * trick of looking for the parent here as some device-trees rely on it + */ + old = of_node_get(ipar); + do { + tmp = (u32 *)get_property(old, "#address-cells", NULL); + tnode = of_get_parent(old); + of_node_put(old); + old = tnode; + } while(old && tmp == NULL); + of_node_put(old); + old = NULL; + addrsize = (tmp == NULL) ? 2 : *tmp; + + DBG(" -> addrsize=%d\n", addrsize); + + /* Now start the actual "proper" walk of the interrupt tree */ + while (ipar != NULL) { + /* Now check if cursor is an interrupt-controller and if it is + * then we are done + */ + if (get_property(ipar, "interrupt-controller", NULL) != NULL) { + DBG(" -> got it !\n"); + memcpy(out_irq->specifier, intspec, + intsize * sizeof(u32)); + out_irq->size = intsize; + out_irq->controller = ipar; + of_node_put(old); + return 0; + } + + /* Now look for an interrupt-map */ + imap = (u32 *)get_property(ipar, "interrupt-map", &imaplen); + /* No interrupt map, check for an interrupt parent */ + if (imap == NULL) { + DBG(" -> no map, getting parent\n"); + newpar = of_irq_find_parent(ipar); + goto skiplevel; + } + imaplen /= sizeof(u32); + + /* Look for a mask */ + imask = (u32 *)get_property(ipar, "interrupt-map-mask", NULL); + + /* If we were passed no "reg" property and we attempt to parse + * an interrupt-map, then #address-cells must be 0. + * Fail if it's not. + */ + if (addr == NULL && addrsize != 0) { + DBG(" -> no reg passed in when needed !\n"); + goto fail; + } + + /* Parse interrupt-map */ + match = 0; + while (imaplen > (addrsize + intsize + 1) && !match) { + /* Compare specifiers */ + match = 1; + for (i = 0; i < addrsize && match; ++i) { + u32 mask = imask ? imask[i] : 0xffffffffu; + match = ((addr[i] ^ imap[i]) & mask) == 0; + } + for (; i < (addrsize + intsize) && match; ++i) { + u32 mask = imask ? imask[i] : 0xffffffffu; + match = + ((intspec[i-addrsize] ^ imap[i]) & mask) == 0; + } + imap += addrsize + intsize; + imaplen -= addrsize + intsize; + + DBG(" -> match=%d (imaplen=%d)\n", match, imaplen); + + /* Get the interrupt parent */ + if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) + newpar = of_node_get(of_irq_dflt_pic); + else + newpar = of_find_node_by_phandle((phandle)*imap); + imap++; + --imaplen; + + /* Check if not found */ + if (newpar == NULL) { + DBG(" -> imap parent not found !\n"); + goto fail; + } + + /* Get #interrupt-cells and #address-cells of new + * parent + */ + tmp = (u32 *)get_property(newpar, "#interrupt-cells", + NULL); + if (tmp == NULL) { + DBG(" -> parent lacks #interrupt-cells !\n"); + goto fail; + } + newintsize = *tmp; + tmp = (u32 *)get_property(newpar, "#address-cells", + NULL); + newaddrsize = (tmp == NULL) ? 0 : *tmp; + + DBG(" -> newintsize=%d, newaddrsize=%d\n", + newintsize, newaddrsize); + + /* Check for malformed properties */ + if (imaplen < (newaddrsize + newintsize)) + goto fail; + + imap += newaddrsize + newintsize; + imaplen -= newaddrsize + newintsize; + + DBG(" -> imaplen=%d\n", imaplen); + } + if (!match) + goto fail; + + of_node_put(old); + old = of_node_get(newpar); + addrsize = newaddrsize; + intsize = newintsize; + intspec = imap - intsize; + addr = intspec - addrsize; + + skiplevel: + /* Iterate again with new parent */ + DBG(" -> new parent: %s\n", newpar ? newpar->full_name : "<>"); + of_node_put(ipar); + ipar = newpar; + newpar = NULL; + } + fail: + of_node_put(ipar); + of_node_put(old); + of_node_put(newpar); + + return -EINVAL; +} +EXPORT_SYMBOL_GPL(of_irq_map_raw); + +#if defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) +static int of_irq_map_oldworld(struct device_node *device, int index, + struct of_irq *out_irq) +{ + u32 *ints; + int intlen; + + /* + * Old machines just have a list of interrupt numbers + * and no interrupt-controller nodes. + */ + ints = (u32 *) get_property(device, "AAPL,interrupts", &intlen); + if (ints == NULL) + return -EINVAL; + intlen /= sizeof(u32); + + if (index >= intlen) + return -EINVAL; + + out_irq->controller = NULL; + out_irq->specifier[0] = ints[index]; + out_irq->size = 1; + + return 0; +} +#else /* defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32) */ +static int of_irq_map_oldworld(struct device_node *device, int index, + struct of_irq *out_irq) +{ + return -EINVAL; +} +#endif /* !(defined(CONFIG_PPC_PMAC) && defined(CONFIG_PPC32)) */ + +int of_irq_map_one(struct device_node *device, int index, struct of_irq *out_irq) +{ + struct device_node *p; + u32 *intspec, *tmp, intsize, intlen, *addr; + int res; + + DBG("of_irq_map_one: dev=%s, index=%d\n", device->full_name, index); + + /* OldWorld mac stuff is "special", handle out of line */ + if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC) + return of_irq_map_oldworld(device, index, out_irq); + + /* Get the interrupts property */ + intspec = (u32 *)get_property(device, "interrupts", &intlen); + if (intspec == NULL) + return -EINVAL; + intlen /= sizeof(u32); + + /* Get the reg property (if any) */ + addr = (u32 *)get_property(device, "reg", NULL); + + /* Look for the interrupt parent. */ + p = of_irq_find_parent(device); + if (p == NULL) + return -EINVAL; + + /* Get size of interrupt specifier */ + tmp = (u32 *)get_property(p, "#interrupt-cells", NULL); + if (tmp == NULL) { + of_node_put(p); + return -EINVAL; + } + intsize = *tmp; + + /* Check index */ + if (index * intsize >= intlen) + return -EINVAL; + + /* Get new specifier and map it */ + res = of_irq_map_raw(p, intspec + index * intsize, addr, out_irq); + of_node_put(p); + return res; +} +EXPORT_SYMBOL_GPL(of_irq_map_one); + +int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq) +{ + struct device_node *dn, *ppnode; + struct pci_dev *ppdev; + u32 lspec; + u32 laddr[3]; + u8 pin; + int rc; + + /* Check if we have a device node, if yes, fallback to standard OF + * parsing + */ + dn = pci_device_to_OF_node(pdev); + if (dn) + return of_irq_map_one(dn, 0, out_irq); + + /* Ok, we don't, time to have fun. Let's start by building up an + * interrupt spec. we assume #interrupt-cells is 1, which is standard + * for PCI. If you do different, then don't use that routine. + */ + rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin); + if (rc != 0) + return rc; + /* No pin, exit */ + if (pin == 0) + return -ENODEV; + + /* Now we walk up the PCI tree */ + lspec = pin; + for (;;) { + /* Get the pci_dev of our parent */ + ppdev = pdev->bus->self; + + /* Ouch, it's a host bridge... */ + if (ppdev == NULL) { +#ifdef CONFIG_PPC64 + ppnode = pci_bus_to_OF_node(pdev->bus); +#else + struct pci_controller *host; + host = pci_bus_to_host(pdev->bus); + ppnode = host ? host->arch_data : NULL; +#endif + /* No node for host bridge ? give up */ + if (ppnode == NULL) + return -EINVAL; + } else + /* We found a P2P bridge, check if it has a node */ + ppnode = pci_device_to_OF_node(ppdev); + + /* Ok, we have found a parent with a device-node, hand over to + * the OF parsing code. + * We build a unit address from the linux device to be used for + * resolution. Note that we use the linux bus number which may + * not match your firmware bus numbering. + * Fortunately, in most cases, interrupt-map-mask doesn't include + * the bus number as part of the matching. + * You should still be careful about that though if you intend + * to rely on this function (you ship a firmware that doesn't + * create device nodes for all PCI devices). + */ + if (ppnode) + break; + + /* We can only get here if we hit a P2P bridge with no node, + * let's do standard swizzling and try again + */ + lspec = of_irq_pci_swizzle(PCI_SLOT(pdev->devfn), lspec); + pdev = ppdev; + } + + laddr[0] = (pdev->bus->number << 16) + | (pdev->devfn << 8); + laddr[1] = laddr[2] = 0; + return of_irq_map_raw(ppnode, &lspec, laddr, out_irq); +} +EXPORT_SYMBOL_GPL(of_irq_map_pci); + diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index c42a860c8d25..8797ae737a7b 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h @@ -10,7 +10,6 @@ #ifndef _PPC64_PTRACE_COMMON_H #define _PPC64_PTRACE_COMMON_H -#include <linux/config.h> #include <asm/system.h> /* diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 5563e2e7d89c..dea75d73f983 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -15,7 +15,6 @@ * this archive for more details. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 826ee3d056de..9b9a230349bc 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c @@ -17,7 +17,6 @@ * this archive for more details. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/mm.h> diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 6eb7e49b394a..cda022657324 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c @@ -297,19 +297,9 @@ unsigned long __init find_and_init_phbs(void) struct device_node *node; struct pci_controller *phb; unsigned int index; - unsigned int root_size_cells = 0; - unsigned int *opprop = NULL; struct device_node *root = of_find_node_by_path("/"); - if (ppc64_interrupt_controller == IC_OPEN_PIC) { - opprop = (unsigned int *)get_property(root, - "platform-open-pic", NULL); - } - - root_size_cells = prom_n_size_cells(root); - index = 0; - for (node = of_get_next_child(root, NULL); node != NULL; node = of_get_next_child(root, node)) { @@ -324,13 +314,6 @@ unsigned long __init find_and_init_phbs(void) setup_phb(node, phb); pci_process_bridge_OF_ranges(phb, node, 0); pci_setup_phb_io(phb, index == 0); -#ifdef CONFIG_PPC_PSERIES - /* XXX This code need serious fixing ... --BenH */ - if (ppc64_interrupt_controller == IC_OPEN_PIC && pSeries_mpic) { - int addr = root_size_cells * (index + 2) - 1; - mpic_assign_isu(pSeries_mpic, index, opprop[addr]); - } -#endif index++; } diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index bd328123af75..c6d7b98af7d5 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c @@ -12,7 +12,6 @@ #undef DEBUG -#include <linux/config.h> #include <linux/module.h> #include <linux/string.h> #include <linux/sched.h> diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 0932a62a1c96..e0df2ba1ab9f 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -2,7 +2,6 @@ * Common prep/pmac/chrp boot and setup code. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/string.h> #include <linux/sched.h> @@ -52,7 +51,6 @@ extern void bootx_init(unsigned long r4, unsigned long phys); -boot_infos_t *boot_infos; struct ide_machdep_calls ppc_ide_md; int boot_cpuid; @@ -241,7 +239,6 @@ void __init setup_arch(char **cmdline_p) ppc_md.init_early(); find_legacy_serial_ports(); - finish_device_tree(); smp_setup_cpu_maps(); diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 175539c9afa0..fd1785e4c9bb 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c @@ -12,7 +12,6 @@ #undef DEBUG -#include <linux/config.h> #include <linux/module.h> #include <linux/string.h> #include <linux/sched.h> @@ -362,12 +361,15 @@ void __init setup_system(void) /* * Fill the ppc64_caches & systemcfg structures with informations - * retrieved from the device-tree. Need to be called before - * finish_device_tree() since the later requires some of the - * informations filled up here to properly parse the interrupt tree. + * retrieved from the device-tree. */ initialize_cache_info(); + /* + * Initialize irq remapping subsystem + */ + irq_early_init(); + #ifdef CONFIG_PPC_RTAS /* * Initialize RTAS if available @@ -395,12 +397,6 @@ void __init setup_system(void) find_legacy_serial_ports(); /* - * "Finish" the device-tree, that is do the actual parsing of - * some of the properties like the interrupt map - */ - finish_device_tree(); - - /* * Initialize xmon */ #ifdef CONFIG_XMON_DEFAULT @@ -428,8 +424,6 @@ void __init setup_system(void) printk("-----------------------------------------------------\n"); printk("ppc64_pft_size = 0x%lx\n", ppc64_pft_size); - printk("ppc64_interrupt_controller = 0x%ld\n", - ppc64_interrupt_controller); printk("physicalMemorySize = 0x%lx\n", lmb_phys_mem_size()); printk("ppc64_caches.dcache_line_size = 0x%x\n", ppc64_caches.dline_size); diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index d73b25e22fca..320353f0926f 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -17,7 +17,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/smp.h> diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 6e75d7ab6d4d..f72e8e823d78 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c @@ -12,7 +12,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/sched.h> #include <linux/mm.h> #include <linux/smp.h> diff --git a/arch/powerpc/kernel/smp-tbsync.c b/arch/powerpc/kernel/smp-tbsync.c index 9adef3bddad4..f19e2e0e61e7 100644 --- a/arch/powerpc/kernel/smp-tbsync.c +++ b/arch/powerpc/kernel/smp-tbsync.c @@ -5,7 +5,6 @@ * */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/smp.h> diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index c5d179d4f818..46c56cfd1b2f 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -17,7 +17,6 @@ #undef DEBUG -#include <linux/config.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/sched.h> diff --git a/arch/powerpc/kernel/swsusp_32.S b/arch/powerpc/kernel/swsusp_32.S index 69773cc1a85f..7369f9a6ad25 100644 --- a/arch/powerpc/kernel/swsusp_32.S +++ b/arch/powerpc/kernel/swsusp_32.S @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/threads.h> #include <asm/processor.h> #include <asm/page.h> diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index ec274e688816..2e292863e982 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c @@ -14,7 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/fs.h> diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 4662b580efa1..010435095550 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <linux/sysdev.h> #include <linux/cpu.h> #include <linux/smp.h> diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index ee75ccf1a802..579de70e0b4d 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -14,7 +14,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/ppc_asm.h> #ifdef CONFIG_PPC64 diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c index 26bd8ea35a4e..368a4934f7ee 100644 --- a/arch/powerpc/kernel/tau_6xx.c +++ b/arch/powerpc/kernel/tau_6xx.c @@ -11,7 +11,6 @@ * life in portables, and add a 'performance/watt' metric somewhere in /proc */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/jiffies.h> #include <linux/kernel.h> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 7dd5dab789a1..774c0a3c5019 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -32,7 +32,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/module.h> #include <linux/sched.h> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index fa6bd97b6b9d..3c668078e524 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c @@ -14,7 +14,6 @@ * This file handles the architecture-dependent parts of hardware exceptions */ -#include <linux/config.h> #include <linux/errno.h> #include <linux/sched.h> #include <linux/kernel.h> diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 759afd5e0d8a..5730906b23d5 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c @@ -10,7 +10,6 @@ */ #include <stdarg.h> -#include <linux/config.h> #include <linux/types.h> #include <linux/sched.h> #include <linux/console.h> diff --git a/arch/powerpc/kernel/udbg_16550.c b/arch/powerpc/kernel/udbg_16550.c index 5d29dcca523c..0835b4841dea 100644 --- a/arch/powerpc/kernel/udbg_16550.c +++ b/arch/powerpc/kernel/udbg_16550.c @@ -8,7 +8,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/types.h> #include <asm/udbg.h> #include <asm/io.h> diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index bc3e15be3087..1a7e19cdab39 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -8,7 +8,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <linux/module.h> #include <linux/errno.h> #include <linux/sched.h> diff --git a/arch/powerpc/kernel/vdso32/cacheflush.S b/arch/powerpc/kernel/vdso32/cacheflush.S index 09629aea3e47..9cb319992c38 100644 --- a/arch/powerpc/kernel/vdso32/cacheflush.S +++ b/arch/powerpc/kernel/vdso32/cacheflush.S @@ -9,7 +9,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/vdso.h> diff --git a/arch/powerpc/kernel/vdso32/datapage.S b/arch/powerpc/kernel/vdso32/datapage.S index 4709f1d9542c..dc21e891d2e7 100644 --- a/arch/powerpc/kernel/vdso32/datapage.S +++ b/arch/powerpc/kernel/vdso32/datapage.S @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/asm-offsets.h> diff --git a/arch/powerpc/kernel/vdso32/gettimeofday.S b/arch/powerpc/kernel/vdso32/gettimeofday.S index 7eebff03a041..05909f754307 100644 --- a/arch/powerpc/kernel/vdso32/gettimeofday.S +++ b/arch/powerpc/kernel/vdso32/gettimeofday.S @@ -10,7 +10,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/vdso.h> diff --git a/arch/powerpc/kernel/vdso32/sigtramp.S b/arch/powerpc/kernel/vdso32/sigtramp.S index 0c6a37b29dde..68d49dd71dcc 100644 --- a/arch/powerpc/kernel/vdso32/sigtramp.S +++ b/arch/powerpc/kernel/vdso32/sigtramp.S @@ -10,7 +10,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/unistd.h> diff --git a/arch/powerpc/kernel/vdso64/cacheflush.S b/arch/powerpc/kernel/vdso64/cacheflush.S index cb4ae0a5edd0..66a36d3cc6ad 100644 --- a/arch/powerpc/kernel/vdso64/cacheflush.S +++ b/arch/powerpc/kernel/vdso64/cacheflush.S @@ -9,7 +9,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/vdso.h> diff --git a/arch/powerpc/kernel/vdso64/datapage.S b/arch/powerpc/kernel/vdso64/datapage.S index 3b2dd7d0c1eb..79796de11737 100644 --- a/arch/powerpc/kernel/vdso64/datapage.S +++ b/arch/powerpc/kernel/vdso64/datapage.S @@ -9,7 +9,6 @@ * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/asm-offsets.h> diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index 4ee871f1cadb..56e76ff5498f 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S @@ -11,7 +11,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/vdso.h> diff --git a/arch/powerpc/kernel/vdso64/sigtramp.S b/arch/powerpc/kernel/vdso64/sigtramp.S index 7479edb101b8..17a83fa6dc52 100644 --- a/arch/powerpc/kernel/vdso64/sigtramp.S +++ b/arch/powerpc/kernel/vdso64/sigtramp.S @@ -10,7 +10,6 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include <linux/config.h> #include <asm/processor.h> #include <asm/ppc_asm.h> #include <asm/unistd.h> diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 9416b4ab92ec..49ac3d6e1399 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S @@ -1,4 +1,3 @@ -#include <linux/config.h> #include <asm/ppc_asm.h> #include <asm/reg.h> diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cdf5867838a6..fad8580f9081 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c @@ -218,7 +218,6 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) { struct vio_dev *viodev; unsigned int *unit_address; - unsigned int *irq_p; /* we need the 'device_type' property, in order to match with drivers */ if (of_node->type == NULL) { @@ -243,16 +242,7 @@ struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) viodev->dev.platform_data = of_node_get(of_node); - viodev->irq = NO_IRQ; - irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); - if (irq_p) { - int virq = virt_irq_create_mapping(*irq_p); - if (virq == NO_IRQ) { - printk(KERN_ERR "Unable to allocate interrupt " - "number for %s\n", of_node->full_name); - } else - viodev->irq = irq_offset_up(virq); - } + viodev->irq = irq_of_parse_and_map(of_node, 0); snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); viodev->name = of_node->name; diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 8b25953dc4f0..02665a02130d 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -1,4 +1,3 @@ -#include <linux/config.h> #ifdef CONFIG_PPC64 #include <asm/page.h> #define PROVIDE32(x) PROVIDE(__unused__##x) |