diff options
Diffstat (limited to 'arch')
122 files changed, 3136 insertions, 1439 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 694c9af520b..3ea332b009e 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -36,3 +36,6 @@ config HAVE_KPROBES config HAVE_KRETPROBES def_bool n + +config HAVE_DMA_ATTRS + def_bool n diff --git a/arch/alpha/kernel/asm-offsets.c b/arch/alpha/kernel/asm-offsets.c index 6c56c754a0b..4b18cd94d59 100644 --- a/arch/alpha/kernel/asm-offsets.c +++ b/arch/alpha/kernel/asm-offsets.c @@ -8,13 +8,9 @@ #include <linux/stddef.h> #include <linux/sched.h> #include <linux/ptrace.h> +#include <linux/kbuild.h> #include <asm/io.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - void foo(void) { DEFINE(TI_TASK, offsetof(struct thread_info, task)); diff --git a/arch/alpha/kernel/pci.c b/arch/alpha/kernel/pci.c index baf57563b14..36ab22a7ea1 100644 --- a/arch/alpha/kernel/pci.c +++ b/arch/alpha/kernel/pci.c @@ -514,8 +514,8 @@ sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn) void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c index 0a0d2479274..4a881258bb1 100644 --- a/arch/arm/kernel/asm-offsets.c +++ b/arch/arm/kernel/asm-offsets.c @@ -16,6 +16,7 @@ #include <asm/thread_info.h> #include <asm/memory.h> #include <asm/procinfo.h> +#include <linux/kbuild.h> /* * Make sure that the compiler and target are compatible. @@ -35,13 +36,6 @@ #error Known good compilers: 3.3 #endif -/* Use marker if you need to separate the values later */ - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c index e2e934c3808..64c420805e6 100644 --- a/arch/arm/kernel/atags.c +++ b/arch/arm/kernel/atags.c @@ -35,7 +35,7 @@ create_proc_entries(void) { struct proc_dir_entry* tags_entry; - tags_entry = create_proc_read_entry("atags", 0400, &proc_root, read_buffer, &tags_buffer); + tags_entry = create_proc_read_entry("atags", 0400, NULL, read_buffer, &tags_buffer); if (!tags_entry) return -ENOMEM; diff --git a/arch/arm/kernel/ecard.c b/arch/arm/kernel/ecard.c index f56d48c451e..a53c0aba5c1 100644 --- a/arch/arm/kernel/ecard.c +++ b/arch/arm/kernel/ecard.c @@ -37,6 +37,7 @@ #include <linux/mm.h> #include <linux/slab.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/device.h> #include <linux/init.h> #include <linux/mutex.h> @@ -723,17 +724,14 @@ unsigned int __ecard_address(ecard_t *ec, card_type_t type, card_speed_t speed) return address; } -static int ecard_prints(char *buffer, ecard_t *ec) +static int ecard_prints(struct seq_file *m, ecard_t *ec) { - char *start = buffer; - - buffer += sprintf(buffer, " %d: %s ", ec->slot_no, - ec->easi ? "EASI" : " "); + seq_printf(m, " %d: %s ", ec->slot_no, ec->easi ? "EASI" : " "); if (ec->cid.id == 0) { struct in_chunk_dir incd; - buffer += sprintf(buffer, "[%04X:%04X] ", + seq_printf(m, "[%04X:%04X] ", ec->cid.manufacturer, ec->cid.product); if (!ec->card_desc && ec->cid.cd && @@ -744,43 +742,43 @@ static int ecard_prints(char *buffer, ecard_t *ec) strcpy((char *)ec->card_desc, incd.d.string); } - buffer += sprintf(buffer, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*"); + seq_printf(m, "%s\n", ec->card_desc ? ec->card_desc : "*unknown*"); } else - buffer += sprintf(buffer, "Simple card %d\n", ec->cid.id); + seq_printf(m, "Simple card %d\n", ec->cid.id); - return buffer - start; + return 0; } -static int get_ecard_dev_info(char *buf, char **start, off_t pos, int count) +static int ecard_devices_proc_show(struct seq_file *m, void *v) { ecard_t *ec = cards; - off_t at = 0; - int len, cnt; - - cnt = 0; - while (ec && count > cnt) { - len = ecard_prints(buf, ec); - at += len; - if (at >= pos) { - if (!*start) { - *start = buf + (pos - (at - len)); - cnt = at - pos; - } else - cnt += len; - buf += len; - } + + while (ec) { + ecard_prints(m, ec); ec = ec->next; } - return (count > cnt) ? cnt : count; + return 0; } +static int ecard_devices_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ecard_devices_proc_show, NULL); +} + +static const struct file_operations bus_ecard_proc_fops = { + .owner = THIS_MODULE, + .open = ecard_devices_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static struct proc_dir_entry *proc_bus_ecard_dir = NULL; static void ecard_proc_init(void) { - proc_bus_ecard_dir = proc_mkdir("ecard", proc_bus); - create_proc_info_entry("devices", 0, proc_bus_ecard_dir, - get_ecard_dev_info); + proc_bus_ecard_dir = proc_mkdir("bus/ecard", NULL); + proc_create("devices", 0, proc_bus_ecard_dir, &bus_ecard_proc_fops); } #define ec_set_resource(ec,nr,st,sz) \ diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c index 4143828a968..c6b94f60e0b 100644 --- a/arch/arm/mach-davinci/clock.c +++ b/arch/arm/mach-davinci/clock.c @@ -311,11 +311,7 @@ static const struct file_operations proc_davinci_ck_operations = { static int __init davinci_ck_proc_init(void) { - struct proc_dir_entry *entry; - - entry = create_proc_entry("davinci_clocks", 0, NULL); - if (entry) - entry->proc_fops = &proc_davinci_ck_operations; + proc_create("davinci_clocks", 0, NULL, &proc_davinci_ck_operations); return 0; } diff --git a/arch/arm/mm/iomap.c b/arch/arm/mm/iomap.c index 62066f3020c..7429f8c0101 100644 --- a/arch/arm/mm/iomap.c +++ b/arch/arm/mm/iomap.c @@ -26,8 +26,8 @@ EXPORT_SYMBOL(ioport_unmap); #ifdef CONFIG_PCI void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/avr32/kernel/asm-offsets.c b/arch/avr32/kernel/asm-offsets.c index 078cd33f467..e4796c67a83 100644 --- a/arch/avr32/kernel/asm-offsets.c +++ b/arch/avr32/kernel/asm-offsets.c @@ -5,14 +5,7 @@ */ #include <linux/thread_info.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); +#include <linux/kbuild.h> void foo(void) { diff --git a/arch/avr32/mm/tlb.c b/arch/avr32/mm/tlb.c index b835257a8fa..cd12edbea9f 100644 --- a/arch/avr32/mm/tlb.c +++ b/arch/avr32/mm/tlb.c @@ -369,11 +369,7 @@ static const struct file_operations proc_tlb_operations = { static int __init proctlb_init(void) { - struct proc_dir_entry *entry; - - entry = create_proc_entry("tlb", 0, NULL); - if (entry) - entry->proc_fops = &proc_tlb_operations; + proc_create("tlb", 0, NULL, &proc_tlb_operations); return 0; } late_initcall(proctlb_init); diff --git a/arch/blackfin/kernel/asm-offsets.c b/arch/blackfin/kernel/asm-offsets.c index b56b2741cde..721f15f3ceb 100644 --- a/arch/blackfin/kernel/asm-offsets.c +++ b/arch/blackfin/kernel/asm-offsets.c @@ -34,8 +34,7 @@ #include <linux/hardirq.h> #include <linux/irq.h> #include <linux/thread_info.h> - -#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val)) +#include <linux/kbuild.h> int main(void) { diff --git a/arch/blackfin/kernel/signal.c b/arch/blackfin/kernel/signal.c index d1fa24401dc..cb9d883d493 100644 --- a/arch/blackfin/kernel/signal.c +++ b/arch/blackfin/kernel/signal.c @@ -212,7 +212,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info, /* Set up registers for signal handler */ wrusp((unsigned long)frame); - if (get_personality & FDPIC_FUNCPTRS) { + if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor *) ka->sa.sa_handler; __get_user(regs->pc, &funcptr->text); diff --git a/arch/cris/kernel/profile.c b/arch/cris/kernel/profile.c index aad0a9e5991..44f7b4f7947 100644 --- a/arch/cris/kernel/profile.c +++ b/arch/cris/kernel/profile.c @@ -75,9 +75,9 @@ __init init_cris_profile(void) sample_buffer_pos = sample_buffer; - entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL); + entry = proc_create("system_profile", S_IWUSR | S_IRUGO, NULL, + &cris_proc_profile_operations); if (entry) { - entry->proc_fops = &cris_proc_profile_operations; entry->size = SAMPLE_BUFFER_SIZE; } prof_running = 1; diff --git a/arch/frv/kernel/asm-offsets.c b/arch/frv/kernel/asm-offsets.c index fbb19fc1af4..9de96843a27 100644 --- a/arch/frv/kernel/asm-offsets.c +++ b/arch/frv/kernel/asm-offsets.c @@ -7,15 +7,13 @@ #include <linux/sched.h> #include <linux/signal.h> #include <linux/personality.h> +#include <linux/kbuild.h> #include <asm/registers.h> #include <asm/ucontext.h> #include <asm/processor.h> #include <asm/thread_info.h> #include <asm/gdb-stub.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - #define DEF_PTREG(sym, reg) \ asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \ : : "i" (offsetof(struct pt_regs, reg))) @@ -32,11 +30,6 @@ asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \ : : "i" (offsetof(struct frv_frame0, reg))) -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - void foo(void) { /* offsets into the thread_info structure */ diff --git a/arch/frv/kernel/signal.c b/arch/frv/kernel/signal.c index d64bcaff54c..3bdb368292a 100644 --- a/arch/frv/kernel/signal.c +++ b/arch/frv/kernel/signal.c @@ -297,7 +297,7 @@ static int setup_frame(int sig, struct k_sigaction *ka, sigset_t *set) __frame->lr = (unsigned long) &frame->retcode; __frame->gr8 = sig; - if (get_personality & FDPIC_FUNCPTRS) { + if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); @@ -396,7 +396,7 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, __frame->gr8 = sig; __frame->gr9 = (unsigned long) &frame->info; - if (get_personality & FDPIC_FUNCPTRS) { + if (current->personality & FDPIC_FUNCPTRS) { struct fdpic_func_descriptor __user *funcptr = (struct fdpic_func_descriptor __user *) ka->sa.sa_handler; __get_user(__frame->pc, &funcptr->text); diff --git a/arch/frv/kernel/traps.c b/arch/frv/kernel/traps.c index a40df80b2eb..1d2dfe67d44 100644 --- a/arch/frv/kernel/traps.c +++ b/arch/frv/kernel/traps.c @@ -362,11 +362,8 @@ asmlinkage void memory_access_exception(unsigned long esr0, #ifdef CONFIG_MMU unsigned long fixup; - if ((esr0 & ESRx_EC) == ESRx_EC_DATA_ACCESS) - if (handle_misalignment(esr0, ear0, epcr0) == 0) - return; - - if ((fixup = search_exception_table(__frame->pc)) != 0) { + fixup = search_exception_table(__frame->pc); + if (fixup) { __frame->pc = fixup; return; } diff --git a/arch/frv/mb93090-mb00/pci-iomap.c b/arch/frv/mb93090-mb00/pci-iomap.c index 068fa04bd52..35f6df28351 100644 --- a/arch/frv/mb93090-mb00/pci-iomap.c +++ b/arch/frv/mb93090-mb00/pci-iomap.c @@ -13,8 +13,8 @@ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/frv/mm/unaligned.c b/arch/frv/mm/unaligned.c deleted file mode 100644 index 8f0375fc15a..00000000000 --- a/arch/frv/mm/unaligned.c +++ /dev/null @@ -1,217 +0,0 @@ -/* unaligned.c: unalignment fixup handler for CPUs on which it is supported (FR451 only) - * - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - */ - -#include <linux/sched.h> -#include <linux/signal.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/types.h> -#include <linux/user.h> -#include <linux/string.h> -#include <linux/linkage.h> -#include <linux/init.h> - -#include <asm/setup.h> -#include <asm/system.h> -#include <asm/uaccess.h> - -#if 0 -#define kdebug(fmt, ...) printk("FDPIC "fmt"\n" ,##__VA_ARGS__ ) -#else -#define kdebug(fmt, ...) do {} while(0) -#endif - -#define _MA_SIGNED 0x01 -#define _MA_HALF 0x02 -#define _MA_WORD 0x04 -#define _MA_DWORD 0x08 -#define _MA_SZ_MASK 0x0e -#define _MA_LOAD 0x10 -#define _MA_STORE 0x20 -#define _MA_UPDATE 0x40 -#define _MA_IMM 0x80 - -#define _MA_LDxU _MA_LOAD | _MA_UPDATE -#define _MA_LDxI _MA_LOAD | _MA_IMM -#define _MA_STxU _MA_STORE | _MA_UPDATE -#define _MA_STxI _MA_STORE | _MA_IMM - -static const uint8_t tbl_LDGRk_reg[0x40] = { - [0x02] = _MA_LOAD | _MA_HALF | _MA_SIGNED, /* LDSH @(GRi,GRj),GRk */ - [0x03] = _MA_LOAD | _MA_HALF, /* LDUH @(GRi,GRj),GRk */ - [0x04] = _MA_LOAD | _MA_WORD, /* LD @(GRi,GRj),GRk */ - [0x05] = _MA_LOAD | _MA_DWORD, /* LDD @(GRi,GRj),GRk */ - [0x12] = _MA_LDxU | _MA_HALF | _MA_SIGNED, /* LDSHU @(GRi,GRj),GRk */ - [0x13] = _MA_LDxU | _MA_HALF, /* LDUHU @(GRi,GRj),GRk */ - [0x14] = _MA_LDxU | _MA_WORD, /* LDU @(GRi,GRj),GRk */ - [0x15] = _MA_LDxU | _MA_DWORD, /* LDDU @(GRi,GRj),GRk */ -}; - -static const uint8_t tbl_STGRk_reg[0x40] = { - [0x01] = _MA_STORE | _MA_HALF, /* STH @(GRi,GRj),GRk */ - [0x02] = _MA_STORE | _MA_WORD, /* ST @(GRi,GRj),GRk */ - [0x03] = _MA_STORE | _MA_DWORD, /* STD @(GRi,GRj),GRk */ - [0x11] = _MA_STxU | _MA_HALF, /* STHU @(GRi,GRj),GRk */ - [0x12] = _MA_STxU | _MA_WORD, /* STU @(GRi,GRj),GRk */ - [0x13] = _MA_STxU | _MA_DWORD, /* STDU @(GRi,GRj),GRk */ -}; - -static const uint8_t tbl_LDSTGRk_imm[0x80] = { - [0x31] = _MA_LDxI | _MA_HALF | _MA_SIGNED, /* LDSHI @(GRi,d12),GRk */ - [0x32] = _MA_LDxI | _MA_WORD, /* LDI @(GRi,d12),GRk */ - [0x33] = _MA_LDxI | _MA_DWORD, /* LDDI @(GRi,d12),GRk */ - [0x36] = _MA_LDxI | _MA_HALF, /* LDUHI @(GRi,d12),GRk */ - [0x51] = _MA_STxI | _MA_HALF, /* STHI @(GRi,d12),GRk */ - [0x52] = _MA_STxI | _MA_WORD, /* STI @(GRi,d12),GRk */ - [0x53] = _MA_STxI | _MA_DWORD, /* STDI @(GRi,d12),GRk */ -}; - - -/*****************************************************************************/ -/* - * see if we can handle the exception by fixing up a misaligned memory access - */ -int handle_misalignment(unsigned long esr0, unsigned long ear0, unsigned long epcr0) -{ - unsigned long insn, addr, *greg; - int GRi, GRj, GRk, D12, op; - - union { - uint64_t _64; - uint32_t _32[2]; - uint16_t _16; - uint8_t _8[8]; - } x; - - if (!(esr0 & ESR0_EAV) || !(epcr0 & EPCR0_V) || !(ear0 & 7)) - return -EAGAIN; - - epcr0 &= EPCR0_PC; - - if (__frame->pc != epcr0) { - kdebug("MISALIGN: Execution not halted on excepting instruction\n"); - BUG(); - } - - if (__get_user(insn, (unsigned long *) epcr0) < 0) - return -EFAULT; - - /* determine the instruction type first */ - switch ((insn >> 18) & 0x7f) { - case 0x2: - /* LDx @(GRi,GRj),GRk */ - op = tbl_LDGRk_reg[(insn >> 6) & 0x3f]; - break; - - case 0x3: - /* STx GRk,@(GRi,GRj) */ - op = tbl_STGRk_reg[(insn >> 6) & 0x3f]; - break; - - default: - op = tbl_LDSTGRk_imm[(insn >> 18) & 0x7f]; - break; - } - - if (!op) - return -EAGAIN; - - kdebug("MISALIGN: pc=%08lx insn=%08lx ad=%08lx op=%02x\n", epcr0, insn, ear0, op); - - memset(&x, 0xba, 8); - - /* validate the instruction parameters */ - greg = (unsigned long *) &__frame->tbr; - - GRi = (insn >> 12) & 0x3f; - GRk = (insn >> 25) & 0x3f; - - if (GRi > 31 || GRk > 31) - return -ENOENT; - - if (op & _MA_DWORD && GRk & 1) - return -EINVAL; - - if (op & _MA_IMM) { - D12 = insn & 0xfff; - asm ("slli %0,#20,%0 ! srai %0,#20,%0" : "=r"(D12) : "0"(D12)); /* sign extend */ - addr = (GRi ? greg[GRi] : 0) + D12; - } - else { - GRj = (insn >> 0) & 0x3f; - if (GRj > 31) - return -ENOENT; - addr = (GRi ? greg[GRi] : 0) + (GRj ? greg[GRj] : 0); - } - - if (addr != ear0) { - kdebug("MISALIGN: Calculated addr (%08lx) does not match EAR0 (%08lx)\n", - addr, ear0); - return -EFAULT; - } - - /* check the address is okay */ - if (user_mode(__frame) && ___range_ok(ear0, 8) < 0) - return -EFAULT; - - /* perform the memory op */ - if (op & _MA_STORE) { - /* perform a store */ - x._32[0] = 0; - if (GRk != 0) { - if (op & _MA_HALF) { - x._16 = greg[GRk]; - } - else { - x._32[0] = greg[GRk]; - } - } - if (op & _MA_DWORD) - x._32[1] = greg[GRk + 1]; - - kdebug("MISALIGN: Store GR%d { %08x:%08x } -> %08lx (%dB)\n", - GRk, x._32[1], x._32[0], addr, op & _MA_SZ_MASK); - - if (__memcpy_user((void *) addr, &x, op & _MA_SZ_MASK) != 0) - return -EFAULT; - } - else { - /* perform a load */ - if (__memcpy_user(&x, (void *) addr, op & _MA_SZ_MASK) != 0) - return -EFAULT; - - if (op & _MA_HALF) { - if (op & _MA_SIGNED) - asm ("slli %0,#16,%0 ! srai %0,#16,%0" - : "=r"(x._32[0]) : "0"(x._16)); - else - asm ("sethi #0,%0" - : "=r"(x._32[0]) : "0"(x._16)); - } - - kdebug("MISALIGN: Load %08lx (%dB) -> GR%d, { %08x:%08x }\n", - addr, op & _MA_SZ_MASK, GRk, x._32[1], x._32[0]); - - if (GRk != 0) - greg[GRk] = x._32[0]; - if (op & _MA_DWORD) - greg[GRk + 1] = x._32[1]; - } - - /* update the base pointer if required */ - if (op & _MA_UPDATE) - greg[GRi] = addr; - - /* well... we've done that insn */ - __frame->pc = __frame->pc + 4; - - return 0; -} /* end handle_misalignment() */ diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c index fc30b4fd091..2042552e087 100644 --- a/arch/h8300/kernel/asm-offsets.c +++ b/arch/h8300/kernel/asm-offsets.c @@ -13,15 +13,11 @@ #include <linux/kernel_stat.h> #include <linux/ptrace.h> #include <linux/hardirq.h> +#include <linux/kbuild.h> #include <asm/bootinfo.h> #include <asm/irq.h> #include <asm/ptrace.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { /* offsets into the task struct */ diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 3aa6c821449..0df5f6f75ed 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -19,6 +19,7 @@ config IA64 select HAVE_OPROFILE select HAVE_KPROBES select HAVE_KRETPROBES + select HAVE_DMA_ATTRS select HAVE_KVM default y help @@ -47,6 +48,9 @@ config MMU config SWIOTLB bool +config IOMMU_HELPER + bool + config GENERIC_LOCKBREAK bool default y @@ -615,7 +619,7 @@ config IRQ_PER_CPU default y config IOMMU_HELPER - def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC) + def_bool (IA64_HP_ZX1 || IA64_HP_ZX1_SWIOTLB || IA64_GENERIC || SWIOTLB) source "arch/ia64/hp/sim/Kconfig" diff --git a/arch/ia64/hp/common/hwsw_iommu.c b/arch/ia64/hp/common/hwsw_iommu.c index 8f6bcfe1dad..1c44ec2a1d5 100644 --- a/arch/ia64/hp/common/hwsw_iommu.c +++ b/arch/ia64/hp/common/hwsw_iommu.c @@ -20,10 +20,10 @@ extern int swiotlb_late_init_with_default_size (size_t size); extern ia64_mv_dma_alloc_coherent swiotlb_alloc_coherent; extern ia64_mv_dma_free_coherent swiotlb_free_coherent; -extern ia64_mv_dma_map_single swiotlb_map_single; -extern ia64_mv_dma_unmap_single swiotlb_unmap_single; -extern ia64_mv_dma_map_sg swiotlb_map_sg; -extern ia64_mv_dma_unmap_sg swiotlb_unmap_sg; +extern ia64_mv_dma_map_single_attrs swiotlb_map_single_attrs; +extern ia64_mv_dma_unmap_single_attrs swiotlb_unmap_single_attrs; +extern ia64_mv_dma_map_sg_attrs swiotlb_map_sg_attrs; +extern ia64_mv_dma_unmap_sg_attrs swiotlb_unmap_sg_attrs; extern ia64_mv_dma_supported swiotlb_dma_supported; extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error; @@ -31,19 +31,19 @@ extern ia64_mv_dma_mapping_error swiotlb_dma_mapping_error; extern ia64_mv_dma_alloc_coherent sba_alloc_coherent; extern ia64_mv_dma_free_coherent sba_free_coherent; -extern ia64_mv_dma_map_single sba_map_single; -extern ia64_mv_dma_unmap_single sba_unmap_single; -extern ia64_mv_dma_map_sg sba_map_sg; -extern ia64_mv_dma_unmap_sg sba_unmap_sg; +extern ia64_mv_dma_map_single_attrs sba_map_single_attrs; +extern ia64_mv_dma_unmap_single_attrs sba_unmap_single_attrs; +extern ia64_mv_dma_map_sg_attrs sba_map_sg_attrs; +extern ia64_mv_dma_unmap_sg_attrs sba_unmap_sg_attrs; extern ia64_mv_dma_supported sba_dma_supported; extern ia64_mv_dma_mapping_error sba_dma_mapping_error; #define hwiommu_alloc_coherent sba_alloc_coherent #define hwiommu_free_coherent sba_free_coherent -#define hwiommu_map_single sba_map_single -#define hwiommu_unmap_single sba_unmap_single -#define hwiommu_map_sg sba_map_sg -#define hwiommu_unmap_sg sba_unmap_sg +#define hwiommu_map_single_attrs sba_map_single_attrs +#define hwiommu_unmap_single_attrs sba_unmap_single_attrs +#define hwiommu_map_sg_attrs sba_map_sg_attrs +#define hwiommu_unmap_sg_attrs sba_unmap_sg_attrs #define hwiommu_dma_supported sba_dma_supported #define hwiommu_dma_mapping_error sba_dma_mapping_error #define hwiommu_sync_single_for_cpu machvec_dma_sync_single @@ -98,41 +98,48 @@ hwsw_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma } dma_addr_t -hwsw_map_single (struct device *dev, void *addr, size_t size, int dir) +hwsw_map_single_attrs(struct device *dev, void *addr, size_t size, int dir, + struct dma_attrs *attrs) { if (use_swiotlb(dev)) - return swiotlb_map_single(dev, addr, size, dir); + return swiotlb_map_single_attrs(dev, addr, size, dir, attrs); else - return hwiommu_map_single(dev, addr, size, dir); + return hwiommu_map_single_attrs(dev, addr, size, dir, attrs); } +EXPORT_SYMBOL(hwsw_map_single_attrs); void -hwsw_unmap_single (struct device *dev, dma_addr_t iova, size_t size, int dir) +hwsw_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, + int dir, struct dma_attrs *attrs) { if (use_swiotlb(dev)) - return swiotlb_unmap_single(dev, iova, size, dir); + return swiotlb_unmap_single_attrs(dev, iova, size, dir, attrs); else - return hwiommu_unmap_single(dev, iova, size, dir); + return hwiommu_unmap_single_attrs(dev, iova, size, dir, attrs); } - +EXPORT_SYMBOL(hwsw_unmap_single_attrs); int -hwsw_map_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) +hwsw_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, + int dir, struct dma_attrs *attrs) { if (use_swiotlb(dev)) - return swiotlb_map_sg(dev, sglist, nents, dir); + return swiotlb_map_sg_attrs(dev, sglist, nents, dir, attrs); else - return hwiommu_map_sg(dev, sglist, nents, dir); + return hwiommu_map_sg_attrs(dev, sglist, nents, dir, attrs); } +EXPORT_SYMBOL(hwsw_map_sg_attrs); void -hwsw_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) +hwsw_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, + int dir, struct dma_attrs *attrs) { if (use_swiotlb(dev)) - return swiotlb_unmap_sg(dev, sglist, nents, dir); + return swiotlb_unmap_sg_attrs(dev, sglist, nents, dir, attrs); else - return hwiommu_unmap_sg(dev, sglist, nents, dir); + return hwiommu_unmap_sg_attrs(dev, sglist, nents, dir, attrs); } +EXPORT_SYMBOL(hwsw_unmap_sg_attrs); void hwsw_sync_single_for_cpu (struct device *dev, dma_addr_t addr, size_t size, int dir) @@ -185,10 +192,6 @@ hwsw_dma_mapping_error (dma_addr_t dma_addr) } EXPORT_SYMBOL(hwsw_dma_mapping_error); -EXPORT_SYMBOL(hwsw_map_single); -EXPORT_SYMBOL(hwsw_unmap_single); -EXPORT_SYMBOL(hwsw_map_sg); -EXPORT_SYMBOL(hwsw_unmap_sg); EXPORT_SYMBOL(hwsw_dma_supported); EXPORT_SYMBOL(hwsw_alloc_coherent); EXPORT_SYMBOL(hwsw_free_coherent); diff --git a/arch/ia64/hp/common/sba_iommu.c b/arch/ia64/hp/common/sba_iommu.c index 9409de5c944..34421aed1e2 100644 --- a/arch/ia64/hp/common/sba_iommu.c +++ b/arch/ia64/hp/common/sba_iommu.c @@ -899,16 +899,18 @@ sba_mark_invalid(struct ioc *ioc, dma_addr_t iova, size_t byte_cnt) } /** - * sba_map_single - map one buffer and return IOVA for DMA + * sba_map_single_attrs - map one buffer and return IOVA for DMA * @dev: instance of PCI owned by the driver that's asking. * @addr: driver buffer to map. * @size: number of bytes to map in driver buffer. * @dir: R/W or both. + * @attrs: optional dma attributes * * See Documentation/DMA-mapping.txt */ dma_addr_t -sba_map_single(struct device *dev, void *addr, size_t size, int dir) +sba_map_single_attrs(struct device *dev, void *addr, size_t size, int dir, + struct dma_attrs *attrs) { struct ioc *ioc; dma_addr_t iovp; @@ -932,7 +934,8 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir) ** Device is bit capable of DMA'ing to the buffer... ** just return the PCI address of ptr */ - DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n", + DBG_BYPASS("sba_map_single_attrs() bypass mask/addr: " + "0x%lx/0x%lx\n", to_pci_dev(dev)->dma_mask, pci_addr); return pci_addr; } @@ -953,7 +956,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir) #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); - if (sba_check_pdir(ioc,"Check before sba_map_single()")) + if (sba_check_pdir(ioc,"Check before sba_map_single_attrs()")) panic("Sanity check failed"); spin_unlock_irqrestore(&ioc->res_lock, flags); #endif @@ -982,11 +985,12 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir) /* form complete address */ #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); - sba_check_pdir(ioc,"Check after sba_map_single()"); + sba_check_pdir(ioc,"Check after sba_map_single_attrs()"); spin_unlock_irqrestore(&ioc->res_lock, flags); #endif return SBA_IOVA(ioc, iovp, offset); } +EXPORT_SYMBOL(sba_map_single_attrs); #ifdef ENABLE_MARK_CLEAN static SBA_INLINE void @@ -1013,15 +1017,17 @@ sba_mark_clean(struct ioc *ioc, dma_addr_t iova, size_t size) #endif /** - * sba_unmap_single - unmap one IOVA and free resources + * sba_unmap_single_attrs - unmap one IOVA and free resources * @dev: instance of PCI owned by the driver that's asking. * @iova: IOVA of driver buffer previously mapped. * @size: number of bytes mapped in driver buffer. * @dir: R/W or both. + * @attrs: optional dma attributes * * See Documentation/DMA-mapping.txt */ -void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir) +void sba_unmap_single_attrs(struct device *dev, dma_addr_t iova, size_t size, + int dir, struct dma_attrs *attrs) { struct ioc *ioc; #if DELAYED_RESOURCE_CNT > 0 @@ -1038,7 +1044,8 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir) /* ** Address does not fall w/in IOVA, must be bypassing */ - DBG_BYPASS("sba_unmap_single() bypass addr: 0x%lx\n", iova); + DBG_BYPASS("sba_unmap_single_atttrs() bypass addr: 0x%lx\n", + iova); #ifdef ENABLE_MARK_CLEAN if (dir == DMA_FROM_DEVICE) { @@ -1087,7 +1094,7 @@ void sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, int dir) spin_unlock_irqrestore(&ioc->res_lock, flags); #endif /* DELAYED_RESOURCE_CNT == 0 */ } - +EXPORT_SYMBOL(sba_unmap_single_attrs); /** * sba_alloc_coherent - allocate/map shared mem for DMA @@ -1144,7 +1151,8 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp * If device can't bypass or bypass is disabled, pass the 32bit fake * device to map single to get an iova mapping. */ - *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0); + *dma_handle = sba_map_single_attrs(&ioc->sac_only_dev->dev, addr, + size, 0, NULL); return addr; } @@ -1161,7 +1169,7 @@ sba_alloc_coherent (struct device *dev, size_t size, dma_addr_t *dma_handle, gfp */ void sba_free_coherent (struct device *dev, size_t size, void *vaddr, dma_addr_t dma_handle) { - sba_unmap_single(dev, dma_handle, size, 0); + sba_unmap_single_attrs(dev, dma_handle, size, 0, NULL); free_pages((unsigned long) vaddr, get_order(size)); } @@ -1410,10 +1418,12 @@ sba_coalesce_chunks(struct ioc *ioc, struct device *dev, * @sglist: array of buffer/length pairs * @nents: number of entries in list * @dir: R/W or both. + * @attrs: optional dma attributes * * See Documentation/DMA-mapping.txt */ -int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int dir) +int sba_map_sg_attrs(struct device *dev, struct scatterlist *sglist, int nents, + int dir, struct dma_attrs *attrs) { struct ioc *ioc; int coalesced, filled = 0; @@ -1441,16 +1451,16 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di /* Fast path single entry scatterlists. */ if (nents == 1) { sglist->dma_length = sglist->length; - sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, dir); + sglist->dma_address = sba_map_single_attrs(dev, sba_sg_address(sglist), sglist->length, dir, attrs); return 1; } #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); - if (sba_check_pdir(ioc,"Check before sba_map_sg()")) + if (sba_check_pdir(ioc,"Check before sba_map_sg_attrs()")) { sba_dump_sg(ioc, sglist, nents); - panic("Check before sba_map_sg()"); + panic("Check before sba_map_sg_attrs()"); } spin_unlock_irqrestore(&ioc->res_lock, flags); #endif @@ -1479,10 +1489,10 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); - if (sba_check_pdir(ioc,"Check after sba_map_sg()")) + if (sba_check_pdir(ioc,"Check after sba_map_sg_attrs()")) { sba_dump_sg(ioc, sglist, nents); - panic("Check after sba_map_sg()\n"); + panic("Check after sba_map_sg_attrs()\n"); } spin_unlock_irqrestore(&ioc->res_lock, flags); #endif @@ -1492,18 +1502,20 @@ int sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int di return filled; } - +EXPORT_SYMBOL(sba_map_sg_attrs); /** - * sba_unmap_sg - unmap Scatter/Gather list + * sba_unmap_sg_attrs - unmap Scatter/Gather list * @dev: instance of PCI owned by the driver that's asking. * @sglist: array of buffer/length pairs * @nents: number of entries in list * @dir: R/W or both. + * @attrs: optional dma attributes * * See Documentation/DMA-mapping.txt */ -void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) +void sba_unmap_sg_attrs(struct device *dev, struct scatterlist *sglist, + int nents, int dir, struct dma_attrs *attrs) { #ifdef ASSERT_PDIR_SANITY struct ioc *ioc; @@ -1518,13 +1530,14 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in ASSERT(ioc); spin_lock_irqsave(&ioc->res_lock, flags); - sba_check_pdir(ioc,"Check before sba_unmap_sg()"); + sba_check_pdir(ioc,"Check before sba_unmap_sg_attrs()"); spin_unlock_irqrestore(&ioc->res_lock, flags); #endif while (nents && sglist->dma_length) { - sba_unmap_single(dev, sglist->dma_address, sglist->dma_length, dir); + sba_unmap_single_attrs(dev, sglist->dma_address, + sglist->dma_length, dir, attrs); sglist = sg_next(sglist); nents--; } @@ -1533,11 +1546,12 @@ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, in #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); - sba_check_pdir(ioc,"Check after sba_unmap_sg()"); + sba_check_pdir(ioc,"Check after sba_unmap_sg_attrs()"); spin_unlock_irqrestore(&ioc->res_lock, flags); #endif } +EXPORT_SYMBOL(sba_unmap_sg_attrs); /************************************************************** * @@ -1918,15 +1932,13 @@ static const struct file_operations ioc_fops = { static void __init ioc_proc_init(void) { - struct proc_dir_entry *dir, *entry; + struct proc_dir_entry *dir; dir = proc_mkdir("bus/mckinley", NULL); if (!dir) return; - entry = create_proc_entry(ioc_list->name, 0, dir); - if (entry) - entry->proc_fops = &ioc_fops; + proc_create(ioc_list->name, 0, dir, &ioc_fops); } #endif @@ -2166,10 +2178,6 @@ sba_page_override(char *str) __setup("sbapagesize=",sba_page_override); EXPORT_SYMBOL(sba_dma_mapping_error); -EXPORT_SYMBOL(sba_map_single); -EXPORT_SYMBOL(sba_unmap_single); -EXPORT_SYMBOL(sba_map_sg); -EXPORT_SYMBOL(sba_unmap_sg); EXPORT_SYMBOL(sba_dma_supported); EXPORT_SYMBOL(sba_alloc_coherent); EXPORT_SYMBOL(sba_free_coherent); diff --git a/arch/ia64/kernel/asm-offsets.c b/arch/ia64/kernel/asm-offsets.c index 230a6f92367..c64a55af9b9 100644 --- a/arch/ia64/kernel/asm-offsets.c +++ b/arch/ia64/kernel/asm-offsets.c @@ -9,7 +9,7 @@ #include <linux/sched.h> #include <linux/pid.h> #include <linux/clocksource.h> - +#include <linux/kbuild.h> #include <asm-ia64/processor.h> #include <asm-ia64/ptrace.h> #include <asm-ia64/siginfo.h> @@ -19,11 +19,6 @@ #include "../kernel/sigframe.h" #include "../kernel/fsyscall_gtod_data.h" -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - void foo(void) { DEFINE(IA64_TASK_SIZE, sizeof (struct task_struct)); diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index c8e403752a0..7fbb51e10bb 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -6695,16 +6695,12 @@ pfm_init(void) /* * create /proc/perfmon (mostly for debugging purposes) */ - perfmon_dir = create_proc_entry("perfmon", S_IRUGO, NULL); + perfmon_dir = proc_create("perfmon", S_IRUGO, NULL, &pfm_proc_fops); if (perfmon_dir == NULL) { printk(KERN_ERR "perfmon: cannot create /proc entry, perfmon disabled\n"); pmu_conf = NULL; return -1; } - /* - * install customized file operations for /proc/perfmon entry - */ - perfmon_dir->proc_fops = &pfm_proc_fops; /* * create /proc/sys/kernel/perfmon (for debugging purposes) diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index b11bb50a197..ecb9eb78d68 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -648,18 +648,16 @@ salinfo_init(void) if (!dir) continue; - entry = create_proc_entry("event", S_IRUSR, dir); + entry = proc_create_data("event", S_IRUSR, dir, + &salinfo_event_fops, data); if (!entry) continue; - entry->data = data; - entry->proc_fops = &salinfo_event_fops; *sdir++ = entry; - entry = create_proc_entry("data", S_IRUSR | S_IWUSR, dir); + entry = proc_create_data("data", S_IRUSR | S_IWUSR, dir, + &salinfo_data_fops, data); if (!entry) continue; - entry->data = data; - entry->proc_fops = &salinfo_data_fops; *sdir++ = entry; /* we missed any events before now */ diff --git a/arch/ia64/sn/kernel/sn2/sn2_smp.c b/arch/ia64/sn/kernel/sn2/sn2_smp.c index dfc6bf1c7b4..49d3120415e 100644 --- a/arch/ia64/sn/kernel/sn2/sn2_smp.c +++ b/arch/ia64/sn/kernel/sn2/sn2_smp.c @@ -550,11 +550,12 @@ static int __init sn2_ptc_init(void) if (!ia64_platform_is("sn2")) return 0; - if (!(proc_sn2_ptc = create_proc_entry(PTC_BASENAME, 0444, NULL))) { + proc_sn2_ptc = proc_create(PTC_BASENAME, 0444, + NULL, &proc_sn2_ptc_operations); + if (!&proc_sn2_ptc_operations) { printk(KERN_ERR "unable to create %s proc entry", PTC_BASENAME); return -EINVAL; } - proc_sn2_ptc->proc_fops = &proc_sn2_ptc_operations; spin_lock_init(&sn2_global_ptc_lock); return 0; } diff --git a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c index 62b3e9a496a..2526e5c783a 100644 --- a/arch/ia64/sn/kernel/sn2/sn_proc_fs.c +++ b/arch/ia64/sn/kernel/sn2/sn_proc_fs.c @@ -139,30 +139,21 @@ static const struct file_operations proc_sn_topo_fops = { void register_sn_procfs(void) { static struct proc_dir_entry *sgi_proc_dir = NULL; - struct proc_dir_entry *pde; BUG_ON(sgi_proc_dir != NULL); if (!(sgi_proc_dir = proc_mkdir("sgi_sn", NULL))) return; - pde = create_proc_entry("partition_id", 0444, sgi_proc_dir); - if (pde) - pde->proc_fops = &proc_partition_id_fops; - pde = create_proc_entry("system_serial_number", 0444, sgi_proc_dir); - if (pde) - pde->proc_fops = &proc_system_sn_fops; - pde = create_proc_entry("licenseID", 0444, sgi_proc_dir); - if (pde) - pde->proc_fops = &proc_license_id_fops; - pde = create_proc_entry("sn_force_interrupt", 0644, sgi_proc_dir); - if (pde) - pde->proc_fops = &proc_sn_force_intr_fops; - pde = create_proc_entry("coherence_id", 0444, sgi_proc_dir); - if (pde) - pde->proc_fops = &proc_coherence_id_fops; - pde = create_proc_entry("sn_topology", 0444, sgi_proc_dir); - if (pde) - pde->proc_fops = &proc_sn_topo_fops; + proc_create("partition_id", 0444, sgi_proc_dir, + &proc_partition_id_fops); + proc_create("system_serial_number", 0444, sgi_proc_dir, + &proc_system_sn_fops); + proc_create("licenseID", 0444, sgi_proc_dir, &proc_license_id_fops); + proc_create("sn_force_interrupt", 0644, sgi_proc_dir, + &proc_sn_force_intr_fops); + proc_create("coherence_id", 0444, sgi_proc_dir, + &proc_coherence_id_fops); + proc_create("sn_topology", 0444, sgi_proc_dir, &proc_sn_topo_fops); } #endif /* CONFIG_PROC_FS */ diff --git a/arch/ia64/sn/pci/pci_dma.c b/arch/ia64/sn/pci/pci_dma.c index 18b94b792d5..52175af299a 100644 --- a/arch/ia64/sn/pci/pci_dma.c +++ b/arch/ia64/sn/pci/pci_dma.c @@ -10,6 +10,7 @@ */ #include <linux/module.h> +#include <linux/dma-attrs.h> #include <asm/dma.h> #include <asm/sn/intr.h> #include <asm/sn/pcibus_provider_defs.h> @@ -149,11 +150,12 @@ void sn_dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, EXPORT_SYMBOL(sn_dma_free_coherent); /** - * sn_dma_map_single - map a single page for DMA + * sn_dma_map_single_attrs - map a single page for DMA * @dev: device to map for * @cpu_addr: kernel virtual address of the region to map * @size: size of the region * @direction: DMA direction + * @attrs: optional dma attributes * * Map the region pointed to by @cpu_addr for DMA and return the * DMA address. @@ -163,42 +165,59 @@ EXPORT_SYMBOL(sn_dma_free_coherent); * no way of saving the dmamap handle from the alloc to later free * (which is pretty much unacceptable). * + * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with + * dma_map_consistent() so that writes force a flush of pending DMA. + * (See "SGI Altix Architecture Considerations for Linux Device Drivers", + * Document Number: 007-4763-001) + * * TODO: simplify our interface; * figure out how to save dmamap handle so can use two step. */ -dma_addr_t sn_dma_map_single(struct device *dev, void *cpu_addr, size_t size, - int direction) +dma_addr_t sn_dma_map_single_attrs(struct device *dev, void *cpu_addr, + size_t size, int direction, + struct dma_attrs *attrs) { dma_addr_t dma_addr; unsigned long phys_addr; struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); + int dmabarr; + + dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs); BUG_ON(dev->bus != &pci_bus_type); phys_addr = __pa(cpu_addr); - dma_addr = provider->dma_map(pdev, phys_addr, size, SN_DMA_ADDR_PHYS); + if (dmabarr) + dma_addr = provider->dma_map_consistent(pdev, phys_addr, + size, SN_DMA_ADDR_PHYS); + else + dma_addr = provider->dma_map(pdev, phys_addr, size, + SN_DMA_ADDR_PHYS); + if (!dma_addr) { printk(KERN_ERR "%s: out of ATEs\n", __func__); return 0; } return dma_addr; } -EXPORT_SYMBOL(sn_dma_map_single); +EXPORT_SYMBOL(sn_dma_map_single_attrs); /** - * sn_dma_unmap_single - unamp a DMA mapped page + * sn_dma_unmap_single_attrs - unamp a DMA mapped page * @dev: device to sync * @dma_addr: DMA address to sync * @size: size of region * @direction: DMA direction + * @attrs: optional dma attributes * * This routine is supposed to sync the DMA region specified * by @dma_handle into the coherence domain. On SN, we're always cache * coherent, so we just need to free any ATEs associated with this mapping. */ -void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, - int direction) +void sn_dma_unmap_single_attrs(struct device *dev, dma_addr_t dma_addr, + size_t size, int direction, + struct dma_attrs *attrs) { struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); @@ -207,19 +226,21 @@ void sn_dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, provider->dma_unmap(pdev, dma_addr, direction); } -EXPORT_SYMBOL(sn_dma_unmap_single); +EXPORT_SYMBOL(sn_dma_unmap_single_attrs); /** - * sn_dma_unmap_sg - unmap a DMA scatterlist + * sn_dma_unmap_sg_attrs - unmap a DMA scatterlist * @dev: device to unmap * @sg: scatterlist to unmap * @nhwentries: number of scatterlist entries * @direction: DMA direction + * @attrs: optional dma attributes * * Unmap a set of streaming mode DMA translations. */ -void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, - int nhwentries, int direction) +void sn_dma_unmap_sg_attrs(struct device *dev, struct scatterlist *sgl, + int nhwentries, int direction, + struct dma_attrs *attrs) { int i; struct pci_dev *pdev = to_pci_dev(dev); @@ -234,25 +255,34 @@ void sn_dma_unmap_sg(struct device *dev, struct scatterlist *sgl, sg->dma_length = 0; } } -EXPORT_SYMBOL(sn_dma_unmap_sg); +EXPORT_SYMBOL(sn_dma_unmap_sg_attrs); /** - * sn_dma_map_sg - map a scatterlist for DMA + * sn_dma_map_sg_attrs - map a scatterlist for DMA * @dev: device to map for * @sg: scatterlist to map * @nhwentries: number of entries * @direction: direction of the DMA transaction + * @attrs: optional dma attributes + * + * mappings with the DMA_ATTR_WRITE_BARRIER get mapped with + * dma_map_consistent() so that writes force a flush of pending DMA. + * (See "SGI Altix Architecture Considerations for Linux Device Drivers", + * Document Number: 007-4763-001) * * Maps each entry of @sg for DMA. */ -int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries, - int direction) +int sn_dma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, + int nhwentries, int direction, struct dma_attrs *attrs) { unsigned long phys_addr; struct scatterlist *saved_sg = sgl, *sg; struct pci_dev *pdev = to_pci_dev(dev); struct sn_pcibus_provider *provider = SN_PCIDEV_BUSPROVIDER(pdev); int i; + int dmabarr; + + dmabarr = dma_get_attr(DMA_ATTR_WRITE_BARRIER, attrs); BUG_ON(dev->bus != &pci_bus_type); @@ -260,11 +290,19 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries, * Setup a DMA address for each entry in the scatterlist. */ for_each_sg(sgl, sg, nhwentries, i) { + dma_addr_t dma_addr; phys_addr = SG_ENT_PHYS_ADDRESS(sg); - sg->dma_address = provider->dma_map(pdev, - phys_addr, sg->length, - SN_DMA_ADDR_PHYS); + if (dmabarr) + dma_addr = provider->dma_map_consistent(pdev, + phys_addr, + sg->length, + SN_DMA_ADDR_PHYS); + else + dma_addr = provider->dma_map(pdev, phys_addr, + sg->length, + SN_DMA_ADDR_PHYS); + sg->dma_address = dma_addr; if (!sg->dma_address) { printk(KERN_ERR "%s: out of ATEs\n", __func__); @@ -272,7 +310,8 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries, * Free any successfully allocated entries. */ if (i > 0) - sn_dma_unmap_sg(dev, saved_sg, i, direction); + sn_dma_unmap_sg_attrs(dev, saved_sg, i, + direction, attrs); return 0; } @@ -281,7 +320,7 @@ int sn_dma_map_sg(struct device *dev, struct scatterlist *sgl, int nhwentries, return nhwentries; } -EXPORT_SYMBOL(sn_dma_map_sg); +EXPORT_SYMBOL(sn_dma_map_sg_attrs); void sn_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, int direction) diff --git a/arch/m68k/kernel/asm-offsets.c b/arch/m68k/kernel/asm-offsets.c index 246a8820c22..b1f012f6c49 100644 --- a/arch/m68k/kernel/asm-offsets.c +++ b/arch/m68k/kernel/asm-offsets.c @@ -11,14 +11,12 @@ #include <linux/stddef.h> #include <linux/sched.h> #include <linux/kernel_stat.h> +#include <linux/kbuild.h> #include <asm/bootinfo.h> #include <asm/irq.h> #include <asm/amigahw.h> #include <linux/font.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - int main(void) { /* offsets into the task struct */ diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 5b2799eb96a..326fb997809 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -109,7 +109,6 @@ #include <linux/mm.h> #include <linux/delay.h> #include <linux/init.h> -#include <linux/proc_fs.h> #include <linux/interrupt.h> #include <asm/bootinfo.h> @@ -124,10 +123,6 @@ int iop_scc_present,iop_ism_present; -#ifdef CONFIG_PROC_FS -static int iop_get_proc_info(char *, char **, off_t, int); -#endif /* CONFIG_PROC_FS */ - /* structure for tracking channel listeners */ struct listener { @@ -299,12 +294,6 @@ void __init iop_init(void) iop_listeners[IOP_NUM_ISM][i].devname = NULL; iop_listeners[IOP_NUM_ISM][i].handler = NULL; } - -#if 0 /* Crashing in 2.4 now, not yet sure why. --jmt */ -#ifdef CONFIG_PROC_FS - create_proc_info_entry("mac_iop", 0, &proc_root, iop_get_proc_info); -#endif -#endif } /* @@ -637,77 +626,3 @@ irqreturn_t iop_ism_irq(int irq, void *dev_id) } return IRQ_HANDLED; } - -#ifdef CONFIG_PROC_FS - -char *iop_chan_state(int state) -{ - switch(state) { - case IOP_MSG_IDLE : return "idle "; - case IOP_MSG_NEW : return "new "; - case IOP_MSG_RCVD : return "received "; - case IOP_MSG_COMPLETE : return "completed "; - default : return "unknown "; - } -} - -int iop_dump_one_iop(char *buf, int iop_num, char *iop_name) -{ - int i,len = 0; - volatile struct mac_iop *iop = iop_base[iop_num]; - - len += sprintf(buf+len, "%s IOP channel states:\n\n", iop_name); - len += sprintf(buf+len, "## send_state recv_state device\n"); - len += sprintf(buf+len, "------------------------------------------------\n"); - for (i = 0 ; i < NUM_IOP_CHAN ; i++) { - len += sprintf(buf+len, "%2d %10s %10s %s\n", i, - iop_chan_state(iop_readb(iop, IOP_ADDR_SEND_STATE+i)), - iop_chan_state(iop_readb(iop, IOP_ADDR_RECV_STATE+i)), - iop_listeners[iop_num][i].handler? - iop_listeners[iop_num][i].devname : ""); - - } - len += sprintf(buf+len, "\n"); - return len; -} - -static int iop_get_proc_info(char *buf, char **start, off_t pos, int count) -{ - int len, cnt; - - cnt = 0; - len = sprintf(buf, "IOPs detected:\n\n"); - - if (iop_scc_present) { - len += sprintf(buf+len, "SCC IOP (%p): status %02X\n", - iop_base[IOP_NUM_SCC], - (uint) iop_base[IOP_NUM_SCC]->status_ctrl); - } - if (iop_ism_present) { - len += sprintf(buf+len, "ISM IOP (%p): status %02X\n\n", - iop_base[IOP_NUM_ISM], - (uint) iop_base[IOP_NUM_ISM]->status_ctrl); - } - - if (iop_scc_present) { - len += iop_dump_one_iop(buf+len, IOP_NUM_SCC, "SCC"); - - } - - if (iop_ism_present) { - len += iop_dump_one_iop(buf+len, IOP_NUM_ISM, "ISM"); - - } - - if (len >= pos) { - if (!*start) { - *start = buf + pos; - cnt = len - pos; - } else { - cnt += len; - } - } - return (count > cnt) ? cnt : count; -} - -#endif /* CONFIG_PROC_FS */ diff --git a/arch/m68knommu/kernel/asm-offsets.c b/arch/m68knommu/kernel/asm-offsets.c index d97b89bae53..fd0c685a7f1 100644 --- a/arch/m68knommu/kernel/asm-offsets.c +++ b/arch/m68knommu/kernel/asm-offsets.c @@ -13,15 +13,11 @@ #include <linux/kernel_stat.h> #include <linux/ptrace.h> #include <linux/hardirq.h> +#include <linux/kbuild.h> #include <asm/bootinfo.h> #include <asm/irq.h> #include <asm/thread_info.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { /* offsets into the task struct */ diff --git a/arch/mips/basler/excite/excite_procfs.c b/arch/mips/basler/excite/excite_procfs.c index 9ee67a95f6b..08923e6825b 100644 --- a/arch/mips/basler/excite/excite_procfs.c +++ b/arch/mips/basler/excite/excite_procfs.c @@ -18,8 +18,9 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - +#include <linux/module.h> #include <linux/proc_fs.h> +#include <linux/seq_file.h> #include <linux/stat.h> #include <asm/page.h> #include <asm/io.h> @@ -28,14 +29,25 @@ #include <excite.h> -static int excite_get_unit_id(char *buf, char **addr, off_t offs, int size) +static int excite_unit_id_proc_show(struct seq_file *m, void *v) { - const int len = snprintf(buf, PAGE_SIZE, "%06x", unit_id); - const int w = len - offs; - *addr = buf + offs; - return w < size ? w : size; + seq_printf(m, "%06x", unit_id); + return 0; } +static int excite_unit_id_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, excite_unit_id_proc_show, NULL); +} + +static const struct file_operations excite_unit_id_proc_fops = { + .owner = THIS_MODULE, + .open = excite_unit_id_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + static int excite_bootrom_read(char *page, char **start, off_t off, int count, int *eof, void *data) @@ -65,12 +77,12 @@ excite_bootrom_read(char *page, char **start, off_t off, int count, void excite_procfs_init(void) { /* Create & populate /proc/excite */ - struct proc_dir_entry * const pdir = proc_mkdir("excite", &proc_root); + struct proc_dir_entry * const pdir = proc_mkdir("excite", NULL); if (pdir) { struct proc_dir_entry * e; - e = create_proc_info_entry("unit_id", S_IRUGO, pdir, - excite_get_unit_id); + e = proc_create("unit_id", S_IRUGO, pdir, + &excite_unit_id_proc_fops); if (e) e->size = 6; e = create_proc_read_entry("bootrom", S_IRUGO, pdir, diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index 5bf03b3c415..72942226fcd 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -13,327 +13,285 @@ #include <linux/sched.h> #include <linux/mm.h> #include <linux/interrupt.h> - +#include <linux/kbuild.h> #include <asm/ptrace.h> #include <asm/processor.h> -#define text(t) __asm__("\n->#" t) -#define _offset(type, member) (&(((type *)NULL)->member)) -#define offset(string, ptr, member) \ - __asm__("\n->" string " %0" : : "i" (_offset(ptr, member))) -#define constant(string, member) \ - __asm__("\n->" string " %0" : : "ri" (member)) -#define size(string, size) \ - __asm__("\n->" string " %0" : : "i" (sizeof(size))) -#define linefeed text("") - void output_ptreg_defines(void) { - text("MIPS pt_regs offsets."); - offset("PT_R0", struct pt_regs, regs[0]); - offset("PT_R1", struct pt_regs, regs[1]); - offset("PT_R2", struct pt_regs, regs[2]); - offset("PT_R3", struct pt_regs, regs[3]); - offset("PT_R4", struct pt_regs, regs[4]); - offset("PT_R5", struct pt_regs, regs[5]); - offset("PT_R6", struct pt_regs, regs[6]); - offset("PT_R7", struct pt_regs, regs[7]); - offset("PT_R8", struct pt_regs, regs[8]); - offset("PT_R9", struct pt_regs, regs[9]); - offset("PT_R10", struct pt_regs, regs[10]); - offset("PT_R11", struct pt_regs, regs[11]); - offset("PT_R12", struct pt_regs, regs[12]); - offset("PT_R13", struct pt_regs, regs[13]); - offset("PT_R14", struct pt_regs, regs[14]); - offset("PT_R15", struct pt_regs, regs[15]); - offset("PT_R16", struct pt_regs, regs[16]); - offset("PT_R17", struct pt_regs, regs[17]); - offset("PT_R18", struct pt_regs, regs[18]); - offset("PT_R19", struct pt_regs, regs[19]); - offset("PT_R20", struct pt_regs, regs[20]); - offset("PT_R21", struct pt_regs, regs[21]); - offset("PT_R22", struct pt_regs, regs[22]); - offset("PT_R23", struct pt_regs, regs[23]); - offset("PT_R24", struct pt_regs, regs[24]); - offset("PT_R25", struct pt_regs, regs[25]); - offset("PT_R26", struct pt_regs, regs[26]); - offset("PT_R27", struct pt_regs, regs[27]); - offset("PT_R28", struct pt_regs, regs[28]); - offset("PT_R29", struct pt_regs, regs[29]); - offset("PT_R30", struct pt_regs, regs[30]); - offset("PT_R31", struct pt_regs, regs[31]); - offset("PT_LO", struct pt_regs, lo); - offset("PT_HI", struct pt_regs, hi); + COMMENT("MIPS pt_regs offsets."); + OFFSET(PT_R0, pt_regs, regs[0]); + OFFSET(PT_R1, pt_regs, regs[1]); + OFFSET(PT_R2, pt_regs, regs[2]); + OFFSET(PT_R3, pt_regs, regs[3]); + OFFSET(PT_R4, pt_regs, regs[4]); + OFFSET(PT_R5, pt_regs, regs[5]); + OFFSET(PT_R6, pt_regs, regs[6]); + OFFSET(PT_R7, pt_regs, regs[7]); + OFFSET(PT_R8, pt_regs, regs[8]); + OFFSET(PT_R9, pt_regs, regs[9]); + OFFSET(PT_R10, pt_regs, regs[10]); + OFFSET(PT_R11, pt_regs, regs[11]); + OFFSET(PT_R12, pt_regs, regs[12]); + OFFSET(PT_R13, pt_regs, regs[13]); + OFFSET(PT_R14, pt_regs, regs[14]); + OFFSET(PT_R15, pt_regs, regs[15]); + OFFSET(PT_R16, pt_regs, regs[16]); + OFFSET(PT_R17, pt_regs, regs[17]); + OFFSET(PT_R18, pt_regs, regs[18]); + OFFSET(PT_R19, pt_regs, regs[19]); + OFFSET(PT_R20, pt_regs, regs[20]); + OFFSET(PT_R21, pt_regs, regs[21]); + OFFSET(PT_R22, pt_regs, regs[22]); + OFFSET(PT_R23, pt_regs, regs[23]); + OFFSET(PT_R24, pt_regs, regs[24]); + OFFSET(PT_R25, pt_regs, regs[25]); + OFFSET(PT_R26, pt_regs, regs[26]); + OFFSET(PT_R27, pt_regs, regs[27]); + OFFSET(PT_R28, pt_regs, regs[28]); + OFFSET(PT_R29, pt_regs, regs[29]); + OFFSET(PT_R30, pt_regs, regs[30]); + OFFSET(PT_R31, pt_regs, regs[31]); + OFFSET(PT_LO, pt_regs, lo); + OFFSET(PT_HI, pt_regs, hi); #ifdef CONFIG_CPU_HAS_SMARTMIPS - offset("PT_ACX", struct pt_regs, acx); + OFFSET(PT_ACX, pt_regs, acx); #endif - offset("PT_EPC", struct pt_regs, cp0_epc); - offset("PT_BVADDR", struct pt_regs, cp0_badvaddr); - offset("PT_STATUS", struct pt_regs, cp0_status); - offset("PT_CAUSE", struct pt_regs, cp0_cause); + OFFSET(PT_EPC, pt_regs, cp0_epc); + OFFSET(PT_BVADDR, pt_regs, cp0_badvaddr); + OFFSET(PT_STATUS, pt_regs, cp0_status); + OFFSET(PT_CAUSE, pt_regs, cp0_cause); #ifdef CONFIG_MIPS_MT_SMTC - offset("PT_TCSTATUS", struct pt_regs, cp0_tcstatus); + OFFSET(PT_TCSTATUS, pt_regs, cp0_tcstatus); #endif /* CONFIG_MIPS_MT_SMTC */ - size("PT_SIZE", struct pt_regs); - linefeed; + DEFINE(PT_SIZE, sizeof(struct pt_regs)); + BLANK(); } void output_task_defines(void) { - text("MIPS task_struct offsets."); - offset("TASK_STATE", struct task_struct, state); - offset("TASK_THREAD_INFO", struct task_struct, stack); - offset("TASK_FLAGS", struct task_struct, flags); - offset("TASK_MM", struct task_struct, mm); - offset("TASK_PID", struct task_struct, pid); - size( "TASK_STRUCT_SIZE", struct task_struct); - linefeed; + COMMENT("MIPS task_struct offsets."); + OFFSET(TASK_STATE, task_struct, state); + OFFSET(TASK_THREAD_INFO, task_struct, stack); + OFFSET(TASK_FLAGS, task_struct, flags); + OFFSET(TASK_MM, task_struct, mm); + OFFSET(TASK_PID, task_struct, pid); + DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct)); + BLANK(); } void output_thread_info_defines(void) { - text("MIPS thread_info offsets."); - offset("TI_TASK", struct thread_info, task); - offset("TI_EXEC_DOMAIN", struct thread_info, exec_domain); - offset("TI_FLAGS", struct thread_info, flags); - offset("TI_TP_VALUE", struct thread_info, tp_value); - offset("TI_CPU", struct thread_info, cpu); - offset("TI_PRE_COUNT", struct thread_info, preempt_count); - offset("TI_ADDR_LIMIT", struct thread_info, addr_limit); - offset("TI_RESTART_BLOCK", struct thread_info, restart_block); - offset("TI_REGS", struct thread_info, regs); - constant("_THREAD_SIZE", THREAD_SIZE); - constant("_THREAD_MASK", THREAD_MASK); - linefeed; + COMMENT("MIPS thread_info offsets."); + OFFSET(TI_TASK, thread_info, task); + OFFSET(TI_EXEC_DOMAIN, thread_info, exec_domain); + OFFSET(TI_FLAGS, thread_info, flags); + OFFSET(TI_TP_VALUE, thread_info, tp_value); + OFFSET(TI_CPU, thread_info, cpu); + OFFSET(TI_PRE_COUNT, thread_info, preempt_count); + OFFSET(TI_ADDR_LIMIT, thread_info, addr_limit); + OFFSET(TI_RESTART_BLOCK, thread_info, restart_block); + OFFSET(TI_REGS, thread_info, regs); + DEFINE(_THREAD_SIZE, THREAD_SIZE); + DEFINE(_THREAD_MASK, THREAD_MASK); + BLANK(); } void output_thread_defines(void) { - text("MIPS specific thread_struct offsets."); - offset("THREAD_REG16", struct task_struct, thread.reg16); - offset("THREAD_REG17", struct task_struct, thread.reg17); - offset("THREAD_REG18", struct task_struct, thread.reg18); - offset("THREAD_REG19", struct task_struct, thread.reg19); - offset("THREAD_REG20", struct task_struct, thread.reg20); - offset("THREAD_REG21", struct task_struct, thread.reg21); - offset("THREAD_REG22", struct task_struct, thread.reg22); - offset("THREAD_REG23", struct task_struct, thread.reg23); - offset("THREAD_REG29", struct task_struct, thread.reg29); - offset("THREAD_REG30", struct task_struct, thread.reg30); - offset("THREAD_REG31", struct task_struct, thread.reg31); - offset("THREAD_STATUS", struct task_struct, + COMMENT("MIPS specific thread_struct offsets."); + OFFSET(THREAD_REG16, task_struct, thread.reg16); + OFFSET(THREAD_REG17, task_struct, thread.reg17); + OFFSET(THREAD_REG18, task_struct, thread.reg18); + OFFSET(THREAD_REG19, task_struct, thread.reg19); + OFFSET(THREAD_REG20, task_struct, thread.reg20); + OFFSET(THREAD_REG21, task_struct, thread.reg21); + OFFSET(THREAD_REG22, task_struct, thread.reg22); + OFFSET(THREAD_REG23, task_struct, thread.reg23); + OFFSET(THREAD_REG29, task_struct, thread.reg29); + OFFSET(THREAD_REG30, task_struct, thread.reg30); + OFFSET(THREAD_REG31, task_struct, thread.reg31); + OFFSET(THREAD_STATUS, task_struct, thread.cp0_status); - offset("THREAD_FPU", struct task_struct, thread.fpu); + OFFSET(THREAD_FPU, task_struct, thread.fpu); - offset("THREAD_BVADDR", struct task_struct, \ + OFFSET(THREAD_BVADDR, task_struct, \ thread.cp0_badvaddr); - offset("THREAD_BUADDR", struct task_struct, \ + OFFSET(THREAD_BUADDR, task_struct, \ thread.cp0_baduaddr); - offset("THREAD_ECODE", struct task_struct, \ + OFFSET(THREAD_ECODE, task_struct, \ thread.error_code); - offset("THREAD_TRAPNO", struct task_struct, thread.trap_no); - offset("THREAD_TRAMP", struct task_struct, \ + OFFSET(THREAD_TRAPNO, task_struct, thread.trap_no); + OFFSET(THREAD_TRAMP, task_struct, \ thread.irix_trampoline); - offset("THREAD_OLDCTX", struct task_struct, \ + OFFSET(THREAD_OLDCTX, task_struct, \ thread.irix_oldctx); - linefeed; + BLANK(); } void output_thread_fpu_defines(void) { - offset("THREAD_FPR0", - struct task_struct, thread.fpu.fpr[0]); - offset("THREAD_FPR1", - struct task_struct, thread.fpu.fpr[1]); - offset("THREAD_FPR2", - struct task_struct, thread.fpu.fpr[2]); - offset("THREAD_FPR3", - struct task_struct, thread.fpu.fpr[3]); - offset("THREAD_FPR4", - struct task_struct, thread.fpu.fpr[4]); - offset("THREAD_FPR5", - struct task_struct, thread.fpu.fpr[5]); - offset("THREAD_FPR6", - struct task_struct, thread.fpu.fpr[6]); - offset("THREAD_FPR7", - struct task_struct, thread.fpu.fpr[7]); - offset("THREAD_FPR8", - struct task_struct, thread.fpu.fpr[8]); - offset("THREAD_FPR9", - struct task_struct, thread.fpu.fpr[9]); - offset("THREAD_FPR10", - struct task_struct, thread.fpu.fpr[10]); - offset("THREAD_FPR11", - struct task_struct, thread.fpu.fpr[11]); - offset("THREAD_FPR12", - struct task_struct, thread.fpu.fpr[12]); - offset("THREAD_FPR13", - struct task_struct, thread.fpu.fpr[13]); - offset("THREAD_FPR14", - struct task_struct, thread.fpu.fpr[14]); - offset("THREAD_FPR15", - struct task_struct, thread.fpu.fpr[15]); - offset("THREAD_FPR16", - struct task_struct, thread.fpu.fpr[16]); - offset("THREAD_FPR17", - struct task_struct, thread.fpu.fpr[17]); - offset("THREAD_FPR18", - struct task_struct, thread.fpu.fpr[18]); - offset("THREAD_FPR19", - struct task_struct, thread.fpu.fpr[19]); - offset("THREAD_FPR20", - struct task_struct, thread.fpu.fpr[20]); - offset("THREAD_FPR21", - struct task_struct, thread.fpu.fpr[21]); - offset("THREAD_FPR22", - struct task_struct, thread.fpu.fpr[22]); - offset("THREAD_FPR23", - struct task_struct, thread.fpu.fpr[23]); - offset("THREAD_FPR24", - struct task_struct, thread.fpu.fpr[24]); - offset("THREAD_FPR25", - struct task_struct, thread.fpu.fpr[25]); - offset("THREAD_FPR26", - struct task_struct, thread.fpu.fpr[26]); - offset("THREAD_FPR27", - struct task_struct, thread.fpu.fpr[27]); - offset("THREAD_FPR28", - struct task_struct, thread.fpu.fpr[28]); - offset("THREAD_FPR29", - struct task_struct, thread.fpu.fpr[29]); - offset("THREAD_FPR30", - struct task_struct, thread.fpu.fpr[30]); - offset("THREAD_FPR31", - struct task_struct, thread.fpu.fpr[31]); + OFFSET(THREAD_FPR0, task_struct, thread.fpu.fpr[0]); + OFFSET(THREAD_FPR1, task_struct, thread.fpu.fpr[1]); + OFFSET(THREAD_FPR2, task_struct, thread.fpu.fpr[2]); + OFFSET(THREAD_FPR3, task_struct, thread.fpu.fpr[3]); + OFFSET(THREAD_FPR4, task_struct, thread.fpu.fpr[4]); + OFFSET(THREAD_FPR5, task_struct, thread.fpu.fpr[5]); + OFFSET(THREAD_FPR6, task_struct, thread.fpu.fpr[6]); + OFFSET(THREAD_FPR7, task_struct, thread.fpu.fpr[7]); + OFFSET(THREAD_FPR8, task_struct, thread.fpu.fpr[8]); + OFFSET(THREAD_FPR9, task_struct, thread.fpu.fpr[9]); + OFFSET(THREAD_FPR10, task_struct, thread.fpu.fpr[10]); + OFFSET(THREAD_FPR11, task_struct, thread.fpu.fpr[11]); + OFFSET(THREAD_FPR12, task_struct, thread.fpu.fpr[12]); + OFFSET(THREAD_FPR13, task_struct, thread.fpu.fpr[13]); + OFFSET(THREAD_FPR14, task_struct, thread.fpu.fpr[14]); + OFFSET(THREAD_FPR15, task_struct, thread.fpu.fpr[15]); + OFFSET(THREAD_FPR16, task_struct, thread.fpu.fpr[16]); + OFFSET(THREAD_FPR17, task_struct, thread.fpu.fpr[17]); + OFFSET(THREAD_FPR18, task_struct, thread.fpu.fpr[18]); + OFFSET(THREAD_FPR19, task_struct, thread.fpu.fpr[19]); + OFFSET(THREAD_FPR20, task_struct, thread.fpu.fpr[20]); + OFFSET(THREAD_FPR21, task_struct, thread.fpu.fpr[21]); + OFFSET(THREAD_FPR22, task_struct, thread.fpu.fpr[22]); + OFFSET(THREAD_FPR23, task_struct, thread.fpu.fpr[23]); + OFFSET(THREAD_FPR24, task_struct, thread.fpu.fpr[24]); + OFFSET(THREAD_FPR25, task_struct, thread.fpu.fpr[25]); + OFFSET(THREAD_FPR26, task_struct, thread.fpu.fpr[26]); + OFFSET(THREAD_FPR27, task_struct, thread.fpu.fpr[27]); + OFFSET(THREAD_FPR28, task_struct, thread.fpu.fpr[28]); + OFFSET(THREAD_FPR29, task_struct, thread.fpu.fpr[29]); + OFFSET(THREAD_FPR30, task_struct, thread.fpu.fpr[30]); + OFFSET(THREAD_FPR31, task_struct, thread.fpu.fpr[31]); - offset("THREAD_FCR31", - struct task_struct, thread.fpu.fcr31); - linefeed; + OFFSET(THREAD_FCR31, task_struct, thread.fpu.fcr31); + BLANK(); } void output_mm_defines(void) { - text("Size of struct page"); - size("STRUCT_PAGE_SIZE", struct page); - linefeed; - text("Linux mm_struct offsets."); - offset("MM_USERS", struct mm_struct, mm_users); - offset("MM_PGD", struct mm_struct, pgd); - offset("MM_CONTEXT", struct mm_struct, context); - linefeed; - constant("_PAGE_SIZE", PAGE_SIZE); - constant("_PAGE_SHIFT", PAGE_SHIFT); - linefeed; - constant("_PGD_T_SIZE", sizeof(pgd_t)); - constant("_PMD_T_SIZE", sizeof(pmd_t)); - constant("_PTE_T_SIZE", sizeof(pte_t)); - linefeed; - constant("_PGD_T_LOG2", PGD_T_LOG2); - constant("_PMD_T_LOG2", PMD_T_LOG2); - constant("_PTE_T_LOG2", PTE_T_LOG2); - linefeed; - constant("_PGD_ORDER", PGD_ORDER); - constant("_PMD_ORDER", PMD_ORDER); - constant("_PTE_ORDER", PTE_ORDER); - linefeed; - constant("_PMD_SHIFT", PMD_SHIFT); - constant("_PGDIR_SHIFT", PGDIR_SHIFT); - linefeed; - constant("_PTRS_PER_PGD", PTRS_PER_PGD); - constant("_PTRS_PER_PMD", PTRS_PER_PMD); - constant("_PTRS_PER_PTE", PTRS_PER_PTE); - linefeed; + COMMENT("Size of struct page"); + DEFINE(STRUCT_PAGE_SIZE, sizeof(struct page)); + BLANK(); + COMMENT("Linux mm_struct offsets."); + OFFSET(MM_USERS, mm_struct, mm_users); + OFFSET(MM_PGD, mm_struct, pgd); + OFFSET(MM_CONTEXT, mm_struct, context); + BLANK(); + DEFINE(_PAGE_SIZE, PAGE_SIZE); + DEFINE(_PAGE_SHIFT, PAGE_SHIFT); + BLANK(); + DEFINE(_PGD_T_SIZE, sizeof(pgd_t)); + DEFINE(_PMD_T_SIZE, sizeof(pmd_t)); + DEFINE(_PTE_T_SIZE, sizeof(pte_t)); + BLANK(); + DEFINE(_PGD_T_LOG2, PGD_T_LOG2); + DEFINE(_PMD_T_LOG2, PMD_T_LOG2); + DEFINE(_PTE_T_LOG2, PTE_T_LOG2); + BLANK(); + DEFINE(_PGD_ORDER, PGD_ORDER); + DEFINE(_PMD_ORDER, PMD_ORDER); + DEFINE(_PTE_ORDER, PTE_ORDER); + BLANK(); + DEFINE(_PMD_SHIFT, PMD_SHIFT); + DEFINE(_PGDIR_SHIFT, PGDIR_SHIFT); + BLANK(); + DEFINE(_PTRS_PER_PGD, PTRS_PER_PGD); + DEFINE(_PTRS_PER_PMD, PTRS_PER_PMD); + DEFINE(_PTRS_PER_PTE, PTRS_PER_PTE); + BLANK(); } #ifdef CONFIG_32BIT void output_sc_defines(void) { - text("Linux sigcontext offsets."); - offset("SC_REGS", struct sigcontext, sc_regs); - offset("SC_FPREGS", struct sigcontext, sc_fpregs); - offset("SC_ACX", struct sigcontext, sc_acx); - offset("SC_MDHI", struct sigcontext, sc_mdhi); - offset("SC_MDLO", struct sigcontext, sc_mdlo); - offset("SC_PC", struct sigcontext, sc_pc); - offset("SC_FPC_CSR", struct sigcontext, sc_fpc_csr); - offset("SC_FPC_EIR", struct sigcontext, sc_fpc_eir); - offset("SC_HI1", struct sigcontext, sc_hi1); - offset("SC_LO1", struct sigcontext, sc_lo1); - offset("SC_HI2", struct sigcontext, sc_hi2); - offset("SC_LO2", struct sigcontext, sc_lo2); - offset("SC_HI3", struct sigcontext, sc_hi3); - offset("SC_LO3", struct sigcontext, sc_lo3); - linefeed; + COMMENT("Linux sigcontext offsets."); + OFFSET(SC_REGS, sigcontext, sc_regs); + OFFSET(SC_FPREGS, sigcontext, sc_fpregs); + OFFSET(SC_ACX, sigcontext, sc_acx); + OFFSET(SC_MDHI, sigcontext, sc_mdhi); + OFFSET(SC_MDLO, sigcontext, sc_mdlo); + OFFSET(SC_PC, sigcontext, sc_pc); + OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr); + OFFSET(SC_FPC_EIR, sigcontext, sc_fpc_eir); + OFFSET(SC_HI1, sigcontext, sc_hi1); + OFFSET(SC_LO1, sigcontext, sc_lo1); + OFFSET(SC_HI2, sigcontext, sc_hi2); + OFFSET(SC_LO2, sigcontext, sc_lo2); + OFFSET(SC_HI3, sigcontext, sc_hi3); + OFFSET(SC_LO3, sigcontext, sc_lo3); + BLANK(); } #endif #ifdef CONFIG_64BIT void output_sc_defines(void) { - text("Linux sigcontext offsets."); - offset("SC_REGS", struct sigcontext, sc_regs); - offset("SC_FPREGS", struct sigcontext, sc_fpregs); - offset("SC_MDHI", struct sigcontext, sc_mdhi); - offset("SC_MDLO", struct sigcontext, sc_mdlo); - offset("SC_PC", struct sigcontext, sc_pc); - offset("SC_FPC_CSR", struct sigcontext, sc_fpc_csr); - linefeed; + COMMENT("Linux sigcontext offsets."); + OFFSET(SC_REGS, sigcontext, sc_regs); + OFFSET(SC_FPREGS, sigcontext, sc_fpregs); + OFFSET(SC_MDHI, sigcontext, sc_mdhi); + OFFSET(SC_MDLO, sigcontext, sc_mdlo); + OFFSET(SC_PC, sigcontext, sc_pc); + OFFSET(SC_FPC_CSR, sigcontext, sc_fpc_csr); + BLANK(); } #endif #ifdef CONFIG_MIPS32_COMPAT void output_sc32_defines(void) { - text("Linux 32-bit sigcontext offsets."); - offset("SC32_FPREGS", struct sigcontext32, sc_fpregs); - offset("SC32_FPC_CSR", struct sigcontext32, sc_fpc_csr); - offset("SC32_FPC_EIR", struct sigcontext32, sc_fpc_eir); - linefeed; + COMMENT("Linux 32-bit sigcontext offsets."); + OFFSET(SC32_FPREGS, sigcontext32, sc_fpregs); + OFFSET(SC32_FPC_CSR, sigcontext32, sc_fpc_csr); + OFFSET(SC32_FPC_EIR, sigcontext32, sc_fpc_eir); + BLANK(); } #endif void output_signal_defined(void) { - text("Linux signal numbers."); - constant("_SIGHUP", SIGHUP); - constant("_SIGINT", SIGINT); - constant("_SIGQUIT", SIGQUIT); - constant("_SIGILL", SIGILL); - constant("_SIGTRAP", SIGTRAP); - constant("_SIGIOT", SIGIOT); - constant("_SIGABRT", SIGABRT); - constant("_SIGEMT", SIGEMT); - constant("_SIGFPE", SIGFPE); - constant("_SIGKILL", SIGKILL); - constant("_SIGBUS", SIGBUS); - constant("_SIGSEGV", SIGSEGV); - constant("_SIGSYS", SIGSYS); - constant("_SIGPIPE", SIGPIPE); - constant("_SIGALRM", SIGALRM); - constant("_SIGTERM", SIGTERM); - constant("_SIGUSR1", SIGUSR1); - constant("_SIGUSR2", SIGUSR2); - constant("_SIGCHLD", SIGCHLD); - constant("_SIGPWR", SIGPWR); - constant("_SIGWINCH", SIGWINCH); - constant("_SIGURG", SIGURG); - constant("_SIGIO", SIGIO); - constant("_SIGSTOP", SIGSTOP); - constant("_SIGTSTP", SIGTSTP); - constant("_SIGCONT", SIGCONT); - constant("_SIGTTIN", SIGTTIN); - constant("_SIGTTOU", SIGTTOU); - constant("_SIGVTALRM", SIGVTALRM); - constant("_SIGPROF", SIGPROF); - constant("_SIGXCPU", SIGXCPU); - constant("_SIGXFSZ", SIGXFSZ); - linefeed; + COMMENT("Linux signal numbers."); + DEFINE(_SIGHUP, SIGHUP); + DEFINE(_SIGINT, SIGINT); + DEFINE(_SIGQUIT, SIGQUIT); + DEFINE(_SIGILL, SIGILL); + DEFINE(_SIGTRAP, SIGTRAP); + DEFINE(_SIGIOT, SIGIOT); + DEFINE(_SIGABRT, SIGABRT); + DEFINE(_SIGEMT, SIGEMT); + DEFINE(_SIGFPE, SIGFPE); + DEFINE(_SIGKILL, SIGKILL); + DEFINE(_SIGBUS, SIGBUS); + DEFINE(_SIGSEGV, SIGSEGV); + DEFINE(_SIGSYS, SIGSYS); + DEFINE(_SIGPIPE, SIGPIPE); + DEFINE(_SIGALRM, SIGALRM); + DEFINE(_SIGTERM, SIGTERM); + DEFINE(_SIGUSR1, SIGUSR1); + DEFINE(_SIGUSR2, SIGUSR2); + DEFINE(_SIGCHLD, SIGCHLD); + DEFINE(_SIGPWR, SIGPWR); + DEFINE(_SIGWINCH, SIGWINCH); + DEFINE(_SIGURG, SIGURG); + DEFINE(_SIGIO, SIGIO); + DEFINE(_SIGSTOP, SIGSTOP); + DEFINE(_SIGTSTP, SIGTSTP); + DEFINE(_SIGCONT, SIGCONT); + DEFINE(_SIGTTIN, SIGTTIN); + DEFINE(_SIGTTOU, SIGTTOU); + DEFINE(_SIGVTALRM, SIGVTALRM); + DEFINE(_SIGPROF, SIGPROF); + DEFINE(_SIGXCPU, SIGXCPU); + DEFINE(_SIGXFSZ, SIGXFSZ); + BLANK(); } void output_irq_cpustat_t_defines(void) { - text("Linux irq_cpustat_t offsets."); - offset("IC_SOFTIRQ_PENDING", irq_cpustat_t, __softirq_pending); - size("IC_IRQ_CPUSTAT_T", irq_cpustat_t); - linefeed; + COMMENT("Linux irq_cpustat_t offsets."); + DEFINE(IC_SOFTIRQ_PENDING, + offsetof(irq_cpustat_t, __softirq_pending)); + DEFINE(IC_IRQ_CPUSTAT_T, sizeof(irq_cpustat_t)); + BLANK(); } diff --git a/arch/mips/lib/iomap-pci.c b/arch/mips/lib/iomap-pci.c index c11b2494bb6..2ab899c4b4c 100644 --- a/arch/mips/lib/iomap-pci.c +++ b/arch/mips/lib/iomap-pci.c @@ -45,8 +45,8 @@ static void __iomem *ioport_map_pci(struct pci_dev *dev, */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/mips/pmc-sierra/yosemite/setup.c b/arch/mips/pmc-sierra/yosemite/setup.c index 855977ca51c..6537d90a25b 100644 --- a/arch/mips/pmc-sierra/yosemite/setup.c +++ b/arch/mips/pmc-sierra/yosemite/setup.c @@ -143,9 +143,6 @@ void __init plat_time_init(void) mips_hpt_frequency = 33000000 * 3 * 5; } -/* No other usable initialization hook than this ... */ -extern void (*late_time_init)(void); - unsigned long ocd_base; EXPORT_SYMBOL(ocd_base); diff --git a/arch/mn10300/kernel/asm-offsets.c b/arch/mn10300/kernel/asm-offsets.c index ee2d9f8af5a..2646fcbd7d8 100644 --- a/arch/mn10300/kernel/asm-offsets.c +++ b/arch/mn10300/kernel/asm-offsets.c @@ -7,6 +7,7 @@ #include <linux/sched.h> #include <linux/signal.h> #include <linux/personality.h> +#include <linux/kbuild.h> #include <asm/ucontext.h> #include <asm/processor.h> #include <asm/thread_info.h> @@ -14,14 +15,6 @@ #include "sigframe.h" #include "mn10300-serial.h" -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->") - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - void foo(void) { OFFSET(SIGCONTEXT_d0, sigcontext, d0); diff --git a/arch/mn10300/unit-asb2305/pci-iomap.c b/arch/mn10300/unit-asb2305/pci-iomap.c index dbceae4307d..c1a8d8f941f 100644 --- a/arch/mn10300/unit-asb2305/pci-iomap.c +++ b/arch/mn10300/unit-asb2305/pci-iomap.c @@ -16,8 +16,8 @@ */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index eaa79bc14d9..3efc0b73e4f 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -32,6 +32,7 @@ #include <linux/thread_info.h> #include <linux/ptrace.h> #include <linux/hardirq.h> +#include <linux/kbuild.h> #include <asm/pgtable.h> #include <asm/ptrace.h> @@ -39,11 +40,6 @@ #include <asm/pdc.h> #include <asm/uaccess.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - #ifdef CONFIG_64BIT #define FRAME_SIZE 128 #else diff --git a/arch/parisc/kernel/pci-dma.c b/arch/parisc/kernel/pci-dma.c index 9448d4e9114..ccd61b9567a 100644 --- a/arch/parisc/kernel/pci-dma.c +++ b/arch/parisc/kernel/pci-dma.c @@ -397,10 +397,9 @@ pcxl_dma_init(void) "pcxl_dma_init: Unable to create gsc /proc dir entry\n"); else { struct proc_dir_entry* ent; - ent = create_proc_entry("pcxl_dma", 0, proc_gsc_root); - if (ent) - ent->proc_fops = &proc_pcxl_dma_ops; - else + ent = proc_create("pcxl_dma", 0, proc_gsc_root, + &proc_pcxl_dma_ops); + if (!ent) printk(KERN_WARNING "pci-dma.c: Unable to create pcxl_dma /proc entry.\n"); } diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c index f4a811690ab..9abed07db7f 100644 --- a/arch/parisc/lib/iomap.c +++ b/arch/parisc/lib/iomap.c @@ -438,8 +438,8 @@ void ioport_unmap(void __iomem *addr) /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 4e40c122bf2..3934e265940 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -608,6 +608,19 @@ source "drivers/pcmcia/Kconfig" source "drivers/pci/hotplug/Kconfig" +config HAS_RAPIDIO + bool + default n + +config RAPIDIO + bool "RapidIO support" + depends on HAS_RAPIDIO + help + If you say Y here, the kernel will include drivers and + infrastructure code to support RapidIO interconnect devices. + +source "drivers/rapidio/Kconfig" + endmenu menu "Advanced setup" diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 807a2dce626..a7d24e692ba 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -118,7 +118,6 @@ config XMON_DISASSEMBLY config IRQSTACKS bool "Use separate kernel stacks when processing interrupts" - depends on PPC64 help If you say Y here the kernel will use separate kernel stacks for handling hard and soft interrupts. This can help avoid diff --git a/arch/powerpc/boot/dts/mpc8641_hpcn.dts b/arch/powerpc/boot/dts/mpc8641_hpcn.dts index 7f9b999843c..1e4bfe9cadb 100644 --- a/arch/powerpc/boot/dts/mpc8641_hpcn.dts +++ b/arch/powerpc/boot/dts/mpc8641_hpcn.dts @@ -26,6 +26,7 @@ serial1 = &serial1; pci0 = &pci0; pci1 = &pci1; + rapidio0 = &rapidio0; }; cpus { @@ -500,4 +501,15 @@ 0x0 0x00100000>; }; }; + rapidio0: rapidio@f80c0000 { + #address-cells = <2>; + #size-cells = <2>; + compatible = "fsl,rapidio-delta"; + reg = <0xf80c0000 0x20000>; + ranges = <0 0 0xc0000000 0 0x20000000>; + interrupt-parent = <&mpic>; + /* err_irq bell_outb_irq bell_inb_irq + msg1_tx_irq msg1_rx_irq msg2_tx_irq msg2_rx_irq */ + interrupts = <48 2 49 2 50 2 53 2 54 2 55 2 56 2>; + }; }; diff --git a/arch/powerpc/configs/g5_defconfig b/arch/powerpc/configs/g5_defconfig index a20501f8947..88338a9f5e9 100644 --- a/arch/powerpc/configs/g5_defconfig +++ b/arch/powerpc/configs/g5_defconfig @@ -696,6 +696,7 @@ CONFIG_WINDFARM=y CONFIG_WINDFARM_PM81=y CONFIG_WINDFARM_PM91=y CONFIG_WINDFARM_PM112=y +CONFIG_WINDFARM_PM121=y # CONFIG_PMAC_RACKMETER is not set CONFIG_NETDEVICES=y # CONFIG_NETDEVICES_MULTIQUEUE is not set diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9177b21b1a9..d14cebf62bb 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -73,7 +73,6 @@ pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ pci-common.o obj-$(CONFIG_PCI_MSI) += msi.o -obj-$(CONFIG_RAPIDIO) += rio.o obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ machine_kexec_$(CONFIG_WORD_SIZE).o obj-$(CONFIG_AUDIT) += audit.o diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 62134845af0..ec9228d687b 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -30,6 +30,7 @@ #include <linux/time.h> #include <linux/hardirq.h> #endif +#include <linux/kbuild.h> #include <asm/io.h> #include <asm/page.h> @@ -51,11 +52,6 @@ #include <asm/iseries/alpaca.h> #endif -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { DEFINE(THREAD, offsetof(struct task_struct, thread)); @@ -67,6 +63,7 @@ int main(void) #endif /* CONFIG_PPC64 */ DEFINE(KSP, offsetof(struct thread_struct, ksp)); + DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit)); DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 84c86863306..0c8614d9875 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -137,11 +137,12 @@ transfer_to_handler: 2: /* if from kernel, check interrupted DOZE/NAP mode and * check for stack overflow */ - lwz r9,THREAD_INFO-THREAD(r12) - cmplw r1,r9 /* if r1 <= current->thread_info */ + lwz r9,KSP_LIMIT(r12) + cmplw r1,r9 /* if r1 <= ksp_limit */ ble- stack_ovf /* then the kernel stack overflowed */ 5: #ifdef CONFIG_6xx + rlwinm r9,r1,0,0,31-THREAD_SHIFT tophys(r9,r9) /* check local flags */ lwz r12,TI_LOCAL_FLAGS(r9) mtcrf 0x01,r12 diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 215973a2c8d..024805e1747 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -239,6 +239,10 @@ instruction_access_slb_pSeries: .globl system_call_pSeries system_call_pSeries: HMT_MEDIUM +BEGIN_FTR_SECTION + cmpdi r0,0x1ebe + beq- 1f +END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) mr r9,r13 mfmsr r10 mfspr r13,SPRN_SPRG3 @@ -253,6 +257,13 @@ system_call_pSeries: rfid b . /* prevent speculative execution */ +/* Fast LE/BE switch system call */ +1: mfspr r12,SPRN_SRR1 + xori r12,r12,MSR_LE + mtspr SPRN_SRR1,r12 + rfid /* return to userspace */ + b . + STD_EXCEPTION_PSERIES(0xd00, single_step) STD_EXCEPTION_PSERIES(0xe00, trap_0e) diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 425616f92d1..2f73f705d56 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -307,6 +307,7 @@ void do_IRQ(struct pt_regs *regs) if (curtp != irqtp) { struct irq_desc *desc = irq_desc + irq; void *handler = desc->handle_irq; + unsigned long saved_sp_limit = current->thread.ksp_limit; if (handler == NULL) handler = &__do_IRQ; irqtp->task = curtp->task; @@ -319,7 +320,10 @@ void do_IRQ(struct pt_regs *regs) (irqtp->preempt_count & ~SOFTIRQ_MASK) | (curtp->preempt_count & SOFTIRQ_MASK); + current->thread.ksp_limit = (unsigned long)irqtp + + _ALIGN_UP(sizeof(struct thread_info), 16); call_handle_irq(irq, desc, irqtp, handler); + current->thread.ksp_limit = saved_sp_limit; irqtp->task = NULL; @@ -352,9 +356,7 @@ void __init init_IRQ(void) { if (ppc_md.init_IRQ) ppc_md.init_IRQ(); -#ifdef CONFIG_PPC64 irq_ctx_init(); -#endif } @@ -383,11 +385,15 @@ void irq_ctx_init(void) static inline void do_softirq_onstack(void) { struct thread_info *curtp, *irqtp; + unsigned long saved_sp_limit = current->thread.ksp_limit; curtp = current_thread_info(); irqtp = softirq_ctx[smp_processor_id()]; irqtp->task = curtp->task; + current->thread.ksp_limit = (unsigned long)irqtp + + _ALIGN_UP(sizeof(struct thread_info), 16); call_do_softirq(irqtp); + current->thread.ksp_limit = saved_sp_limit; irqtp->task = NULL; } diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 1ffacc698ff..1e656b43ad7 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c @@ -591,10 +591,8 @@ int __init lparcfg_init(void) !firmware_has_feature(FW_FEATURE_ISERIES)) mode |= S_IWUSR; - ent = create_proc_entry("ppc64/lparcfg", mode, NULL); - if (ent) { - ent->proc_fops = &lparcfg_fops; - } else { + ent = proc_create("ppc64/lparcfg", mode, NULL, &lparcfg_fops); + if (!ent) { printk(KERN_ERR "Failed to create ppc64/lparcfg\n"); return -EIO; } diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 92ccc6fcc5b..89aaaa6f356 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S @@ -32,6 +32,31 @@ .text +#ifdef CONFIG_IRQSTACKS +_GLOBAL(call_do_softirq) + mflr r0 + stw r0,4(r1) + stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) + mr r1,r3 + bl __do_softirq + lwz r1,0(r1) + lwz r0,4(r1) + mtlr r0 + blr + +_GLOBAL(call_handle_irq) + mflr r0 + stw r0,4(r1) + mtctr r6 + stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5) + mr r1,r5 + bctrl + lwz r1,0(r1) + lwz r0,4(r1) + mtlr r0 + blr +#endif /* CONFIG_IRQSTACKS */ + /* * This returns the high 64 bits of the product of two 64-bit numbers. */ diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index f78dfce1b77..c647ddef40d 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c @@ -68,12 +68,11 @@ static int __init proc_ppc64_init(void) { struct proc_dir_entry *pde; - pde = create_proc_entry("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL); + pde = proc_create_data("ppc64/systemcfg", S_IFREG|S_IRUGO, NULL, + &page_map_fops, vdso_data); if (!pde) return 1; - pde->data = vdso_data; pde->size = PAGE_SIZE; - pde->proc_fops = &page_map_fops; return 0; } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6caad17ea72..7de41c3948e 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -589,6 +589,8 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, kregs = (struct pt_regs *) sp; sp -= STACK_FRAME_OVERHEAD; p->thread.ksp = sp; + p->thread.ksp_limit = (unsigned long)task_stack_page(p) + + _ALIGN_UP(sizeof(struct thread_info), 16); #ifdef CONFIG_PPC64 if (cpu_has_feature(CPU_FTR_SLB)) { diff --git a/arch/powerpc/kernel/rio.c b/arch/powerpc/kernel/rio.c deleted file mode 100644 index 29487fedfc7..00000000000 --- a/arch/powerpc/kernel/rio.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * RapidIO PPC32 support - * - * Copyright 2005 MontaVista Software, Inc. - * Matt Porter <mporter@kernel.crashing.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/rio.h> - -#include <asm/rio.h> - -/** - * platform_rio_init - Do platform specific RIO init - * - * Any platform specific initialization of RapdIO - * hardware is done here as well as registration - * of any active master ports in the system. - */ -void __attribute__ ((weak)) - platform_rio_init(void) -{ - printk(KERN_WARNING "RIO: No platform_rio_init() present\n"); -} - -/** - * ppc_rio_init - Do PPC32 RIO init - * - * Calls platform-specific RIO init code and then calls - * rio_init_mports() to initialize any master ports that - * have been registered with the RIO subsystem. - */ -static int __init ppc_rio_init(void) -{ - printk(KERN_INFO "RIO: RapidIO init\n"); - - /* Platform specific initialization */ - platform_rio_init(); - - /* Enumerate all registered ports */ - rio_init_mports(); - - return 0; -} - -subsys_initcall(ppc_rio_init); diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index f2e3bc714d7..f9c6abc84a9 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c @@ -255,8 +255,6 @@ static void check_location(struct seq_file *m, const char *c); static int __init proc_rtas_init(void) { - struct proc_dir_entry *entry; - if (!machine_is(pseries)) return -ENODEV; @@ -264,35 +262,20 @@ static int __init proc_rtas_init(void) if (rtas_node == NULL) return -ENODEV; - entry = create_proc_entry("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_progress_operations; - - entry = create_proc_entry("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_clock_operations; - - entry = create_proc_entry("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_poweron_operations; - - entry = create_proc_entry("ppc64/rtas/sensors", S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_sensors_operations; - - entry = create_proc_entry("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, - NULL); - if (entry) - entry->proc_fops = &ppc_rtas_tone_freq_operations; - - entry = create_proc_entry("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_tone_volume_operations; - - entry = create_proc_entry("ppc64/rtas/rmo_buffer", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &ppc_rtas_rmo_buf_ops; - + proc_create("ppc64/rtas/progress", S_IRUGO|S_IWUSR, NULL, + &ppc_rtas_progress_operations); + proc_create("ppc64/rtas/clock", S_IRUGO|S_IWUSR, NULL, + &ppc_rtas_clock_operations); + proc_create("ppc64/rtas/poweron", S_IWUSR|S_IRUGO, NULL, + &ppc_rtas_poweron_operations); + proc_create("ppc64/rtas/sensors", S_IRUGO, NULL, + &ppc_rtas_sensors_operations); + proc_create("ppc64/rtas/frequency", S_IWUSR|S_IRUGO, NULL, + &ppc_rtas_tone_freq_operations); + proc_create("ppc64/rtas/volume", S_IWUSR|S_IRUGO, NULL, + &ppc_rtas_tone_volume_operations); + proc_create("ppc64/rtas/rmo_buffer", S_IRUSR, NULL, + &ppc_rtas_rmo_buf_ops); return 0; } diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 627f126d184..0a5e22b2272 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c @@ -704,18 +704,11 @@ static int initialize_flash_pde_data(const char *rtas_call_name, static struct proc_dir_entry *create_flash_pde(const char *filename, const struct file_operations *fops) { - struct proc_dir_entry *ent = NULL; - - ent = create_proc_entry(filename, S_IRUSR | S_IWUSR, NULL); - if (ent != NULL) { - ent->proc_fops = fops; - ent->owner = THIS_MODULE; - } - - return ent; + return proc_create(filename, S_IRUSR | S_IWUSR, NULL, fops); } static const struct file_operations rtas_flash_operations = { + .owner = THIS_MODULE, .read = rtas_flash_read, .write = rtas_flash_write, .open = rtas_excl_open, @@ -723,6 +716,7 @@ static const struct file_operations rtas_flash_operations = { }; static const struct file_operations manage_flash_operations = { + .owner = THIS_MODULE, .read = manage_flash_read, .write = manage_flash_write, .open = rtas_excl_open, @@ -730,6 +724,7 @@ static const struct file_operations manage_flash_operations = { }; static const struct file_operations validate_flash_operations = { + .owner = THIS_MODULE, .read = validate_flash_read, .write = validate_flash_write, .open = rtas_excl_open, diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 36f6779c88d..5112a4aa801 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -16,6 +16,7 @@ #include <linux/root_dev.h> #include <linux/cpu.h> #include <linux/console.h> +#include <linux/lmb.h> #include <asm/io.h> #include <asm/prom.h> @@ -229,6 +230,24 @@ int __init ppc_init(void) arch_initcall(ppc_init); +#ifdef CONFIG_IRQSTACKS +static void __init irqstack_early_init(void) +{ + unsigned int i; + + /* interrupt stacks must be in lowmem, we get that for free on ppc32 + * as the lmb is limited to lowmem by LMB_REAL_LIMIT */ + for_each_possible_cpu(i) { + softirq_ctx[i] = (struct thread_info *) + __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); + hardirq_ctx[i] = (struct thread_info *) + __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); + } +} +#else +#define irqstack_early_init() +#endif + /* Warning, IO base is not yet inited */ void __init setup_arch(char **cmdline_p) { @@ -286,6 +305,8 @@ void __init setup_arch(char **cmdline_p) init_mm.end_data = (unsigned long) _edata; init_mm.brk = klimit; + irqstack_early_init(); + /* set up the bootmem stuff with available memory */ do_init_bootmem(); if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index d9e37f365b5..f67e118116f 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c @@ -154,19 +154,35 @@ out: /* * walk_memory_resource() needs to make sure there is no holes in a given - * memory range. On PPC64, since this range comes from /sysfs, the range - * is guaranteed to be valid, non-overlapping and can not contain any - * holes. By the time we get here (memory add or remove), /proc/device-tree - * is updated and correct. Only reason we need to check against device-tree - * would be if we allow user-land to specify a memory range through a - * system call/ioctl etc. instead of doing offline/online through /sysfs. + * memory range. PPC64 does not maintain the memory layout in /proc/iomem. + * Instead it maintains it in lmb.memory structures. Walk through the + * memory regions, find holes and callback for contiguous regions. */ int walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, int (*func)(unsigned long, unsigned long, void *)) { - return (*func)(start_pfn, nr_pages, arg); + struct lmb_property res; + unsigned long pfn, len; + u64 end; + int ret = -1; + + res.base = (u64) start_pfn << PAGE_SHIFT; + res.size = (u64) nr_pages << PAGE_SHIFT; + + end = res.base + res.size - 1; + while ((res.base < end) && (lmb_find(&res) >= 0)) { + pfn = (unsigned long)(res.base >> PAGE_SHIFT); + len = (unsigned long)(res.size >> PAGE_SHIFT); + ret = (*func)(pfn, len, arg); + if (ret) + break; + res.base += (res.size + 1); + res.size = (end - res.base + 1); + } + return ret; } +EXPORT_SYMBOL_GPL(walk_memory_resource); #endif /* CONFIG_MEMORY_HOTPLUG */ diff --git a/arch/powerpc/platforms/86xx/Kconfig b/arch/powerpc/platforms/86xx/Kconfig index 7442c58d44f..053f49a1dca 100644 --- a/arch/powerpc/platforms/86xx/Kconfig +++ b/arch/powerpc/platforms/86xx/Kconfig @@ -8,6 +8,7 @@ config MPC8641_HPCN select PPC_I8259 select DEFAULT_UIMAGE select FSL_ULI1575 + select HAS_RAPIDIO help This option enables support for the MPC8641 HPCN board. diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c index f947f555fd4..f13704aabbe 100644 --- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c +++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c @@ -221,6 +221,7 @@ mpc86xx_time_init(void) static __initdata struct of_device_id of_bus_ids[] = { { .compatible = "simple-bus", }, + { .compatible = "fsl,rapidio-delta", }, {}, }; diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 00528ef84ad..45dcd269350 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -1063,10 +1063,9 @@ int __init spu_sched_init(void) mod_timer(&spuloadavg_timer, 0); - entry = create_proc_entry("spu_loadavg", 0, NULL); + entry = proc_create("spu_loadavg", 0, NULL, &spu_loadavg_fops); if (!entry) goto out_stop_kthread; - entry->proc_fops = &spu_loadavg_fops; pr_debug("spusched: tick: %d, min ticks: %d, default ticks: %d\n", SPUSCHED_TICK, MIN_SPU_TIMESLICE, DEF_SPU_TIMESLICE); diff --git a/arch/powerpc/platforms/cell/spufs/sputrace.c b/arch/powerpc/platforms/cell/spufs/sputrace.c index 79aa773f3c9..aea5286f124 100644 --- a/arch/powerpc/platforms/cell/spufs/sputrace.c +++ b/arch/powerpc/platforms/cell/spufs/sputrace.c @@ -201,10 +201,9 @@ static int __init sputrace_init(void) if (!sputrace_log) goto out; - entry = create_proc_entry("sputrace", S_IRUSR, NULL); + entry = proc_create("sputrace", S_IRUSR, NULL, &sputrace_fops); if (!entry) goto out_free_log; - entry->proc_fops = &sputrace_fops; for (i = 0; i < ARRAY_SIZE(spu_probes); i++) { struct spu_probe *p = &spu_probes[i]; diff --git a/arch/powerpc/platforms/iseries/lpevents.c b/arch/powerpc/platforms/iseries/lpevents.c index e5b40e3e008..b0f8a857ec0 100644 --- a/arch/powerpc/platforms/iseries/lpevents.c +++ b/arch/powerpc/platforms/iseries/lpevents.c @@ -330,15 +330,11 @@ static const struct file_operations proc_lpevents_operations = { static int __init proc_lpevents_init(void) { - struct proc_dir_entry *e; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) return 0; - e = create_proc_entry("iSeries/lpevents", S_IFREG|S_IRUGO, NULL); - if (e) - e->proc_fops = &proc_lpevents_operations; - + proc_create("iSeries/lpevents", S_IFREG|S_IRUGO, NULL, + &proc_lpevents_operations); return 0; } __initcall(proc_lpevents_init); diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index c0f2433bc16..1dc7295746d 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c @@ -1255,11 +1255,11 @@ static int __init mf_proc_init(void) if (i == 3) /* no vmlinux entry for 'D' */ continue; - ent = create_proc_entry("vmlinux", S_IFREG|S_IWUSR, mf); + ent = proc_create_data("vmlinux", S_IFREG|S_IWUSR, mf, + &proc_vmlinux_operations, + (void *)(long)i); if (!ent) return 1; - ent->data = (void *)(long)i; - ent->proc_fops = &proc_vmlinux_operations; } ent = create_proc_entry("side", S_IFREG|S_IRUSR|S_IWUSR, mf_proc_root); diff --git a/arch/powerpc/platforms/iseries/proc.c b/arch/powerpc/platforms/iseries/proc.c index f2cde418020..91f4c6cd4b9 100644 --- a/arch/powerpc/platforms/iseries/proc.c +++ b/arch/powerpc/platforms/iseries/proc.c @@ -110,15 +110,11 @@ static const struct file_operations proc_titantod_operations = { static int __init iseries_proc_init(void) { - struct proc_dir_entry *e; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) return 0; - e = create_proc_entry("iSeries/titanTod", S_IFREG|S_IRUGO, NULL); - if (e) - e->proc_fops = &proc_titantod_operations; - + proc_create("iSeries/titanTod", S_IFREG|S_IRUGO, NULL, + &proc_titantod_operations); return 0; } __initcall(iseries_proc_init); diff --git a/arch/powerpc/platforms/iseries/viopath.c b/arch/powerpc/platforms/iseries/viopath.c index df23331eb25..49ff4dc422b 100644 --- a/arch/powerpc/platforms/iseries/viopath.c +++ b/arch/powerpc/platforms/iseries/viopath.c @@ -180,15 +180,10 @@ static const struct file_operations proc_viopath_operations = { static int __init vio_proc_init(void) { - struct proc_dir_entry *e; - if (!firmware_has_feature(FW_FEATURE_ISERIES)) return 0; - e = create_proc_entry("iSeries/config", 0, NULL); - if (e) - e->proc_fops = &proc_viopath_operations; - + proc_create("iSeries/config", 0, NULL, &proc_viopath_operations); return 0; } __initcall(vio_proc_init); diff --git a/arch/powerpc/platforms/powermac/Makefile b/arch/powerpc/platforms/powermac/Makefile index 78093d7f97a..4d72c8f7215 100644 --- a/arch/powerpc/platforms/powermac/Makefile +++ b/arch/powerpc/platforms/powermac/Makefile @@ -6,7 +6,10 @@ obj-y += pic.o setup.o time.o feature.o pci.o \ obj-$(CONFIG_PMAC_BACKLIGHT) += backlight.o obj-$(CONFIG_CPU_FREQ_PMAC) += cpufreq_32.o obj-$(CONFIG_CPU_FREQ_PMAC64) += cpufreq_64.o -obj-$(CONFIG_NVRAM) += nvram.o +# CONFIG_NVRAM is an arch. independant tristate symbol, for pmac32 we really +# need this to be a bool. Cheat here and pretend CONFIG_NVRAM=m is really +# CONFIG_NVRAM=y +obj-$(CONFIG_NVRAM:m=y) += nvram.o # ppc64 pmac doesn't define CONFIG_NVRAM but needs nvram stuff obj-$(CONFIG_PPC64) += nvram.o obj-$(CONFIG_PPC32) += bootx_init.o diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index bf44c5441a3..00bd0166d07 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -337,7 +337,8 @@ static void __init pmac_setup_arch(void) find_via_pmu(); smu_init(); -#if defined(CONFIG_NVRAM) || defined(CONFIG_PPC64) +#if defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE) || \ + defined(CONFIG_PPC64) pmac_nvram_init(); #endif diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index bd2593ed28d..554c6e42ef2 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -18,6 +18,7 @@ obj-$(CONFIG_PCI) += pci.o pci_dlpar.o obj-$(CONFIG_PCI_MSI) += msi.o obj-$(CONFIG_HOTPLUG_CPU) += hotplug-cpu.o +obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVCS) += hvcserver.o diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index a3fd56b186e..6f544ba4b37 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/arch/powerpc/platforms/pseries/eeh.c @@ -1259,14 +1259,8 @@ static const struct file_operations proc_eeh_operations = { static int __init eeh_init_proc(void) { - struct proc_dir_entry *e; - - if (machine_is(pseries)) { - e = create_proc_entry("ppc64/eeh", 0, NULL); - if (e) - e->proc_fops = &proc_eeh_operations; - } - + if (machine_is(pseries)) + proc_create("ppc64/eeh", 0, NULL, &proc_eeh_operations); return 0; } __initcall(eeh_init_proc); diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c new file mode 100644 index 00000000000..3c5727dd5aa --- /dev/null +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -0,0 +1,141 @@ +/* + * pseries Memory Hotplug infrastructure. + * + * Copyright (C) 2008 Badari Pulavarty, IBM Corporation + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include <linux/of.h> +#include <linux/lmb.h> +#include <asm/firmware.h> +#include <asm/machdep.h> +#include <asm/pSeries_reconfig.h> + +static int pseries_remove_memory(struct device_node *np) +{ + const char *type; + const unsigned int *my_index; + const unsigned int *regs; + u64 start_pfn, start; + struct zone *zone; + int ret = -EINVAL; + + /* + * Check to see if we are actually removing memory + */ + type = of_get_property(np, "device_type", NULL); + if (type == NULL || strcmp(type, "memory") != 0) + return 0; + + /* + * Find the memory index and size of the removing section + */ + my_index = of_get_property(np, "ibm,my-drc-index", NULL); + if (!my_index) + return ret; + + regs = of_get_property(np, "reg", NULL); + if (!regs) + return ret; + + start_pfn = section_nr_to_pfn(*my_index & 0xffff); + zone = page_zone(pfn_to_page(start_pfn)); + + /* + * Remove section mappings and sysfs entries for the + * section of the memory we are removing. + * + * NOTE: Ideally, this should be done in generic code like + * remove_memory(). But remove_memory() gets called by writing + * to sysfs "state" file and we can't remove sysfs entries + * while writing to it. So we have to defer it to here. + */ + ret = __remove_pages(zone, start_pfn, regs[3] >> PAGE_SHIFT); + if (ret) + return ret; + + /* + * Update memory regions for memory remove + */ + lmb_remove(start_pfn << PAGE_SHIFT, regs[3]); + + /* + * Remove htab bolted mappings for this section of memory + */ + start = (unsigned long)__va(start_pfn << PAGE_SHIFT); + ret = remove_section_mapping(start, start + regs[3]); + return ret; +} + +static int pseries_add_memory(struct device_node *np) +{ + const char *type; + const unsigned int *my_index; + const unsigned int *regs; + u64 start_pfn; + int ret = -EINVAL; + + /* + * Check to see if we are actually adding memory + */ + type = of_get_property(np, "device_type", NULL); + if (type == NULL || strcmp(type, "memory") != 0) + return 0; + + /* + * Find the memory index and size of the added section + */ + my_index = of_get_property(np, "ibm,my-drc-index", NULL); + if (!my_index) + return ret; + + regs = of_get_property(np, "reg", NULL); + if (!regs) + return ret; + + start_pfn = section_nr_to_pfn(*my_index & 0xffff); + + /* + * Update memory region to represent the memory add + */ + lmb_add(start_pfn << PAGE_SHIFT, regs[3]); + return 0; +} + +static int pseries_memory_notifier(struct notifier_block *nb, + unsigned long action, void *node) +{ + int err = NOTIFY_OK; + + switch (action) { + case PSERIES_RECONFIG_ADD: + if (pseries_add_memory(node)) + err = NOTIFY_BAD; + break; + case PSERIES_RECONFIG_REMOVE: + if (pseries_remove_memory(node)) + err = NOTIFY_BAD; + break; + default: + err = NOTIFY_DONE; + break; + } + return err; +} + +static struct notifier_block pseries_mem_nb = { + .notifier_call = pseries_memory_notifier, +}; + +static int __init pseries_memory_hotplug_init(void) +{ + if (firmware_has_feature(FW_FEATURE_LPAR)) + pSeries_reconfig_notifier_register(&pseries_mem_nb); + + return 0; +} +machine_device_initcall(pseries, pseries_memory_hotplug_init); diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index ac75c10de27..75769aae41d 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c @@ -512,12 +512,9 @@ static int proc_ppc64_create_ofdt(void) if (!machine_is(pseries)) return 0; - ent = create_proc_entry("ppc64/ofdt", S_IWUSR, NULL); - if (ent) { - ent->data = NULL; + ent = proc_create("ppc64/ofdt", S_IWUSR, NULL, &ofdt_fops); + if (ent) ent->size = 0; - ent->proc_fops = &ofdt_fops; - } return 0; } diff --git a/arch/powerpc/platforms/pseries/rtasd.c b/arch/powerpc/platforms/pseries/rtasd.c index befadd4f952..7d3e2b0bd4d 100644 --- a/arch/powerpc/platforms/pseries/rtasd.c +++ b/arch/powerpc/platforms/pseries/rtasd.c @@ -468,10 +468,9 @@ static int __init rtas_init(void) return -ENOMEM; } - entry = create_proc_entry("ppc64/rtas/error_log", S_IRUSR, NULL); - if (entry) - entry->proc_fops = &proc_rtas_log_operations; - else + entry = proc_create("ppc64/rtas/error_log", S_IRUSR, NULL, + &proc_rtas_log_operations); + if (!entry) printk(KERN_ERR "Failed to create error_log proc entry\n"); if (kernel_thread(rtasd, NULL, CLONE_FS) < 0) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index af2425e4655..3d920376f58 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -1,5 +1,8 @@ /* - * MPC85xx RapidIO support + * Freescale MPC85xx/MPC86xx RapidIO support + * + * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc. + * Zhang Wei <wei.zhang@freescale.com> * * Copyright 2005 MontaVista Software, Inc. * Matt Porter <mporter@kernel.crashing.org> @@ -17,12 +20,23 @@ #include <linux/interrupt.h> #include <linux/rio.h> #include <linux/rio_drv.h> +#include <linux/of_platform.h> +#include <linux/delay.h> #include <asm/io.h> -#define RIO_REGS_BASE (CCSRBAR + 0xc0000) +/* RapidIO definition irq, which read from OF-tree */ +#define IRQ_RIO_BELL(m) (((struct rio_priv *)(m->priv))->bellirq) +#define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq) +#define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) + #define RIO_ATMU_REGS_OFFSET 0x10c00 -#define RIO_MSG_REGS_OFFSET 0x11000 +#define RIO_P_MSG_REGS_OFFSET 0x11000 +#define RIO_S_MSG_REGS_OFFSET 0x13000 +#define RIO_ESCSR 0x158 +#define RIO_CCSR 0x15c +#define RIO_ISR_AACR 0x10120 +#define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ #define RIO_MAINT_WIN_SIZE 0x400000 #define RIO_DBELL_WIN_SIZE 0x1000 @@ -50,18 +64,18 @@ #define DOORBELL_DSR_TE 0x00000080 #define DOORBELL_DSR_QFI 0x00000010 #define DOORBELL_DSR_DIQI 0x00000001 -#define DOORBELL_TID_OFFSET 0x03 -#define DOORBELL_SID_OFFSET 0x05 +#define DOORBELL_TID_OFFSET 0x02 +#define DOORBELL_SID_OFFSET 0x04 #define DOORBELL_INFO_OFFSET 0x06 #define DOORBELL_MESSAGE_SIZE 0x08 -#define DBELL_SID(x) (*(u8 *)(x + DOORBELL_SID_OFFSET)) -#define DBELL_TID(x) (*(u8 *)(x + DOORBELL_TID_OFFSET)) +#define DBELL_SID(x) (*(u16 *)(x + DOORBELL_SID_OFFSET)) +#define DBELL_TID(x) (*(u16 *)(x + DOORBELL_TID_OFFSET)) #define DBELL_INF(x) (*(u16 *)(x + DOORBELL_INFO_OFFSET)) struct rio_atmu_regs { u32 rowtar; - u32 pad1; + u32 rowtear; u32 rowbar; u32 pad2; u32 rowar; @@ -87,7 +101,15 @@ struct rio_msg_regs { u32 ifqdpar; u32 pad6; u32 ifqepar; - u32 pad7[250]; + u32 pad7[226]; + u32 odmr; + u32 odsr; + u32 res0[4]; + u32 oddpr; + u32 oddatr; + u32 res1[3]; + u32 odretcr; + u32 res2[12]; u32 dmr; u32 dsr; u32 pad8; @@ -112,20 +134,12 @@ struct rio_tx_desc { u32 res4; }; -static u32 regs_win; -static struct rio_atmu_regs *atmu_regs; -static struct rio_atmu_regs *maint_atmu_regs; -static struct rio_atmu_regs *dbell_atmu_regs; -static u32 dbell_win; -static u32 maint_win; -static struct rio_msg_regs *msg_regs; - -static struct rio_dbell_ring { +struct rio_dbell_ring { void *virt; dma_addr_t phys; -} dbell_ring; +}; -static struct rio_msg_tx_ring { +struct rio_msg_tx_ring { void *virt; dma_addr_t phys; void *virt_buffer[RIO_MAX_TX_RING_SIZE]; @@ -133,19 +147,35 @@ static struct rio_msg_tx_ring { int tx_slot; int size; void *dev_id; -} msg_tx_ring; +}; -static struct rio_msg_rx_ring { +struct rio_msg_rx_ring { void *virt; dma_addr_t phys; void *virt_buffer[RIO_MAX_RX_RING_SIZE]; int rx_slot; int size; void *dev_id; -} msg_rx_ring; +}; + +struct rio_priv { + void __iomem *regs_win; + struct rio_atmu_regs __iomem *atmu_regs; + struct rio_atmu_regs __iomem *maint_atmu_regs; + struct rio_atmu_regs __iomem *dbell_atmu_regs; + void __iomem *dbell_win; + void __iomem *maint_win; + struct rio_msg_regs __iomem *msg_regs; + struct rio_dbell_ring dbell_ring; + struct rio_msg_tx_ring msg_tx_ring; + struct rio_msg_rx_ring msg_rx_ring; + int bellirq; + int txirq; + int rxirq; +}; /** - * mpc85xx_rio_doorbell_send - Send a MPC85xx doorbell message + * fsl_rio_doorbell_send - Send a MPC85xx doorbell message * @index: ID of RapidIO interface * @destid: Destination ID of target device * @data: 16-bit info field of RapidIO doorbell message @@ -153,18 +183,34 @@ static struct rio_msg_rx_ring { * Sends a MPC85xx doorbell message. Returns %0 on success or * %-EINVAL on failure. */ -static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data) +static int fsl_rio_doorbell_send(struct rio_mport *mport, + int index, u16 destid, u16 data) { - pr_debug("mpc85xx_doorbell_send: index %d destid %4.4x data %4.4x\n", + struct rio_priv *priv = mport->priv; + pr_debug("fsl_doorbell_send: index %d destid %4.4x data %4.4x\n", index, destid, data); - out_be32((void *)&dbell_atmu_regs->rowtar, destid << 22); - out_be16((void *)(dbell_win), data); + switch (mport->phy_type) { + case RIO_PHY_PARALLEL: + out_be32(&priv->dbell_atmu_regs->rowtar, destid << 22); + out_be16(priv->dbell_win, data); + break; + case RIO_PHY_SERIAL: + /* In the serial version silicons, such as MPC8548, MPC8641, + * below operations is must be. + */ + out_be32(&priv->msg_regs->odmr, 0x00000000); + out_be32(&priv->msg_regs->odretcr, 0x00000004); + out_be32(&priv->msg_regs->oddpr, destid << 16); + out_be32(&priv->msg_regs->oddatr, data); + out_be32(&priv->msg_regs->odmr, 0x00000001); + break; + } return 0; } /** - * mpc85xx_local_config_read - Generate a MPC85xx local config space read + * fsl_local_config_read - Generate a MPC85xx local config space read * @index: ID of RapdiIO interface * @offset: Offset into configuration space * @len: Length (in bytes) of the maintenance transaction @@ -173,17 +219,19 @@ static int mpc85xx_rio_doorbell_send(int index, u16 destid, u16 data) * Generates a MPC85xx local configuration space read. Returns %0 on * success or %-EINVAL on failure. */ -static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data) +static int fsl_local_config_read(struct rio_mport *mport, + int index, u32 offset, int len, u32 *data) { - pr_debug("mpc85xx_local_config_read: index %d offset %8.8x\n", index, + struct rio_priv *priv = mport->priv; + pr_debug("fsl_local_config_read: index %d offset %8.8x\n", index, offset); - *data = in_be32((void *)(regs_win + offset)); + *data = in_be32(priv->regs_win + offset); return 0; } /** - * mpc85xx_local_config_write - Generate a MPC85xx local config space write + * fsl_local_config_write - Generate a MPC85xx local config space write * @index: ID of RapdiIO interface * @offset: Offset into configuration space * @len: Length (in bytes) of the maintenance transaction @@ -192,18 +240,20 @@ static int mpc85xx_local_config_read(int index, u32 offset, int len, u32 * data) * Generates a MPC85xx local configuration space write. Returns %0 on * success or %-EINVAL on failure. */ -static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data) +static int fsl_local_config_write(struct rio_mport *mport, + int index, u32 offset, int len, u32 data) { + struct rio_priv *priv = mport->priv; pr_debug - ("mpc85xx_local_config_write: index %d offset %8.8x data %8.8x\n", + ("fsl_local_config_write: index %d offset %8.8x data %8.8x\n", index, offset, data); - out_be32((void *)(regs_win + offset), data); + out_be32(priv->regs_win + offset, data); return 0; } /** - * mpc85xx_rio_config_read - Generate a MPC85xx read maintenance transaction + * fsl_rio_config_read - Generate a MPC85xx read maintenance transaction * @index: ID of RapdiIO interface * @destid: Destination ID of transaction * @hopcount: Number of hops to target device @@ -215,18 +265,19 @@ static int mpc85xx_local_config_write(int index, u32 offset, int len, u32 data) * success or %-EINVAL on failure. */ static int -mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len, - u32 * val) +fsl_rio_config_read(struct rio_mport *mport, int index, u16 destid, + u8 hopcount, u32 offset, int len, u32 *val) { + struct rio_priv *priv = mport->priv; u8 *data; pr_debug - ("mpc85xx_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n", + ("fsl_rio_config_read: index %d destid %d hopcount %d offset %8.8x len %d\n", index, destid, hopcount, offset, len); - out_be32((void *)&maint_atmu_regs->rowtar, + out_be32(&priv->maint_atmu_regs->rowtar, (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); - data = (u8 *) maint_win + offset; + data = (u8 *) priv->maint_win + offset; switch (len) { case 1: *val = in_8((u8 *) data); @@ -243,7 +294,7 @@ mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len, } /** - * mpc85xx_rio_config_write - Generate a MPC85xx write maintenance transaction + * fsl_rio_config_write - Generate a MPC85xx write maintenance transaction * @index: ID of RapdiIO interface * @destid: Destination ID of transaction * @hopcount: Number of hops to target device @@ -255,17 +306,18 @@ mpc85xx_rio_config_read(int index, u16 destid, u8 hopcount, u32 offset, int len, * success or %-EINVAL on failure. */ static int -mpc85xx_rio_config_write(int index, u16 destid, u8 hopcount, u32 offset, - int len, u32 val) +fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, + u8 hopcount, u32 offset, int len, u32 val) { + struct rio_priv *priv = mport->priv; u8 *data; pr_debug - ("mpc85xx_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", + ("fsl_rio_config_write: index %d destid %d hopcount %d offset %8.8x len %d val %8.8x\n", index, destid, hopcount, offset, len, val); - out_be32((void *)&maint_atmu_regs->rowtar, + out_be32(&priv->maint_atmu_regs->rowtar, (destid << 22) | (hopcount << 12) | ((offset & ~0x3) >> 9)); - data = (u8 *) maint_win + offset; + data = (u8 *) priv->maint_win + offset; switch (len) { case 1: out_8((u8 *) data, val); @@ -296,9 +348,10 @@ int rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, void *buffer, size_t len) { + struct rio_priv *priv = mport->priv; u32 omr; - struct rio_tx_desc *desc = - (struct rio_tx_desc *)msg_tx_ring.virt + msg_tx_ring.tx_slot; + struct rio_tx_desc *desc = (struct rio_tx_desc *)priv->msg_tx_ring.virt + + priv->msg_tx_ring.tx_slot; int ret = 0; pr_debug @@ -311,31 +364,43 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, } /* Copy and clear rest of buffer */ - memcpy(msg_tx_ring.virt_buffer[msg_tx_ring.tx_slot], buffer, len); + memcpy(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot], buffer, + len); if (len < (RIO_MAX_MSG_SIZE - 4)) - memset((void *)((u32) msg_tx_ring. - virt_buffer[msg_tx_ring.tx_slot] + len), 0, - RIO_MAX_MSG_SIZE - len); + memset(priv->msg_tx_ring.virt_buffer[priv->msg_tx_ring.tx_slot] + + len, 0, RIO_MAX_MSG_SIZE - len); - /* Set mbox field for message */ - desc->dport = mbox & 0x3; + switch (mport->phy_type) { + case RIO_PHY_PARALLEL: + /* Set mbox field for message */ + desc->dport = mbox & 0x3; - /* Enable EOMI interrupt, set priority, and set destid */ - desc->dattr = 0x28000000 | (rdev->destid << 2); + /* Enable EOMI interrupt, set priority, and set destid */ + desc->dattr = 0x28000000 | (rdev->destid << 2); + break; + case RIO_PHY_SERIAL: + /* Set mbox field for message, and set destid */ + desc->dport = (rdev->destid << 16) | (mbox & 0x3); + + /* Enable EOMI interrupt and priority */ + desc->dattr = 0x28000000; + break; + } /* Set transfer size aligned to next power of 2 (in double words) */ desc->dwcnt = is_power_of_2(len) ? len : 1 << get_bitmask_order(len); /* Set snooping and source buffer address */ - desc->saddr = 0x00000004 | msg_tx_ring.phys_buffer[msg_tx_ring.tx_slot]; + desc->saddr = 0x00000004 + | priv->msg_tx_ring.phys_buffer[priv->msg_tx_ring.tx_slot]; /* Increment enqueue pointer */ - omr = in_be32((void *)&msg_regs->omr); - out_be32((void *)&msg_regs->omr, omr | RIO_MSG_OMR_MUI); + omr = in_be32(&priv->msg_regs->omr); + out_be32(&priv->msg_regs->omr, omr | RIO_MSG_OMR_MUI); /* Go to next descriptor */ - if (++msg_tx_ring.tx_slot == msg_tx_ring.size) - msg_tx_ring.tx_slot = 0; + if (++priv->msg_tx_ring.tx_slot == priv->msg_tx_ring.size) + priv->msg_tx_ring.tx_slot = 0; out: return ret; @@ -344,7 +409,7 @@ rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox, EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); /** - * mpc85xx_rio_tx_handler - MPC85xx outbound message interrupt handler + * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler * @irq: Linux interrupt number * @dev_instance: Pointer to interrupt-specific data * @@ -352,32 +417,34 @@ EXPORT_SYMBOL_GPL(rio_hw_add_outb_message); * mailbox event handler and acks the interrupt occurrence. */ static irqreturn_t -mpc85xx_rio_tx_handler(int irq, void *dev_instance) +fsl_rio_tx_handler(int irq, void *dev_instance) { int osr; struct rio_mport *port = (struct rio_mport *)dev_instance; + struct rio_priv *priv = port->priv; - osr = in_be32((void *)&msg_regs->osr); + osr = in_be32(&priv->msg_regs->osr); if (osr & RIO_MSG_OSR_TE) { pr_info("RIO: outbound message transmission error\n"); - out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_TE); + out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_TE); goto out; } if (osr & RIO_MSG_OSR_QOI) { pr_info("RIO: outbound message queue overflow\n"); - out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_QOI); + out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_QOI); goto out; } if (osr & RIO_MSG_OSR_EOMI) { - u32 dqp = in_be32((void *)&msg_regs->odqdpar); - int slot = (dqp - msg_tx_ring.phys) >> 5; - port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot); + u32 dqp = in_be32(&priv->msg_regs->odqdpar); + int slot = (dqp - priv->msg_tx_ring.phys) >> 5; + port->outb_msg[0].mcback(port, priv->msg_tx_ring.dev_id, -1, + slot); /* Ack the end-of-message interrupt */ - out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI); + out_be32(&priv->msg_regs->osr, RIO_MSG_OSR_EOMI); } out: @@ -398,6 +465,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance) int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, j, rc = 0; + struct rio_priv *priv = mport->priv; if ((entries < RIO_MIN_TX_RING_SIZE) || (entries > RIO_MAX_TX_RING_SIZE) || (!is_power_of_2(entries))) { @@ -406,54 +474,53 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr } /* Initialize shadow copy ring */ - msg_tx_ring.dev_id = dev_id; - msg_tx_ring.size = entries; - - for (i = 0; i < msg_tx_ring.size; i++) { - if (! - (msg_tx_ring.virt_buffer[i] = - dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE, - &msg_tx_ring.phys_buffer[i], - GFP_KERNEL))) { + priv->msg_tx_ring.dev_id = dev_id; + priv->msg_tx_ring.size = entries; + + for (i = 0; i < priv->msg_tx_ring.size; i++) { + priv->msg_tx_ring.virt_buffer[i] = + dma_alloc_coherent(NULL, RIO_MSG_BUFFER_SIZE, + &priv->msg_tx_ring.phys_buffer[i], GFP_KERNEL); + if (!priv->msg_tx_ring.virt_buffer[i]) { rc = -ENOMEM; - for (j = 0; j < msg_tx_ring.size; j++) - if (msg_tx_ring.virt_buffer[j]) + for (j = 0; j < priv->msg_tx_ring.size; j++) + if (priv->msg_tx_ring.virt_buffer[j]) dma_free_coherent(NULL, - RIO_MSG_BUFFER_SIZE, - msg_tx_ring. - virt_buffer[j], - msg_tx_ring. - phys_buffer[j]); + RIO_MSG_BUFFER_SIZE, + priv->msg_tx_ring. + virt_buffer[j], + priv->msg_tx_ring. + phys_buffer[j]); goto out; } } /* Initialize outbound message descriptor ring */ - if (!(msg_tx_ring.virt = dma_alloc_coherent(NULL, - msg_tx_ring.size * - RIO_MSG_DESC_SIZE, - &msg_tx_ring.phys, - GFP_KERNEL))) { + priv->msg_tx_ring.virt = dma_alloc_coherent(NULL, + priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE, + &priv->msg_tx_ring.phys, GFP_KERNEL); + if (!priv->msg_tx_ring.virt) { rc = -ENOMEM; goto out_dma; } - memset(msg_tx_ring.virt, 0, msg_tx_ring.size * RIO_MSG_DESC_SIZE); - msg_tx_ring.tx_slot = 0; + memset(priv->msg_tx_ring.virt, 0, + priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE); + priv->msg_tx_ring.tx_slot = 0; /* Point dequeue/enqueue pointers at first entry in ring */ - out_be32((void *)&msg_regs->odqdpar, msg_tx_ring.phys); - out_be32((void *)&msg_regs->odqepar, msg_tx_ring.phys); + out_be32(&priv->msg_regs->odqdpar, priv->msg_tx_ring.phys); + out_be32(&priv->msg_regs->odqepar, priv->msg_tx_ring.phys); /* Configure for snooping */ - out_be32((void *)&msg_regs->osar, 0x00000004); + out_be32(&priv->msg_regs->osar, 0x00000004); /* Clear interrupt status */ - out_be32((void *)&msg_regs->osr, 0x000000b3); + out_be32(&priv->msg_regs->osr, 0x000000b3); /* Hook up outbound message handler */ - if ((rc = - request_irq(MPC85xx_IRQ_RIO_TX, mpc85xx_rio_tx_handler, 0, - "msg_tx", (void *)mport)) < 0) + rc = request_irq(IRQ_RIO_TX(mport), fsl_rio_tx_handler, 0, + "msg_tx", (void *)mport); + if (rc < 0) goto out_irq; /* @@ -463,28 +530,28 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr * Chaining mode * Disable */ - out_be32((void *)&msg_regs->omr, 0x00100220); + out_be32(&priv->msg_regs->omr, 0x00100220); /* Set number of entries */ - out_be32((void *)&msg_regs->omr, - in_be32((void *)&msg_regs->omr) | + out_be32(&priv->msg_regs->omr, + in_be32(&priv->msg_regs->omr) | ((get_bitmask_order(entries) - 2) << 12)); /* Now enable the unit */ - out_be32((void *)&msg_regs->omr, in_be32((void *)&msg_regs->omr) | 0x1); + out_be32(&priv->msg_regs->omr, in_be32(&priv->msg_regs->omr) | 0x1); out: return rc; out_irq: - dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE, - msg_tx_ring.virt, msg_tx_ring.phys); + dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE, + priv->msg_tx_ring.virt, priv->msg_tx_ring.phys); out_dma: - for (i = 0; i < msg_tx_ring.size; i++) + for (i = 0; i < priv->msg_tx_ring.size; i++) dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE, - msg_tx_ring.virt_buffer[i], - msg_tx_ring.phys_buffer[i]); + priv->msg_tx_ring.virt_buffer[i], + priv->msg_tx_ring.phys_buffer[i]); return rc; } @@ -499,19 +566,20 @@ int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entr */ void rio_close_outb_mbox(struct rio_mport *mport, int mbox) { + struct rio_priv *priv = mport->priv; /* Disable inbound message unit */ - out_be32((void *)&msg_regs->omr, 0); + out_be32(&priv->msg_regs->omr, 0); /* Free ring */ - dma_free_coherent(NULL, msg_tx_ring.size * RIO_MSG_DESC_SIZE, - msg_tx_ring.virt, msg_tx_ring.phys); + dma_free_coherent(NULL, priv->msg_tx_ring.size * RIO_MSG_DESC_SIZE, + priv->msg_tx_ring.virt, priv->msg_tx_ring.phys); /* Free interrupt */ - free_irq(MPC85xx_IRQ_RIO_TX, (void *)mport); + free_irq(IRQ_RIO_TX(mport), (void *)mport); } /** - * mpc85xx_rio_rx_handler - MPC85xx inbound message interrupt handler + * fsl_rio_rx_handler - MPC85xx inbound message interrupt handler * @irq: Linux interrupt number * @dev_instance: Pointer to interrupt-specific data * @@ -519,16 +587,17 @@ void rio_close_outb_mbox(struct rio_mport *mport, int mbox) * mailbox event handler and acks the interrupt occurrence. */ static irqreturn_t -mpc85xx_rio_rx_handler(int irq, void *dev_instance) +fsl_rio_rx_handler(int irq, void *dev_instance) { int isr; struct rio_mport *port = (struct rio_mport *)dev_instance; + struct rio_priv *priv = port->priv; - isr = in_be32((void *)&msg_regs->isr); + isr = in_be32(&priv->msg_regs->isr); if (isr & RIO_MSG_ISR_TE) { pr_info("RIO: inbound message reception error\n"); - out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_TE); + out_be32((void *)&priv->msg_regs->isr, RIO_MSG_ISR_TE); goto out; } @@ -540,10 +609,10 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance) * make the callback with an unknown/invalid mailbox number * argument. */ - port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1); + port->inb_msg[0].mcback(port, priv->msg_rx_ring.dev_id, -1, -1); /* Ack the queueing interrupt */ - out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI); + out_be32(&priv->msg_regs->isr, RIO_MSG_ISR_DIQI); } out: @@ -564,6 +633,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance) int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, rc = 0; + struct rio_priv *priv = mport->priv; if ((entries < RIO_MIN_RX_RING_SIZE) || (entries > RIO_MAX_RX_RING_SIZE) || (!is_power_of_2(entries))) { @@ -572,36 +642,35 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri } /* Initialize client buffer ring */ - msg_rx_ring.dev_id = dev_id; - msg_rx_ring.size = entries; - msg_rx_ring.rx_slot = 0; - for (i = 0; i < msg_rx_ring.size; i++) - msg_rx_ring.virt_buffer[i] = NULL; + priv->msg_rx_ring.dev_id = dev_id; + priv->msg_rx_ring.size = entries; + priv->msg_rx_ring.rx_slot = 0; + for (i = 0; i < priv->msg_rx_ring.size; i++) + priv->msg_rx_ring.virt_buffer[i] = NULL; /* Initialize inbound message ring */ - if (!(msg_rx_ring.virt = dma_alloc_coherent(NULL, - msg_rx_ring.size * - RIO_MAX_MSG_SIZE, - &msg_rx_ring.phys, - GFP_KERNEL))) { + priv->msg_rx_ring.virt = dma_alloc_coherent(NULL, + priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE, + &priv->msg_rx_ring.phys, GFP_KERNEL); + if (!priv->msg_rx_ring.virt) { rc = -ENOMEM; goto out; } /* Point dequeue/enqueue pointers at first entry in ring */ - out_be32((void *)&msg_regs->ifqdpar, (u32) msg_rx_ring.phys); - out_be32((void *)&msg_regs->ifqepar, (u32) msg_rx_ring.phys); + out_be32(&priv->msg_regs->ifqdpar, (u32) priv->msg_rx_ring.phys); + out_be32(&priv->msg_regs->ifqepar, (u32) priv->msg_rx_ring.phys); /* Clear interrupt status */ - out_be32((void *)&msg_regs->isr, 0x00000091); + out_be32(&priv->msg_regs->isr, 0x00000091); /* Hook up inbound message handler */ - if ((rc = - request_irq(MPC85xx_IRQ_RIO_RX, mpc85xx_rio_rx_handler, 0, - "msg_rx", (void *)mport)) < 0) { + rc = request_irq(IRQ_RIO_RX(mport), fsl_rio_rx_handler, 0, + "msg_rx", (void *)mport); + if (rc < 0) { dma_free_coherent(NULL, RIO_MSG_BUFFER_SIZE, - msg_tx_ring.virt_buffer[i], - msg_tx_ring.phys_buffer[i]); + priv->msg_tx_ring.virt_buffer[i], + priv->msg_tx_ring.phys_buffer[i]); goto out; } @@ -612,15 +681,13 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri * Unmask all interrupt sources * Disable */ - out_be32((void *)&msg_regs->imr, 0x001b0060); + out_be32(&priv->msg_regs->imr, 0x001b0060); /* Set number of queue entries */ - out_be32((void *)&msg_regs->imr, - in_be32((void *)&msg_regs->imr) | - ((get_bitmask_order(entries) - 2) << 12)); + setbits32(&priv->msg_regs->imr, (get_bitmask_order(entries) - 2) << 12); /* Now enable the unit */ - out_be32((void *)&msg_regs->imr, in_be32((void *)&msg_regs->imr) | 0x1); + setbits32(&priv->msg_regs->imr, 0x1); out: return rc; @@ -636,15 +703,16 @@ int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entri */ void rio_close_inb_mbox(struct rio_mport *mport, int mbox) { + struct rio_priv *priv = mport->priv; /* Disable inbound message unit */ - out_be32((void *)&msg_regs->imr, 0); + out_be32(&priv->msg_regs->imr, 0); /* Free ring */ - dma_free_coherent(NULL, msg_rx_ring.size * RIO_MAX_MSG_SIZE, - msg_rx_ring.virt, msg_rx_ring.phys); + dma_free_coherent(NULL, priv->msg_rx_ring.size * RIO_MAX_MSG_SIZE, + priv->msg_rx_ring.virt, priv->msg_rx_ring.phys); /* Free interrupt */ - free_irq(MPC85xx_IRQ_RIO_RX, (void *)mport); + free_irq(IRQ_RIO_RX(mport), (void *)mport); } /** @@ -659,21 +727,22 @@ void rio_close_inb_mbox(struct rio_mport *mport, int mbox) int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf) { int rc = 0; + struct rio_priv *priv = mport->priv; pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n", - msg_rx_ring.rx_slot); + priv->msg_rx_ring.rx_slot); - if (msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot]) { + if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) { printk(KERN_ERR "RIO: error adding inbound buffer %d, buffer exists\n", - msg_rx_ring.rx_slot); + priv->msg_rx_ring.rx_slot); rc = -EINVAL; goto out; } - msg_rx_ring.virt_buffer[msg_rx_ring.rx_slot] = buf; - if (++msg_rx_ring.rx_slot == msg_rx_ring.size) - msg_rx_ring.rx_slot = 0; + priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot] = buf; + if (++priv->msg_rx_ring.rx_slot == priv->msg_rx_ring.size) + priv->msg_rx_ring.rx_slot = 0; out: return rc; @@ -691,20 +760,21 @@ EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer); */ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) { - u32 imr; + struct rio_priv *priv = mport->priv; u32 phys_buf, virt_buf; void *buf = NULL; int buf_idx; - phys_buf = in_be32((void *)&msg_regs->ifqdpar); + phys_buf = in_be32(&priv->msg_regs->ifqdpar); /* If no more messages, then bail out */ - if (phys_buf == in_be32((void *)&msg_regs->ifqepar)) + if (phys_buf == in_be32(&priv->msg_regs->ifqepar)) goto out2; - virt_buf = (u32) msg_rx_ring.virt + (phys_buf - msg_rx_ring.phys); - buf_idx = (phys_buf - msg_rx_ring.phys) / RIO_MAX_MSG_SIZE; - buf = msg_rx_ring.virt_buffer[buf_idx]; + virt_buf = (u32) priv->msg_rx_ring.virt + (phys_buf + - priv->msg_rx_ring.phys); + buf_idx = (phys_buf - priv->msg_rx_ring.phys) / RIO_MAX_MSG_SIZE; + buf = priv->msg_rx_ring.virt_buffer[buf_idx]; if (!buf) { printk(KERN_ERR @@ -716,11 +786,10 @@ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) memcpy(buf, (void *)virt_buf, RIO_MAX_MSG_SIZE); /* Clear the available buffer */ - msg_rx_ring.virt_buffer[buf_idx] = NULL; + priv->msg_rx_ring.virt_buffer[buf_idx] = NULL; out1: - imr = in_be32((void *)&msg_regs->imr); - out_be32((void *)&msg_regs->imr, imr | RIO_MSG_IMR_MI); + setbits32(&priv->msg_regs->imr, RIO_MSG_IMR_MI); out2: return buf; @@ -729,7 +798,7 @@ void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox) EXPORT_SYMBOL_GPL(rio_hw_get_inb_message); /** - * mpc85xx_rio_dbell_handler - MPC85xx doorbell interrupt handler + * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler * @irq: Linux interrupt number * @dev_instance: Pointer to interrupt-specific data * @@ -737,31 +806,31 @@ EXPORT_SYMBOL_GPL(rio_hw_get_inb_message); * doorbell event handlers and executes a matching event handler. */ static irqreturn_t -mpc85xx_rio_dbell_handler(int irq, void *dev_instance) +fsl_rio_dbell_handler(int irq, void *dev_instance) { int dsr; struct rio_mport *port = (struct rio_mport *)dev_instance; + struct rio_priv *priv = port->priv; - dsr = in_be32((void *)&msg_regs->dsr); + dsr = in_be32(&priv->msg_regs->dsr); if (dsr & DOORBELL_DSR_TE) { pr_info("RIO: doorbell reception error\n"); - out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_TE); + out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_TE); goto out; } if (dsr & DOORBELL_DSR_QFI) { pr_info("RIO: doorbell queue full\n"); - out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_QFI); + out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_QFI); goto out; } /* XXX Need to check/dispatch until queue empty */ if (dsr & DOORBELL_DSR_DIQI) { u32 dmsg = - (u32) dbell_ring.virt + - (in_be32((void *)&msg_regs->dqdpar) & 0xfff); - u32 dmr; + (u32) priv->dbell_ring.virt + + (in_be32(&priv->msg_regs->dqdpar) & 0xfff); struct rio_dbell *dbell; int found = 0; @@ -784,9 +853,8 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance) ("RIO: spurious doorbell, sid %2.2x tid %2.2x info %4.4x\n", DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); } - dmr = in_be32((void *)&msg_regs->dmr); - out_be32((void *)&msg_regs->dmr, dmr | DOORBELL_DMR_DI); - out_be32((void *)&msg_regs->dsr, DOORBELL_DSR_DIQI); + setbits32(&priv->msg_regs->dmr, DOORBELL_DMR_DI); + out_be32(&priv->msg_regs->dsr, DOORBELL_DSR_DIQI); } out: @@ -794,21 +862,22 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance) } /** - * mpc85xx_rio_doorbell_init - MPC85xx doorbell interface init + * fsl_rio_doorbell_init - MPC85xx doorbell interface init * @mport: Master port implementing the inbound doorbell unit * * Initializes doorbell unit hardware and inbound DMA buffer - * ring. Called from mpc85xx_rio_setup(). Returns %0 on success + * ring. Called from fsl_rio_setup(). Returns %0 on success * or %-ENOMEM on failure. */ -static int mpc85xx_rio_doorbell_init(struct rio_mport *mport) +static int fsl_rio_doorbell_init(struct rio_mport *mport) { + struct rio_priv *priv = mport->priv; int rc = 0; /* Map outbound doorbell window immediately after maintenance window */ - if (!(dbell_win = - (u32) ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE, - RIO_DBELL_WIN_SIZE))) { + priv->dbell_win = ioremap(mport->iores.start + RIO_MAINT_WIN_SIZE, + RIO_DBELL_WIN_SIZE); + if (!priv->dbell_win) { printk(KERN_ERR "RIO: unable to map outbound doorbell window\n"); rc = -ENOMEM; @@ -816,37 +885,36 @@ static int mpc85xx_rio_doorbell_init(struct rio_mport *mport) } /* Initialize inbound doorbells */ - if (!(dbell_ring.virt = dma_alloc_coherent(NULL, - 512 * DOORBELL_MESSAGE_SIZE, - &dbell_ring.phys, - GFP_KERNEL))) { + priv->dbell_ring.virt = dma_alloc_coherent(NULL, 512 * + DOORBELL_MESSAGE_SIZE, &priv->dbell_ring.phys, GFP_KERNEL); + if (!priv->dbell_ring.virt) { printk(KERN_ERR "RIO: unable allocate inbound doorbell ring\n"); rc = -ENOMEM; - iounmap((void *)dbell_win); + iounmap(priv->dbell_win); goto out; } /* Point dequeue/enqueue pointers at first entry in ring */ - out_be32((void *)&msg_regs->dqdpar, (u32) dbell_ring.phys); - out_be32((void *)&msg_regs->dqepar, (u32) dbell_ring.phys); + out_be32(&priv->msg_regs->dqdpar, (u32) priv->dbell_ring.phys); + out_be32(&priv->msg_regs->dqepar, (u32) priv->dbell_ring.phys); /* Clear interrupt status */ - out_be32((void *)&msg_regs->dsr, 0x00000091); + out_be32(&priv->msg_regs->dsr, 0x00000091); /* Hook up doorbell handler */ - if ((rc = - request_irq(MPC85xx_IRQ_RIO_BELL, mpc85xx_rio_dbell_handler, 0, - "dbell_rx", (void *)mport) < 0)) { - iounmap((void *)dbell_win); + rc = request_irq(IRQ_RIO_BELL(mport), fsl_rio_dbell_handler, 0, + "dbell_rx", (void *)mport); + if (rc < 0) { + iounmap(priv->dbell_win); dma_free_coherent(NULL, 512 * DOORBELL_MESSAGE_SIZE, - dbell_ring.virt, dbell_ring.phys); + priv->dbell_ring.virt, priv->dbell_ring.phys); printk(KERN_ERR "MPC85xx RIO: unable to request inbound doorbell irq"); goto out; } /* Configure doorbells for snooping, 512 entries, and enable */ - out_be32((void *)&msg_regs->dmr, 0x00108161); + out_be32(&priv->msg_regs->dmr, 0x00108161); out: return rc; @@ -854,7 +922,7 @@ static int mpc85xx_rio_doorbell_init(struct rio_mport *mport) static char *cmdline = NULL; -static int mpc85xx_rio_get_hdid(int index) +static int fsl_rio_get_hdid(int index) { /* XXX Need to parse multiple entries in some format */ if (!cmdline) @@ -863,7 +931,7 @@ static int mpc85xx_rio_get_hdid(int index) return simple_strtol(cmdline, NULL, 0); } -static int mpc85xx_rio_get_cmdline(char *s) +static int fsl_rio_get_cmdline(char *s) { if (!s) return 0; @@ -872,61 +940,266 @@ static int mpc85xx_rio_get_cmdline(char *s) return 1; } -__setup("riohdid=", mpc85xx_rio_get_cmdline); +__setup("riohdid=", fsl_rio_get_cmdline); + +static inline void fsl_rio_info(struct device *dev, u32 ccsr) +{ + const char *str; + if (ccsr & 1) { + /* Serial phy */ + switch (ccsr >> 30) { + case 0: + str = "1"; + break; + case 1: + str = "4"; + break; + default: + str = "Unknown"; + break;; + } + dev_info(dev, "Hardware port width: %s\n", str); + + switch ((ccsr >> 27) & 7) { + case 0: + str = "Single-lane 0"; + break; + case 1: + str = "Single-lane 2"; + break; + case 2: + str = "Four-lane"; + break; + default: + str = "Unknown"; + break; + } + dev_info(dev, "Training connection status: %s\n", str); + } else { + /* Parallel phy */ + if (!(ccsr & 0x80000000)) + dev_info(dev, "Output port operating in 8-bit mode\n"); + if (!(ccsr & 0x08000000)) + dev_info(dev, "Input port operating in 8-bit mode\n"); + } +} /** - * mpc85xx_rio_setup - Setup MPC85xx RapidIO interface - * @law_start: Starting physical address of RapidIO LAW - * @law_size: Size of RapidIO LAW + * fsl_rio_setup - Setup MPC85xx RapidIO interface + * @fsl_rio_setup - Setup Freescale PowerPC RapidIO interface * * Initializes MPC85xx RapidIO hardware interface, configures * master port with system-specific info, and registers the * master port with the RapidIO subsystem. */ -void mpc85xx_rio_setup(int law_start, int law_size) +int fsl_rio_setup(struct of_device *dev) { struct rio_ops *ops; struct rio_mport *port; + struct rio_priv *priv; + int rc = 0; + const u32 *dt_range, *cell; + struct resource regs; + int rlen; + u32 ccsr; + u64 law_start, law_size; + int paw, aw, sw; + + if (!dev->node) { + dev_err(&dev->dev, "Device OF-Node is NULL"); + return -EFAULT; + } + + rc = of_address_to_resource(dev->node, 0, ®s); + if (rc) { + dev_err(&dev->dev, "Can't get %s property 'reg'\n", + dev->node->full_name); + return -EFAULT; + } + dev_info(&dev->dev, "Of-device full name %s\n", dev->node->full_name); + dev_info(&dev->dev, "Regs start 0x%08x size 0x%08x\n", regs.start, + regs.end - regs.start + 1); + + dt_range = of_get_property(dev->node, "ranges", &rlen); + if (!dt_range) { + dev_err(&dev->dev, "Can't get %s property 'ranges'\n", + dev->node->full_name); + return -EFAULT; + } + + /* Get node address wide */ + cell = of_get_property(dev->node, "#address-cells", NULL); + if (cell) + aw = *cell; + else + aw = of_n_addr_cells(dev->node); + /* Get node size wide */ + cell = of_get_property(dev->node, "#size-cells", NULL); + if (cell) + sw = *cell; + else + sw = of_n_size_cells(dev->node); + /* Get parent address wide wide */ + paw = of_n_addr_cells(dev->node); + + law_start = of_read_number(dt_range + aw, paw); + law_size = of_read_number(dt_range + aw + paw, sw); + + dev_info(&dev->dev, "LAW start 0x%016llx, size 0x%016llx.\n", + law_start, law_size); ops = kmalloc(sizeof(struct rio_ops), GFP_KERNEL); - ops->lcread = mpc85xx_local_config_read; - ops->lcwrite = mpc85xx_local_config_write; - ops->cread = mpc85xx_rio_config_read; - ops->cwrite = mpc85xx_rio_config_write; - ops->dsend = mpc85xx_rio_doorbell_send; + ops->lcread = fsl_local_config_read; + ops->lcwrite = fsl_local_config_write; + ops->cread = fsl_rio_config_read; + ops->cwrite = fsl_rio_config_write; + ops->dsend = fsl_rio_doorbell_send; - port = kmalloc(sizeof(struct rio_mport), GFP_KERNEL); + port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL); port->id = 0; port->index = 0; + + priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL); + if (!priv) { + printk(KERN_ERR "Can't alloc memory for 'priv'\n"); + rc = -ENOMEM; + goto err; + } + INIT_LIST_HEAD(&port->dbells); port->iores.start = law_start; port->iores.end = law_start + law_size; port->iores.flags = IORESOURCE_MEM; + priv->bellirq = irq_of_parse_and_map(dev->node, 2); + priv->txirq = irq_of_parse_and_map(dev->node, 3); + priv->rxirq = irq_of_parse_and_map(dev->node, 4); + dev_info(&dev->dev, "bellirq: %d, txirq: %d, rxirq %d\n", priv->bellirq, + priv->txirq, priv->rxirq); + rio_init_dbell_res(&port->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff); rio_init_mbox_res(&port->riores[RIO_INB_MBOX_RESOURCE], 0, 0); rio_init_mbox_res(&port->riores[RIO_OUTB_MBOX_RESOURCE], 0, 0); strcpy(port->name, "RIO0 mport"); port->ops = ops; - port->host_deviceid = mpc85xx_rio_get_hdid(port->id); + port->host_deviceid = fsl_rio_get_hdid(port->id); + port->priv = priv; rio_register_mport(port); - regs_win = (u32) ioremap(RIO_REGS_BASE, 0x20000); - atmu_regs = (struct rio_atmu_regs *)(regs_win + RIO_ATMU_REGS_OFFSET); - maint_atmu_regs = atmu_regs + 1; - dbell_atmu_regs = atmu_regs + 2; - msg_regs = (struct rio_msg_regs *)(regs_win + RIO_MSG_REGS_OFFSET); + priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1); + + /* Probe the master port phy type */ + ccsr = in_be32(priv->regs_win + RIO_CCSR); + port->phy_type = (ccsr & 1) ? RIO_PHY_SERIAL : RIO_PHY_PARALLEL; + dev_info(&dev->dev, "RapidIO PHY type: %s\n", + (port->phy_type == RIO_PHY_PARALLEL) ? "parallel" : + ((port->phy_type == RIO_PHY_SERIAL) ? "serial" : + "unknown")); + /* Checking the port training status */ + if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) { + dev_err(&dev->dev, "Port is not ready. " + "Try to restart connection...\n"); + switch (port->phy_type) { + case RIO_PHY_SERIAL: + /* Disable ports */ + out_be32(priv->regs_win + RIO_CCSR, 0); + /* Set 1x lane */ + setbits32(priv->regs_win + RIO_CCSR, 0x02000000); + /* Enable ports */ + setbits32(priv->regs_win + RIO_CCSR, 0x00600000); + break; + case RIO_PHY_PARALLEL: + /* Disable ports */ + out_be32(priv->regs_win + RIO_CCSR, 0x22000000); + /* Enable ports */ + out_be32(priv->regs_win + RIO_CCSR, 0x44000000); + break; + } + msleep(100); + if (in_be32((priv->regs_win + RIO_ESCSR)) & 1) { + dev_err(&dev->dev, "Port restart failed.\n"); + rc = -ENOLINK; + goto err; + } + dev_info(&dev->dev, "Port restart success!\n"); + } + fsl_rio_info(&dev->dev, ccsr); + + port->sys_size = (in_be32((priv->regs_win + RIO_PEF_CAR)) + & RIO_PEF_CTLS) >> 4; + dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n", + port->sys_size ? 65536 : 256); + + priv->atmu_regs = (struct rio_atmu_regs *)(priv->regs_win + + RIO_ATMU_REGS_OFFSET); + priv->maint_atmu_regs = priv->atmu_regs + 1; + priv->dbell_atmu_regs = priv->atmu_regs + 2; + priv->msg_regs = (struct rio_msg_regs *)(priv->regs_win + + ((port->phy_type == RIO_PHY_SERIAL) ? + RIO_S_MSG_REGS_OFFSET : RIO_P_MSG_REGS_OFFSET)); + + /* Set to receive any dist ID for serial RapidIO controller. */ + if (port->phy_type == RIO_PHY_SERIAL) + out_be32((priv->regs_win + RIO_ISR_AACR), RIO_ISR_AACR_AA); /* Configure maintenance transaction window */ - out_be32((void *)&maint_atmu_regs->rowbar, 0x000c0000); - out_be32((void *)&maint_atmu_regs->rowar, 0x80077015); + out_be32(&priv->maint_atmu_regs->rowbar, 0x000c0000); + out_be32(&priv->maint_atmu_regs->rowar, 0x80077015); - maint_win = (u32) ioremap(law_start, RIO_MAINT_WIN_SIZE); + priv->maint_win = ioremap(law_start, RIO_MAINT_WIN_SIZE); /* Configure outbound doorbell window */ - out_be32((void *)&dbell_atmu_regs->rowbar, 0x000c0400); - out_be32((void *)&dbell_atmu_regs->rowar, 0x8004200b); - mpc85xx_rio_doorbell_init(port); + out_be32(&priv->dbell_atmu_regs->rowbar, 0x000c0400); + out_be32(&priv->dbell_atmu_regs->rowar, 0x8004200b); + fsl_rio_doorbell_init(port); + + return 0; +err: + if (priv) + iounmap(priv->regs_win); + kfree(ops); + kfree(priv); + kfree(port); + return rc; +} + +/* The probe function for RapidIO peer-to-peer network. + */ +static int __devinit fsl_of_rio_rpn_probe(struct of_device *dev, + const struct of_device_id *match) +{ + int rc; + printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n", + dev->node->full_name); + + rc = fsl_rio_setup(dev); + if (rc) + goto out; + + /* Enumerate all registered ports */ + rc = rio_init_mports(); +out: + return rc; +}; + +static const struct of_device_id fsl_of_rio_rpn_ids[] = { + { + .compatible = "fsl,rapidio-delta", + }, + {}, +}; + +static struct of_platform_driver fsl_of_rio_rpn_driver = { + .name = "fsl-of-rio", + .match_table = fsl_of_rio_rpn_ids, + .probe = fsl_of_rio_rpn_probe, +}; + +static __init int fsl_of_rio_rpn_init(void) +{ + return of_register_platform_driver(&fsl_of_rio_rpn_driver); } + +subsys_initcall(fsl_of_rio_rpn_init); diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h deleted file mode 100644 index 6d3ff30b157..00000000000 --- a/arch/powerpc/sysdev/fsl_rio.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * MPC85xx RapidIO definitions - * - * Copyright 2005 MontaVista Software, Inc. - * Matt Porter <mporter@kernel.crashing.org> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - */ - -#ifndef __PPC_SYSLIB_PPC85XX_RIO_H -#define __PPC_SYSLIB_PPC85XX_RIO_H - -#include <linux/init.h> - -extern void mpc85xx_rio_setup(int law_start, int law_size); - -#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */ diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index a51a1771423..8dcbdd6c2d2 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -18,6 +18,8 @@ #include <linux/suspend.h> #include <linux/mman.h> #include <linux/mm.h> +#include <linux/kbuild.h> + #include <asm/io.h> #include <asm/page.h> #include <asm/pgtable.h> @@ -26,11 +28,6 @@ #include <asm/thread_info.h> #include <asm/vdso_datapage.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main(void) { diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 50ce83f20ad..df3ef6db072 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1121,8 +1121,8 @@ void __init pci_init_resource(struct resource *res, resource_size_t start, void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len) diff --git a/arch/ppc/platforms/sbc82xx.c b/arch/ppc/platforms/sbc82xx.c index 0df6aacb823..24f6e0694ac 100644 --- a/arch/ppc/platforms/sbc82xx.c +++ b/arch/ppc/platforms/sbc82xx.c @@ -30,8 +30,6 @@ static void (*callback_init_IRQ)(void); extern unsigned char __res[sizeof(bd_t)]; -extern void (*late_time_init)(void); - #ifdef CONFIG_GEN_RTC TODC_ALLOC(); diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 1375f8a4469..fa28ecae636 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -5,44 +5,38 @@ */ #include <linux/sched.h> - -/* Use marker if you need to separate the values later */ - -#define DEFINE(sym, val, marker) \ - asm volatile("\n->" #sym " %0 " #val " " #marker : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) +#include <linux/kbuild.h> int main(void) { - DEFINE(__THREAD_info, offsetof(struct task_struct, stack),); - DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp),); - DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info),); + DEFINE(__THREAD_info, offsetof(struct task_struct, stack)); + DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp)); + DEFINE(__THREAD_per, offsetof(struct task_struct, thread.per_info)); DEFINE(__THREAD_mm_segment, - offsetof(struct task_struct, thread.mm_segment),); + offsetof(struct task_struct, thread.mm_segment)); BLANK(); - DEFINE(__TASK_pid, offsetof(struct task_struct, pid),); + DEFINE(__TASK_pid, offsetof(struct task_struct, pid)); BLANK(); - DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid),); - DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address),); - DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id),); + DEFINE(__PER_atmid, offsetof(per_struct, lowcore.words.perc_atmid)); + DEFINE(__PER_address, offsetof(per_struct, lowcore.words.address)); + DEFINE(__PER_access_id, offsetof(per_struct, lowcore.words.access_id)); BLANK(); - DEFINE(__TI_task, offsetof(struct thread_info, task),); - DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain),); - DEFINE(__TI_flags, offsetof(struct thread_info, flags),); - DEFINE(__TI_cpu, offsetof(struct thread_info, cpu),); - DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count),); + DEFINE(__TI_task, offsetof(struct thread_info, task)); + DEFINE(__TI_domain, offsetof(struct thread_info, exec_domain)); + DEFINE(__TI_flags, offsetof(struct thread_info, flags)); + DEFINE(__TI_cpu, offsetof(struct thread_info, cpu)); + DEFINE(__TI_precount, offsetof(struct thread_info, preempt_count)); BLANK(); - DEFINE(__PT_ARGS, offsetof(struct pt_regs, args),); - DEFINE(__PT_PSW, offsetof(struct pt_regs, psw),); - DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs),); - DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2),); - DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc),); - DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap),); - DEFINE(__PT_SIZE, sizeof(struct pt_regs),); + DEFINE(__PT_ARGS, offsetof(struct pt_regs, args)); + DEFINE(__PT_PSW, offsetof(struct pt_regs, psw)); + DEFINE(__PT_GPRS, offsetof(struct pt_regs, gprs)); + DEFINE(__PT_ORIG_GPR2, offsetof(struct pt_regs, orig_gpr2)); + DEFINE(__PT_ILC, offsetof(struct pt_regs, ilc)); + DEFINE(__PT_TRAP, offsetof(struct pt_regs, trap)); + DEFINE(__PT_SIZE, sizeof(struct pt_regs)); BLANK(); - DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain),); - DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs),); - DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1),); + DEFINE(__SF_BACKCHAIN, offsetof(struct stack_frame, back_chain)); + DEFINE(__SF_GPRS, offsetof(struct stack_frame, gprs)); + DEFINE(__SF_EMPTY, offsetof(struct stack_frame, empty1)); return 0; } diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index c36d8123ca1..c59a86dca58 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -60,8 +60,6 @@ init_IRQ(void) /* * Switch to the asynchronous interrupt stack for softirq execution. */ -extern void __do_softirq(void); - asmlinkage void do_softirq(void) { unsigned long flags, old, new; diff --git a/arch/sh/drivers/pci/pci.c b/arch/sh/drivers/pci/pci.c index 49b435c3a57..08d2e732525 100644 --- a/arch/sh/drivers/pci/pci.c +++ b/arch/sh/drivers/pci/pci.c @@ -191,8 +191,8 @@ void __init pcibios_update_irq(struct pci_dev *dev, int irq) void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (unlikely(!len || !start)) diff --git a/arch/sh/kernel/asm-offsets.c b/arch/sh/kernel/asm-offsets.c index dc6725c51a8..57cf0e0680f 100644 --- a/arch/sh/kernel/asm-offsets.c +++ b/arch/sh/kernel/asm-offsets.c @@ -11,12 +11,9 @@ #include <linux/stddef.h> #include <linux/types.h> #include <linux/mm.h> -#include <asm/thread_info.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) +#include <linux/kbuild.h> -#define BLANK() asm volatile("\n->" : : ) +#include <asm/thread_info.h> int main(void) { diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c index 9bf19b00696..a2a99e487e3 100644 --- a/arch/sh/kernel/irq.c +++ b/arch/sh/kernel/irq.c @@ -200,8 +200,6 @@ void irq_ctx_exit(int cpu) hardirq_ctx[cpu] = NULL; } -extern asmlinkage void __do_softirq(void); - asmlinkage void do_softirq(void) { unsigned long flags; diff --git a/arch/sparc/kernel/asm-offsets.c b/arch/sparc/kernel/asm-offsets.c index 6773ed76e41..cd3f7694e9b 100644 --- a/arch/sparc/kernel/asm-offsets.c +++ b/arch/sparc/kernel/asm-offsets.c @@ -12,11 +12,7 @@ #include <linux/sched.h> // #include <linux/mm.h> - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) +#include <linux/kbuild.h> int foo(void) { diff --git a/arch/sparc/lib/iomap.c b/arch/sparc/lib/iomap.c index 54501c1ca78..9ef37e13a92 100644 --- a/arch/sparc/lib/iomap.c +++ b/arch/sparc/lib/iomap.c @@ -21,8 +21,8 @@ EXPORT_SYMBOL(ioport_unmap); /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/sparc64/lib/iomap.c b/arch/sparc64/lib/iomap.c index ac556db0697..7120ebbd4d0 100644 --- a/arch/sparc64/lib/iomap.c +++ b/arch/sparc64/lib/iomap.c @@ -21,8 +21,8 @@ EXPORT_SYMBOL(ioport_unmap); /* Create a virtual mapping cookie for a PCI BAR (memory or IO) */ void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen) { - unsigned long start = pci_resource_start(dev, bar); - unsigned long len = pci_resource_len(dev, bar); + resource_size_t start = pci_resource_start(dev, bar); + resource_size_t len = pci_resource_len(dev, bar); unsigned long flags = pci_resource_flags(dev, bar); if (!len || !start) diff --git a/arch/um/kernel/exitcode.c b/arch/um/kernel/exitcode.c index 984f80e668c..6540d2c9fbb 100644 --- a/arch/um/kernel/exitcode.c +++ b/arch/um/kernel/exitcode.c @@ -59,7 +59,7 @@ static int make_proc_exitcode(void) { struct proc_dir_entry *ent; - ent = create_proc_entry("exitcode", 0600, &proc_root); + ent = create_proc_entry("exitcode", 0600, NULL); if (ent == NULL) { printk(KERN_WARNING "make_proc_exitcode : Failed to register " "/proc/exitcode\n"); diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index e8cb9ff183e..83603cfbde8 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c @@ -364,7 +364,7 @@ int __init make_proc_sysemu(void) if (!sysemu_supported) return 0; - ent = create_proc_entry("sysemu", 0600, &proc_root); + ent = create_proc_entry("sysemu", 0600, NULL); if (ent == NULL) { diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index e066e84493b..0d0cea2ac98 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -4,6 +4,7 @@ */ #include <linux/clockchips.h> +#include <linux/init.h> #include <linux/interrupt.h> #include <linux/jiffies.h> #include <linux/threads.h> @@ -109,8 +110,6 @@ static void __init setup_itimer(void) clockevents_register_device(&itimer_clockevent); } -extern void (*late_time_init)(void); - void __init time_init(void) { long long nsecs; diff --git a/arch/v850/kernel/asm-offsets.c b/arch/v850/kernel/asm-offsets.c index cee5c3142d4..581e6986a77 100644 --- a/arch/v850/kernel/asm-offsets.c +++ b/arch/v850/kernel/asm-offsets.c @@ -13,14 +13,11 @@ #include <linux/kernel_stat.h> #include <linux/ptrace.h> #include <linux/hardirq.h> +#include <linux/kbuild.h> + #include <asm/irq.h> #include <asm/errno.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - int main (void) { /* offsets into the task struct */ diff --git a/arch/v850/kernel/rte_mb_a_pci.c b/arch/v850/kernel/rte_mb_a_pci.c index 7165478824e..687e367d8b6 100644 --- a/arch/v850/kernel/rte_mb_a_pci.c +++ b/arch/v850/kernel/rte_mb_a_pci.c @@ -790,8 +790,8 @@ pci_free_consistent (struct pci_dev *pdev, size_t size, void *cpu_addr, void __iomem *pci_iomap (struct pci_dev *dev, int bar, unsigned long max) { - unsigned long start = pci_resource_start (dev, bar); - unsigned long len = pci_resource_len (dev, bar); + resource_size_t start = pci_resource_start (dev, bar); + resource_size_t len = pci_resource_len (dev, bar); if (!start || len == 0) return 0; diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index a12dbb2b93f..f70e3e3a9fa 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -537,9 +537,6 @@ config CALGARY_IOMMU_ENABLED_BY_DEFAULT Calgary anyway, pass 'iommu=calgary' on the kernel command line. If unsure, say Y. -config IOMMU_HELPER - def_bool (CALGARY_IOMMU || GART_IOMMU) - # need this always selected by IOMMU for the VIA workaround config SWIOTLB bool @@ -550,6 +547,8 @@ config SWIOTLB access 32-bits of memory can be used on systems with more than 3 GB of memory. If unsure, say Y. +config IOMMU_HELPER + def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB) config NR_CPUS int "Maximum number of CPUs (2-255)" @@ -1505,6 +1504,10 @@ config PCI_GODIRECT config PCI_GOANY bool "Any" +config PCI_GOOLPC + bool "OLPC" + depends on OLPC + endchoice config PCI_BIOS @@ -1514,12 +1517,17 @@ config PCI_BIOS # x86-64 doesn't support PCI BIOS access from long mode so always go direct. config PCI_DIRECT def_bool y - depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY) || X86_VISWS) + depends on PCI && (X86_64 || (PCI_GODIRECT || PCI_GOANY || PCI_GOOLPC) || X86_VISWS) config PCI_MMCONFIG def_bool y depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) +config PCI_OLPC + bool + depends on PCI && PCI_GOOLPC + default y + config PCI_DOMAINS def_bool y depends on PCI @@ -1639,6 +1647,13 @@ config GEODE_MFGPT_TIMER MFGPTs have a better resolution and max interval than the generic PIT, and are suitable for use as high-res timers. +config OLPC + bool "One Laptop Per Child support" + default n + help + Add support for detecting the unique features of the OLPC + XO hardware. + endif # X86_32 config K8_NB diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index d84a48ece78..03399d64013 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.c @@ -126,17 +126,25 @@ void query_edd(void) { char eddarg[8]; int do_mbr = 1; +#ifdef CONFIG_EDD_OFF + int do_edd = 0; +#else int do_edd = 1; +#endif int be_quiet; int devno; struct edd_info ei, *edp; u32 *mbrptr; if (cmdline_find_option("edd", eddarg, sizeof eddarg) > 0) { - if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) + if (!strcmp(eddarg, "skipmbr") || !strcmp(eddarg, "skip")) { + do_edd = 1; do_mbr = 0; + } else if (!strcmp(eddarg, "off")) do_edd = 0; + else if (!strcmp(eddarg, "on")) + do_edd = 1; } be_quiet = cmdline_find_option_bool("quiet"); diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index fa19c381954..30d54ed27e5 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -91,6 +91,8 @@ endif obj-$(CONFIG_SCx200) += scx200.o scx200-y += scx200_32.o +obj-$(CONFIG_OLPC) += olpc.o + ### # 64 bit specific files ifeq ($(CONFIG_X86_64),y) @@ -101,4 +103,6 @@ ifeq ($(CONFIG_X86_64),y) obj-$(CONFIG_GART_IOMMU) += pci-gart_64.o aperture_64.o obj-$(CONFIG_CALGARY_IOMMU) += pci-calgary_64.o tce_64.o obj-$(CONFIG_SWIOTLB) += pci-swiotlb_64.o + + obj-$(CONFIG_PCI_MMCONFIG) += mmconf-fam10h_64.o endif diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 977ed5cdeaa..c49ebcc6c41 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -771,6 +771,32 @@ static void __init acpi_register_lapic_address(unsigned long address) boot_cpu_physical_apicid = GET_APIC_ID(read_apic_id()); } +static int __init early_acpi_parse_madt_lapic_addr_ovr(void) +{ + int count; + + if (!cpu_has_apic) + return -ENODEV; + + /* + * Note that the LAPIC address is obtained from the MADT (32-bit value) + * and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value). + */ + + count = + acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE, + acpi_parse_lapic_addr_ovr, 0); + if (count < 0) { + printk(KERN_ERR PREFIX + "Error parsing LAPIC address override entry\n"); + return count; + } + + acpi_register_lapic_address(acpi_lapic_addr); + + return count; +} + static int __init acpi_parse_madt_lapic_entries(void) { int count; @@ -901,6 +927,33 @@ static inline int acpi_parse_madt_ioapic_entries(void) } #endif /* !CONFIG_X86_IO_APIC */ +static void __init early_acpi_process_madt(void) +{ +#ifdef CONFIG_X86_LOCAL_APIC + int error; + + if (!acpi_table_parse(ACPI_SIG_MADT, acpi_parse_madt)) { + + /* + * Parse MADT LAPIC entries + */ + error = early_acpi_parse_madt_lapic_addr_ovr(); + if (!error) { + acpi_lapic = 1; + smp_found_config = 1; + } + if (error == -EINVAL) { + /* + * Dell Precision Workstation 410, 610 come here. + */ + printk(KERN_ERR PREFIX + "Invalid BIOS MADT, disabling ACPI\n"); + disable_acpi(); + } + } +#endif +} + static void __init acpi_process_madt(void) { #ifdef CONFIG_X86_LOCAL_APIC @@ -1233,6 +1286,23 @@ int __init acpi_boot_table_init(void) return 0; } +int __init early_acpi_boot_init(void) +{ + /* + * If acpi_disabled, bail out + * One exception: acpi=ht continues far enough to enumerate LAPICs + */ + if (acpi_disabled && !acpi_ht) + return 1; + + /* + * Process the Multiple APIC Description Table (MADT), if present + */ + early_acpi_process_madt(); + + return 0; +} + int __init acpi_boot_init(void) { /* diff --git a/arch/x86/kernel/asm-offsets_32.c b/arch/x86/kernel/asm-offsets_32.c index 670c3c31128..92588083950 100644 --- a/arch/x86/kernel/asm-offsets_32.c +++ b/arch/x86/kernel/asm-offsets_32.c @@ -9,6 +9,7 @@ #include <linux/signal.h> #include <linux/personality.h> #include <linux/suspend.h> +#include <linux/kbuild.h> #include <asm/ucontext.h> #include "sigframe.h" #include <asm/pgtable.h> @@ -23,14 +24,6 @@ #include <linux/lguest.h> #include "../../../drivers/lguest/lg.h" -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)); - /* workaround for a warning with -Wmissing-prototypes */ void foo(void); diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 494e1e096ee..f126c05d617 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c @@ -10,6 +10,7 @@ #include <linux/errno.h> #include <linux/hardirq.h> #include <linux/suspend.h> +#include <linux/kbuild.h> #include <asm/pda.h> #include <asm/processor.h> #include <asm/segment.h> @@ -17,14 +18,6 @@ #include <asm/ia32.h> #include <asm/bootparam.h> -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - -#define OFFSET(sym, str, mem) \ - DEFINE(sym, offsetof(struct str, mem)) - #define __NO_STUBS 1 #undef __SYSCALL #undef _ASM_X86_64_UNISTD_H_ diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index 8db8f73503b..b0c8208df9f 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -601,6 +601,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { policy->cpus = perf->shared_cpu_map; } + policy->related_cpus = perf->shared_cpu_map; #ifdef CONFIG_SMP dmi_check_system(sw_any_bug_dmi_table); diff --git a/arch/x86/kernel/cpu/mtrr/if.c b/arch/x86/kernel/cpu/mtrr/if.c index 1960f1985e5..84c480bb371 100644 --- a/arch/x86/kernel/cpu/mtrr/if.c +++ b/arch/x86/kernel/cpu/mtrr/if.c @@ -424,7 +424,7 @@ static int __init mtrr_if_init(void) return -ENODEV; proc_root_mtrr = - proc_create("mtrr", S_IWUSR | S_IRUGO, &proc_root, &mtrr_fops); + proc_create("mtrr", S_IWUSR | S_IRUGO, NULL, &mtrr_fops); if (proc_root_mtrr) proc_root_mtrr->owner = THIS_MODULE; diff --git a/arch/x86/kernel/irq_32.c b/arch/x86/kernel/irq_32.c index 00bda7bcda6..147352df28b 100644 --- a/arch/x86/kernel/irq_32.c +++ b/arch/x86/kernel/irq_32.c @@ -190,8 +190,6 @@ void irq_ctx_exit(int cpu) hardirq_ctx[cpu] = NULL; } -extern asmlinkage void __do_softirq(void); - asmlinkage void do_softirq(void) { unsigned long flags; diff --git a/arch/x86/kernel/mmconf-fam10h_64.c b/arch/x86/kernel/mmconf-fam10h_64.c new file mode 100644 index 00000000000..edc5fbfe85c --- /dev/null +++ b/arch/x86/kernel/mmconf-fam10h_64.c @@ -0,0 +1,243 @@ +/* + * AMD Family 10h mmconfig enablement + */ + +#include <linux/types.h> +#include <linux/mm.h> +#include <linux/string.h> +#include <linux/pci.h> +#include <linux/dmi.h> +#include <asm/pci-direct.h> +#include <linux/sort.h> +#include <asm/io.h> +#include <asm/msr.h> +#include <asm/acpi.h> + +#include "../pci/pci.h" + +struct pci_hostbridge_probe { + u32 bus; + u32 slot; + u32 vendor; + u32 device; +}; + +static u64 __cpuinitdata fam10h_pci_mmconf_base; +static int __cpuinitdata fam10h_pci_mmconf_base_status; + +static struct pci_hostbridge_probe pci_probes[] __cpuinitdata = { + { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 }, + { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, +}; + +struct range { + u64 start; + u64 end; +}; + +static int __cpuinit cmp_range(const void *x1, const void *x2) +{ + const struct range *r1 = x1; + const struct range *r2 = x2; + int start1, start2; + + start1 = r1->start >> 32; + start2 = r2->start >> 32; + + return start1 - start2; +} + +/*[47:0] */ +/* need to avoid (0xfd<<32) and (0xfe<<32), ht used space */ +#define FAM10H_PCI_MMCONF_BASE (0xfcULL<<32) +#define BASE_VALID(b) ((b != (0xfdULL << 32)) && (b != (0xfeULL << 32))) +static void __cpuinit get_fam10h_pci_mmconf_base(void) +{ + int i; + unsigned bus; + unsigned slot; + int found; + + u64 val; + u32 address; + u64 tom2; + u64 base = FAM10H_PCI_MMCONF_BASE; + + int hi_mmio_num; + struct range range[8]; + + /* only try to get setting from BSP */ + /* -1 or 1 */ + if (fam10h_pci_mmconf_base_status) + return; + + if (!early_pci_allowed()) + goto fail; + + found = 0; + for (i = 0; i < ARRAY_SIZE(pci_probes); i++) { + u32 id; + u16 device; + u16 vendor; + + bus = pci_probes[i].bus; + slot = pci_probes[i].slot; + id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID); + + vendor = id & 0xffff; + device = (id>>16) & 0xffff; + if (pci_probes[i].vendor == vendor && + pci_probes[i].device == device) { + found = 1; + break; + } + } + + if (!found) + goto fail; + + /* SYS_CFG */ + address = MSR_K8_SYSCFG; + rdmsrl(address, val); + + /* TOP_MEM2 is not enabled? */ + if (!(val & (1<<21))) { + tom2 = 0; + } else { + /* TOP_MEM2 */ + address = MSR_K8_TOP_MEM2; + rdmsrl(address, val); + tom2 = val & (0xffffULL<<32); + } + + if (base <= tom2) + base = tom2 + (1ULL<<32); + + /* + * need to check if the range is in the high mmio range that is + * above 4G + */ + hi_mmio_num = 0; + for (i = 0; i < 8; i++) { + u32 reg; + u64 start; + u64 end; + reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3)); + if (!(reg & 3)) + continue; + + start = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/ + reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3)); + end = (((u64)reg) << 8) & (0xffULL << 32); /* 39:16 on 31:8*/ + + if (!end) + continue; + + range[hi_mmio_num].start = start; + range[hi_mmio_num].end = end; + hi_mmio_num++; + } + + if (!hi_mmio_num) + goto out; + + /* sort the range */ + sort(range, hi_mmio_num, sizeof(struct range), cmp_range, NULL); + + if (range[hi_mmio_num - 1].end < base) + goto out; + if (range[0].start > base) + goto out; + + /* need to find one window */ + base = range[0].start - (1ULL << 32); + if ((base > tom2) && BASE_VALID(base)) + goto out; + base = range[hi_mmio_num - 1].end + (1ULL << 32); + if ((base > tom2) && BASE_VALID(base)) + goto out; + /* need to find window between ranges */ + if (hi_mmio_num > 1) + for (i = 0; i < hi_mmio_num - 1; i++) { + if (range[i + 1].start > (range[i].end + (1ULL << 32))) { + base = range[i].end + (1ULL << 32); + if ((base > tom2) && BASE_VALID(base)) + goto out; + } + } + +fail: + fam10h_pci_mmconf_base_status = -1; + return; +out: + fam10h_pci_mmconf_base = base; + fam10h_pci_mmconf_base_status = 1; +} + +void __cpuinit fam10h_check_enable_mmcfg(void) +{ + u64 val; + u32 address; + + if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) + return; + + address = MSR_FAM10H_MMIO_CONF_BASE; + rdmsrl(address, val); + + /* try to make sure that AP's setting is identical to BSP setting */ + if (val & FAM10H_MMIO_CONF_ENABLE) { + unsigned busnbits; + busnbits = (val >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & + FAM10H_MMIO_CONF_BUSRANGE_MASK; + + /* only trust the one handle 256 buses, if acpi=off */ + if (!acpi_pci_disabled || busnbits >= 8) { + u64 base; + base = val & (0xffffULL << 32); + if (fam10h_pci_mmconf_base_status <= 0) { + fam10h_pci_mmconf_base = base; + fam10h_pci_mmconf_base_status = 1; + return; + } else if (fam10h_pci_mmconf_base == base) + return; + } + } + + /* + * if it is not enabled, try to enable it and assume only one segment + * with 256 buses + */ + get_fam10h_pci_mmconf_base(); + if (fam10h_pci_mmconf_base_status <= 0) + return; + + printk(KERN_INFO "Enable MMCONFIG on AMD Family 10h\n"); + val &= ~((FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT) | + (FAM10H_MMIO_CONF_BUSRANGE_MASK<<FAM10H_MMIO_CONF_BUSRANGE_SHIFT)); + val |= fam10h_pci_mmconf_base | (8 << FAM10H_MMIO_CONF_BUSRANGE_SHIFT) | + FAM10H_MMIO_CONF_ENABLE; + wrmsrl(address, val); +} + +static int __devinit set_check_enable_amd_mmconf(const struct dmi_system_id *d) +{ + pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF; + return 0; +} + +static struct dmi_system_id __devinitdata mmconf_dmi_table[] = { + { + .callback = set_check_enable_amd_mmconf, + .ident = "Sun Microsystems Machine", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Sun Microsystems"), + }, + }, + {} +}; + +void __init check_enable_amd_mmconf_dmi(void) +{ + dmi_check_system(mmconf_dmi_table); +} diff --git a/arch/x86/kernel/olpc.c b/arch/x86/kernel/olpc.c new file mode 100644 index 00000000000..3e667227480 --- /dev/null +++ b/arch/x86/kernel/olpc.c @@ -0,0 +1,260 @@ +/* + * Support for the OLPC DCON and OLPC EC access + * + * Copyright © 2006 Advanced Micro Devices, Inc. + * Copyright © 2007-2008 Andres Salomon <dilinger@debian.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/delay.h> +#include <linux/spinlock.h> +#include <linux/io.h> +#include <linux/string.h> +#include <asm/geode.h> +#include <asm/olpc.h> + +#ifdef CONFIG_OPEN_FIRMWARE +#include <asm/ofw.h> +#endif + +struct olpc_platform_t olpc_platform_info; +EXPORT_SYMBOL_GPL(olpc_platform_info); + +static DEFINE_SPINLOCK(ec_lock); + +/* what the timeout *should* be (in ms) */ +#define EC_BASE_TIMEOUT 20 + +/* the timeout that bugs in the EC might force us to actually use */ +static int ec_timeout = EC_BASE_TIMEOUT; + +static int __init olpc_ec_timeout_set(char *str) +{ + if (get_option(&str, &ec_timeout) != 1) { + ec_timeout = EC_BASE_TIMEOUT; + printk(KERN_ERR "olpc-ec: invalid argument to " + "'olpc_ec_timeout=', ignoring!\n"); + } + printk(KERN_DEBUG "olpc-ec: using %d ms delay for EC commands.\n", + ec_timeout); + return 1; +} +__setup("olpc_ec_timeout=", olpc_ec_timeout_set); + +/* + * These {i,o}bf_status functions return whether the buffers are full or not. + */ + +static inline unsigned int ibf_status(unsigned int port) +{ + return !!(inb(port) & 0x02); +} + +static inline unsigned int obf_status(unsigned int port) +{ + return inb(port) & 0x01; +} + +#define wait_on_ibf(p, d) __wait_on_ibf(__LINE__, (p), (d)) +static int __wait_on_ibf(unsigned int line, unsigned int port, int desired) +{ + unsigned int timeo; + int state = ibf_status(port); + + for (timeo = ec_timeout; state != desired && timeo; timeo--) { + mdelay(1); + state = ibf_status(port); + } + + if ((state == desired) && (ec_timeout > EC_BASE_TIMEOUT) && + timeo < (ec_timeout - EC_BASE_TIMEOUT)) { + printk(KERN_WARNING "olpc-ec: %d: waited %u ms for IBF!\n", + line, ec_timeout - timeo); + } + + return !(state == desired); +} + +#define wait_on_obf(p, d) __wait_on_obf(__LINE__, (p), (d)) +static int __wait_on_obf(unsigned int line, unsigned int port, int desired) +{ + unsigned int timeo; + int state = obf_status(port); + + for (timeo = ec_timeout; state != desired && timeo; timeo--) { + mdelay(1); + state = obf_status(port); + } + + if ((state == desired) && (ec_timeout > EC_BASE_TIMEOUT) && + timeo < (ec_timeout - EC_BASE_TIMEOUT)) { + printk(KERN_WARNING "olpc-ec: %d: waited %u ms for OBF!\n", + line, ec_timeout - timeo); + } + + return !(state == desired); +} + +/* + * This allows the kernel to run Embedded Controller commands. The EC is + * documented at <http://wiki.laptop.org/go/Embedded_controller>, and the + * available EC commands are here: + * <http://wiki.laptop.org/go/Ec_specification>. Unfortunately, while + * OpenFirmware's source is available, the EC's is not. + */ +int olpc_ec_cmd(unsigned char cmd, unsigned char *inbuf, size_t inlen, + unsigned char *outbuf, size_t outlen) +{ + unsigned long flags; + int ret = -EIO; + int i; + + spin_lock_irqsave(&ec_lock, flags); + + /* Clear OBF */ + for (i = 0; i < 10 && (obf_status(0x6c) == 1); i++) + inb(0x68); + if (i == 10) { + printk(KERN_ERR "olpc-ec: timeout while attempting to " + "clear OBF flag!\n"); + goto err; + } + + if (wait_on_ibf(0x6c, 0)) { + printk(KERN_ERR "olpc-ec: timeout waiting for EC to " + "quiesce!\n"); + goto err; + } + +restart: + /* + * Note that if we time out during any IBF checks, that's a failure; + * we have to return. There's no way for the kernel to clear that. + * + * If we time out during an OBF check, we can restart the command; + * reissuing it will clear the OBF flag, and we should be alright. + * The OBF flag will sometimes misbehave due to what we believe + * is a hardware quirk.. + */ + printk(KERN_DEBUG "olpc-ec: running cmd 0x%x\n", cmd); + outb(cmd, 0x6c); + + if (wait_on_ibf(0x6c, 0)) { + printk(KERN_ERR "olpc-ec: timeout waiting for EC to read " + "command!\n"); + goto err; + } + + if (inbuf && inlen) { + /* write data to EC */ + for (i = 0; i < inlen; i++) { + if (wait_on_ibf(0x6c, 0)) { + printk(KERN_ERR "olpc-ec: timeout waiting for" + " EC accept data!\n"); + goto err; + } + printk(KERN_DEBUG "olpc-ec: sending cmd arg 0x%x\n", + inbuf[i]); + outb(inbuf[i], 0x68); + } + } + if (outbuf && outlen) { + /* read data from EC */ + for (i = 0; i < outlen; i++) { + if (wait_on_obf(0x6c, 1)) { + printk(KERN_ERR "olpc-ec: timeout waiting for" + " EC to provide data!\n"); + goto restart; + } + outbuf[i] = inb(0x68); + printk(KERN_DEBUG "olpc-ec: received 0x%x\n", + outbuf[i]); + } + } + + ret = 0; +err: + spin_unlock_irqrestore(&ec_lock, flags); + return ret; +} +EXPORT_SYMBOL_GPL(olpc_ec_cmd); + +#ifdef CONFIG_OPEN_FIRMWARE +static void __init platform_detect(void) +{ + size_t propsize; + u32 rev; + + if (ofw("getprop", 4, 1, NULL, "board-revision-int", &rev, 4, + &propsize) || propsize != 4) { + printk(KERN_ERR "ofw: getprop call failed!\n"); + rev = 0; + } + olpc_platform_info.boardrev = be32_to_cpu(rev); +} +#else +static void __init platform_detect(void) +{ + /* stopgap until OFW support is added to the kernel */ + olpc_platform_info.boardrev = be32_to_cpu(0xc2); +} +#endif + +static int __init olpc_init(void) +{ + unsigned char *romsig; + + /* The ioremap check is dangerous; limit what we run it on */ + if (!is_geode() || geode_has_vsa2()) + return 0; + + spin_lock_init(&ec_lock); + + romsig = ioremap(0xffffffc0, 16); + if (!romsig) + return 0; + + if (strncmp(romsig, "CL1 Q", 7)) + goto unmap; + if (strncmp(romsig+6, romsig+13, 3)) { + printk(KERN_INFO "OLPC BIOS signature looks invalid. " + "Assuming not OLPC\n"); + goto unmap; + } + + printk(KERN_INFO "OLPC board with OpenFirmware %.16s\n", romsig); + olpc_platform_info.flags |= OLPC_F_PRESENT; + + /* get the platform revision */ + platform_detect(); + + /* assume B1 and above models always have a DCON */ + if (olpc_board_at_least(olpc_board(0xb1))) + olpc_platform_info.flags |= OLPC_F_DCON; + + /* get the EC revision */ + olpc_ec_cmd(EC_FIRMWARE_REV, NULL, 0, + (unsigned char *) &olpc_platform_info.ecver, 1); + + /* check to see if the VSA exists */ + if (geode_has_vsa2()) + olpc_platform_info.flags |= OLPC_F_VSA; + + printk(KERN_INFO "OLPC board revision %s%X (EC=%x)\n", + ((olpc_platform_info.boardrev & 0xf) < 8) ? "pre" : "", + olpc_platform_info.boardrev >> 4, + olpc_platform_info.ecver); + +unmap: + iounmap(romsig); + return 0; +} + +postcore_initcall(olpc_init); diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index a94fb959a87..22c14e21c97 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -29,6 +29,7 @@ #include <linux/crash_dump.h> #include <linux/root_dev.h> #include <linux/pci.h> +#include <asm/pci-direct.h> #include <linux/efi.h> #include <linux/acpi.h> #include <linux/kallsyms.h> @@ -40,6 +41,7 @@ #include <linux/dmi.h> #include <linux/dma-mapping.h> #include <linux/ctype.h> +#include <linux/sort.h> #include <linux/uaccess.h> #include <linux/init_ohci1394_dma.h> #include <linux/kvm_para.h> @@ -288,6 +290,18 @@ static void __init parse_setup_data(void) } } +#ifdef CONFIG_PCI_MMCONFIG +extern void __cpuinit fam10h_check_enable_mmcfg(void); +extern void __init check_enable_amd_mmconf_dmi(void); +#else +void __cpuinit fam10h_check_enable_mmcfg(void) +{ +} +void __init check_enable_amd_mmconf_dmi(void) +{ +} +#endif + /* * setup_arch - architecture-specific boot-time initializations * @@ -515,6 +529,9 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif #endif + + /* do this before identify_cpu for boot cpu */ + check_enable_amd_mmconf_dmi(); } static int __cpuinit get_model_name(struct cpuinfo_x86 *c) @@ -767,6 +784,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) /* MFENCE stops RDTSC speculation */ set_cpu_cap(c, X86_FEATURE_MFENCE_RDTSC); + if (c->x86 == 0x10) + fam10h_check_enable_mmcfg(); + if (amd_apic_timer_broken()) disable_apic_timer = 1; diff --git a/arch/x86/kernel/time_32.c b/arch/x86/kernel/time_32.c index 1a89e93f3f1..2ff21f39893 100644 --- a/arch/x86/kernel/time_32.c +++ b/arch/x86/kernel/time_32.c @@ -115,7 +115,6 @@ irqreturn_t timer_interrupt(int irq, void *dev_id) return IRQ_HANDLED; } -extern void (*late_time_init)(void); /* Duplicate of time_init() below, with hpet_enable part added */ void __init hpet_time_init(void) { diff --git a/arch/x86/mm/k8topology_64.c b/arch/x86/mm/k8topology_64.c index 86808e666f9..1f476e47784 100644 --- a/arch/x86/mm/k8topology_64.c +++ b/arch/x86/mm/k8topology_64.c @@ -13,12 +13,15 @@ #include <linux/nodemask.h> #include <asm/io.h> #include <linux/pci_ids.h> +#include <linux/acpi.h> #include <asm/types.h> #include <asm/mmzone.h> #include <asm/proto.h> #include <asm/e820.h> #include <asm/pci-direct.h> #include <asm/numa.h> +#include <asm/mpspec.h> +#include <asm/apic.h> static __init int find_northbridge(void) { @@ -44,6 +47,30 @@ static __init int find_northbridge(void) return -1; } +static __init void early_get_boot_cpu_id(void) +{ + /* + * need to get boot_cpu_id so can use that to create apicid_to_node + * in k8_scan_nodes() + */ + /* + * Find possible boot-time SMP configuration: + */ + early_find_smp_config(); +#ifdef CONFIG_ACPI + /* + * Read APIC information from ACPI tables. + */ + early_acpi_boot_init(); +#endif + /* + * get boot-time SMP configuration: + */ + if (smp_found_config) + early_get_smp_config(); + early_init_lapic_mapping(); +} + int __init k8_scan_nodes(unsigned long start, unsigned long end) { unsigned long prevbase; @@ -56,6 +83,7 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) unsigned cores; unsigned bits; int j; + unsigned apicid_base; if (!early_pci_allowed()) return -1; @@ -174,11 +202,19 @@ int __init k8_scan_nodes(unsigned long start, unsigned long end) /* use the coreid bits from early_identify_cpu */ bits = boot_cpu_data.x86_coreid_bits; cores = (1<<bits); + apicid_base = 0; + /* need to get boot_cpu_id early for system with apicid lifting */ + early_get_boot_cpu_id(); + if (boot_cpu_physical_apicid > 0) { + printk(KERN_INFO "BSP APIC ID: %02x\n", + boot_cpu_physical_apicid); + apicid_base = boot_cpu_physical_apicid; + } for (i = 0; i < 8; i++) { if (nodes[i].start != nodes[i].end) { nodeid = nodeids[i]; - for (j = 0; j < cores; j++) + for (j = apicid_base; j < cores + apicid_base; j++) apicid_to_node[(nodeid << bits) + j] = i; setup_node_bootmem(i, nodes[i].start, nodes[i].end); } diff --git a/arch/x86/pci/Makefile_32 b/arch/x86/pci/Makefile_32 index cdd6828b5ab..2a1516efb54 100644 --- a/arch/x86/pci/Makefile_32 +++ b/arch/x86/pci/Makefile_32 @@ -3,6 +3,7 @@ obj-y := i386.o init.o obj-$(CONFIG_PCI_BIOS) += pcbios.o obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_32.o direct.o mmconfig-shared.o obj-$(CONFIG_PCI_DIRECT) += direct.o +obj-$(CONFIG_PCI_OLPC) += olpc.o pci-y := fixup.o pci-$(CONFIG_ACPI) += acpi.o @@ -10,5 +11,6 @@ pci-y += legacy.o irq.o pci-$(CONFIG_X86_VISWS) := visws.o fixup.o pci-$(CONFIG_X86_NUMAQ) := numa.o irq.o +pci-$(CONFIG_NUMA) += mp_bus_to_node.o obj-y += $(pci-y) common.o early.o diff --git a/arch/x86/pci/Makefile_64 b/arch/x86/pci/Makefile_64 index 7d8c467bf14..8fbd19832cf 100644 --- a/arch/x86/pci/Makefile_64 +++ b/arch/x86/pci/Makefile_64 @@ -13,5 +13,5 @@ obj-y += legacy.o irq.o common.o early.o # mmconfig has a 64bit special obj-$(CONFIG_PCI_MMCONFIG) += mmconfig_64.o direct.o mmconfig-shared.o -obj-$(CONFIG_NUMA) += k8-bus_64.o +obj-y += k8-bus_64.o diff --git a/arch/x86/pci/acpi.c b/arch/x86/pci/acpi.c index 2664cb3fc96..1a9c0c6a1a1 100644 --- a/arch/x86/pci/acpi.c +++ b/arch/x86/pci/acpi.c @@ -191,7 +191,10 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do { struct pci_bus *bus; struct pci_sysdata *sd; + int node; +#ifdef CONFIG_ACPI_NUMA int pxm; +#endif dmi_check_system(acpi_pciprobe_dmi_table); @@ -201,6 +204,17 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do return NULL; } + node = -1; +#ifdef CONFIG_ACPI_NUMA + pxm = acpi_get_pxm(device->handle); + if (pxm >= 0) + node = pxm_to_node(pxm); + if (node != -1) + set_mp_bus_to_node(busnum, node); + else + node = get_mp_bus_to_node(busnum); +#endif + /* Allocate per-root-bus (not per bus) arch-specific data. * TODO: leak; this memory is never freed. * It's arguable whether it's worth the trouble to care. @@ -212,13 +226,7 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do } sd->domain = domain; - sd->node = -1; - - pxm = acpi_get_pxm(device->handle); -#ifdef CONFIG_ACPI_NUMA - if (pxm >= 0) - sd->node = pxm_to_node(pxm); -#endif + sd->node = node; /* * Maybe the desired pci bus has been already scanned. In such case * it is unnecessary to scan the pci bus with the given domain,busnum. @@ -238,9 +246,9 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do kfree(sd); #ifdef CONFIG_ACPI_NUMA - if (bus != NULL) { + if (bus) { if (pxm >= 0) { - printk("bus %d -> pxm %d -> node %d\n", + printk(KERN_DEBUG "bus %02x -> pxm %d -> node %d\n", busnum, pxm, pxm_to_node(pxm)); } } @@ -248,7 +256,6 @@ struct pci_bus * __devinit pci_acpi_scan_root(struct acpi_device *device, int do if (bus && (pci_probe & PCI_USE__CRS)) get_current_resources(device, busnum, domain, bus); - return bus; } diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 75fcc29ecf5..2a4d751818b 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -342,9 +342,14 @@ struct pci_bus * __devinit pcibios_scan_root(int busnum) return NULL; } + sd->node = get_mp_bus_to_node(busnum); + printk(KERN_DEBUG "PCI: Probing PCI hardware (bus %02x)\n", busnum); + bus = pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); + if (!bus) + kfree(sd); - return pci_scan_bus_parented(NULL, busnum, &pci_root_ops, sd); + return bus; } extern u8 pci_cache_line_size; @@ -420,6 +425,10 @@ char * __devinit pcibios_setup(char *str) pci_probe &= ~PCI_PROBE_MMCONF; return NULL; } + else if (!strcmp(str, "check_enable_amd_mmconf")) { + pci_probe |= PCI_CHECK_ENABLE_AMD_MMCONF; + return NULL; + } #endif else if (!strcmp(str, "noacpi")) { acpi_noirq_set(); @@ -480,7 +489,7 @@ void pcibios_disable_device (struct pci_dev *dev) pcibios_disable_irq(dev); } -struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno) +struct pci_bus *pci_scan_bus_on_node(int busno, struct pci_ops *ops, int node) { struct pci_bus *bus = NULL; struct pci_sysdata *sd; @@ -495,10 +504,15 @@ struct pci_bus *__devinit pci_scan_bus_with_sysdata(int busno) printk(KERN_ERR "PCI: OOM, skipping PCI bus %02x\n", busno); return NULL; } - sd->node = -1; - bus = pci_scan_bus(busno, &pci_root_ops, sd); + sd->node = node; + bus = pci_scan_bus(busno, ops, sd); if (!bus) kfree(sd); return bus; } + +struct pci_bus *pci_scan_bus_with_sysdata(int busno) +{ + return pci_scan_bus_on_node(busno, &pci_root_ops, -1); +} diff --git a/arch/x86/pci/direct.c b/arch/x86/pci/direct.c index 42f3e4cad17..21d1e0e0d53 100644 --- a/arch/x86/pci/direct.c +++ b/arch/x86/pci/direct.c @@ -258,7 +258,8 @@ void __init pci_direct_init(int type) { if (type == 0) return; - printk(KERN_INFO "PCI: Using configuration type %d\n", type); + printk(KERN_INFO "PCI: Using configuration type %d for base access\n", + type); if (type == 1) raw_pci_ops = &pci_direct_conf1; else @@ -275,8 +276,10 @@ int __init pci_direct_probe(void) if (!region) goto type2; - if (pci_check_type1()) + if (pci_check_type1()) { + raw_pci_ops = &pci_direct_conf1; return 1; + } release_resource(region); type2: @@ -290,7 +293,6 @@ int __init pci_direct_probe(void) goto fail2; if (pci_check_type2()) { - printk(KERN_INFO "PCI: Using configuration type 2\n"); raw_pci_ops = &pci_direct_conf2; return 2; } diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index a5ef5f55137..b60b2abd480 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -493,3 +493,20 @@ static void __devinit pci_siemens_interrupt_controller(struct pci_dev *dev) } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SIEMENS, 0x0015, pci_siemens_interrupt_controller); + +/* + * Regular PCI devices have 256 bytes, but AMD Family 10h Opteron ext config + * have 4096 bytes. Even if the device is capable, that doesn't mean we can + * access it. Maybe we don't have a way to generate extended config space + * accesses. So check it + */ +static void fam10h_pci_cfg_space_size(struct pci_dev *dev) +{ + dev->cfg_size = pci_cfg_space_size_ext(dev, 0); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1200, fam10h_pci_cfg_space_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1201, fam10h_pci_cfg_space_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1202, fam10h_pci_cfg_space_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1203, fam10h_pci_cfg_space_size); +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, 0x1204, fam10h_pci_cfg_space_size); diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c index 3de9f9ba2da..dd30c6076b5 100644 --- a/arch/x86/pci/init.c +++ b/arch/x86/pci/init.c @@ -6,16 +6,17 @@ in the right sequence from here. */ static __init int pci_access_init(void) { - int type __maybe_unused = 0; - #ifdef CONFIG_PCI_DIRECT + int type = 0; + type = pci_direct_probe(); #endif -#ifdef CONFIG_PCI_MMCONFIG - pci_mmcfg_init(type); + + pci_mmcfg_early_init(); + +#ifdef CONFIG_PCI_OLPC + pci_olpc_init(); #endif - if (raw_pci_ops) - return 0; #ifdef CONFIG_PCI_BIOS pci_pcbios_init(); #endif @@ -28,7 +29,7 @@ static __init int pci_access_init(void) #ifdef CONFIG_PCI_DIRECT pci_direct_init(type); #endif - if (!raw_pci_ops) + if (!raw_pci_ops && !raw_pci_ext_ops) printk(KERN_ERR "PCI: Fatal: No config space access function found\n"); diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 579745ca6b6..0908fca901b 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -136,9 +136,11 @@ static void __init pirq_peer_trick(void) busmap[e->bus] = 1; } for(i = 1; i < 256; i++) { + int node; if (!busmap[i] || pci_find_bus(0, i)) continue; - if (pci_scan_bus_with_sysdata(i)) + node = get_mp_bus_to_node(i); + if (pci_scan_bus_on_node(i, &pci_root_ops, node)) printk(KERN_INFO "PCI: Discovered primary peer " "bus %02x [IRQ]\n", i); } diff --git a/arch/x86/pci/k8-bus_64.c b/arch/x86/pci/k8-bus_64.c index 9cc813e2970..ab6d4b18a88 100644 --- a/arch/x86/pci/k8-bus_64.c +++ b/arch/x86/pci/k8-bus_64.c @@ -1,83 +1,536 @@ #include <linux/init.h> #include <linux/pci.h> +#include <asm/pci-direct.h> #include <asm/mpspec.h> #include <linux/cpumask.h> +#include <linux/topology.h> /* * This discovers the pcibus <-> node mapping on AMD K8. - * - * RED-PEN need to call this again on PCI hotplug - * RED-PEN empty cpus get reported wrong + * also get peer root bus resource for io,mmio */ -#define NODE_ID_REGISTER 0x60 -#define NODE_ID(dword) (dword & 0x07) -#define LDT_BUS_NUMBER_REGISTER_0 0x94 -#define LDT_BUS_NUMBER_REGISTER_1 0xB4 -#define LDT_BUS_NUMBER_REGISTER_2 0xD4 -#define NR_LDT_BUS_NUMBER_REGISTERS 3 -#define SECONDARY_LDT_BUS_NUMBER(dword) ((dword >> 8) & 0xFF) -#define SUBORDINATE_LDT_BUS_NUMBER(dword) ((dword >> 16) & 0xFF) -#define PCI_DEVICE_ID_K8HTCONFIG 0x1100 + +/* + * sub bus (transparent) will use entres from 3 to store extra from root, + * so need to make sure have enought slot there, increase PCI_BUS_NUM_RESOURCES? + */ +#define RES_NUM 16 +struct pci_root_info { + char name[12]; + unsigned int res_num; + struct resource res[RES_NUM]; + int bus_min; + int bus_max; + int node; + int link; +}; + +/* 4 at this time, it may become to 32 */ +#define PCI_ROOT_NR 4 +static int pci_root_num; +static struct pci_root_info pci_root_info[PCI_ROOT_NR]; + +#ifdef CONFIG_NUMA + +#define BUS_NR 256 + +static int mp_bus_to_node[BUS_NR]; + +void set_mp_bus_to_node(int busnum, int node) +{ + if (busnum >= 0 && busnum < BUS_NR) + mp_bus_to_node[busnum] = node; +} + +int get_mp_bus_to_node(int busnum) +{ + int node = -1; + + if (busnum < 0 || busnum > (BUS_NR - 1)) + return node; + + node = mp_bus_to_node[busnum]; + + /* + * let numa_node_id to decide it later in dma_alloc_pages + * if there is no ram on that node + */ + if (node != -1 && !node_online(node)) + node = -1; + + return node; +} +#endif + +void set_pci_bus_resources_arch_default(struct pci_bus *b) +{ + int i; + int j; + struct pci_root_info *info; + + /* if only one root bus, don't need to anything */ + if (pci_root_num < 2) + return; + + for (i = 0; i < pci_root_num; i++) { + if (pci_root_info[i].bus_min == b->number) + break; + } + + if (i == pci_root_num) + return; + + info = &pci_root_info[i]; + for (j = 0; j < info->res_num; j++) { + struct resource *res; + struct resource *root; + + res = &info->res[j]; + b->resource[j] = res; + if (res->flags & IORESOURCE_IO) + root = &ioport_resource; + else + root = &iomem_resource; + insert_resource(root, res); + } +} + +#define RANGE_NUM 16 + +struct res_range { + size_t start; + size_t end; +}; + +static void __init update_range(struct res_range *range, size_t start, + size_t end) +{ + int i; + int j; + + for (j = 0; j < RANGE_NUM; j++) { + if (!range[j].end) + continue; + + if (start <= range[j].start && end >= range[j].end) { + range[j].start = 0; + range[j].end = 0; + continue; + } + + if (start <= range[j].start && end < range[j].end && range[j].start < end + 1) { + range[j].start = end + 1; + continue; + } + + + if (start > range[j].start && end >= range[j].end && range[j].end > start - 1) { + range[j].end = start - 1; + continue; + } + + if (start > range[j].start && end < range[j].end) { + /* find the new spare */ + for (i = 0; i < RANGE_NUM; i++) { + if (range[i].end == 0) + break; + } + if (i < RANGE_NUM) { + range[i].end = range[j].end; + range[i].start = end + 1; + } else { + printk(KERN_ERR "run of slot in ranges\n"); + } + range[j].end = start - 1; + continue; + } + } +} + +static void __init update_res(struct pci_root_info *info, size_t start, + size_t end, unsigned long flags, int merge) +{ + int i; + struct resource *res; + + if (!merge) + goto addit; + + /* try to merge it with old one */ + for (i = 0; i < info->res_num; i++) { + size_t final_start, final_end; + size_t common_start, common_end; + + res = &info->res[i]; + if (res->flags != flags) + continue; + + common_start = max((size_t)res->start, start); + common_end = min((size_t)res->end, end); + if (common_start > common_end + 1) + continue; + + final_start = min((size_t)res->start, start); + final_end = max((size_t)res->end, end); + + res->start = final_start; + res->end = final_end; + return; + } + +addit: + + /* need to add that */ + if (info->res_num >= RES_NUM) + return; + + res = &info->res[info->res_num]; + res->name = info->name; + res->flags = flags; + res->start = start; + res->end = end; + res->child = NULL; + info->res_num++; +} + +struct pci_hostbridge_probe { + u32 bus; + u32 slot; + u32 vendor; + u32 device; +}; + +static struct pci_hostbridge_probe pci_probes[] __initdata = { + { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1100 }, + { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1200 }, + { 0xff, 0, PCI_VENDOR_ID_AMD, 0x1200 }, + { 0, 0x18, PCI_VENDOR_ID_AMD, 0x1300 }, +}; + +static u64 __initdata fam10h_mmconf_start; +static u64 __initdata fam10h_mmconf_end; +static void __init get_pci_mmcfg_amd_fam10h_range(void) +{ + u32 address; + u64 base, msr; + unsigned segn_busn_bits; + + /* assume all cpus from fam10h have mmconf */ + if (boot_cpu_data.x86 < 0x10) + return; + + address = MSR_FAM10H_MMIO_CONF_BASE; + rdmsrl(address, msr); + + /* mmconfig is not enable */ + if (!(msr & FAM10H_MMIO_CONF_ENABLE)) + return; + + base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); + + segn_busn_bits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & + FAM10H_MMIO_CONF_BUSRANGE_MASK; + + fam10h_mmconf_start = base; + fam10h_mmconf_end = base + (1ULL<<(segn_busn_bits + 20)) - 1; +} /** - * fill_mp_bus_to_cpumask() + * early_fill_mp_bus_to_node() + * called before pcibios_scan_root and pci_scan_bus * fills the mp_bus_to_cpumask array based according to the LDT Bus Number * Registers found in the K8 northbridge */ -__init static int -fill_mp_bus_to_cpumask(void) +static int __init early_fill_mp_bus_info(void) { - struct pci_dev *nb_dev = NULL; - int i, j; - u32 ldtbus, nid; - static int lbnr[3] = { - LDT_BUS_NUMBER_REGISTER_0, - LDT_BUS_NUMBER_REGISTER_1, - LDT_BUS_NUMBER_REGISTER_2 - }; - - while ((nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_K8HTCONFIG, nb_dev))) { - pci_read_config_dword(nb_dev, NODE_ID_REGISTER, &nid); - - for (i = 0; i < NR_LDT_BUS_NUMBER_REGISTERS; i++) { - pci_read_config_dword(nb_dev, lbnr[i], &ldtbus); - /* - * if there are no busses hanging off of the current - * ldt link then both the secondary and subordinate - * bus number fields are set to 0. - * - * RED-PEN - * This is slightly broken because it assumes - * HT node IDs == Linux node ids, which is not always - * true. However it is probably mostly true. - */ - if (!(SECONDARY_LDT_BUS_NUMBER(ldtbus) == 0 - && SUBORDINATE_LDT_BUS_NUMBER(ldtbus) == 0)) { - for (j = SECONDARY_LDT_BUS_NUMBER(ldtbus); - j <= SUBORDINATE_LDT_BUS_NUMBER(ldtbus); - j++) { - struct pci_bus *bus; - struct pci_sysdata *sd; - - long node = NODE_ID(nid); - /* Algorithm a bit dumb, but - it shouldn't matter here */ - bus = pci_find_bus(0, j); - if (!bus) - continue; - if (!node_online(node)) - node = 0; - - sd = bus->sysdata; - sd->node = node; - } + int i; + int j; + unsigned bus; + unsigned slot; + int found; + int node; + int link; + int def_node; + int def_link; + struct pci_root_info *info; + u32 reg; + struct resource *res; + size_t start; + size_t end; + struct res_range range[RANGE_NUM]; + u64 val; + u32 address; + +#ifdef CONFIG_NUMA + for (i = 0; i < BUS_NR; i++) + mp_bus_to_node[i] = -1; +#endif + + if (!early_pci_allowed()) + return -1; + + found = 0; + for (i = 0; i < ARRAY_SIZE(pci_probes); i++) { + u32 id; + u16 device; + u16 vendor; + + bus = pci_probes[i].bus; + slot = pci_probes[i].slot; + id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID); + + vendor = id & 0xffff; + device = (id>>16) & 0xffff; + if (pci_probes[i].vendor == vendor && + pci_probes[i].device == device) { + found = 1; + break; + } + } + + if (!found) + return 0; + + pci_root_num = 0; + for (i = 0; i < 4; i++) { + int min_bus; + int max_bus; + reg = read_pci_config(bus, slot, 1, 0xe0 + (i << 2)); + + /* Check if that register is enabled for bus range */ + if ((reg & 7) != 3) + continue; + + min_bus = (reg >> 16) & 0xff; + max_bus = (reg >> 24) & 0xff; + node = (reg >> 4) & 0x07; +#ifdef CONFIG_NUMA + for (j = min_bus; j <= max_bus; j++) + mp_bus_to_node[j] = (unsigned char) node; +#endif + link = (reg >> 8) & 0x03; + + info = &pci_root_info[pci_root_num]; + info->bus_min = min_bus; + info->bus_max = max_bus; + info->node = node; + info->link = link; + sprintf(info->name, "PCI Bus #%02x", min_bus); + pci_root_num++; + } + + /* get the default node and link for left over res */ + reg = read_pci_config(bus, slot, 0, 0x60); + def_node = (reg >> 8) & 0x07; + reg = read_pci_config(bus, slot, 0, 0x64); + def_link = (reg >> 8) & 0x03; + + memset(range, 0, sizeof(range)); + range[0].end = 0xffff; + /* io port resource */ + for (i = 0; i < 4; i++) { + reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3)); + if (!(reg & 3)) + continue; + + start = reg & 0xfff000; + reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3)); + node = reg & 0x07; + link = (reg >> 4) & 0x03; + end = (reg & 0xfff000) | 0xfff; + + /* find the position */ + for (j = 0; j < pci_root_num; j++) { + info = &pci_root_info[j]; + if (info->node == node && info->link == link) + break; + } + if (j == pci_root_num) + continue; /* not found */ + + info = &pci_root_info[j]; + printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n", + node, link, (u64)start, (u64)end); + + /* kernel only handle 16 bit only */ + if (end > 0xffff) + end = 0xffff; + update_res(info, start, end, IORESOURCE_IO, 1); + update_range(range, start, end); + } + /* add left over io port range to def node/link, [0, 0xffff] */ + /* find the position */ + for (j = 0; j < pci_root_num; j++) { + info = &pci_root_info[j]; + if (info->node == def_node && info->link == def_link) + break; + } + if (j < pci_root_num) { + info = &pci_root_info[j]; + for (i = 0; i < RANGE_NUM; i++) { + if (!range[i].end) + continue; + + update_res(info, range[i].start, range[i].end, + IORESOURCE_IO, 1); + } + } + + memset(range, 0, sizeof(range)); + /* 0xfd00000000-0xffffffffff for HT */ + range[0].end = (0xfdULL<<32) - 1; + + /* need to take out [0, TOM) for RAM*/ + address = MSR_K8_TOP_MEM1; + rdmsrl(address, val); + end = (val & 0xffffff8000000ULL); + printk(KERN_INFO "TOM: %016lx aka %ldM\n", end, end>>20); + if (end < (1ULL<<32)) + update_range(range, 0, end - 1); + + /* get mmconfig */ + get_pci_mmcfg_amd_fam10h_range(); + /* need to take out mmconf range */ + if (fam10h_mmconf_end) { + printk(KERN_DEBUG "Fam 10h mmconf [%llx, %llx]\n", fam10h_mmconf_start, fam10h_mmconf_end); + update_range(range, fam10h_mmconf_start, fam10h_mmconf_end); + } + + /* mmio resource */ + for (i = 0; i < 8; i++) { + reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3)); + if (!(reg & 3)) + continue; + + start = reg & 0xffffff00; /* 39:16 on 31:8*/ + start <<= 8; + reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3)); + node = reg & 0x07; + link = (reg >> 4) & 0x03; + end = (reg & 0xffffff00); + end <<= 8; + end |= 0xffff; + + /* find the position */ + for (j = 0; j < pci_root_num; j++) { + info = &pci_root_info[j]; + if (info->node == node && info->link == link) + break; + } + if (j == pci_root_num) + continue; /* not found */ + + info = &pci_root_info[j]; + + printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]", + node, link, (u64)start, (u64)end); + /* + * some sick allocation would have range overlap with fam10h + * mmconf range, so need to update start and end. + */ + if (fam10h_mmconf_end) { + int changed = 0; + u64 endx = 0; + if (start >= fam10h_mmconf_start && + start <= fam10h_mmconf_end) { + start = fam10h_mmconf_end + 1; + changed = 1; + } + + if (end >= fam10h_mmconf_start && + end <= fam10h_mmconf_end) { + end = fam10h_mmconf_start - 1; + changed = 1; + } + + if (start < fam10h_mmconf_start && + end > fam10h_mmconf_end) { + /* we got a hole */ + endx = fam10h_mmconf_start - 1; + update_res(info, start, endx, IORESOURCE_MEM, 0); + update_range(range, start, endx); + printk(KERN_CONT " ==> [%llx, %llx]", (u64)start, endx); + start = fam10h_mmconf_end + 1; + changed = 1; + } + if (changed) { + if (start <= end) { + printk(KERN_CONT " %s [%llx, %llx]", endx?"and":"==>", (u64)start, (u64)end); + } else { + printk(KERN_CONT "%s\n", endx?"":" ==> none"); + continue; + } } } + + update_res(info, start, end, IORESOURCE_MEM, 1); + update_range(range, start, end); + printk(KERN_CONT "\n"); + } + + /* need to take out [4G, TOM2) for RAM*/ + /* SYS_CFG */ + address = MSR_K8_SYSCFG; + rdmsrl(address, val); + /* TOP_MEM2 is enabled? */ + if (val & (1<<21)) { + /* TOP_MEM2 */ + address = MSR_K8_TOP_MEM2; + rdmsrl(address, val); + end = (val & 0xffffff8000000ULL); + printk(KERN_INFO "TOM2: %016lx aka %ldM\n", end, end>>20); + update_range(range, 1ULL<<32, end - 1); + } + + /* + * add left over mmio range to def node/link ? + * that is tricky, just record range in from start_min to 4G + */ + for (j = 0; j < pci_root_num; j++) { + info = &pci_root_info[j]; + if (info->node == def_node && info->link == def_link) + break; + } + if (j < pci_root_num) { + info = &pci_root_info[j]; + + for (i = 0; i < RANGE_NUM; i++) { + if (!range[i].end) + continue; + + update_res(info, range[i].start, range[i].end, + IORESOURCE_MEM, 1); + } + } + +#ifdef CONFIG_NUMA + for (i = 0; i < BUS_NR; i++) { + node = mp_bus_to_node[i]; + if (node >= 0) + printk(KERN_DEBUG "bus: %02x to node: %02x\n", i, node); + } +#endif + + for (i = 0; i < pci_root_num; i++) { + int res_num; + int busnum; + + info = &pci_root_info[i]; + res_num = info->res_num; + busnum = info->bus_min; + printk(KERN_DEBUG "bus: [%02x,%02x] on node %x link %x\n", + info->bus_min, info->bus_max, info->node, info->link); + for (j = 0; j < res_num; j++) { + res = &info->res[j]; + printk(KERN_DEBUG "bus: %02x index %x %s: [%llx, %llx]\n", + busnum, j, + (res->flags & IORESOURCE_IO)?"io port":"mmio", + res->start, res->end); + } } return 0; } -fs_initcall(fill_mp_bus_to_cpumask); +postcore_initcall(early_fill_mp_bus_info); diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index e041ced0ce1..a67921ce60a 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c @@ -12,6 +12,7 @@ static void __devinit pcibios_fixup_peer_bridges(void) { int n, devfn; + long node; if (pcibios_last_bus <= 0 || pcibios_last_bus >= 0xff) return; @@ -21,12 +22,13 @@ static void __devinit pcibios_fixup_peer_bridges(void) u32 l; if (pci_find_bus(0, n)) continue; + node = get_mp_bus_to_node(n); for (devfn = 0; devfn < 256; devfn += 8) { if (!raw_pci_read(0, n, devfn, PCI_VENDOR_ID, 2, &l) && l != 0x0000 && l != 0xffff) { DBG("Found device at %02x:%02x [%04x]\n", n, devfn, l); printk(KERN_INFO "PCI: Discovered peer bus %02x\n", n); - pci_scan_bus_with_sysdata(n); + pci_scan_bus_on_node(n, &pci_root_ops, node); break; } } diff --git a/arch/x86/pci/mmconfig-shared.c b/arch/x86/pci/mmconfig-shared.c index 8d54df4dfaa..0cfebecf2a8 100644 --- a/arch/x86/pci/mmconfig-shared.c +++ b/arch/x86/pci/mmconfig-shared.c @@ -28,7 +28,7 @@ static int __initdata pci_mmcfg_resources_inserted; static const char __init *pci_mmcfg_e7520(void) { u32 win; - pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win); + raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0xce, 2, &win); win = win & 0xf000; if(win == 0x0000 || win == 0xf000) @@ -53,7 +53,7 @@ static const char __init *pci_mmcfg_intel_945(void) pci_mmcfg_config_num = 1; - pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar); + raw_pci_ops->read(0, 0, PCI_DEVFN(0, 0), 0x48, 4, &pciexbar); /* Enable bit */ if (!(pciexbar & 1)) @@ -100,33 +100,102 @@ static const char __init *pci_mmcfg_intel_945(void) return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; } +static const char __init *pci_mmcfg_amd_fam10h(void) +{ + u32 low, high, address; + u64 base, msr; + int i; + unsigned segnbits = 0, busnbits; + + if (!(pci_probe & PCI_CHECK_ENABLE_AMD_MMCONF)) + return NULL; + + address = MSR_FAM10H_MMIO_CONF_BASE; + if (rdmsr_safe(address, &low, &high)) + return NULL; + + msr = high; + msr <<= 32; + msr |= low; + + /* mmconfig is not enable */ + if (!(msr & FAM10H_MMIO_CONF_ENABLE)) + return NULL; + + base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); + + busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & + FAM10H_MMIO_CONF_BUSRANGE_MASK; + + /* + * only handle bus 0 ? + * need to skip it + */ + if (!busnbits) + return NULL; + + if (busnbits > 8) { + segnbits = busnbits - 8; + busnbits = 8; + } + + pci_mmcfg_config_num = (1 << segnbits); + pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) * + pci_mmcfg_config_num, GFP_KERNEL); + if (!pci_mmcfg_config) + return NULL; + + for (i = 0; i < (1 << segnbits); i++) { + pci_mmcfg_config[i].address = base + (1<<28) * i; + pci_mmcfg_config[i].pci_segment = i; + pci_mmcfg_config[i].start_bus_number = 0; + pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1; + } + + return "AMD Family 10h NB"; +} + struct pci_mmcfg_hostbridge_probe { + u32 bus; + u32 devfn; u32 vendor; u32 device; const char *(*probe)(void); }; static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, + { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, + { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, + { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD, + 0x1200, pci_mmcfg_amd_fam10h }, + { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD, + 0x1200, pci_mmcfg_amd_fam10h }, }; static int __init pci_mmcfg_check_hostbridge(void) { u32 l; + u32 bus, devfn; u16 vendor, device; int i; const char *name; - pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0, 4, &l); - vendor = l & 0xffff; - device = (l >> 16) & 0xffff; + if (!raw_pci_ops) + return 0; pci_mmcfg_config_num = 0; pci_mmcfg_config = NULL; name = NULL; for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) { + bus = pci_mmcfg_probes[i].bus; + devfn = pci_mmcfg_probes[i].devfn; + raw_pci_ops->read(0, bus, devfn, 0, 4, &l); + vendor = l & 0xffff; + device = (l >> 16) & 0xffff; + if (pci_mmcfg_probes[i].vendor == vendor && pci_mmcfg_probes[i].device == device) name = pci_mmcfg_probes[i].probe(); @@ -173,9 +242,78 @@ static void __init pci_mmcfg_insert_resources(unsigned long resource_flags) pci_mmcfg_resources_inserted = 1; } -static void __init pci_mmcfg_reject_broken(int type) +static acpi_status __init check_mcfg_resource(struct acpi_resource *res, + void *data) +{ + struct resource *mcfg_res = data; + struct acpi_resource_address64 address; + acpi_status status; + + if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { + struct acpi_resource_fixed_memory32 *fixmem32 = + &res->data.fixed_memory32; + if (!fixmem32) + return AE_OK; + if ((mcfg_res->start >= fixmem32->address) && + (mcfg_res->end < (fixmem32->address + + fixmem32->address_length))) { + mcfg_res->flags = 1; + return AE_CTRL_TERMINATE; + } + } + if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) && + (res->type != ACPI_RESOURCE_TYPE_ADDRESS64)) + return AE_OK; + + status = acpi_resource_to_address64(res, &address); + if (ACPI_FAILURE(status) || + (address.address_length <= 0) || + (address.resource_type != ACPI_MEMORY_RANGE)) + return AE_OK; + + if ((mcfg_res->start >= address.minimum) && + (mcfg_res->end < (address.minimum + address.address_length))) { + mcfg_res->flags = 1; + return AE_CTRL_TERMINATE; + } + return AE_OK; +} + +static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, + void *context, void **rv) +{ + struct resource *mcfg_res = context; + + acpi_walk_resources(handle, METHOD_NAME__CRS, + check_mcfg_resource, context); + + if (mcfg_res->flags) + return AE_CTRL_TERMINATE; + + return AE_OK; +} + +static int __init is_acpi_reserved(unsigned long start, unsigned long end) +{ + struct resource mcfg_res; + + mcfg_res.start = start; + mcfg_res.end = end; + mcfg_res.flags = 0; + + acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL); + + if (!mcfg_res.flags) + acpi_get_devices("PNP0C02", find_mboard_resource, &mcfg_res, + NULL); + + return mcfg_res.flags; +} + +static void __init pci_mmcfg_reject_broken(int early) { typeof(pci_mmcfg_config[0]) *cfg; + int i; if ((pci_mmcfg_config_num == 0) || (pci_mmcfg_config == NULL) || @@ -184,51 +322,80 @@ static void __init pci_mmcfg_reject_broken(int type) cfg = &pci_mmcfg_config[0]; - /* - * Handle more broken MCFG tables on Asus etc. - * They only contain a single entry for bus 0-0. - */ - if (pci_mmcfg_config_num == 1 && - cfg->pci_segment == 0 && - (cfg->start_bus_number | cfg->end_bus_number) == 0) { - printk(KERN_ERR "PCI: start and end of bus number is 0. " - "Rejected as broken MCFG.\n"); - goto reject; + for (i = 0; i < pci_mmcfg_config_num; i++) { + int valid = 0; + u32 size = (cfg->end_bus_number + 1) << 20; + cfg = &pci_mmcfg_config[i]; + printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " + "segment %hu buses %u - %u\n", + i, (unsigned long)cfg->address, cfg->pci_segment, + (unsigned int)cfg->start_bus_number, + (unsigned int)cfg->end_bus_number); + + if (!early && + is_acpi_reserved(cfg->address, cfg->address + size - 1)) { + printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved " + "in ACPI motherboard resources\n", + cfg->address); + valid = 1; + } + + if (valid) + continue; + + if (!early) + printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" + " reserved in ACPI motherboard resources\n", + cfg->address); + /* Don't try to do this check unless configuration + type 1 is available. how about type 2 ?*/ + if (raw_pci_ops && e820_all_mapped(cfg->address, + cfg->address + size - 1, + E820_RESERVED)) { + printk(KERN_NOTICE + "PCI: MCFG area at %Lx reserved in E820\n", + cfg->address); + valid = 1; + } + + if (!valid) + goto reject; } - /* - * Only do this check when type 1 works. If it doesn't work - * assume we run on a Mac and always use MCFG - */ - if (type == 1 && !e820_all_mapped(cfg->address, - cfg->address + MMCONFIG_APER_MIN, - E820_RESERVED)) { - printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" - " E820-reserved\n", cfg->address); - goto reject; - } return; reject: printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); + pci_mmcfg_arch_free(); kfree(pci_mmcfg_config); pci_mmcfg_config = NULL; pci_mmcfg_config_num = 0; } -void __init pci_mmcfg_init(int type) -{ - int known_bridge = 0; +static int __initdata known_bridge; +void __init __pci_mmcfg_init(int early) +{ + /* MMCONFIG disabled */ if ((pci_probe & PCI_PROBE_MMCONF) == 0) return; - if (type == 1 && pci_mmcfg_check_hostbridge()) - known_bridge = 1; + /* MMCONFIG already enabled */ + if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF)) + return; + + /* for late to exit */ + if (known_bridge) + return; + + if (early) { + if (pci_mmcfg_check_hostbridge()) + known_bridge = 1; + } if (!known_bridge) { acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); - pci_mmcfg_reject_broken(type); + pci_mmcfg_reject_broken(early); } if ((pci_mmcfg_config_num == 0) || @@ -249,6 +416,16 @@ void __init pci_mmcfg_init(int type) } } +void __init pci_mmcfg_early_init(void) +{ + __pci_mmcfg_init(1); +} + +void __init pci_mmcfg_late_init(void) +{ + __pci_mmcfg_init(0); +} + static int __init pci_mmcfg_late_insert_resources(void) { /* diff --git a/arch/x86/pci/mmconfig_32.c b/arch/x86/pci/mmconfig_32.c index 081816ada05..f3c761dce69 100644 --- a/arch/x86/pci/mmconfig_32.c +++ b/arch/x86/pci/mmconfig_32.c @@ -136,3 +136,7 @@ int __init pci_mmcfg_arch_init(void) raw_pci_ext_ops = &pci_mmcfg; return 1; } + +void __init pci_mmcfg_arch_free(void) +{ +} diff --git a/arch/x86/pci/mmconfig_64.c b/arch/x86/pci/mmconfig_64.c index 9207fd49233..a1994163c99 100644 --- a/arch/x86/pci/mmconfig_64.c +++ b/arch/x86/pci/mmconfig_64.c @@ -127,7 +127,7 @@ static void __iomem * __init mcfg_ioremap(struct acpi_mcfg_allocation *cfg) int __init pci_mmcfg_arch_init(void) { int i; - pci_mmcfg_virt = kmalloc(sizeof(*pci_mmcfg_virt) * + pci_mmcfg_virt = kzalloc(sizeof(*pci_mmcfg_virt) * pci_mmcfg_config_num, GFP_KERNEL); if (pci_mmcfg_virt == NULL) { printk(KERN_ERR "PCI: Can not allocate memory for mmconfig structures\n"); @@ -141,9 +141,29 @@ int __init pci_mmcfg_arch_init(void) printk(KERN_ERR "PCI: Cannot map mmconfig aperture for " "segment %d\n", pci_mmcfg_config[i].pci_segment); + pci_mmcfg_arch_free(); return 0; } } raw_pci_ext_ops = &pci_mmcfg; return 1; } + +void __init pci_mmcfg_arch_free(void) +{ + int i; + + if (pci_mmcfg_virt == NULL) + return; + + for (i = 0; i < pci_mmcfg_config_num; ++i) { + if (pci_mmcfg_virt[i].virt) { + iounmap(pci_mmcfg_virt[i].virt); + pci_mmcfg_virt[i].virt = NULL; + pci_mmcfg_virt[i].cfg = NULL; + } + } + + kfree(pci_mmcfg_virt); + pci_mmcfg_virt = NULL; +} diff --git a/arch/x86/pci/mp_bus_to_node.c b/arch/x86/pci/mp_bus_to_node.c new file mode 100644 index 00000000000..022943999b8 --- /dev/null +++ b/arch/x86/pci/mp_bus_to_node.c @@ -0,0 +1,23 @@ +#include <linux/pci.h> +#include <linux/init.h> +#include <linux/topology.h> + +#define BUS_NR 256 + +static unsigned char mp_bus_to_node[BUS_NR]; + +void set_mp_bus_to_node(int busnum, int node) +{ + if (busnum >= 0 && busnum < BUS_NR) + mp_bus_to_node[busnum] = (unsigned char) node; +} + +int get_mp_bus_to_node(int busnum) +{ + int node; + + if (busnum < 0 || busnum > (BUS_NR - 1)) + return 0; + node = mp_bus_to_node[busnum]; + return node; +} diff --git a/arch/x86/pci/olpc.c b/arch/x86/pci/olpc.c new file mode 100644 index 00000000000..5e7636558c0 --- /dev/null +++ b/arch/x86/pci/olpc.c @@ -0,0 +1,313 @@ +/* + * Low-level PCI config space access for OLPC systems who lack the VSA + * PCI virtualization software. + * + * Copyright © 2006 Advanced Micro Devices, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * The AMD Geode chipset (ie: GX2 processor, cs5536 I/O companion device) + * has some I/O functions (display, southbridge, sound, USB HCIs, etc) + * that more or less behave like PCI devices, but the hardware doesn't + * directly implement the PCI configuration space headers. AMD provides + * "VSA" (Virtual System Architecture) software that emulates PCI config + * space for these devices, by trapping I/O accesses to PCI config register + * (CF8/CFC) and running some code in System Management Mode interrupt state. + * On the OLPC platform, we don't want to use that VSA code because + * (a) it slows down suspend/resume, and (b) recompiling it requires special + * compilers that are hard to get. So instead of letting the complex VSA + * code simulate the PCI config registers for the on-chip devices, we + * just simulate them the easy way, by inserting the code into the + * pci_write_config and pci_read_config path. Most of the config registers + * are read-only anyway, so the bulk of the simulation is just table lookup. + */ + +#include <linux/pci.h> +#include <linux/init.h> +#include <asm/olpc.h> +#include <asm/geode.h> +#include "pci.h" + +/* + * In the tables below, the first two line (8 longwords) are the + * size masks that are used when the higher level PCI code determines + * the size of the region by writing ~0 to a base address register + * and reading back the result. + * + * The following lines are the values that are read during normal + * PCI config access cycles, i.e. not after just having written + * ~0 to a base address register. + */ + +static const uint32_t lxnb_hdr[] = { /* dev 1 function 0 - devfn = 8 */ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + 0x281022, 0x2200005, 0x6000021, 0x80f808, /* AMD Vendor ID */ + 0x0, 0x0, 0x0, 0x0, /* No virtual registers, hence no BAR */ + 0x0, 0x0, 0x0, 0x28100b, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t gxnb_hdr[] = { /* dev 1 function 0 - devfn = 8 */ + 0xfffffffd, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + 0x28100b, 0x2200005, 0x6000021, 0x80f808, /* NSC Vendor ID */ + 0xac1d, 0x0, 0x0, 0x0, /* I/O BAR - base of virtual registers */ + 0x0, 0x0, 0x0, 0x28100b, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t lxfb_hdr[] = { /* dev 1 function 1 - devfn = 9 */ + 0xff000008, 0xffffc000, 0xffffc000, 0xffffc000, + 0xffffc000, 0x0, 0x0, 0x0, + + 0x20811022, 0x2200003, 0x3000000, 0x0, /* AMD Vendor ID */ + 0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */ + 0xfe00c000, 0x0, 0x0, 0x30100b, /* VIP */ + 0x0, 0x0, 0x0, 0x10e, /* INTA, IRQ14 for graphics accel */ + 0x0, 0x0, 0x0, 0x0, + 0x3d0, 0x3c0, 0xa0000, 0x0, /* VG IO, VG IO, EGA FB, MONO FB */ + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t gxfb_hdr[] = { /* dev 1 function 1 - devfn = 9 */ + 0xff800008, 0xffffc000, 0xffffc000, 0xffffc000, + 0x0, 0x0, 0x0, 0x0, + + 0x30100b, 0x2200003, 0x3000000, 0x0, /* NSC Vendor ID */ + 0xfd000000, 0xfe000000, 0xfe004000, 0xfe008000, /* FB, GP, VG, DF */ + 0x0, 0x0, 0x0, 0x30100b, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x3d0, 0x3c0, 0xa0000, 0x0, /* VG IO, VG IO, EGA FB, MONO FB */ + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t aes_hdr[] = { /* dev 1 function 2 - devfn = 0xa */ + 0xffffc000, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + 0x20821022, 0x2a00006, 0x10100000, 0x8, /* NSC Vendor ID */ + 0xfe010000, 0x0, 0x0, 0x0, /* AES registers */ + 0x0, 0x0, 0x0, 0x20821022, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + + +static const uint32_t isa_hdr[] = { /* dev f function 0 - devfn = 78 */ + 0xfffffff9, 0xffffff01, 0xffffffc1, 0xffffffe1, + 0xffffff81, 0xffffffc1, 0x0, 0x0, + + 0x20901022, 0x2a00049, 0x6010003, 0x802000, + 0x18b1, 0x1001, 0x1801, 0x1881, /* SMB-8 GPIO-256 MFGPT-64 IRQ-32 */ + 0x1401, 0x1841, 0x0, 0x20901022, /* PMS-128 ACPI-64 */ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0xaa5b, /* IRQ steering */ + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t ac97_hdr[] = { /* dev f function 3 - devfn = 7b */ + 0xffffff81, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + 0x20931022, 0x2a00041, 0x4010001, 0x0, + 0x1481, 0x0, 0x0, 0x0, /* I/O BAR-128 */ + 0x0, 0x0, 0x0, 0x20931022, + 0x0, 0x0, 0x0, 0x205, /* IntB, IRQ5 */ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t ohci_hdr[] = { /* dev f function 4 - devfn = 7c */ + 0xfffff000, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + 0x20941022, 0x2300006, 0xc031002, 0x0, + 0xfe01a000, 0x0, 0x0, 0x0, /* MEMBAR-1000 */ + 0x0, 0x0, 0x0, 0x20941022, + 0x0, 0x40, 0x0, 0x40a, /* CapPtr INT-D, IRQA */ + 0xc8020001, 0x0, 0x0, 0x0, /* Capabilities - 40 is R/O, + 44 is mask 8103 (power control) */ + 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, +}; + +static const uint32_t ehci_hdr[] = { /* dev f function 4 - devfn = 7d */ + 0xfffff000, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + 0x20951022, 0x2300006, 0xc032002, 0x0, + 0xfe01b000, 0x0, 0x0, 0x0, /* MEMBAR-1000 */ + 0x0, 0x0, 0x0, 0x20951022, + 0x0, 0x40, 0x0, 0x40a, /* CapPtr INT-D, IRQA */ + 0xc8020001, 0x0, 0x0, 0x0, /* Capabilities - 40 is R/O, 44 is + mask 8103 (power control) */ +#if 0 + 0x1, 0x40080000, 0x0, 0x0, /* EECP - see EHCI spec section 2.1.7 */ +#endif + 0x01000001, 0x0, 0x0, 0x0, /* EECP - see EHCI spec section 2.1.7 */ + 0x2020, 0x0, 0x0, 0x0, /* (EHCI page 8) 60 SBRN (R/O), + 61 FLADJ (R/W), PORTWAKECAP */ +}; + +static uint32_t ff_loc = ~0; +static uint32_t zero_loc; +static int bar_probing; /* Set after a write of ~0 to a BAR */ +static int is_lx; + +#define NB_SLOT 0x1 /* Northbridge - GX chip - Device 1 */ +#define SB_SLOT 0xf /* Southbridge - CS5536 chip - Device F */ + +static int is_simulated(unsigned int bus, unsigned int devfn) +{ + return (!bus && ((PCI_SLOT(devfn) == NB_SLOT) || + (PCI_SLOT(devfn) == SB_SLOT))); +} + +static uint32_t *hdr_addr(const uint32_t *hdr, int reg) +{ + uint32_t addr; + + /* + * This is a little bit tricky. The header maps consist of + * 0x20 bytes of size masks, followed by 0x70 bytes of header data. + * In the normal case, when not probing a BAR's size, we want + * to access the header data, so we add 0x20 to the reg offset, + * thus skipping the size mask area. + * In the BAR probing case, we want to access the size mask for + * the BAR, so we subtract 0x10 (the config header offset for + * BAR0), and don't skip the size mask area. + */ + + addr = (uint32_t)hdr + reg + (bar_probing ? -0x10 : 0x20); + + bar_probing = 0; + return (uint32_t *)addr; +} + +static int pci_olpc_read(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, uint32_t *value) +{ + uint32_t *addr; + + /* Use the hardware mechanism for non-simulated devices */ + if (!is_simulated(bus, devfn)) + return pci_direct_conf1.read(seg, bus, devfn, reg, len, value); + + /* + * No device has config registers past 0x70, so we save table space + * by not storing entries for the nonexistent registers + */ + if (reg >= 0x70) + addr = &zero_loc; + else { + switch (devfn) { + case 0x8: + addr = hdr_addr(is_lx ? lxnb_hdr : gxnb_hdr, reg); + break; + case 0x9: + addr = hdr_addr(is_lx ? lxfb_hdr : gxfb_hdr, reg); + break; + case 0xa: + addr = is_lx ? hdr_addr(aes_hdr, reg) : &ff_loc; + break; + case 0x78: + addr = hdr_addr(isa_hdr, reg); + break; + case 0x7b: + addr = hdr_addr(ac97_hdr, reg); + break; + case 0x7c: + addr = hdr_addr(ohci_hdr, reg); + break; + case 0x7d: + addr = hdr_addr(ehci_hdr, reg); + break; + default: + addr = &ff_loc; + break; + } + } + switch (len) { + case 1: + *value = *(uint8_t *)addr; + break; + case 2: + *value = *(uint16_t *)addr; + break; + case 4: + *value = *addr; + break; + default: + BUG(); + } + + return 0; +} + +static int pci_olpc_write(unsigned int seg, unsigned int bus, + unsigned int devfn, int reg, int len, uint32_t value) +{ + /* Use the hardware mechanism for non-simulated devices */ + if (!is_simulated(bus, devfn)) + return pci_direct_conf1.write(seg, bus, devfn, reg, len, value); + + /* XXX we may want to extend this to simulate EHCI power management */ + + /* + * Mostly we just discard writes, but if the write is a size probe + * (i.e. writing ~0 to a BAR), we remember it and arrange to return + * the appropriate size mask on the next read. This is cheating + * to some extent, because it depends on the fact that the next + * access after such a write will always be a read to the same BAR. + */ + + if ((reg >= 0x10) && (reg < 0x2c)) { + /* write is to a BAR */ + if (value == ~0) + bar_probing = 1; + } else { + /* + * No warning on writes to ROM BAR, CMD, LATENCY_TIMER, + * CACHE_LINE_SIZE, or PM registers. + */ + if ((reg != PCI_ROM_ADDRESS) && (reg != PCI_COMMAND_MASTER) && + (reg != PCI_LATENCY_TIMER) && + (reg != PCI_CACHE_LINE_SIZE) && (reg != 0x44)) + printk(KERN_WARNING "OLPC PCI: Config write to devfn" + " %x reg %x value %x\n", devfn, reg, value); + } + + return 0; +} + +static struct pci_raw_ops pci_olpc_conf = { + .read = pci_olpc_read, + .write = pci_olpc_write, +}; + +void __init pci_olpc_init(void) +{ + if (!machine_is_olpc() || olpc_has_vsa()) + return; + + printk(KERN_INFO "PCI: Using configuration type OLPC\n"); + raw_pci_ops = &pci_olpc_conf; + is_lx = is_geode_lx(); +} diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index c4bddaeff61..c58805a92db 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h @@ -26,6 +26,7 @@ #define PCI_ASSIGN_ALL_BUSSES 0x4000 #define PCI_CAN_SKIP_ISA_ALIGN 0x8000 #define PCI_USE__CRS 0x10000 +#define PCI_CHECK_ENABLE_AMD_MMCONF 0x20000 extern unsigned int pci_probe; extern unsigned long pirq_table_addr; @@ -97,11 +98,12 @@ extern struct pci_raw_ops pci_direct_conf1; extern int pci_direct_probe(void); extern void pci_direct_init(int type); extern void pci_pcbios_init(void); -extern void pci_mmcfg_init(int type); +extern void pci_olpc_init(void); /* pci-mmconfig.c */ extern int __init pci_mmcfg_arch_init(void); +extern void __init pci_mmcfg_arch_free(void); /* * AMD Fam10h CPUs are buggy, and cannot access MMIO config space diff --git a/arch/xtensa/kernel/asm-offsets.c b/arch/xtensa/kernel/asm-offsets.c index ef63adadf7f..070ff8af3a2 100644 --- a/arch/xtensa/kernel/asm-offsets.c +++ b/arch/xtensa/kernel/asm-offsets.c @@ -19,12 +19,11 @@ #include <linux/thread_info.h> #include <linux/ptrace.h> #include <linux/mm.h> +#include <linux/kbuild.h> #include <asm/ptrace.h> #include <asm/uaccess.h> -#define DEFINE(sym, val) asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - int main(void) { /* struct pt_regs */ |