From 0fad979576e26775894b95e580aafbbc69694c6c Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 14 Dec 2006 11:49:53 +0100 Subject: [PATCH] --- yaml --- r: 44673 b: refs/heads/master c: e3a0dd7ced76bb439ddeda244a9667e7b3800fc8 h: refs/heads/master i: 44671: f6839cbba81054de60d7ac313d76b58fdd525a4f v: v3 --- [refs] | 2 +- trunk/Documentation/DocBook/genericirq.tmpl | 4 +- trunk/Makefile | 5 + trunk/arch/i386/defconfig | 2 + .../i386/kernel/cpu/cpufreq/acpi-cpufreq.c | 33 +- trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c | 4 +- trunk/arch/i386/kernel/entry.S | 32 + trunk/arch/i386/kernel/traps.c | 83 ++ trunk/arch/s390/defconfig | 47 +- trunk/arch/s390/hypfs/hypfs_diag.c | 4 +- trunk/arch/s390/kernel/ipl.c | 59 +- trunk/arch/s390/kernel/reipl.S | 6 +- trunk/arch/s390/kernel/reipl64.S | 5 +- trunk/arch/s390/kernel/reset.S | 42 - trunk/arch/sparc/defconfig | 711 +++------ trunk/arch/sparc/kernel/sparc_ksyms.c | 8 + trunk/arch/sparc/kernel/time.c | 5 +- trunk/arch/sparc/lib/Makefile | 4 +- trunk/arch/sparc/lib/atomic32.c | 39 - trunk/arch/sparc/lib/bitops.S | 109 ++ trunk/arch/sparc64/kernel/head.S | 7 +- trunk/arch/sparc64/kernel/irq.c | 24 +- trunk/arch/sparc64/kernel/smp.c | 7 +- trunk/arch/x86_64/Makefile | 2 + trunk/arch/x86_64/defconfig | 2 + trunk/arch/x86_64/kernel/entry.S | 33 + trunk/arch/x86_64/kernel/traps.c | 84 ++ trunk/arch/x86_64/kernel/vmlinux.lds.S | 2 + trunk/drivers/ata/Kconfig | 6 +- trunk/drivers/ata/ahci.c | 2 + trunk/drivers/ata/ata_piix.c | 22 +- trunk/drivers/ata/libata-core.c | 14 +- trunk/drivers/ata/libata-scsi.c | 4 +- trunk/drivers/ata/pata_legacy.c | 4 +- trunk/drivers/ata/pata_qdi.c | 4 +- trunk/drivers/ata/pata_rz1000.c | 2 + trunk/drivers/ata/pata_via.c | 9 +- trunk/drivers/ata/pata_winbond.c | 4 +- trunk/drivers/ata/sata_svw.c | 41 +- trunk/drivers/connector/cn_queue.c | 5 +- trunk/drivers/connector/connector.c | 17 +- trunk/drivers/cpufreq/cpufreq.c | 2 +- .../drivers/infiniband/hw/mthca/mthca_main.c | 113 +- trunk/drivers/infiniband/ulp/srp/ib_srp.c | 2 +- trunk/drivers/infiniband/ulp/srp/ib_srp.h | 2 +- trunk/drivers/input/keyboard/amikbd.c | 2 +- trunk/drivers/input/keyboard/sunkbd.c | 2 +- trunk/drivers/net/bnx2.c | 23 +- trunk/drivers/net/tg3.c | 42 +- trunk/drivers/net/tg3.h | 1 - trunk/drivers/s390/char/sclp_cpi.c | 2 - trunk/drivers/s390/cio/cio.c | 25 +- trunk/drivers/s390/cio/css.c | 3 +- trunk/drivers/s390/cio/qdio.c | 13 +- trunk/drivers/s390/crypto/ap_bus.c | 14 +- trunk/drivers/scsi/sun3_NCR5380.c | 6 +- trunk/drivers/usb/input/Kconfig | 3 +- trunk/include/asm-generic/vmlinux.lds.h | 22 + trunk/include/asm-i386/unwind.h | 91 ++ trunk/include/asm-s390/qdio.h | 1 - trunk/include/asm-s390/reset.h | 1 - trunk/include/asm-sparc/bitops.h | 100 +- trunk/include/asm-sparc64/hw_irq.h | 2 + trunk/include/asm-sparc64/percpu.h | 10 - trunk/include/asm-x86_64/unwind.h | 96 ++ trunk/include/linux/connector.h | 2 +- trunk/include/linux/unwind.h | 63 +- trunk/include/linux/workqueue.h | 36 +- trunk/include/net/ax25.h | 26 +- trunk/include/net/rose.h | 6 +- trunk/include/rdma/ib_verbs.h | 9 +- trunk/kernel/Makefile | 1 + trunk/kernel/unwind.c | 1305 +++++++++++++++++ trunk/kernel/workqueue.c | 16 +- trunk/lib/Kconfig.debug | 18 + trunk/lib/fault-inject.c | 32 +- trunk/mm/mincore.c | 183 ++- trunk/net/ax25/af_ax25.c | 4 +- trunk/net/ax25/ax25_iface.c | 103 +- trunk/net/ax25/ax25_route.c | 2 +- trunk/net/ipv4/route.c | 3 +- trunk/net/ipv4/tcp_ipv4.c | 3 +- trunk/net/ipv6/netfilter/Kconfig | 5 +- trunk/net/netrom/af_netrom.c | 15 +- trunk/net/netrom/nr_dev.c | 24 +- trunk/net/netrom/nr_route.c | 19 +- trunk/net/rose/af_rose.c | 18 +- trunk/net/rose/rose_dev.c | 22 +- trunk/net/rose/rose_loopback.c | 5 +- trunk/net/rose/rose_route.c | 47 +- trunk/sound/oss/dmasound/tas3001c.c | 14 +- trunk/sound/oss/dmasound/tas3004.c | 15 +- 92 files changed, 2770 insertions(+), 1303 deletions(-) create mode 100644 trunk/arch/sparc/lib/bitops.S create mode 100644 trunk/kernel/unwind.c diff --git a/[refs] b/[refs] index 0943ba4bb0ba..d2e9f4ada64c 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a240d9f1d8e6421cb970632b93e71b2f66c2cd70 +refs/heads/master: e3a0dd7ced76bb439ddeda244a9667e7b3800fc8 diff --git a/trunk/Documentation/DocBook/genericirq.tmpl b/trunk/Documentation/DocBook/genericirq.tmpl index 4215f69ce7e6..0f4a4b6321e4 100644 --- a/trunk/Documentation/DocBook/genericirq.tmpl +++ b/trunk/Documentation/DocBook/genericirq.tmpl @@ -303,10 +303,10 @@ desc->status |= running; do { if (desc->status & masked) desc->chip->enable(); - desc->status &= ~pending; + desc-status &= ~pending; handle_IRQ_event(desc->action); } while (status & pending); -desc->status &= ~running; +desc-status &= ~running; desc->chip->end(); diff --git a/trunk/Makefile b/trunk/Makefile index 4a4720387936..dc82462b68ba 100644 --- a/trunk/Makefile +++ b/trunk/Makefile @@ -496,6 +496,11 @@ else CFLAGS += -fomit-frame-pointer endif +ifdef CONFIG_UNWIND_INFO +CFLAGS += -fasynchronous-unwind-tables +LDFLAGS_vmlinux += --eh-frame-hdr +endif + ifdef CONFIG_DEBUG_INFO CFLAGS += -g endif diff --git a/trunk/arch/i386/defconfig b/trunk/arch/i386/defconfig index e075ff05c46d..3265208e5899 100644 --- a/trunk/arch/i386/defconfig +++ b/trunk/arch/i386/defconfig @@ -1493,6 +1493,8 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set # CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y # CONFIG_FORCED_INLINING is not set # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c b/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c index b735458c6e3a..18f4715c655d 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -126,6 +126,27 @@ static unsigned extract_freq(u32 val, struct acpi_cpufreq_data *data) } } +static void wrport(u16 port, u8 bit_width, u32 value) +{ + if (bit_width <= 8) + outb(value, port); + else if (bit_width <= 16) + outw(value, port); + else if (bit_width <= 32) + outl(value, port); +} + +static void rdport(u16 port, u8 bit_width, u32 * ret) +{ + *ret = 0; + if (bit_width <= 8) + *ret = inb(port); + else if (bit_width <= 16) + *ret = inw(port); + else if (bit_width <= 32) + *ret = inl(port); +} + struct msr_addr { u32 reg; }; @@ -156,9 +177,7 @@ static void do_drv_read(struct drv_cmd *cmd) rdmsr(cmd->addr.msr.reg, cmd->val, h); break; case SYSTEM_IO_CAPABLE: - acpi_os_read_port((acpi_io_address)cmd->addr.io.port, - &cmd->val, - (u32)cmd->addr.io.bit_width); + rdport(cmd->addr.io.port, cmd->addr.io.bit_width, &cmd->val); break; default: break; @@ -174,9 +193,7 @@ static void do_drv_write(struct drv_cmd *cmd) wrmsr(cmd->addr.msr.reg, cmd->val, h); break; case SYSTEM_IO_CAPABLE: - acpi_os_write_port((acpi_io_address)cmd->addr.io.port, - cmd->val, - (u32)cmd->addr.io.bit_width); + wrport(cmd->addr.io.port, cmd->addr.io.bit_width, cmd->val); break; default: break; @@ -682,14 +699,14 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) if (result) goto err_freqfree; - switch (perf->control_register.space_id) { + switch (data->cpu_feature) { case ACPI_ADR_SPACE_SYSTEM_IO: /* Current speed is unknown and not detectable by IO port */ policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); break; case ACPI_ADR_SPACE_FIXED_HARDWARE: acpi_cpufreq_driver.get = get_cur_freq_on_cpu; - policy->cur = get_cur_freq_on_cpu(cpu); + get_cur_freq_on_cpu(cpu); break; default: break; diff --git a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c index 6d9c97a690fd..c548daad3476 100644 --- a/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c +++ b/trunk/arch/i386/kernel/cpu/cpufreq/longhaul.c @@ -787,10 +787,8 @@ static int __init longhaul_init(void) switch (c->x86_model) { case 6 ... 9: return cpufreq_register_driver(&longhaul_driver); - case 10: - printk(KERN_ERR PFX "Use acpi-cpufreq driver for VIA C7\n"); default: - ;; + printk (KERN_INFO PFX "Unknown VIA CPU. Contact davej@codemonkey.org.uk\n"); } return -ENODEV; diff --git a/trunk/arch/i386/kernel/entry.S b/trunk/arch/i386/kernel/entry.S index 06461b8b715d..de34b7fed3c1 100644 --- a/trunk/arch/i386/kernel/entry.S +++ b/trunk/arch/i386/kernel/entry.S @@ -979,6 +979,38 @@ ENTRY(spurious_interrupt_bug) jmp error_code CFI_ENDPROC +#ifdef CONFIG_STACK_UNWIND +ENTRY(arch_unwind_init_running) + CFI_STARTPROC + movl 4(%esp), %edx + movl (%esp), %ecx + leal 4(%esp), %eax + movl %ebx, PT_EBX(%edx) + xorl %ebx, %ebx + movl %ebx, PT_ECX(%edx) + movl %ebx, PT_EDX(%edx) + movl %esi, PT_ESI(%edx) + movl %edi, PT_EDI(%edx) + movl %ebp, PT_EBP(%edx) + movl %ebx, PT_EAX(%edx) + movl $__USER_DS, PT_DS(%edx) + movl $__USER_DS, PT_ES(%edx) + movl $0, PT_GS(%edx) + movl %ebx, PT_ORIG_EAX(%edx) + movl %ecx, PT_EIP(%edx) + movl 12(%esp), %ecx + movl $__KERNEL_CS, PT_CS(%edx) + movl %ebx, PT_EFLAGS(%edx) + movl %eax, PT_OLDESP(%edx) + movl 8(%esp), %eax + movl %ecx, 8(%esp) + movl PT_EBX(%edx), %ebx + movl $__KERNEL_DS, PT_OLDSS(%edx) + jmpl *%eax + CFI_ENDPROC +ENDPROC(arch_unwind_init_running) +#endif + ENTRY(kernel_thread_helper) pushl $0 # fake return address for unwinder CFI_STARTPROC diff --git a/trunk/arch/i386/kernel/traps.c b/trunk/arch/i386/kernel/traps.c index 0efad8aeb41a..2b30dbf8d117 100644 --- a/trunk/arch/i386/kernel/traps.c +++ b/trunk/arch/i386/kernel/traps.c @@ -94,6 +94,11 @@ asmlinkage void spurious_interrupt_bug(void); asmlinkage void machine_check(void); int kstack_depth_to_print = 24; +#ifdef CONFIG_STACK_UNWIND +static int call_trace = 1; +#else +#define call_trace (-1) +#endif ATOMIC_NOTIFIER_HEAD(i386die_chain); int register_die_notifier(struct notifier_block *nb) @@ -147,6 +152,33 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo, return ebp; } +struct ops_and_data { + struct stacktrace_ops *ops; + void *data; +}; + +static asmlinkage int +dump_trace_unwind(struct unwind_frame_info *info, void *data) +{ + struct ops_and_data *oad = (struct ops_and_data *)data; + int n = 0; + unsigned long sp = UNW_SP(info); + + if (arch_unw_user_mode(info)) + return -1; + while (unwind(info) == 0 && UNW_PC(info)) { + n++; + oad->ops->address(oad->data, UNW_PC(info)); + if (arch_unw_user_mode(info)) + break; + if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) + && sp > UNW_SP(info)) + break; + sp = UNW_SP(info); + } + return n; +} + #define MSG(msg) ops->warning(data, msg) void dump_trace(struct task_struct *task, struct pt_regs *regs, @@ -158,6 +190,41 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, if (!task) task = current; + if (call_trace >= 0) { + int unw_ret = 0; + struct unwind_frame_info info; + struct ops_and_data oad = { .ops = ops, .data = data }; + + if (regs) { + if (unwind_init_frame_info(&info, task, regs) == 0) + unw_ret = dump_trace_unwind(&info, &oad); + } else if (task == current) + unw_ret = unwind_init_running(&info, dump_trace_unwind, + &oad); + else { + if (unwind_init_blocked(&info, task) == 0) + unw_ret = dump_trace_unwind(&info, &oad); + } + if (unw_ret > 0) { + if (call_trace == 1 && !arch_unw_user_mode(&info)) { + ops->warning_symbol(data, + "DWARF2 unwinder stuck at %s", + UNW_PC(&info)); + if (UNW_SP(&info) >= PAGE_OFFSET) { + MSG("Leftover inexact backtrace:"); + stack = (void *)UNW_SP(&info); + if (!stack) + return; + ebp = UNW_FP(&info); + } else + MSG("Full inexact backtrace again:"); + } else if (call_trace >= 1) + return; + else + MSG("Full inexact backtrace again:"); + } else + MSG("Inexact backtrace:"); + } if (!stack) { unsigned long dummy; stack = &dummy; @@ -1191,3 +1258,19 @@ static int __init kstack_setup(char *s) return 1; } __setup("kstack=", kstack_setup); + +#ifdef CONFIG_STACK_UNWIND +static int __init call_trace_setup(char *s) +{ + if (strcmp(s, "old") == 0) + call_trace = -1; + else if (strcmp(s, "both") == 0) + call_trace = 0; + else if (strcmp(s, "newfallback") == 0) + call_trace = 1; + else if (strcmp(s, "new") == 2) + call_trace = 2; + return 1; +} +__setup("call_trace=", call_trace_setup); +#endif diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index 5368cf4a350e..a6ec919ba83f 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,15 +1,14 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20-rc1 -# Fri Dec 15 16:52:28 2006 +# Linux kernel version: 2.6.19-rc2 +# Wed Oct 18 17:11:10 2006 # CONFIG_MMU=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y CONFIG_S390=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" @@ -38,13 +37,12 @@ CONFIG_AUDIT=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set -CONFIG_SYSFS_DEPRECATED=y # CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set -CONFIG_SYSCTL_SYSCALL=y +# CONFIG_SYSCTL_SYSCALL is not set CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -121,7 +119,6 @@ CONFIG_PACK_STACK=y CONFIG_CHECK_STACK=y CONFIG_STACK_GUARD=256 # CONFIG_WARN_STACK is not set -CONFIG_ARCH_POPULATES_NODE_MAP=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -131,7 +128,6 @@ CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_RESOURCES_64BIT=y -CONFIG_HOLES_IN_ZONE=y # # I/O subsystem configuration @@ -200,7 +196,6 @@ CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=y # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set @@ -216,6 +211,7 @@ CONFIG_INET6_XFRM_MODE_BEET=y # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=y # CONFIG_IPV6_TUNNEL is not set +# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set @@ -250,7 +246,6 @@ CONFIG_IPV6_SIT=y # QoS and/or fair queueing # CONFIG_NET_SCHED=y -CONFIG_NET_SCH_FIFO=y CONFIG_NET_SCH_CLK_JIFFIES=y # CONFIG_NET_SCH_CLK_GETTIMEOFDAY is not set # CONFIG_NET_SCH_CLK_CPU is not set @@ -282,7 +277,6 @@ CONFIG_NET_CLS_ROUTE=y CONFIG_NET_CLS_FW=m CONFIG_NET_CLS_U32=m # CONFIG_CLS_U32_PERF is not set -CONFIG_CLS_U32_MARK=y CONFIG_NET_CLS_RSVP=m CONFIG_NET_CLS_RSVP6=m # CONFIG_NET_EMATCH is not set @@ -321,7 +315,6 @@ CONFIG_SYS_HYPERVISOR=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -# CONFIG_SCSI_TGT is not set CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y @@ -342,7 +335,6 @@ CONFIG_CHR_DEV_SG=y CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y -CONFIG_SCSI_SCAN_ASYNC=y # # SCSI Transports @@ -554,7 +546,6 @@ CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set -CONFIG_GENERIC_ACL=y # # CD-ROM/DVD Filesystems @@ -580,7 +571,7 @@ CONFIG_TMPFS=y CONFIG_TMPFS_POSIX_ACL=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -CONFIG_CONFIGFS_FS=m +# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -625,6 +616,7 @@ CONFIG_SUNRPC=y # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set # CONFIG_9P_FS is not set +CONFIG_GENERIC_ACL=y # # Partition Types @@ -653,14 +645,6 @@ CONFIG_MSDOS_PARTITION=y # # CONFIG_NLS is not set -# -# Distributed Lock Manager -# -CONFIG_DLM=m -CONFIG_DLM_TCP=y -# CONFIG_DLM_SCTP is not set -# CONFIG_DLM_DEBUG is not set - # # Instrumentation Support # @@ -679,8 +663,6 @@ CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_SCHEDSTATS is not set @@ -697,11 +679,13 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set +CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set # CONFIG_FRAME_POINTER is not set # CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y +CONFIG_HEADERS_CHECK=y # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_LKDTM is not set @@ -715,11 +699,10 @@ CONFIG_FORCED_INLINING=y # Cryptographic options # CONFIG_CRYPTO=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_MANAGER=y +CONFIG_CRYPTO_ALGAPI=m +CONFIG_CRYPTO_BLKCIPHER=m +CONFIG_CRYPTO_MANAGER=m # CONFIG_CRYPTO_HMAC is not set -# CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set @@ -730,10 +713,8 @@ CONFIG_CRYPTO_MANAGER=y # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_LRW is not set +CONFIG_CRYPTO_CBC=m # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_DES_S390 is not set # CONFIG_CRYPTO_BLOWFISH is not set @@ -759,10 +740,8 @@ CONFIG_CRYPTO_CBC=y # # Library routines # -CONFIG_BITREVERSE=m # CONFIG_CRC_CCITT is not set # CONFIG_CRC16 is not set CONFIG_CRC32=m # CONFIG_LIBCRC32C is not set CONFIG_PLIST=y -CONFIG_IOMAP_COPY=y diff --git a/trunk/arch/s390/hypfs/hypfs_diag.c b/trunk/arch/s390/hypfs/hypfs_diag.c index 2782cf9da5b4..443fa377d9ff 100644 --- a/trunk/arch/s390/hypfs/hypfs_diag.c +++ b/trunk/arch/s390/hypfs/hypfs_diag.c @@ -379,7 +379,7 @@ static void *diag204_alloc_vbuf(int pages) static void *diag204_alloc_rbuf(void) { diag204_buf = (void*)__get_free_pages(GFP_KERNEL,0); - if (!diag204_buf) + if (diag204_buf) return ERR_PTR(-ENOMEM); diag204_buf_pages = 1; return diag204_buf; @@ -521,7 +521,7 @@ __init int hypfs_diag_init(void) } rc = diag224_get_name_table(); if (rc) { - diag204_free_buffer(); + diag224_delete_name_table(); printk(KERN_ERR "hypfs: could not get name table.\n"); } return rc; diff --git a/trunk/arch/s390/kernel/ipl.c b/trunk/arch/s390/kernel/ipl.c index 9e9972e8a52b..a36bea1188d9 100644 --- a/trunk/arch/s390/kernel/ipl.c +++ b/trunk/arch/s390/kernel/ipl.c @@ -609,12 +609,42 @@ static ssize_t on_panic_store(struct subsystem *subsys, const char *buf, static struct subsys_attribute on_panic_attr = __ATTR(on_panic, 0644, on_panic_show, on_panic_store); +static void print_fcp_block(struct ipl_parameter_block *fcp_block) +{ + printk(KERN_EMERG "wwpn: %016llx\n", + (unsigned long long)fcp_block->ipl_info.fcp.wwpn); + printk(KERN_EMERG "lun: %016llx\n", + (unsigned long long)fcp_block->ipl_info.fcp.lun); + printk(KERN_EMERG "bootprog: %lld\n", + (unsigned long long)fcp_block->ipl_info.fcp.bootprog); + printk(KERN_EMERG "br_lba: %lld\n", + (unsigned long long)fcp_block->ipl_info.fcp.br_lba); + printk(KERN_EMERG "device: %llx\n", + (unsigned long long)fcp_block->ipl_info.fcp.devno); + printk(KERN_EMERG "opt: %x\n", fcp_block->ipl_info.fcp.opt); +} + void do_reipl(void) { struct ccw_dev_id devid; static char buf[100]; char loadparm[LOADPARM_LEN + 1]; + switch (reipl_type) { + case IPL_TYPE_CCW: + reipl_get_ascii_loadparm(loadparm); + printk(KERN_EMERG "reboot on ccw device: 0.0.%04x\n", + reipl_block_ccw->ipl_info.ccw.devno); + printk(KERN_EMERG "loadparm = '%s'\n", loadparm); + break; + case IPL_TYPE_FCP: + printk(KERN_EMERG "reboot on fcp device:\n"); + print_fcp_block(reipl_block_fcp); + break; + default: + break; + } + switch (reipl_method) { case IPL_METHOD_CCW_CIO: devid.devno = reipl_block_ccw->ipl_info.ccw.devno; @@ -624,7 +654,6 @@ void do_reipl(void) reipl_ccw_dev(&devid); break; case IPL_METHOD_CCW_VM: - reipl_get_ascii_loadparm(loadparm); if (strlen(loadparm) == 0) sprintf(buf, "IPL %X", reipl_block_ccw->ipl_info.ccw.devno); @@ -654,6 +683,7 @@ void do_reipl(void) diag308(DIAG308_IPL, NULL); break; } + printk(KERN_EMERG "reboot failed!\n"); signal_processor(smp_processor_id(), sigp_stop_and_store_status); } @@ -662,6 +692,19 @@ static void do_dump(void) struct ccw_dev_id devid; static char buf[100]; + switch (dump_type) { + case IPL_TYPE_CCW: + printk(KERN_EMERG "Automatic dump on ccw device: 0.0.%04x\n", + dump_block_ccw->ipl_info.ccw.devno); + break; + case IPL_TYPE_FCP: + printk(KERN_EMERG "Automatic dump on fcp device:\n"); + print_fcp_block(dump_block_fcp); + break; + default: + return; + } + switch (dump_method) { case IPL_METHOD_CCW_CIO: smp_send_stop(); @@ -994,21 +1037,15 @@ static void do_reset_calls(void) } extern void reset_mcck_handler(void); -extern void reset_pgm_handler(void); -extern __u32 dump_prefix_page; void s390_reset_system(void) { struct _lowcore *lc; - lc = (struct _lowcore *)(unsigned long) store_prefix(); - /* Stack for interrupt/machine check handler */ + lc = (struct _lowcore *)(unsigned long) store_prefix(); lc->panic_stack = S390_lowcore.panic_stack; - /* Save prefix page address for dump case */ - dump_prefix_page = (unsigned long) lc; - /* Disable prefixing */ set_prefix(0); @@ -1019,11 +1056,5 @@ void s390_reset_system(void) S390_lowcore.mcck_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK; S390_lowcore.mcck_new_psw.addr = PSW_ADDR_AMODE | (unsigned long) &reset_mcck_handler; - - /* Set new program check handler */ - S390_lowcore.program_new_psw.mask = PSW_KERNEL_BITS & ~PSW_MASK_MCHECK; - S390_lowcore.program_new_psw.addr = - PSW_ADDR_AMODE | (unsigned long) &reset_pgm_handler; - do_reset_calls(); } diff --git a/trunk/arch/s390/kernel/reipl.S b/trunk/arch/s390/kernel/reipl.S index c3f4d9b95083..f9434d42ce9f 100644 --- a/trunk/arch/s390/kernel/reipl.S +++ b/trunk/arch/s390/kernel/reipl.S @@ -16,7 +16,7 @@ do_reipl_asm: basr %r13,0 stm %r0,%r15,__LC_GPREGS_SAVE_AREA stctl %c0,%c15,__LC_CREGS_SAVE_AREA stam %a0,%a15,__LC_AREGS_SAVE_AREA - mvc __LC_PREFIX_SAVE_AREA(4),dump_prefix_page-.Lpg0(%r13) + stpx __LC_PREFIX_SAVE_AREA stckc .Lclkcmp-.Lpg0(%r13) mvc __LC_CLOCK_COMP_SAVE_AREA(8),.Lclkcmp-.Lpg0(%r13) stpt __LC_CPU_TIMER_SAVE_AREA @@ -79,7 +79,3 @@ do_reipl_asm: basr %r13,0 .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 - .globl dump_prefix_page -dump_prefix_page: - .long 0x00000000 - diff --git a/trunk/arch/s390/kernel/reipl64.S b/trunk/arch/s390/kernel/reipl64.S index dbb3eed38865..f18ef260ca23 100644 --- a/trunk/arch/s390/kernel/reipl64.S +++ b/trunk/arch/s390/kernel/reipl64.S @@ -20,7 +20,7 @@ do_reipl_asm: basr %r13,0 stg %r0,__LC_GPREGS_SAVE_AREA-0x1000+8(%r1) stctg %c0,%c15,__LC_CREGS_SAVE_AREA-0x1000(%r1) stam %a0,%a15,__LC_AREGS_SAVE_AREA-0x1000(%r1) - mvc __LC_PREFIX_SAVE_AREA-0x1000(4,%r1),dump_prefix_page-.Lpg0(%r13) + stpx __LC_PREFIX_SAVE_AREA-0x1000(%r1) stfpc __LC_FP_CREG_SAVE_AREA-0x1000(%r1) stckc .Lclkcmp-.Lpg0(%r13) mvc __LC_CLOCK_COMP_SAVE_AREA-0x1000(8,%r1),.Lclkcmp-.Lpg0(%r13) @@ -103,6 +103,3 @@ do_reipl_asm: basr %r13,0 .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 .long 0x00000000,0x00000000 - .globl dump_prefix_page -dump_prefix_page: - .long 0x00000000 diff --git a/trunk/arch/s390/kernel/reset.S b/trunk/arch/s390/kernel/reset.S index 8a87355161fa..be8688c0665c 100644 --- a/trunk/arch/s390/kernel/reset.S +++ b/trunk/arch/s390/kernel/reset.S @@ -3,7 +3,6 @@ * * Copyright (C) IBM Corp. 2006 * Author(s): Heiko Carstens - * Michael Holzheu */ #include @@ -28,26 +27,6 @@ reset_mcck_handler: s390_reset_mcck_handler: .quad 0 - .globl reset_pgm_handler -reset_pgm_handler: - stmg %r0,%r15,__LC_SAVE_AREA - basr %r13,0 -0: lg %r15,__LC_PANIC_STACK # load panic stack - aghi %r15,-STACK_FRAME_OVERHEAD - lg %r1,s390_reset_pgm_handler-0b(%r13) - ltgr %r1,%r1 - jz 1f - basr %r14,%r1 - lmg %r0,%r15,__LC_SAVE_AREA - lpswe __LC_PGM_OLD_PSW -1: lpswe disabled_wait_psw-0b(%r13) - .globl s390_reset_pgm_handler -s390_reset_pgm_handler: - .quad 0 - .align 8 -disabled_wait_psw: - .quad 0x0002000180000000,0x0000000000000000 + reset_pgm_handler - #else /* CONFIG_64BIT */ .globl reset_mcck_handler @@ -66,25 +45,4 @@ reset_mcck_handler: s390_reset_mcck_handler: .long 0 - .globl reset_pgm_handler -reset_pgm_handler: - stm %r0,%r15,__LC_SAVE_AREA - basr %r13,0 -0: l %r15,__LC_PANIC_STACK # load panic stack - ahi %r15,-STACK_FRAME_OVERHEAD - l %r1,s390_reset_pgm_handler-0b(%r13) - ltr %r1,%r1 - jz 1f - basr %r14,%r1 - lm %r0,%r15,__LC_SAVE_AREA - lpsw __LC_PGM_OLD_PSW - -1: lpsw disabled_wait_psw-0b(%r13) - .globl s390_reset_pgm_handler -s390_reset_pgm_handler: - .long 0 -disabled_wait_psw: - .align 8 - .long 0x000a0000,0x00000000 + reset_pgm_handler - #endif /* CONFIG_64BIT */ diff --git a/trunk/arch/sparc/defconfig b/trunk/arch/sparc/defconfig index 79e54894529d..a69856263009 100644 --- a/trunk/arch/sparc/defconfig +++ b/trunk/arch/sparc/defconfig @@ -1,59 +1,41 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.20-rc1 -# Sun Dec 17 14:20:47 2006 # CONFIG_MMU=y +CONFIG_UID16=y CONFIG_HIGHMEM=y CONFIG_GENERIC_ISA_DMA=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y CONFIG_BROKEN_ON_SMP=y -CONFIG_INIT_ENV_ARG_LIMIT=32 # # General setup # -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_UTS_NS is not set +CONFIG_SYSCTL=y # CONFIG_AUDIT is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_HOTPLUG is not set # CONFIG_IKCONFIG is not set -CONFIG_SYSFS_DEPRECATED=y -# CONFIG_RELAY is not set -CONFIG_INITRAMFS_SOURCE="" -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y -CONFIG_SHMEM=y -CONFIG_SLAB=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -61,36 +43,17 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y # -# Block layer -# -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" - -# -# General machine setup +# General setup # +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y # CONFIG_SMP is not set -CONFIG_SPARC=y CONFIG_SPARC32=y CONFIG_SBUS=y CONFIG_SBUSCHAR=y @@ -98,170 +61,73 @@ CONFIG_SERIAL_CONSOLE=y CONFIG_SUN_AUXIO=y CONFIG_SUN_IO=y CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_ARCH_MAY_HAVE_PC_FDC=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_SUN_PM=y # CONFIG_SUN4 is not set CONFIG_PCI=y -# CONFIG_PCI_MULTITHREAD_PROBE is not set -# CONFIG_PCI_DEBUG is not set +# CONFIG_PCI_LEGACY_PROC is not set +# CONFIG_PCI_NAMES is not set CONFIG_SUN_OPENPROMFS=m -# CONFIG_SPARC_LED is not set CONFIG_BINFMT_ELF=y CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_MISC=m CONFIG_SUNOS_EMUL=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -# CONFIG_NETDEBUG is not set -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -CONFIG_XFRM=y -CONFIG_XFRM_USER=m -# CONFIG_XFRM_SUB_POLICY is not set -CONFIG_NET_KEY=m -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=y -CONFIG_IP_PNP_DHCP=y -# CONFIG_IP_PNP_BOOTP is not set -# CONFIG_IP_PNP_RARP is not set -# CONFIG_NET_IPIP is not set -# CONFIG_NET_IPGRE is not set -# CONFIG_ARPD is not set -# CONFIG_SYN_COOKIES is not set -CONFIG_INET_AH=y -CONFIG_INET_ESP=y -CONFIG_INET_IPCOMP=y -CONFIG_INET_XFRM_TUNNEL=y -CONFIG_INET_TUNNEL=y -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -CONFIG_IPV6=m -CONFIG_IPV6_PRIVACY=y -# CONFIG_IPV6_ROUTER_PREF is not set -CONFIG_INET6_AH=m -CONFIG_INET6_ESP=m -CONFIG_INET6_IPCOMP=m -# CONFIG_IPV6_MIP6 is not set -CONFIG_INET6_XFRM_TUNNEL=m -CONFIG_INET6_TUNNEL=m -CONFIG_INET6_XFRM_MODE_TRANSPORT=m -CONFIG_INET6_XFRM_MODE_TUNNEL=m -CONFIG_INET6_XFRM_MODE_BEET=m -# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set -CONFIG_IPV6_SIT=m -CONFIG_IPV6_TUNNEL=m -# CONFIG_IPV6_MULTIPLE_TABLES is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# -# CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# -CONFIG_IP_SCTP=m -# CONFIG_SCTP_DBG_MSG is not set -CONFIG_SCTP_DBG_OBJCNT=y -# CONFIG_SCTP_HMAC_NONE is not set -# CONFIG_SCTP_HMAC_SHA1 is not set -CONFIG_SCTP_HMAC_MD5=y - -# -# TIPC Configuration (EXPERIMENTAL) -# -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set # -# QoS and/or fair queueing +# Parallel port support # -# CONFIG_NET_SCHED is not set +# CONFIG_PARPORT is not set # -# Network testing +# Generic Driver Options # -CONFIG_NET_PKTGEN=m -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_IEEE80211 is not set +# CONFIG_DEBUG_DRIVER is not set # -# Device Drivers +# Graphics support # +# CONFIG_FB is not set # -# Generic Driver Options +# Console display driver support # -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_MDA_CONSOLE is not set +# CONFIG_PROM_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y # -# Connector - unified userspace <-> kernelspace linker +# Memory Technology Devices (MTD) # -# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set # -# Memory Technology Devices (MTD) +# Serial drivers # -# CONFIG_MTD is not set +# CONFIG_SERIAL_8250 is not set # -# Parallel port support +# Non-8250 serial port support # -# CONFIG_PARPORT is not set +CONFIG_SERIAL_SUNCORE=y +CONFIG_SERIAL_SUNZILOG=y +CONFIG_SERIAL_SUNZILOG_CONSOLE=y +CONFIG_SERIAL_SUNSU=y +CONFIG_SERIAL_SUNSU_CONSOLE=y +# CONFIG_SERIAL_SUNSAB is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y # -# Plug and Play support +# Misc Linux/SPARC drivers # +CONFIG_SUN_OPENPROMIO=m +CONFIG_SUN_MOSTEK_RTC=m +# CONFIG_SUN_BPP is not set +# CONFIG_SUN_VIDEOPIX is not set +# CONFIG_SUN_AURORA is not set +# CONFIG_TADPOLE_TS102_UCTRL is not set +# CONFIG_SUN_JSFLASH is not set +CONFIG_APM_RTC_IS_GMT=y +CONFIG_RTC=m # # Block devices @@ -271,37 +137,28 @@ CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_UMEM is not set -# CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=m CONFIG_BLK_DEV_CRYPTOLOOP=m # CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set +# CONFIG_BLK_DEV_CARMEL is not set CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set # -# Misc devices +# ATA/ATAPI/MFM/RLL support # -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set +# CONFIG_IDE is not set # -# ATA/ATAPI/MFM/RLL support +# ISDN subsystem # -# CONFIG_IDE is not set +# CONFIG_ISDN is not set # # SCSI device support # -# CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set CONFIG_SCSI_PROC_FS=y # @@ -313,7 +170,6 @@ CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=m # CONFIG_BLK_DEV_SR_VENDOR is not set CONFIG_CHR_DEV_SG=m -# CONFIG_CHR_DEV_SCH is not set # # Some SCSI devices (e.g. CD jukebox) support multiple LUNs @@ -321,58 +177,57 @@ CONFIG_CHR_DEV_SG=m # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set # -# SCSI Transports +# SCSI Transport Attributes # CONFIG_SCSI_SPI_ATTRS=m # CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set # # SCSI low-level drivers # -# CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set # CONFIG_SCSI_ACARD is not set # CONFIG_SCSI_AACRAID is not set # CONFIG_SCSI_AIC7XXX is not set # CONFIG_SCSI_AIC7XXX_OLD is not set # CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC94XX is not set # CONFIG_SCSI_DPT_I2O is not set -# CONFIG_SCSI_ARCMSR is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_IPR is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLOGICPTI=m -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set -# CONFIG_SCSI_LPFC is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set CONFIG_SCSI_SUNESP=y -# CONFIG_SCSI_SRP is not set # -# Serial ATA (prod) and Parallel ATA (experimental) drivers +# Fibre Channel support # -# CONFIG_ATA is not set +# CONFIG_FC4 is not set # # Multi-device support (RAID and LVM) @@ -380,42 +235,91 @@ CONFIG_SCSI_SUNESP=y # CONFIG_MD is not set # -# Fusion MPT device support +# Networking support +# +CONFIG_NET=y + +# +# Networking options # -# CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_NETLINK_DEV=y +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_PNP=y +CONFIG_IP_PNP_DHCP=y +# CONFIG_IP_PNP_BOOTP is not set +# CONFIG_IP_PNP_RARP is not set +# CONFIG_NET_IPIP is not set +# CONFIG_NET_IPGRE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +CONFIG_INET_AH=y +CONFIG_INET_ESP=y +CONFIG_INET_IPCOMP=y +CONFIG_IPV6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_TUNNEL=m +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m # -# IEEE 1394 (FireWire) support +# SCTP Configuration (EXPERIMENTAL) # -# CONFIG_IEEE1394 is not set +CONFIG_IP_SCTP=m +# CONFIG_SCTP_DBG_MSG is not set +CONFIG_SCTP_DBG_OBJCNT=y +# CONFIG_SCTP_HMAC_NONE is not set +# CONFIG_SCTP_HMAC_SHA1 is not set +CONFIG_SCTP_HMAC_MD5=y +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_HW_FLOWCONTROL is not set # -# I2O device support +# QoS and/or fair queueing # -# CONFIG_I2O is not set +# CONFIG_NET_SCHED is not set # -# Network device support +# Network testing # +CONFIG_NET_PKTGEN=m +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=m # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m +# CONFIG_ETHERTAP is not set # # ARCnet devices # # CONFIG_ARCNET is not set -# -# PHY device support -# -# CONFIG_PHYLIB is not set - # # Ethernet (10 or 100Mbit) # @@ -426,7 +330,6 @@ CONFIG_HAPPYMEAL=m CONFIG_SUNBMAC=m CONFIG_SUNQE=m # CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set # CONFIG_NET_VENDOR_3COM is not set # @@ -447,22 +350,14 @@ CONFIG_SUNQE=m # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set -# CONFIG_QLA3XXX is not set # # Ethernet (10000 Mbit) # -# CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set -# CONFIG_MYRI10GE is not set -# CONFIG_NETXEN_NIC is not set # # Token Ring devices @@ -485,24 +380,17 @@ CONFIG_SUNQE=m # CONFIG_NET_FC is not set # CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set - -# -# ISDN subsystem -# -# CONFIG_ISDN is not set # -# Telephony Support +# Unix98 PTY support # -# CONFIG_PHONE is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 # # Input device support # CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set # # Userland interfaces @@ -516,6 +404,17 @@ CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=m CONFIG_INPUT_EVBUG=m +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=m +# CONFIG_SERIO_I8042 is not set +CONFIG_SERIO_SERPORT=m +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + # # Input Device Drivers # @@ -525,7 +424,6 @@ CONFIG_KEYBOARD_SUNKBD=m # CONFIG_KEYBOARD_LKKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set CONFIG_INPUT_MOUSE=y CONFIG_MOUSE_PS2=m CONFIG_MOUSE_SERIAL=m @@ -534,209 +432,6 @@ CONFIG_MOUSE_SERIAL=m # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set -# -# Hardware I/O ports -# -CONFIG_SERIO=m -# CONFIG_SERIO_I8042 is not set -CONFIG_SERIO_SERPORT=m -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=m -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SUNCORE=y -CONFIG_SERIAL_SUNZILOG=y -CONFIG_SERIAL_SUNZILOG_CONSOLE=y -CONFIG_SERIAL_SUNSU=y -CONFIG_SERIAL_SUNSU_CONSOLE=y -# CONFIG_SERIAL_SUNSAB is not set -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# -# CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# -# CONFIG_WATCHDOG is not set -CONFIG_HW_RANDOM=m -CONFIG_RTC=m -# CONFIG_DTLK is not set -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_DRM is not set -# CONFIG_RAW_DRIVER is not set - -# -# TPM devices -# -# CONFIG_TCG_TPM is not set - -# -# I2C support -# -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# -# CONFIG_W1 is not set - -# -# Hardware Monitoring support -# -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ABITUGURU is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_HWMON_DEBUG_CHIP is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set - -# -# Digital Video Broadcasting Devices -# -# CONFIG_DVB is not set - -# -# Graphics support -# -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB is not set - -# -# Console display driver support -# -# CONFIG_PROM_CONSOLE is not set -CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Sound -# -# CONFIG_SOUND is not set - -# -# HID Devices -# -CONFIG_HID=y - -# -# USB support -# -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# -# CONFIG_MMC is not set - -# -# LED devices -# -# CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - -# -# InfiniBand support -# -# CONFIG_INFINIBAND is not set - -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# -# CONFIG_RTC_CLASS is not set - -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# - -# -# Virtualization -# - -# -# Misc Linux/SPARC drivers -# -CONFIG_SUN_OPENPROMIO=m -CONFIG_SUN_MOSTEK_RTC=m -# CONFIG_SUN_BPP is not set -# CONFIG_SUN_VIDEOPIX is not set -# CONFIG_TADPOLE_TS102_UCTRL is not set -# CONFIG_SUN_JSFLASH is not set - -# -# Unix98 PTY support -# -CONFIG_UNIX98_PTY_COUNT=256 - # # File systems # @@ -744,30 +439,23 @@ CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT2_FS_POSIX_ACL=y CONFIG_EXT2_FS_SECURITY=y -# CONFIG_EXT2_FS_XIP is not set # CONFIG_EXT3_FS is not set -# CONFIG_EXT4DEV_FS is not set +# CONFIG_JBD is not set CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m +CONFIG_XFS_RT=y CONFIG_XFS_QUOTA=y CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y -CONFIG_XFS_RT=y -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set CONFIG_ROMFS_FS=m -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_QUOTACTL=y -CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m -# CONFIG_FUSE_FS is not set # # CD-ROM/DVD Filesystems @@ -780,8 +468,7 @@ CONFIG_ISO9660_FS=m # # DOS/FAT/NT Filesystems # -# CONFIG_MSDOS_FS is not set -# CONFIG_VFAT_FS is not set +# CONFIG_FAT_FS is not set # CONFIG_NTFS_FS is not set # @@ -789,12 +476,13 @@ CONFIG_ISO9660_FS=m # CONFIG_PROC_FS=y CONFIG_PROC_KCORE=y -CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_CONFIGFS_FS is not set # # Miscellaneous filesystems @@ -824,23 +512,17 @@ CONFIG_NFS_FS=y # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y -CONFIG_NFS_COMMON=y +# CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=m CONFIG_RPCSEC_GSS_KRB5=m -# CONFIG_RPCSEC_GSS_SPKM3 is not set # CONFIG_SMB_FS is not set CONFIG_CIFS=m # CONFIG_CIFS_STATS is not set -# CONFIG_CIFS_WEAK_PW_HASH is not set -# CONFIG_CIFS_XATTR is not set -# CONFIG_CIFS_DEBUG2 is not set -# CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set CONFIG_AFS_FS=m CONFIG_RXRPC=m -# CONFIG_9P_FS is not set # # Partition Types @@ -877,7 +559,6 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set -# CONFIG_NLS_ASCII is not set # CONFIG_NLS_ISO8859_1 is not set # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set @@ -894,104 +575,70 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_UTF8 is not set # -# Distributed Lock Manager +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support # -# CONFIG_DLM is not set +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set # -# Instrumentation Support +# Watchdog Cards # -# CONFIG_PROFILING is not set +# CONFIG_WATCHDOG is not set # # Kernel hacking # -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set -# CONFIG_DEBUG_FS is not set -# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=14 -CONFIG_DETECT_SOFTLOCKUP=y -# CONFIG_SCHEDSTATS is not set +# CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set +CONFIG_MAGIC_SYSRQ=y # CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RWSEMS is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_HIGHMEM is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_BUGVERBOSE is not set # # Security options # -# CONFIG_KEYS is not set # CONFIG_SECURITY is not set # # Cryptographic options # CONFIG_CRYPTO=y -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y -# CONFIG_CRYPTO_XCBC is not set CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_SHA1=y CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA512=m -# CONFIG_CRYPTO_WP512 is not set -# CONFIG_CRYPTO_TGR192 is not set -# CONFIG_CRYPTO_GF128MUL is not set -CONFIG_CRYPTO_ECB=m -CONFIG_CRYPTO_CBC=y -# CONFIG_CRYPTO_LRW is not set CONFIG_CRYPTO_DES=y CONFIG_CRYPTO_BLOWFISH=m CONFIG_CRYPTO_TWOFISH=m -CONFIG_CRYPTO_TWOFISH_COMMON=m CONFIG_CRYPTO_SERPENT=m CONFIG_CRYPTO_AES=m CONFIG_CRYPTO_CAST5=m CONFIG_CRYPTO_CAST6=m -# CONFIG_CRYPTO_TEA is not set CONFIG_CRYPTO_ARC4=m -# CONFIG_CRYPTO_KHAZAD is not set -# CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_TEST is not set -# -# Hardware crypto devices -# - # # Library routines # -CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set CONFIG_CRC32=y CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y -CONFIG_PLIST=y -CONFIG_IOMAP_COPY=y diff --git a/trunk/arch/sparc/kernel/sparc_ksyms.c b/trunk/arch/sparc/kernel/sparc_ksyms.c index d8e008a04e2b..33dadd9f2871 100644 --- a/trunk/arch/sparc/kernel/sparc_ksyms.c +++ b/trunk/arch/sparc/kernel/sparc_ksyms.c @@ -83,6 +83,9 @@ extern int __divdi3(int, int); /* Private functions with odd calling conventions. */ extern void ___atomic24_add(void); extern void ___atomic24_sub(void); +extern void ___set_bit(void); +extern void ___clear_bit(void); +extern void ___change_bit(void); extern void ___rw_read_enter(void); extern void ___rw_read_try(void); extern void ___rw_read_exit(void); @@ -122,6 +125,11 @@ EXPORT_SYMBOL(pfn_base); EXPORT_SYMBOL(___atomic24_add); EXPORT_SYMBOL(___atomic24_sub); +/* Bit operations. */ +EXPORT_SYMBOL(___set_bit); +EXPORT_SYMBOL(___clear_bit); +EXPORT_SYMBOL(___change_bit); + /* Per-CPU information table */ EXPORT_PER_CPU_SYMBOL(__cpu_data); diff --git a/trunk/arch/sparc/kernel/time.c b/trunk/arch/sparc/kernel/time.c index 2fcce000d877..6c7aa51b590f 100644 --- a/trunk/arch/sparc/kernel/time.c +++ b/trunk/arch/sparc/kernel/time.c @@ -78,6 +78,7 @@ unsigned long profile_pc(struct pt_regs *regs) extern char __copy_user_begin[], __copy_user_end[]; extern char __atomic_begin[], __atomic_end[]; extern char __bzero_begin[], __bzero_end[]; + extern char __bitops_begin[], __bitops_end[]; unsigned long pc = regs->pc; @@ -87,7 +88,9 @@ unsigned long profile_pc(struct pt_regs *regs) (pc >= (unsigned long) __atomic_begin && pc < (unsigned long) __atomic_end) || (pc >= (unsigned long) __bzero_begin && - pc < (unsigned long) __bzero_end)) + pc < (unsigned long) __bzero_end) || + (pc >= (unsigned long) __bitops_begin && + pc < (unsigned long) __bitops_end)) pc = regs->u_regs[UREG_RETPC]; return pc; } diff --git a/trunk/arch/sparc/lib/Makefile b/trunk/arch/sparc/lib/Makefile index 9ddc5b9ce3bd..5db7e1d85385 100644 --- a/trunk/arch/sparc/lib/Makefile +++ b/trunk/arch/sparc/lib/Makefile @@ -7,7 +7,7 @@ EXTRA_AFLAGS := -ansi -DST_DIV0=0x02 lib-y := mul.o rem.o sdiv.o udiv.o umul.o urem.o ashrdi3.o memcpy.o memset.o \ strlen.o checksum.o blockops.o memscan.o memcmp.o strncmp.o \ strncpy_from_user.o divdi3.o udivdi3.o strlen_user.o \ - copy_user.o locks.o atomic.o \ + copy_user.o locks.o atomic.o atomic32.o bitops.o \ lshrdi3.o ashldi3.o rwsem.o muldi3.o bitext.o -obj-y += iomap.o atomic32.o +obj-y += iomap.o diff --git a/trunk/arch/sparc/lib/atomic32.c b/trunk/arch/sparc/lib/atomic32.c index 53ddcd9d1e60..de84f8534bac 100644 --- a/trunk/arch/sparc/lib/atomic32.c +++ b/trunk/arch/sparc/lib/atomic32.c @@ -76,42 +76,3 @@ void atomic_set(atomic_t *v, int i) spin_unlock_irqrestore(ATOMIC_HASH(v), flags); } EXPORT_SYMBOL(atomic_set); - -unsigned long ___set_bit(unsigned long *addr, unsigned long mask) -{ - unsigned long old, flags; - - spin_lock_irqsave(ATOMIC_HASH(addr), flags); - old = *addr; - *addr = old | mask; - spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); - - return old & mask; -} -EXPORT_SYMBOL(___set_bit); - -unsigned long ___clear_bit(unsigned long *addr, unsigned long mask) -{ - unsigned long old, flags; - - spin_lock_irqsave(ATOMIC_HASH(addr), flags); - old = *addr; - *addr = old & ~mask; - spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); - - return old & mask; -} -EXPORT_SYMBOL(___clear_bit); - -unsigned long ___change_bit(unsigned long *addr, unsigned long mask) -{ - unsigned long old, flags; - - spin_lock_irqsave(ATOMIC_HASH(addr), flags); - old = *addr; - *addr = old ^ mask; - spin_unlock_irqrestore(ATOMIC_HASH(addr), flags); - - return old & mask; -} -EXPORT_SYMBOL(___change_bit); diff --git a/trunk/arch/sparc/lib/bitops.S b/trunk/arch/sparc/lib/bitops.S new file mode 100644 index 000000000000..cb7fb66a40c8 --- /dev/null +++ b/trunk/arch/sparc/lib/bitops.S @@ -0,0 +1,109 @@ +/* bitops.S: Low level assembler bit operations. + * + * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) + */ + +#include +#include + + .text + .align 4 + + .globl __bitops_begin +__bitops_begin: + + /* Take bits in %g2 and set them in word at %g1, + * return whether bits were set in original value + * in %g2. %g4 holds value to restore into %o7 + * in delay slot of jmpl return, %g3 + %g5 + %g7 can be + * used as temporaries and thus is considered clobbered + * by all callers. + */ + .globl ___set_bit +___set_bit: + rd %psr, %g3 + nop; nop; nop; + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop +#ifdef CONFIG_SMP + set bitops_spinlock, %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ld [%g1], %g7 + or %g7, %g2, %g5 + and %g7, %g2, %g2 +#ifdef CONFIG_SMP + st %g5, [%g1] + set bitops_spinlock, %g5 + stb %g0, [%g5] +#else + st %g5, [%g1] +#endif + wr %g3, 0x0, %psr + nop; nop; nop + jmpl %o7, %g0 + mov %g4, %o7 + + /* Same as above, but clears the bits from %g2 instead. */ + .globl ___clear_bit +___clear_bit: + rd %psr, %g3 + nop; nop; nop + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop +#ifdef CONFIG_SMP + set bitops_spinlock, %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ld [%g1], %g7 + andn %g7, %g2, %g5 + and %g7, %g2, %g2 +#ifdef CONFIG_SMP + st %g5, [%g1] + set bitops_spinlock, %g5 + stb %g0, [%g5] +#else + st %g5, [%g1] +#endif + wr %g3, 0x0, %psr + nop; nop; nop + jmpl %o7, %g0 + mov %g4, %o7 + + /* Same thing again, but this time toggles the bits from %g2. */ + .globl ___change_bit +___change_bit: + rd %psr, %g3 + nop; nop; nop + or %g3, PSR_PIL, %g5 + wr %g5, 0x0, %psr + nop; nop; nop +#ifdef CONFIG_SMP + set bitops_spinlock, %g5 +2: ldstub [%g5], %g7 ! Spin on the byte lock for SMP. + orcc %g7, 0x0, %g0 ! Did we get it? + bne 2b ! Nope... +#endif + ld [%g1], %g7 + xor %g7, %g2, %g5 + and %g7, %g2, %g2 +#ifdef CONFIG_SMP + st %g5, [%g1] + set bitops_spinlock, %g5 + stb %g0, [%g5] +#else + st %g5, [%g1] +#endif + wr %g3, 0x0, %psr + nop; nop; nop + jmpl %o7, %g0 + mov %g4, %o7 + + .globl __bitops_end +__bitops_end: diff --git a/trunk/arch/sparc64/kernel/head.S b/trunk/arch/sparc64/kernel/head.S index baea10a98196..03ffaf895a22 100644 --- a/trunk/arch/sparc64/kernel/head.S +++ b/trunk/arch/sparc64/kernel/head.S @@ -78,7 +78,11 @@ sparc_ramdisk_image64: /* PROM cif handler code address is in %o4. */ sparc64_boot: - mov %o4, %l7 +1: rd %pc, %g7 + set 1b, %g1 + cmp %g1, %g7 + be,pn %xcc, sparc64_boot_after_remap + mov %o4, %l7 /* We need to remap the kernel. Use position independant * code to remap us to KERNBASE. @@ -291,6 +295,7 @@ is_sun4v: add %sp, (192 + 128), %sp +sparc64_boot_after_remap: sethi %hi(prom_root_compatible), %g1 or %g1, %lo(prom_root_compatible), %g1 sethi %hi(prom_sun4v_name), %g7 diff --git a/trunk/arch/sparc64/kernel/irq.c b/trunk/arch/sparc64/kernel/irq.c index c3d068c7a412..d64b1ea848de 100644 --- a/trunk/arch/sparc64/kernel/irq.c +++ b/trunk/arch/sparc64/kernel/irq.c @@ -372,14 +372,14 @@ static void run_pre_handler(unsigned int virt_irq) } } -static struct irq_chip sun4u_irq = { +static struct hw_interrupt_type sun4u_irq = { .typename = "sun4u", .enable = sun4u_irq_enable, .disable = sun4u_irq_disable, .end = sun4u_irq_end, }; -static struct irq_chip sun4u_irq_ack = { +static struct hw_interrupt_type sun4u_irq_ack = { .typename = "sun4u+ack", .enable = sun4u_irq_enable, .disable = sun4u_irq_disable, @@ -387,14 +387,14 @@ static struct irq_chip sun4u_irq_ack = { .end = sun4u_irq_end, }; -static struct irq_chip sun4v_irq = { +static struct hw_interrupt_type sun4v_irq = { .typename = "sun4v", .enable = sun4v_irq_enable, .disable = sun4v_irq_disable, .end = sun4v_irq_end, }; -static struct irq_chip sun4v_irq_ack = { +static struct hw_interrupt_type sun4v_irq_ack = { .typename = "sun4v+ack", .enable = sun4v_irq_enable, .disable = sun4v_irq_disable, @@ -493,6 +493,22 @@ unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino) return bucket->virt_irq; } +void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq) +{ + struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); + unsigned long pstate; + unsigned int *ent; + + __asm__ __volatile__("rdpr %%pstate, %0" : "=r" (pstate)); + __asm__ __volatile__("wrpr %0, %1, %%pstate" + : : "r" (pstate), "i" (PSTATE_IE)); + ent = irq_work(smp_processor_id()); + bucket->irq_chain = *ent; + *ent = __irq(bucket); + set_softint(1 << PIL_DEVICE_IRQ); + __asm__ __volatile__("wrpr %0, 0x0, %%pstate" : : "r" (pstate)); +} + void ack_bad_irq(unsigned int virt_irq) { struct ino_bucket *bucket = virt_irq_to_bucket(virt_irq); diff --git a/trunk/arch/sparc64/kernel/smp.c b/trunk/arch/sparc64/kernel/smp.c index 0a4958536bcd..cc09d8266414 100644 --- a/trunk/arch/sparc64/kernel/smp.c +++ b/trunk/arch/sparc64/kernel/smp.c @@ -1447,8 +1447,11 @@ void __init setup_per_cpu_areas(void) char *ptr; /* Copy section for each CPU (we discard the original) */ - goal = PERCPU_ENOUGH_ROOM; - + goal = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES); +#ifdef CONFIG_MODULES + if (goal < PERCPU_ENOUGH_ROOM) + goal = PERCPU_ENOUGH_ROOM; +#endif __per_cpu_shift = 0; for (size = 1UL; size < goal; size <<= 1UL) __per_cpu_shift++; diff --git a/trunk/arch/x86_64/Makefile b/trunk/arch/x86_64/Makefile index 2941a915d4ef..b471b8550d03 100644 --- a/trunk/arch/x86_64/Makefile +++ b/trunk/arch/x86_64/Makefile @@ -45,7 +45,9 @@ cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections # actually it makes the kernel smaller too. cflags-y += -fno-reorder-blocks cflags-y += -Wno-sign-compare +ifneq ($(CONFIG_UNWIND_INFO),y) cflags-y += -fno-asynchronous-unwind-tables +endif ifneq ($(CONFIG_DEBUG_INFO),y) # -fweb shrinks the kernel a bit, but the difference is very small # it also messes up debugging, so don't use it for now. diff --git a/trunk/arch/x86_64/defconfig b/trunk/arch/x86_64/defconfig index ac80b1209fc0..1a1c6a1a299b 100644 --- a/trunk/arch/x86_64/defconfig +++ b/trunk/arch/x86_64/defconfig @@ -1523,6 +1523,8 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set # CONFIG_FRAME_POINTER is not set +CONFIG_UNWIND_INFO=y +CONFIG_STACK_UNWIND=y # CONFIG_FORCED_INLINING is not set # CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set diff --git a/trunk/arch/x86_64/kernel/entry.S b/trunk/arch/x86_64/kernel/entry.S index 9f5dac64aa8f..601d332c4b79 100644 --- a/trunk/arch/x86_64/kernel/entry.S +++ b/trunk/arch/x86_64/kernel/entry.S @@ -1155,3 +1155,36 @@ ENTRY(call_softirq) ret CFI_ENDPROC ENDPROC(call_softirq) + +#ifdef CONFIG_STACK_UNWIND +ENTRY(arch_unwind_init_running) + CFI_STARTPROC + movq %r15, R15(%rdi) + movq %r14, R14(%rdi) + xchgq %rsi, %rdx + movq %r13, R13(%rdi) + movq %r12, R12(%rdi) + xorl %eax, %eax + movq %rbp, RBP(%rdi) + movq %rbx, RBX(%rdi) + movq (%rsp), %rcx + movq %rax, R11(%rdi) + movq %rax, R10(%rdi) + movq %rax, R9(%rdi) + movq %rax, R8(%rdi) + movq %rax, RAX(%rdi) + movq %rax, RCX(%rdi) + movq %rax, RDX(%rdi) + movq %rax, RSI(%rdi) + movq %rax, RDI(%rdi) + movq %rax, ORIG_RAX(%rdi) + movq %rcx, RIP(%rdi) + leaq 8(%rsp), %rcx + movq $__KERNEL_CS, CS(%rdi) + movq %rax, EFLAGS(%rdi) + movq %rcx, RSP(%rdi) + movq $__KERNEL_DS, SS(%rdi) + jmpq *%rdx + CFI_ENDPROC +ENDPROC(arch_unwind_init_running) +#endif diff --git a/trunk/arch/x86_64/kernel/traps.c b/trunk/arch/x86_64/kernel/traps.c index 1d9eb6db732a..b54ccc07f379 100644 --- a/trunk/arch/x86_64/kernel/traps.c +++ b/trunk/arch/x86_64/kernel/traps.c @@ -110,6 +110,11 @@ static inline void preempt_conditional_cli(struct pt_regs *regs) } int kstack_depth_to_print = 12; +#ifdef CONFIG_STACK_UNWIND +static int call_trace = 1; +#else +#define call_trace (-1) +#endif #ifdef CONFIG_KALLSYMS void printk_address(unsigned long address) @@ -212,6 +217,32 @@ static unsigned long *in_exception_stack(unsigned cpu, unsigned long stack, return NULL; } +struct ops_and_data { + struct stacktrace_ops *ops; + void *data; +}; + +static int dump_trace_unwind(struct unwind_frame_info *info, void *context) +{ + struct ops_and_data *oad = (struct ops_and_data *)context; + int n = 0; + unsigned long sp = UNW_SP(info); + + if (arch_unw_user_mode(info)) + return -1; + while (unwind(info) == 0 && UNW_PC(info)) { + n++; + oad->ops->address(oad->data, UNW_PC(info)); + if (arch_unw_user_mode(info)) + break; + if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1)) + && sp > UNW_SP(info)) + break; + sp = UNW_SP(info); + } + return n; +} + #define MSG(txt) ops->warning(data, txt) /* @@ -239,6 +270,40 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, if (!tsk) tsk = current; + if (call_trace >= 0) { + int unw_ret = 0; + struct unwind_frame_info info; + struct ops_and_data oad = { .ops = ops, .data = data }; + + if (regs) { + if (unwind_init_frame_info(&info, tsk, regs) == 0) + unw_ret = dump_trace_unwind(&info, &oad); + } else if (tsk == current) + unw_ret = unwind_init_running(&info, dump_trace_unwind, + &oad); + else { + if (unwind_init_blocked(&info, tsk) == 0) + unw_ret = dump_trace_unwind(&info, &oad); + } + if (unw_ret > 0) { + if (call_trace == 1 && !arch_unw_user_mode(&info)) { + ops->warning_symbol(data, + "DWARF2 unwinder stuck at %s", + UNW_PC(&info)); + if ((long)UNW_SP(&info) < 0) { + MSG("Leftover inexact backtrace:"); + stack = (unsigned long *)UNW_SP(&info); + if (!stack) + goto out; + } else + MSG("Full inexact backtrace again:"); + } else if (call_trace >= 1) + goto out; + else + MSG("Full inexact backtrace again:"); + } else + MSG("Inexact backtrace:"); + } if (!stack) { unsigned long dummy; stack = &dummy; @@ -322,6 +387,7 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs, tinfo = current_thread_info(); HANDLE_STACK (valid_stack_ptr(tinfo, stack)); #undef HANDLE_STACK +out: put_cpu(); } EXPORT_SYMBOL(dump_trace); @@ -1122,3 +1188,21 @@ static int __init kstack_setup(char *s) return 0; } early_param("kstack", kstack_setup); + +#ifdef CONFIG_STACK_UNWIND +static int __init call_trace_setup(char *s) +{ + if (!s) + return -EINVAL; + if (strcmp(s, "old") == 0) + call_trace = -1; + else if (strcmp(s, "both") == 0) + call_trace = 0; + else if (strcmp(s, "newfallback") == 0) + call_trace = 1; + else if (strcmp(s, "new") == 0) + call_trace = 2; + return 0; +} +early_param("call_trace", call_trace_setup); +#endif diff --git a/trunk/arch/x86_64/kernel/vmlinux.lds.S b/trunk/arch/x86_64/kernel/vmlinux.lds.S index 1e54ddf2338d..514be5dd2303 100644 --- a/trunk/arch/x86_64/kernel/vmlinux.lds.S +++ b/trunk/arch/x86_64/kernel/vmlinux.lds.S @@ -221,7 +221,9 @@ SECTIONS /* Sections to be discarded */ /DISCARD/ : { *(.exitcall.exit) +#ifndef CONFIG_UNWIND_INFO *(.eh_frame) +#endif } STABS_DEBUG diff --git a/trunk/drivers/ata/Kconfig b/trunk/drivers/ata/Kconfig index b34e0a958d0f..984ab284382a 100644 --- a/trunk/drivers/ata/Kconfig +++ b/trunk/drivers/ata/Kconfig @@ -40,9 +40,9 @@ config ATA_PIIX tristate "Intel PIIX/ICH SATA support" depends on PCI help - This option enables support for ICH5/6/7/8 Serial ATA - and support for PATA on the Intel PIIX3/PIIX4/ICH series - PATA host controllers. + This option enables support for ICH5/6/7/8 Serial ATA. + If PATA support was enabled previously, this enables + support for select Intel PIIX/ICH PATA host controllers. If unsure, say N. diff --git a/trunk/drivers/ata/ahci.c b/trunk/drivers/ata/ahci.c index dbae6d971041..f36da488a2c1 100644 --- a/trunk/drivers/ata/ahci.c +++ b/trunk/drivers/ata/ahci.c @@ -645,6 +645,8 @@ static int ahci_reset_controller(void __iomem *mmio, struct pci_dev *pdev) u32 cap_save, impl_save, tmp; cap_save = readl(mmio + HOST_CAP); + cap_save &= ( (1<<28) | (1<<17) ); + cap_save |= (1 << 27); impl_save = readl(mmio + HOST_PORTS_IMPL); /* global controller reset */ diff --git a/trunk/drivers/ata/ata_piix.c b/trunk/drivers/ata/ata_piix.c index 47701b286f8b..c7de0bb1591f 100644 --- a/trunk/drivers/ata/ata_piix.c +++ b/trunk/drivers/ata/ata_piix.c @@ -226,26 +226,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x27c0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, /* 2801GBM/GHM (ICH7M, identical to ICH6M) */ { 0x8086, 0x27c4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6m_sata_ahci }, - /* Enterprise Southbridge 2 (631xESB/632xESB) */ + /* Enterprise Southbridge 2 (where's the datasheet?) */ { 0x8086, 0x2680, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich6_sata_ahci }, - /* SATA Controller 1 IDE (ICH8) */ + /* SATA Controller 1 IDE (ICH8, no datasheet yet) */ { 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller 2 IDE (ICH8) */ + /* SATA Controller 2 IDE (ICH8, ditto) */ { 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* Mobile SATA Controller IDE (ICH8M) */ + /* Mobile SATA Controller IDE (ICH8M, ditto) */ { 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2921, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller IDE (ICH9) */ - { 0x8086, 0x2926, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x2928, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x292d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, - /* SATA Controller IDE (ICH9M) */ - { 0x8086, 0x292e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_ahci }, { } /* terminate list */ }; @@ -342,7 +330,7 @@ static const struct ata_port_operations ich_pata_ops = { .port_start = ata_port_start, .port_stop = ata_port_stop, - .host_stop = piix_host_stop, + .host_stop = ata_host_stop, }; static const struct ata_port_operations piix_sata_ops = { diff --git a/trunk/drivers/ata/libata-core.c b/trunk/drivers/ata/libata-core.c index 0d51d13b16bf..011c0a8a2dcc 100644 --- a/trunk/drivers/ata/libata-core.c +++ b/trunk/drivers/ata/libata-core.c @@ -1332,7 +1332,7 @@ unsigned ata_exec_internal_sg(struct ata_device *dev, } /** - * ata_exec_internal - execute libata internal command + * ata_exec_internal_sg - execute libata internal command * @dev: Device to which the command is sent * @tf: Taskfile registers for the command and the result * @cdb: CDB for packet command @@ -1353,17 +1353,11 @@ unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, int dma_dir, void *buf, unsigned int buflen) { - struct scatterlist *psg = NULL, sg; - unsigned int n_elem = 0; + struct scatterlist sg; - if (dma_dir != DMA_NONE) { - WARN_ON(!buf); - sg_init_one(&sg, buf, buflen); - psg = &sg; - n_elem++; - } + sg_init_one(&sg, buf, buflen); - return ata_exec_internal_sg(dev, tf, cdb, dma_dir, psg, n_elem); + return ata_exec_internal_sg(dev, tf, cdb, dma_dir, &sg, 1); } /** diff --git a/trunk/drivers/ata/libata-scsi.c b/trunk/drivers/ata/libata-scsi.c index a4790be41d1c..664e1377b54c 100644 --- a/trunk/drivers/ata/libata-scsi.c +++ b/trunk/drivers/ata/libata-scsi.c @@ -1539,7 +1539,7 @@ static unsigned int ata_scsi_rbuf_get(struct scsi_cmnd *cmd, u8 **buf_out) struct scatterlist *sg; sg = (struct scatterlist *) cmd->request_buffer; - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buf = kmap_atomic(sg->page, KM_USER0) + sg->offset; buflen = sg->length; } else { buf = cmd->request_buffer; @@ -1567,7 +1567,7 @@ static inline void ata_scsi_rbuf_put(struct scsi_cmnd *cmd, u8 *buf) struct scatterlist *sg; sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(buf - sg->offset, KM_IRQ0); + kunmap_atomic(buf - sg->offset, KM_USER0); } } diff --git a/trunk/drivers/ata/pata_legacy.c b/trunk/drivers/ata/pata_legacy.c index e7bf9d89c8ee..c7d1738e4e69 100644 --- a/trunk/drivers/ata/pata_legacy.c +++ b/trunk/drivers/ata/pata_legacy.c @@ -698,10 +698,8 @@ static __init int legacy_init_one(int port, unsigned long io, unsigned long ctrl goto fail_io; pdev = platform_device_register_simple(DRV_NAME, nr_legacy_host, NULL, 0); - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); + if (pdev == NULL) goto fail_dev; - } if (ht6560a & mask) { ops = &ht6560a_port_ops; diff --git a/trunk/drivers/ata/pata_qdi.c b/trunk/drivers/ata/pata_qdi.c index afc0d990e7d6..36f621abc390 100644 --- a/trunk/drivers/ata/pata_qdi.c +++ b/trunk/drivers/ata/pata_qdi.c @@ -247,8 +247,8 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i */ pdev = platform_device_register_simple(DRV_NAME, nr_qdi_host, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); + if (pdev == NULL) + return -ENOMEM; memset(&ae, 0, sizeof(struct ata_probe_ent)); INIT_LIST_HEAD(&ae.node); diff --git a/trunk/drivers/ata/pata_rz1000.c b/trunk/drivers/ata/pata_rz1000.c index adf4cc134f25..3677c642c9f9 100644 --- a/trunk/drivers/ata/pata_rz1000.c +++ b/trunk/drivers/ata/pata_rz1000.c @@ -105,6 +105,8 @@ static struct ata_port_operations rz1000_port_ops = { .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, + .error_handler = rz1000_error_handler, + .bmdma_setup = ata_bmdma_setup, .bmdma_start = ata_bmdma_start, .bmdma_stop = ata_bmdma_stop, diff --git a/trunk/drivers/ata/pata_via.c b/trunk/drivers/ata/pata_via.c index ff93e8f71cf8..cc09d47fb927 100644 --- a/trunk/drivers/ata/pata_via.c +++ b/trunk/drivers/ata/pata_via.c @@ -161,15 +161,10 @@ static int via_pre_reset(struct ata_port *ap) return -ENOENT; } - if ((config->flags & VIA_UDMA) >= VIA_UDMA_100) + if ((config->flags & VIA_UDMA) >= VIA_UDMA_66) ap->cbl = via_cable_detect(ap); - /* The UDMA66 series has no cable detect so do drive side detect */ - else if ((config->flags & VIA_UDMA) < VIA_UDMA_66) - ap->cbl = ATA_CBL_PATA40; else - ap->cbl = ATA_CBL_PATA_UNK; - - + ap->cbl = ATA_CBL_PATA40; return ata_std_prereset(ap); } diff --git a/trunk/drivers/ata/pata_winbond.c b/trunk/drivers/ata/pata_winbond.c index 5d1f518e1cc7..3ea345cde52e 100644 --- a/trunk/drivers/ata/pata_winbond.c +++ b/trunk/drivers/ata/pata_winbond.c @@ -206,8 +206,8 @@ static __init int winbond_init_one(unsigned long port) */ pdev = platform_device_register_simple(DRV_NAME, nr_winbond_host, NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); + if (pdev == NULL) + return -ENOMEM; memset(&ae, 0, sizeof(struct ata_probe_ent)); INIT_LIST_HEAD(&ae.node); diff --git a/trunk/drivers/ata/sata_svw.c b/trunk/drivers/ata/sata_svw.c index d89c9590b845..db32d15b7fa1 100644 --- a/trunk/drivers/ata/sata_svw.c +++ b/trunk/drivers/ata/sata_svw.c @@ -56,8 +56,6 @@ #define DRV_VERSION "2.0" enum { - K2_FLAG_NO_ATAPI_DMA = (1 << 29), - /* Taskfile registers offsets */ K2_SATA_TF_CMD_OFFSET = 0x00, K2_SATA_TF_DATA_OFFSET = 0x00, @@ -85,33 +83,11 @@ enum { /* Port stride */ K2_SATA_PORT_OFFSET = 0x100, - - board_svw4 = 0, - board_svw8 = 1, -}; - -static const struct k2_board_info { - unsigned int n_ports; - unsigned long port_flags; -} k2_board_info[] = { - /* board_svw4 */ - { 4, K2_FLAG_NO_ATAPI_DMA }, - - /* board_svw8 */ - { 8, K2_FLAG_NO_ATAPI_DMA }, }; static u8 k2_stat_check_status(struct ata_port *ap); -static int k2_sata_check_atapi_dma(struct ata_queued_cmd *qc) -{ - if (qc->ap->flags & K2_FLAG_NO_ATAPI_DMA) - return -1; /* ATAPI DMA not supported */ - - return 0; -} - static u32 k2_sata_scr_read (struct ata_port *ap, unsigned int sc_reg) { if (sc_reg > SCR_CONTROL) @@ -337,7 +313,6 @@ static const struct ata_port_operations k2_sata_ops = { .check_status = k2_stat_check_status, .exec_command = ata_exec_command, .dev_select = ata_std_dev_select, - .check_atapi_dma = k2_sata_check_atapi_dma, .bmdma_setup = k2_bmdma_setup_mmio, .bmdma_start = k2_bmdma_start_mmio, .bmdma_stop = ata_bmdma_stop, @@ -384,8 +359,6 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e struct ata_probe_ent *probe_ent = NULL; unsigned long base; void __iomem *mmio_base; - const struct k2_board_info *board_info = - &k2_board_info[ent->driver_data]; int pci_dev_busy = 0; int rc; int i; @@ -451,7 +424,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e probe_ent->sht = &k2_sata_sht; probe_ent->port_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | board_info->port_flags; + ATA_FLAG_MMIO; probe_ent->port_ops = &k2_sata_ops; probe_ent->n_ports = 4; probe_ent->irq = pdev->irq; @@ -468,7 +441,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e /* different controllers have different number of ports - currently 4 or 8 */ /* All ports are on the same function. Multi-function device is no * longer available. This should not be seen in any system. */ - for (i = 0; i < board_info->n_ports; i++) + for (i = 0; i < ent->driver_data; i++) k2_sata_setup_port(&probe_ent->port[i], base + i * K2_SATA_PORT_OFFSET); pci_set_master(pdev); @@ -496,11 +469,11 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e * controller * */ static const struct pci_device_id k2_sata_pci_tbl[] = { - { PCI_VDEVICE(SERVERWORKS, 0x0240), board_svw4 }, - { PCI_VDEVICE(SERVERWORKS, 0x0241), board_svw4 }, - { PCI_VDEVICE(SERVERWORKS, 0x0242), board_svw8 }, - { PCI_VDEVICE(SERVERWORKS, 0x024a), board_svw4 }, - { PCI_VDEVICE(SERVERWORKS, 0x024b), board_svw4 }, + { PCI_VDEVICE(SERVERWORKS, 0x0240), 4 }, + { PCI_VDEVICE(SERVERWORKS, 0x0241), 4 }, + { PCI_VDEVICE(SERVERWORKS, 0x0242), 8 }, + { PCI_VDEVICE(SERVERWORKS, 0x024a), 4 }, + { PCI_VDEVICE(SERVERWORKS, 0x024b), 4 }, { } }; diff --git a/trunk/drivers/connector/cn_queue.c b/trunk/drivers/connector/cn_queue.c index 296f51002b55..b418b16e910e 100644 --- a/trunk/drivers/connector/cn_queue.c +++ b/trunk/drivers/connector/cn_queue.c @@ -34,7 +34,7 @@ void cn_queue_wrapper(struct work_struct *work) { struct cn_callback_entry *cbq = - container_of(work, struct cn_callback_entry, work); + container_of(work, struct cn_callback_entry, work.work); struct cn_callback_data *d = &cbq->data; d->callback(d->callback_priv); @@ -59,12 +59,13 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struc memcpy(&cbq->id.id, id, sizeof(struct cb_id)); cbq->data.callback = callback; - INIT_WORK(&cbq->work, &cn_queue_wrapper); + INIT_DELAYED_WORK(&cbq->work, &cn_queue_wrapper); return cbq; } static void cn_queue_free_callback(struct cn_callback_entry *cbq) { + cancel_delayed_work(&cbq->work); flush_workqueue(cbq->pdev->cn_queue); kfree(cbq); diff --git a/trunk/drivers/connector/connector.c b/trunk/drivers/connector/connector.c index a44db75bc25b..5e7cd45d10ee 100644 --- a/trunk/drivers/connector/connector.c +++ b/trunk/drivers/connector/connector.c @@ -135,15 +135,17 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { if (cn_cb_equal(&__cbq->id.id, &msg->id)) { - if (likely(!work_pending(&__cbq->work) && + if (likely(!test_bit(WORK_STRUCT_PENDING, + &__cbq->work.work.management) && __cbq->data.ddata == NULL)) { __cbq->data.callback_priv = msg; __cbq->data.ddata = data; __cbq->data.destruct_data = destruct_data; - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; } else { struct cn_callback_data *d; @@ -157,11 +159,12 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v d->destruct_data = destruct_data; d->free = __cbq; - INIT_WORK(&__cbq->work, - &cn_queue_wrapper); + INIT_DELAYED_WORK(&__cbq->work, + &cn_queue_wrapper); - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) + if (queue_delayed_work( + dev->cbdev->cn_queue, + &__cbq->work, 0)) err = 0; else { kfree(__cbq); diff --git a/trunk/drivers/cpufreq/cpufreq.c b/trunk/drivers/cpufreq/cpufreq.c index d91330432ba2..9fb2edf36611 100644 --- a/trunk/drivers/cpufreq/cpufreq.c +++ b/trunk/drivers/cpufreq/cpufreq.c @@ -959,7 +959,7 @@ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, /** - * cpufreq_quick_get - get the CPU frequency (in kHz) from policy->cur + * cpufreq_quick_get - get the CPU frequency (in kHz) frpm policy->cur * @cpu: CPU number * * This is the last known freq, without actually getting it from the driver. diff --git a/trunk/drivers/infiniband/hw/mthca/mthca_main.c b/trunk/drivers/infiniband/hw/mthca/mthca_main.c index 44bc6cc734ab..0491ec7a7c0a 100644 --- a/trunk/drivers/infiniband/hw/mthca/mthca_main.c +++ b/trunk/drivers/infiniband/hw/mthca/mthca_main.c @@ -80,61 +80,24 @@ static int tune_pci = 0; module_param(tune_pci, int, 0444); MODULE_PARM_DESC(tune_pci, "increase PCI burst from the default set by BIOS if nonzero"); -DEFINE_MUTEX(mthca_device_mutex); - -#define MTHCA_DEFAULT_NUM_QP (1 << 16) -#define MTHCA_DEFAULT_RDB_PER_QP (1 << 2) -#define MTHCA_DEFAULT_NUM_CQ (1 << 16) -#define MTHCA_DEFAULT_NUM_MCG (1 << 13) -#define MTHCA_DEFAULT_NUM_MPT (1 << 17) -#define MTHCA_DEFAULT_NUM_MTT (1 << 20) -#define MTHCA_DEFAULT_NUM_UDAV (1 << 15) -#define MTHCA_DEFAULT_NUM_RESERVED_MTTS (1 << 18) -#define MTHCA_DEFAULT_NUM_UARC_SIZE (1 << 18) - -static struct mthca_profile hca_profile = { - .num_qp = MTHCA_DEFAULT_NUM_QP, - .rdb_per_qp = MTHCA_DEFAULT_RDB_PER_QP, - .num_cq = MTHCA_DEFAULT_NUM_CQ, - .num_mcg = MTHCA_DEFAULT_NUM_MCG, - .num_mpt = MTHCA_DEFAULT_NUM_MPT, - .num_mtt = MTHCA_DEFAULT_NUM_MTT, - .num_udav = MTHCA_DEFAULT_NUM_UDAV, /* Tavor only */ - .fmr_reserved_mtts = MTHCA_DEFAULT_NUM_RESERVED_MTTS, /* Tavor only */ - .uarc_size = MTHCA_DEFAULT_NUM_UARC_SIZE, /* Arbel only */ -}; - -module_param_named(num_qp, hca_profile.num_qp, int, 0444); -MODULE_PARM_DESC(num_qp, "maximum number of QPs per HCA"); - -module_param_named(rdb_per_qp, hca_profile.rdb_per_qp, int, 0444); -MODULE_PARM_DESC(rdb_per_qp, "number of RDB buffers per QP"); - -module_param_named(num_cq, hca_profile.num_cq, int, 0444); -MODULE_PARM_DESC(num_cq, "maximum number of CQs per HCA"); - -module_param_named(num_mcg, hca_profile.num_mcg, int, 0444); -MODULE_PARM_DESC(num_mcg, "maximum number of multicast groups per HCA"); - -module_param_named(num_mpt, hca_profile.num_mpt, int, 0444); -MODULE_PARM_DESC(num_mpt, - "maximum number of memory protection table entries per HCA"); - -module_param_named(num_mtt, hca_profile.num_mtt, int, 0444); -MODULE_PARM_DESC(num_mtt, - "maximum number of memory translation table segments per HCA"); - -module_param_named(num_udav, hca_profile.num_udav, int, 0444); -MODULE_PARM_DESC(num_udav, "maximum number of UD address vectors per HCA"); - -module_param_named(fmr_reserved_mtts, hca_profile.fmr_reserved_mtts, int, 0444); -MODULE_PARM_DESC(fmr_reserved_mtts, - "number of memory translation table segments reserved for FMR"); +struct mutex mthca_device_mutex; static const char mthca_version[] __devinitdata = DRV_NAME ": Mellanox InfiniBand HCA driver v" DRV_VERSION " (" DRV_RELDATE ")\n"; +static struct mthca_profile default_profile = { + .num_qp = 1 << 16, + .rdb_per_qp = 4, + .num_cq = 1 << 16, + .num_mcg = 1 << 13, + .num_mpt = 1 << 17, + .num_mtt = 1 << 20, + .num_udav = 1 << 15, /* Tavor only */ + .fmr_reserved_mtts = 1 << 18, /* Tavor only */ + .uarc_size = 1 << 18, /* Arbel only */ +}; + static int mthca_tune_pci(struct mthca_dev *mdev) { int cap; @@ -340,7 +303,7 @@ static int mthca_init_tavor(struct mthca_dev *mdev) goto err_disable; } - profile = hca_profile; + profile = default_profile; profile.num_uar = dev_lim.uar_size / PAGE_SIZE; profile.uarc_size = 0; if (mdev->mthca_flags & MTHCA_FLAG_SRQ) @@ -658,7 +621,7 @@ static int mthca_init_arbel(struct mthca_dev *mdev) goto err_stop_fw; } - profile = hca_profile; + profile = default_profile; profile.num_uar = dev_lim.uar_size / PAGE_SIZE; profile.num_udav = 0; if (mdev->mthca_flags & MTHCA_FLAG_SRQ) @@ -1315,55 +1278,11 @@ static struct pci_driver mthca_driver = { .remove = __devexit_p(mthca_remove_one) }; -static void __init __mthca_check_profile_val(const char *name, int *pval, - int pval_default) -{ - /* value must be positive and power of 2 */ - int old_pval = *pval; - - if (old_pval <= 0) - *pval = pval_default; - else - *pval = roundup_pow_of_two(old_pval); - - if (old_pval != *pval) { - printk(KERN_WARNING PFX "Invalid value %d for %s in module parameter.\n", - old_pval, name); - printk(KERN_WARNING PFX "Corrected %s to %d.\n", name, *pval); - } -} - -#define mthca_check_profile_val(name, default) \ - __mthca_check_profile_val(#name, &hca_profile.name, default) - -static void __init mthca_validate_profile(void) -{ - mthca_check_profile_val(num_qp, MTHCA_DEFAULT_NUM_QP); - mthca_check_profile_val(rdb_per_qp, MTHCA_DEFAULT_RDB_PER_QP); - mthca_check_profile_val(num_cq, MTHCA_DEFAULT_NUM_CQ); - mthca_check_profile_val(num_mcg, MTHCA_DEFAULT_NUM_MCG); - mthca_check_profile_val(num_mpt, MTHCA_DEFAULT_NUM_MPT); - mthca_check_profile_val(num_mtt, MTHCA_DEFAULT_NUM_MTT); - mthca_check_profile_val(num_udav, MTHCA_DEFAULT_NUM_UDAV); - mthca_check_profile_val(fmr_reserved_mtts, MTHCA_DEFAULT_NUM_RESERVED_MTTS); - - if (hca_profile.fmr_reserved_mtts >= hca_profile.num_mtt) { - printk(KERN_WARNING PFX "Invalid fmr_reserved_mtts module parameter %d.\n", - hca_profile.fmr_reserved_mtts); - printk(KERN_WARNING PFX "(Must be smaller than num_mtt %d)\n", - hca_profile.num_mtt); - hca_profile.fmr_reserved_mtts = hca_profile.num_mtt / 2; - printk(KERN_WARNING PFX "Corrected fmr_reserved_mtts to %d.\n", - hca_profile.fmr_reserved_mtts); - } -} - static int __init mthca_init(void) { int ret; - mthca_validate_profile(); - + mutex_init(&mthca_device_mutex); ret = mthca_catas_init(); if (ret) return ret; diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index cdecbf5911c8..e9b6a6f07dd7 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -1898,7 +1898,7 @@ static void srp_add_one(struct ib_device *device) */ srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1); srp_dev->fmr_page_size = 1 << srp_dev->fmr_page_shift; - srp_dev->fmr_page_mask = ~((u64) srp_dev->fmr_page_size - 1); + srp_dev->fmr_page_mask = ~((unsigned long) srp_dev->fmr_page_size - 1); INIT_LIST_HEAD(&srp_dev->dev_list); diff --git a/trunk/drivers/infiniband/ulp/srp/ib_srp.h b/trunk/drivers/infiniband/ulp/srp/ib_srp.h index c21772317b86..868a540ef7cd 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.h +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.h @@ -87,7 +87,7 @@ struct srp_device { struct ib_fmr_pool *fmr_pool; int fmr_page_shift; int fmr_page_size; - u64 fmr_page_mask; + unsigned long fmr_page_mask; }; struct srp_host { diff --git a/trunk/drivers/input/keyboard/amikbd.c b/trunk/drivers/input/keyboard/amikbd.c index c67e84ec2d6a..16583d71753b 100644 --- a/trunk/drivers/input/keyboard/amikbd.c +++ b/trunk/drivers/input/keyboard/amikbd.c @@ -187,7 +187,7 @@ static irqreturn_t amikbd_interrupt(int irq, void *dummy) static int __init amikbd_init(void) { - int i, j, err; + int i, j; if (!AMIGAHW_PRESENT(AMI_KEYBOARD)) return -ENODEV; diff --git a/trunk/drivers/input/keyboard/sunkbd.c b/trunk/drivers/input/keyboard/sunkbd.c index cc0238366414..3826db9403e6 100644 --- a/trunk/drivers/input/keyboard/sunkbd.c +++ b/trunk/drivers/input/keyboard/sunkbd.c @@ -225,7 +225,7 @@ static void sunkbd_reinit(struct work_struct *work) static void sunkbd_enable(struct sunkbd *sunkbd, int enable) { serio_pause_rx(sunkbd->serio); - sunkbd->enabled = enable; + sunkbd->enabled = 1; serio_continue_rx(sunkbd->serio); } diff --git a/trunk/drivers/net/bnx2.c b/trunk/drivers/net/bnx2.c index ada5e9b9988c..7d824cf8ee2d 100644 --- a/trunk/drivers/net/bnx2.c +++ b/trunk/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.5.2" -#define DRV_MODULE_RELDATE "December 13, 2006" +#define DRV_MODULE_VERSION "1.5.1" +#define DRV_MODULE_RELDATE "November 15, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -217,16 +217,9 @@ static inline u32 bnx2_tx_avail(struct bnx2 *bp) u32 diff; smp_mb(); - - /* The ring uses 256 indices for 255 entries, one of them - * needs to be skipped. - */ - diff = bp->tx_prod - bp->tx_cons; - if (unlikely(diff >= TX_DESC_CNT)) { - diff &= 0xffff; - if (diff == TX_DESC_CNT) - diff = MAX_TX_DESC_CNT; - } + diff = TX_RING_IDX(bp->tx_prod) - TX_RING_IDX(bp->tx_cons); + if (diff > MAX_TX_DESC_CNT) + diff = (diff & MAX_TX_DESC_CNT) - 1; return (bp->tx_ring_size - diff); } @@ -3096,7 +3089,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if ((align_start = (offset32 & 3))) { offset32 &= ~3; - len32 += (4 - align_start); + len32 += align_start; if ((rc = bnx2_nvram_read(bp, offset32, start, 4))) return rc; } @@ -3114,7 +3107,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, if (align_start || align_end) { buf = kmalloc(len32, GFP_KERNEL); - if (buf == NULL) + if (buf == 0) return -ENOMEM; if (align_start) { memcpy(buf, start, 4); @@ -4005,7 +3998,7 @@ bnx2_run_loopback(struct bnx2 *bp, int loopback_mode) if (!skb) return -ENOMEM; packet = skb_put(skb, pkt_size); - memcpy(packet, bp->dev->dev_addr, 6); + memcpy(packet, bp->mac_addr, 6); memset(packet + 6, 0x0, 8); for (i = 14; i < pkt_size; i++) packet[i] = (unsigned char) (i & 0xff); diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index 4056ba1ff3c7..571320ae87ab 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -68,8 +68,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.71" -#define DRV_MODULE_RELDATE "December 15, 2006" +#define DRV_MODULE_VERSION "3.70" +#define DRV_MODULE_RELDATE "December 1, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -959,13 +959,6 @@ static int tg3_phy_reset(struct tg3 *tp) u32 phy_status; int err; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 val; - - val = tr32(GRC_MISC_CFG); - tw32_f(GRC_MISC_CFG, val & ~GRC_MISC_CFG_EPHY_IDDQ); - udelay(40); - } err = tg3_readphy(tp, MII_BMSR, &phy_status); err |= tg3_readphy(tp, MII_BMSR, &phy_status); if (err != 0) @@ -1177,15 +1170,7 @@ static void tg3_power_down_phy(struct tg3 *tp) if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) return; - if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906) { - u32 val; - - tg3_bmcr_reset(tp); - val = tr32(GRC_MISC_CFG); - tw32_f(GRC_MISC_CFG, val | GRC_MISC_CFG_EPHY_IDDQ); - udelay(40); - return; - } else { + if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5906) { tg3_writephy(tp, MII_TG3_EXT_CTRL, MII_TG3_EXT_CTRL_FORCE_LED_OFF); tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x01b2); @@ -4441,7 +4426,7 @@ static void tg3_free_consistent(struct tg3 *tp) */ static int tg3_alloc_consistent(struct tg3 *tp) { - tp->rx_std_buffers = kzalloc((sizeof(struct ring_info) * + tp->rx_std_buffers = kmalloc((sizeof(struct ring_info) * (TG3_RX_RING_SIZE + TG3_RX_JUMBO_RING_SIZE)) + (sizeof(struct tx_ring_info) * @@ -4450,6 +4435,13 @@ static int tg3_alloc_consistent(struct tg3 *tp) if (!tp->rx_std_buffers) return -ENOMEM; + memset(tp->rx_std_buffers, 0, + (sizeof(struct ring_info) * + (TG3_RX_RING_SIZE + + TG3_RX_JUMBO_RING_SIZE)) + + (sizeof(struct tx_ring_info) * + TG3_TX_RING_SIZE)); + tp->rx_jumbo_buffers = &tp->rx_std_buffers[TG3_RX_RING_SIZE]; tp->tx_buffers = (struct tx_ring_info *) &tp->rx_jumbo_buffers[TG3_RX_JUMBO_RING_SIZE]; @@ -6996,8 +6988,6 @@ static int tg3_open(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); int err; - netif_carrier_off(tp->dev); - tg3_full_lock(tp, 0); err = tg3_set_power_state(tp, PCI_D0); @@ -7991,10 +7981,6 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) tp->link_config.duplex = cmd->duplex; } - tp->link_config.orig_speed = tp->link_config.speed; - tp->link_config.orig_duplex = tp->link_config.duplex; - tp->link_config.orig_autoneg = tp->link_config.autoneg; - if (netif_running(dev)) tg3_setup_phy(tp, 1); @@ -11937,8 +11923,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, */ pci_save_state(tp->pdev); - pci_set_drvdata(pdev, dev); - err = register_netdev(dev); if (err) { printk(KERN_ERR PFX "Cannot register net device, " @@ -11946,6 +11930,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, goto err_out_iounmap; } + pci_set_drvdata(pdev, dev); + printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %s Ethernet ", dev->name, tp->board_part_number, @@ -11976,6 +11962,8 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, (pdev->dma_mask == DMA_32BIT_MASK) ? 32 : (((u64) pdev->dma_mask == DMA_40BIT_MASK) ? 40 : 64)); + netif_carrier_off(tp->dev); + return 0; err_out_iounmap: diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index cf78a7e5997b..dfaf4ed127bd 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -1350,7 +1350,6 @@ #define GRC_MISC_CFG_BOARD_ID_5788 0x00010000 #define GRC_MISC_CFG_BOARD_ID_5788M 0x00018000 #define GRC_MISC_CFG_BOARD_ID_AC91002A1 0x00018000 -#define GRC_MISC_CFG_EPHY_IDDQ 0x00200000 #define GRC_MISC_CFG_KEEP_GPHY_POWER 0x04000000 #define GRC_LOCAL_CTRL 0x00006808 #define GRC_LCLCTRL_INT_ACTIVE 0x00000001 diff --git a/trunk/drivers/s390/char/sclp_cpi.c b/trunk/drivers/s390/char/sclp_cpi.c index 4f873ae148b7..f7c10d954ec6 100644 --- a/trunk/drivers/s390/char/sclp_cpi.c +++ b/trunk/drivers/s390/char/sclp_cpi.c @@ -49,8 +49,6 @@ static struct sclp_register sclp_cpi_event = .send_mask = EvTyp_CtlProgIdent_Mask }; -MODULE_LICENSE("GPL"); - MODULE_AUTHOR( "Martin Peschke, IBM Deutschland Entwicklung GmbH " ""); diff --git a/trunk/drivers/s390/cio/cio.c b/trunk/drivers/s390/cio/cio.c index 3a403f195cf8..7835a714a405 100644 --- a/trunk/drivers/s390/cio/cio.c +++ b/trunk/drivers/s390/cio/cio.c @@ -871,32 +871,11 @@ __clear_subchannel_easy(struct subchannel_id schid) return -EBUSY; } -static int pgm_check_occured; - -static void cio_reset_pgm_check_handler(void) -{ - pgm_check_occured = 1; -} - -static int stsch_reset(struct subchannel_id schid, volatile struct schib *addr) -{ - int rc; - - pgm_check_occured = 0; - s390_reset_pgm_handler = cio_reset_pgm_check_handler; - rc = stsch(schid, addr); - s390_reset_pgm_handler = NULL; - if (pgm_check_occured) - return -EIO; - else - return rc; -} - static int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) { struct schib schib; - if (stsch_reset(schid, &schib)) + if (stsch_err(schid, &schib)) return -ENXIO; if (!schib.pmcw.ena) return 0; @@ -993,7 +972,7 @@ static int __reipl_subchannel_match(struct subchannel_id schid, void *data) struct schib schib; struct sch_match_id *match_id = data; - if (stsch_reset(schid, &schib)) + if (stsch_err(schid, &schib)) return -ENXIO; if (schib.pmcw.dnv && (schib.pmcw.dev == match_id->devid.devno) && diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 9d6c02446863..4c81d890791e 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -139,8 +139,6 @@ css_register_subchannel(struct subchannel *sch) sch->dev.release = &css_subchannel_release; sch->dev.groups = subch_attr_groups; - css_get_ssd_info(sch); - /* make it known to the system */ ret = css_sch_device_register(sch); if (ret) { @@ -148,6 +146,7 @@ css_register_subchannel(struct subchannel *sch) __func__, sch->dev.bus_id); return ret; } + css_get_ssd_info(sch); return ret; } diff --git a/trunk/drivers/s390/cio/qdio.c b/trunk/drivers/s390/cio/qdio.c index 6fd1940842eb..9d4ea449a608 100644 --- a/trunk/drivers/s390/cio/qdio.c +++ b/trunk/drivers/s390/cio/qdio.c @@ -979,11 +979,12 @@ __qdio_outbound_processing(struct qdio_q *q) if (q->is_iqdio_q) { /* - * for asynchronous queues, we better check, if the sent - * buffer is already switched from PRIMED to EMPTY. + * for asynchronous queues, we better check, if the fill + * level is too high. for synchronous queues, the fill + * level will never be that high. */ - if ((q->queue_type == QDIO_IQDIO_QFMT_ASYNCH) && - !qdio_is_outbound_q_done(q)) + if (atomic_read(&q->number_of_buffers_used)> + IQDIO_FILL_LEVEL_TO_POLL) qdio_mark_q(q); } else if (!q->hydra_gives_outbound_pcis) @@ -1824,10 +1825,6 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, q->sbal[j]=*(outbound_sbals_array++); q->queue_type=q_format; - if ((q->queue_type == QDIO_IQDIO_QFMT) && - (no_output_qs > 1) && - (i == no_output_qs-1)) - q->queue_type = QDIO_IQDIO_QFMT_ASYNCH; q->int_parm=int_parm; q->is_input_q=0; q->schid = irq_ptr->schid; diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index 81b5899f4010..ad60afe5dd11 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -1129,15 +1129,7 @@ static void ap_poll_thread_stop(void) mutex_unlock(&ap_poll_thread_mutex); } -static void ap_reset_domain(void) -{ - int i; - - for (i = 0; i < AP_DEVICES; i++) - ap_reset_queue(AP_MKQID(i, ap_domain_index)); -} - -static void ap_reset_all(void) +static void ap_reset(void) { int i, j; @@ -1147,7 +1139,7 @@ static void ap_reset_all(void) } static struct reset_call ap_reset_call = { - .fn = ap_reset_all, + .fn = ap_reset, }; /** @@ -1237,12 +1229,10 @@ void ap_module_exit(void) int i; struct device *dev; - ap_reset_domain(); ap_poll_thread_stop(); del_timer_sync(&ap_config_timer); del_timer_sync(&ap_poll_timer); destroy_workqueue(ap_work_queue); - tasklet_kill(&ap_tasklet); s390_root_dev_unregister(ap_root_device); while ((dev = bus_find_device(&ap_bus_type, NULL, NULL, __ap_match_all))) diff --git a/trunk/drivers/scsi/sun3_NCR5380.c b/trunk/drivers/scsi/sun3_NCR5380.c index 98e3fe10c1dc..43f5b6aa7dc4 100644 --- a/trunk/drivers/scsi/sun3_NCR5380.c +++ b/trunk/drivers/scsi/sun3_NCR5380.c @@ -266,7 +266,7 @@ static struct scsi_host_template *the_template = NULL; (struct NCR5380_hostdata *)(in)->hostdata #define HOSTDATA(in) ((struct NCR5380_hostdata *)(in)->hostdata) -#define NEXT(cmd) (*(struct scsi_cmnd **)&((cmd)->host_scribble)) +#define NEXT(cmd) ((struct scsi_cmnd *)((cmd)->host_scribble)) #define NEXTADDR(cmd) ((struct scsi_cmnd **)&((cmd)->host_scribble)) #define HOSTNO instance->host_no @@ -650,7 +650,7 @@ __inline__ void NCR5380_print_phase(struct Scsi_Host *instance) { }; #include static volatile int main_running = 0; -static DECLARE_WORK(NCR5380_tqueue, NCR5380_main); +static DECLARE_WORK(NCR5380_tqueue, (void (*)(void*))NCR5380_main, NULL); static __inline__ void queue_main(void) { @@ -1031,7 +1031,7 @@ static int NCR5380_queue_command(struct scsi_cmnd *cmd, * reenable them. This prevents reentrancy and kernel stack overflow. */ -static void NCR5380_main (struct work_struct *bl) +static void NCR5380_main (void *bl) { struct scsi_cmnd *tmp, *prev; struct Scsi_Host *instance = first_instance; diff --git a/trunk/drivers/usb/input/Kconfig b/trunk/drivers/usb/input/Kconfig index 8a62d4785755..e308f6dc2b87 100644 --- a/trunk/drivers/usb/input/Kconfig +++ b/trunk/drivers/usb/input/Kconfig @@ -7,7 +7,8 @@ comment "USB Input Devices" config USB_HID tristate "USB Human Interface Device (full HID) support" default y - depends on USB && HID + depends on USB + select HID ---help--- Say Y here if you want full HID support to connect USB keyboards, mice, joysticks, graphic tablets, or any other HID based devices diff --git a/trunk/include/asm-generic/vmlinux.lds.h b/trunk/include/asm-generic/vmlinux.lds.h index 1587121730c5..7437ccaada77 100644 --- a/trunk/include/asm-generic/vmlinux.lds.h +++ b/trunk/include/asm-generic/vmlinux.lds.h @@ -119,6 +119,8 @@ *(__ksymtab_strings) \ } \ \ + EH_FRAME \ + \ /* Built-in module parameters. */ \ __param : AT(ADDR(__param) - LOAD_OFFSET) { \ VMLINUX_SYMBOL(__start___param) = .; \ @@ -158,6 +160,26 @@ *(.kprobes.text) \ VMLINUX_SYMBOL(__kprobes_text_end) = .; +#ifdef CONFIG_STACK_UNWIND +#define EH_FRAME \ + /* Unwind data binary search table */ \ + . = ALIGN(8); \ + .eh_frame_hdr : AT(ADDR(.eh_frame_hdr) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_unwind_hdr) = .; \ + *(.eh_frame_hdr) \ + VMLINUX_SYMBOL(__end_unwind_hdr) = .; \ + } \ + /* Unwind data */ \ + . = ALIGN(8); \ + .eh_frame : AT(ADDR(.eh_frame) - LOAD_OFFSET) { \ + VMLINUX_SYMBOL(__start_unwind) = .; \ + *(.eh_frame) \ + VMLINUX_SYMBOL(__end_unwind) = .; \ + } +#else +#define EH_FRAME +#endif + /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ diff --git a/trunk/include/asm-i386/unwind.h b/trunk/include/asm-i386/unwind.h index 43c70c3de2f9..aa2c931e30db 100644 --- a/trunk/include/asm-i386/unwind.h +++ b/trunk/include/asm-i386/unwind.h @@ -1,6 +1,95 @@ #ifndef _ASM_I386_UNWIND_H #define _ASM_I386_UNWIND_H +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich + * This code is released under version 2 of the GNU GPL. + */ + +#ifdef CONFIG_STACK_UNWIND + +#include +#include +#include +#include + +struct unwind_frame_info +{ + struct pt_regs regs; + struct task_struct *task; + unsigned call_frame:1; +}; + +#define UNW_PC(frame) (frame)->regs.eip +#define UNW_SP(frame) (frame)->regs.esp +#ifdef CONFIG_FRAME_POINTER +#define UNW_FP(frame) (frame)->regs.ebp +#define FRAME_RETADDR_OFFSET 4 +#define FRAME_LINK_OFFSET 0 +#define STACK_BOTTOM(tsk) STACK_LIMIT((tsk)->thread.esp0) +#define STACK_TOP(tsk) ((tsk)->thread.esp0) +#else +#define UNW_FP(frame) ((void)(frame), 0) +#endif +#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) + +#define UNW_REGISTER_INFO \ + PTREGS_INFO(eax), \ + PTREGS_INFO(ecx), \ + PTREGS_INFO(edx), \ + PTREGS_INFO(ebx), \ + PTREGS_INFO(esp), \ + PTREGS_INFO(ebp), \ + PTREGS_INFO(esi), \ + PTREGS_INFO(edi), \ + PTREGS_INFO(eip) + +#define UNW_DEFAULT_RA(raItem, dataAlign) \ + ((raItem).where == Memory && \ + !((raItem).value * (dataAlign) + 4)) + +static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, + /*const*/ struct pt_regs *regs) +{ + if (user_mode_vm(regs)) + info->regs = *regs; + else { + memcpy(&info->regs, regs, offsetof(struct pt_regs, esp)); + info->regs.esp = (unsigned long)®s->esp; + info->regs.xss = __KERNEL_DS; + } +} + +static inline void arch_unw_init_blocked(struct unwind_frame_info *info) +{ + memset(&info->regs, 0, sizeof(info->regs)); + info->regs.eip = info->task->thread.eip; + info->regs.xcs = __KERNEL_CS; + __get_user(info->regs.ebp, (long *)info->task->thread.esp); + info->regs.esp = info->task->thread.esp; + info->regs.xss = __KERNEL_DS; + info->regs.xds = __USER_DS; + info->regs.xes = __USER_DS; + info->regs.xgs = __KERNEL_PDA; +} + +extern asmlinkage int arch_unwind_init_running(struct unwind_frame_info *, + asmlinkage int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg); + +static inline int arch_unw_user_mode(/*const*/ struct unwind_frame_info *info) +{ + return user_mode_vm(&info->regs) + || info->regs.eip < PAGE_OFFSET + || (info->regs.eip >= __fix_to_virt(FIX_VDSO) + && info->regs.eip < __fix_to_virt(FIX_VDSO) + PAGE_SIZE) + || info->regs.esp < PAGE_OFFSET; +} + +#else + #define UNW_PC(frame) ((void)(frame), 0) #define UNW_SP(frame) ((void)(frame), 0) #define UNW_FP(frame) ((void)(frame), 0) @@ -10,4 +99,6 @@ static inline int arch_unw_user_mode(const void *info) return 0; } +#endif + #endif /* _ASM_I386_UNWIND_H */ diff --git a/trunk/include/asm-s390/qdio.h b/trunk/include/asm-s390/qdio.h index 127f72e77419..7189c79bc673 100644 --- a/trunk/include/asm-s390/qdio.h +++ b/trunk/include/asm-s390/qdio.h @@ -34,7 +34,6 @@ #define QDIO_QETH_QFMT 0 #define QDIO_ZFCP_QFMT 1 #define QDIO_IQDIO_QFMT 2 -#define QDIO_IQDIO_QFMT_ASYNCH 3 struct qdio_buffer_element{ unsigned int flags; diff --git a/trunk/include/asm-s390/reset.h b/trunk/include/asm-s390/reset.h index 532e65a2aafc..9b439cf67800 100644 --- a/trunk/include/asm-s390/reset.h +++ b/trunk/include/asm-s390/reset.h @@ -19,6 +19,5 @@ extern void register_reset_call(struct reset_call *reset); extern void unregister_reset_call(struct reset_call *reset); extern void s390_reset_system(void); extern void (*s390_reset_mcck_handler)(void); -extern void (*s390_reset_pgm_handler)(void); #endif /* _ASM_S390_RESET_H */ diff --git a/trunk/include/asm-sparc/bitops.h b/trunk/include/asm-sparc/bitops.h index 329e696e7751..04aa3318f76a 100644 --- a/trunk/include/asm-sparc/bitops.h +++ b/trunk/include/asm-sparc/bitops.h @@ -14,10 +14,6 @@ #ifdef __KERNEL__ -extern unsigned long ___set_bit(unsigned long *addr, unsigned long mask); -extern unsigned long ___clear_bit(unsigned long *addr, unsigned long mask); -extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask); - /* * Set bit 'nr' in 32-bit quantity at address 'addr' where bit '0' * is in the highest of the four bytes and bit '31' is the high bit @@ -26,62 +22,134 @@ extern unsigned long ___change_bit(unsigned long *addr, unsigned long mask); */ static inline int test_and_set_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long *ADDR, mask; + register unsigned long mask asm("g2"); + register unsigned long *ADDR asm("g1"); + register int tmp1 asm("g3"); + register int tmp2 asm("g4"); + register int tmp3 asm("g5"); + register int tmp4 asm("g7"); ADDR = ((unsigned long *) addr) + (nr >> 5); mask = 1 << (nr & 31); - return ___set_bit(ADDR, mask) != 0; + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___set_bit\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) + : "0" (mask), "r" (ADDR) + : "memory", "cc"); + + return mask != 0; } static inline void set_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long *ADDR, mask; + register unsigned long mask asm("g2"); + register unsigned long *ADDR asm("g1"); + register int tmp1 asm("g3"); + register int tmp2 asm("g4"); + register int tmp3 asm("g5"); + register int tmp4 asm("g7"); ADDR = ((unsigned long *) addr) + (nr >> 5); mask = 1 << (nr & 31); - (void) ___set_bit(ADDR, mask); + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___set_bit\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) + : "0" (mask), "r" (ADDR) + : "memory", "cc"); } static inline int test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long *ADDR, mask; + register unsigned long mask asm("g2"); + register unsigned long *ADDR asm("g1"); + register int tmp1 asm("g3"); + register int tmp2 asm("g4"); + register int tmp3 asm("g5"); + register int tmp4 asm("g7"); ADDR = ((unsigned long *) addr) + (nr >> 5); mask = 1 << (nr & 31); - return ___clear_bit(ADDR, mask) != 0; + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___clear_bit\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) + : "0" (mask), "r" (ADDR) + : "memory", "cc"); + + return mask != 0; } static inline void clear_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long *ADDR, mask; + register unsigned long mask asm("g2"); + register unsigned long *ADDR asm("g1"); + register int tmp1 asm("g3"); + register int tmp2 asm("g4"); + register int tmp3 asm("g5"); + register int tmp4 asm("g7"); ADDR = ((unsigned long *) addr) + (nr >> 5); mask = 1 << (nr & 31); - (void) ___clear_bit(ADDR, mask); + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___clear_bit\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) + : "0" (mask), "r" (ADDR) + : "memory", "cc"); } static inline int test_and_change_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long *ADDR, mask; + register unsigned long mask asm("g2"); + register unsigned long *ADDR asm("g1"); + register int tmp1 asm("g3"); + register int tmp2 asm("g4"); + register int tmp3 asm("g5"); + register int tmp4 asm("g7"); ADDR = ((unsigned long *) addr) + (nr >> 5); mask = 1 << (nr & 31); - return ___change_bit(ADDR, mask) != 0; + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___change_bit\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) + : "0" (mask), "r" (ADDR) + : "memory", "cc"); + + return mask != 0; } static inline void change_bit(unsigned long nr, volatile unsigned long *addr) { - unsigned long *ADDR, mask; + register unsigned long mask asm("g2"); + register unsigned long *ADDR asm("g1"); + register int tmp1 asm("g3"); + register int tmp2 asm("g4"); + register int tmp3 asm("g5"); + register int tmp4 asm("g7"); ADDR = ((unsigned long *) addr) + (nr >> 5); mask = 1 << (nr & 31); - (void) ___change_bit(ADDR, mask); + __asm__ __volatile__( + "mov %%o7, %%g4\n\t" + "call ___change_bit\n\t" + " add %%o7, 8, %%o7\n" + : "=&r" (mask), "=r" (tmp1), "=r" (tmp2), "=r" (tmp3), "=r" (tmp4) + : "0" (mask), "r" (ADDR) + : "memory", "cc"); } #include diff --git a/trunk/include/asm-sparc64/hw_irq.h b/trunk/include/asm-sparc64/hw_irq.h index 8e44a8360829..599b3b073450 100644 --- a/trunk/include/asm-sparc64/hw_irq.h +++ b/trunk/include/asm-sparc64/hw_irq.h @@ -1,4 +1,6 @@ #ifndef __ASM_SPARC64_HW_IRQ_H #define __ASM_SPARC64_HW_IRQ_H +extern void hw_resend_irq(struct hw_interrupt_type *handler, unsigned int virt_irq); + #endif diff --git a/trunk/include/asm-sparc64/percpu.h b/trunk/include/asm-sparc64/percpu.h index 0d3df76aa47f..ced8cbde046d 100644 --- a/trunk/include/asm-sparc64/percpu.h +++ b/trunk/include/asm-sparc64/percpu.h @@ -5,16 +5,6 @@ #ifdef CONFIG_SMP -#ifdef CONFIG_MODULES -# define PERCPU_MODULE_RESERVE 8192 -#else -# define PERCPU_MODULE_RESERVE 0 -#endif - -#define PERCPU_ENOUGH_ROOM \ - (ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES) + \ - PERCPU_MODULE_RESERVE) - extern void setup_per_cpu_areas(void); extern unsigned long __per_cpu_base; diff --git a/trunk/include/asm-x86_64/unwind.h b/trunk/include/asm-x86_64/unwind.h index 02710f6a4560..2f6349e48717 100644 --- a/trunk/include/asm-x86_64/unwind.h +++ b/trunk/include/asm-x86_64/unwind.h @@ -1,6 +1,100 @@ #ifndef _ASM_X86_64_UNWIND_H #define _ASM_X86_64_UNWIND_H +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich + * This code is released under version 2 of the GNU GPL. + */ + +#ifdef CONFIG_STACK_UNWIND + +#include +#include +#include +#include + +struct unwind_frame_info +{ + struct pt_regs regs; + struct task_struct *task; + unsigned call_frame:1; +}; + +#define UNW_PC(frame) (frame)->regs.rip +#define UNW_SP(frame) (frame)->regs.rsp +#ifdef CONFIG_FRAME_POINTER +#define UNW_FP(frame) (frame)->regs.rbp +#define FRAME_RETADDR_OFFSET 8 +#define FRAME_LINK_OFFSET 0 +#define STACK_BOTTOM(tsk) (((tsk)->thread.rsp0 - 1) & ~(THREAD_SIZE - 1)) +#define STACK_TOP(tsk) ((tsk)->thread.rsp0) +#endif +/* Might need to account for the special exception and interrupt handling + stacks here, since normally + EXCEPTION_STACK_ORDER < THREAD_ORDER < IRQSTACK_ORDER, + but the construct is needed only for getting across the stack switch to + the interrupt stack - thus considering the IRQ stack itself is unnecessary, + and the overhead of comparing against all exception handling stacks seems + not desirable. */ +#define STACK_LIMIT(ptr) (((ptr) - 1) & ~(THREAD_SIZE - 1)) + +#define UNW_REGISTER_INFO \ + PTREGS_INFO(rax), \ + PTREGS_INFO(rdx), \ + PTREGS_INFO(rcx), \ + PTREGS_INFO(rbx), \ + PTREGS_INFO(rsi), \ + PTREGS_INFO(rdi), \ + PTREGS_INFO(rbp), \ + PTREGS_INFO(rsp), \ + PTREGS_INFO(r8), \ + PTREGS_INFO(r9), \ + PTREGS_INFO(r10), \ + PTREGS_INFO(r11), \ + PTREGS_INFO(r12), \ + PTREGS_INFO(r13), \ + PTREGS_INFO(r14), \ + PTREGS_INFO(r15), \ + PTREGS_INFO(rip) + +#define UNW_DEFAULT_RA(raItem, dataAlign) \ + ((raItem).where == Memory && \ + !((raItem).value * (dataAlign) + 8)) + +static inline void arch_unw_init_frame_info(struct unwind_frame_info *info, + /*const*/ struct pt_regs *regs) +{ + info->regs = *regs; +} + +static inline void arch_unw_init_blocked(struct unwind_frame_info *info) +{ + extern const char thread_return[]; + + memset(&info->regs, 0, sizeof(info->regs)); + info->regs.rip = (unsigned long)thread_return; + info->regs.cs = __KERNEL_CS; + __get_user(info->regs.rbp, (unsigned long *)info->task->thread.rsp); + info->regs.rsp = info->task->thread.rsp; + info->regs.ss = __KERNEL_DS; +} + +extern int arch_unwind_init_running(struct unwind_frame_info *, + int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg); + +static inline int arch_unw_user_mode(const struct unwind_frame_info *info) +{ + return user_mode(&info->regs) + || (long)info->regs.rip >= 0 + || (info->regs.rip >= VSYSCALL_START && info->regs.rip < VSYSCALL_END) + || (long)info->regs.rsp >= 0; +} + +#else + #define UNW_PC(frame) ((void)(frame), 0UL) #define UNW_SP(frame) ((void)(frame), 0UL) @@ -9,4 +103,6 @@ static inline int arch_unw_user_mode(const void *info) return 0; } +#endif + #endif /* _ASM_X86_64_UNWIND_H */ diff --git a/trunk/include/linux/connector.h b/trunk/include/linux/connector.h index 10eb56b2940a..3ea1cd58de97 100644 --- a/trunk/include/linux/connector.h +++ b/trunk/include/linux/connector.h @@ -133,7 +133,7 @@ struct cn_callback_data { struct cn_callback_entry { struct list_head callback_entry; struct cn_callback *cb; - struct work_struct work; + struct delayed_work work; struct cn_queue_dev *pdev; struct cn_callback_id id; diff --git a/trunk/include/linux/unwind.h b/trunk/include/linux/unwind.h index 7760860fa170..749928c161fb 100644 --- a/trunk/include/linux/unwind.h +++ b/trunk/include/linux/unwind.h @@ -14,6 +14,63 @@ struct module; +#ifdef CONFIG_STACK_UNWIND + +#include + +#ifndef ARCH_UNWIND_SECTION_NAME +#define ARCH_UNWIND_SECTION_NAME ".eh_frame" +#endif + +/* + * Initialize unwind support. + */ +extern void unwind_init(void); +extern void unwind_setup(void); + +#ifdef CONFIG_MODULES + +extern void *unwind_add_table(struct module *, + const void *table_start, + unsigned long table_size); + +extern void unwind_remove_table(void *handle, int init_only); + +#endif + +extern int unwind_init_frame_info(struct unwind_frame_info *, + struct task_struct *, + /*const*/ struct pt_regs *); + +/* + * Prepare to unwind a blocked task. + */ +extern int unwind_init_blocked(struct unwind_frame_info *, + struct task_struct *); + +/* + * Prepare to unwind the currently running thread. + */ +extern int unwind_init_running(struct unwind_frame_info *, + asmlinkage int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg); + +/* + * Unwind to previous to frame. Returns 0 if successful, negative + * number in case of an error. + */ +extern int unwind(struct unwind_frame_info *); + +/* + * Unwind until the return pointer is in user-land (or until an error + * occurs). Returns 0 if successful, negative number in case of + * error. + */ +extern int unwind_to_user(struct unwind_frame_info *); + +#else + struct unwind_frame_info {}; static inline void unwind_init(void) {} @@ -28,12 +85,12 @@ static inline void *unwind_add_table(struct module *mod, return NULL; } +#endif + static inline void unwind_remove_table(void *handle, int init_only) { } -#endif - static inline int unwind_init_frame_info(struct unwind_frame_info *info, struct task_struct *tsk, const struct pt_regs *regs) @@ -65,4 +122,6 @@ static inline int unwind_to_user(struct unwind_frame_info *info) return -ENOSYS; } +#endif + #endif /* _LINUX_UNWIND_H */ diff --git a/trunk/include/linux/workqueue.h b/trunk/include/linux/workqueue.h index 2a7b38d87018..edef8d50b26b 100644 --- a/trunk/include/linux/workqueue.h +++ b/trunk/include/linux/workqueue.h @@ -8,21 +8,16 @@ #include #include #include -#include struct workqueue_struct; struct work_struct; typedef void (*work_func_t)(struct work_struct *work); -/* - * The first word is the work queue pointer and the flags rolled into - * one - */ -#define work_data_bits(work) ((unsigned long *)(&(work)->data)) - struct work_struct { - atomic_long_t data; + /* the first word is the work queue pointer and the flags rolled into + * one */ + unsigned long management; #define WORK_STRUCT_PENDING 0 /* T if work item pending execution */ #define WORK_STRUCT_NOAUTOREL 1 /* F if work item automatically released on exec */ #define WORK_STRUCT_FLAG_MASK (3UL) @@ -31,9 +26,6 @@ struct work_struct { work_func_t func; }; -#define WORK_DATA_INIT(autorelease) \ - ATOMIC_LONG_INIT((autorelease) << WORK_STRUCT_NOAUTOREL) - struct delayed_work { struct work_struct work; struct timer_list timer; @@ -44,13 +36,13 @@ struct execute_work { }; #define __WORK_INITIALIZER(n, f) { \ - .data = WORK_DATA_INIT(0), \ + .management = 0, \ .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ } #define __WORK_INITIALIZER_NAR(n, f) { \ - .data = WORK_DATA_INIT(1), \ + .management = (1 << WORK_STRUCT_NOAUTOREL), \ .entry = { &(n).entry, &(n).entry }, \ .func = (f), \ } @@ -90,21 +82,17 @@ struct execute_work { /* * initialize all of a work item in one go - * - * NOTE! No point in using "atomic_long_set()": useing a direct - * assignment of the work data initializer allows the compiler - * to generate better code. */ #define INIT_WORK(_work, _func) \ do { \ - (_work)->data = (atomic_long_t) WORK_DATA_INIT(0); \ + (_work)->management = 0; \ INIT_LIST_HEAD(&(_work)->entry); \ PREPARE_WORK((_work), (_func)); \ } while (0) #define INIT_WORK_NAR(_work, _func) \ do { \ - (_work)->data = (atomic_long_t) WORK_DATA_INIT(1); \ + (_work)->management = (1 << WORK_STRUCT_NOAUTOREL); \ INIT_LIST_HEAD(&(_work)->entry); \ PREPARE_WORK((_work), (_func)); \ } while (0) @@ -126,15 +114,15 @@ struct execute_work { * @work: The work item in question */ #define work_pending(work) \ - test_bit(WORK_STRUCT_PENDING, work_data_bits(work)) + test_bit(WORK_STRUCT_PENDING, &(work)->management) /** * delayed_work_pending - Find out whether a delayable work item is currently * pending * @work: The work item in question */ -#define delayed_work_pending(w) \ - work_pending(&(w)->work) +#define delayed_work_pending(work) \ + test_bit(WORK_STRUCT_PENDING, &(work)->work.management) /** * work_release - Release a work item under execution @@ -155,7 +143,7 @@ struct execute_work { * This should also be used to release a delayed work item. */ #define work_release(work) \ - clear_bit(WORK_STRUCT_PENDING, work_data_bits(work)) + clear_bit(WORK_STRUCT_PENDING, &(work)->management) extern struct workqueue_struct *__create_workqueue(const char *name, @@ -200,7 +188,7 @@ static inline int cancel_delayed_work(struct delayed_work *work) ret = del_timer_sync(&work->timer); if (ret) - work_release(&work->work); + clear_bit(WORK_STRUCT_PENDING, &work->work.management); return ret; } diff --git a/trunk/include/net/ax25.h b/trunk/include/net/ax25.h index 5ae10dd2e32e..14b72d868f03 100644 --- a/trunk/include/net/ax25.h +++ b/trunk/include/net/ax25.h @@ -277,7 +277,7 @@ struct sock *ax25_get_socket(ax25_address *, ax25_address *, int); extern ax25_cb *ax25_find_cb(ax25_address *, ax25_address *, ax25_digi *, struct net_device *); extern void ax25_send_to_raw(ax25_address *, struct sk_buff *, int); extern void ax25_destroy_socket(ax25_cb *); -extern ax25_cb * __must_check ax25_create_cb(void); +extern ax25_cb *ax25_create_cb(void); extern void ax25_fillin_cb(ax25_cb *, ax25_dev *); extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *); @@ -333,25 +333,11 @@ extern void ax25_ds_t3timer_expiry(ax25_cb *); extern void ax25_ds_idletimer_expiry(ax25_cb *); /* ax25_iface.c */ - -struct ax25_protocol { - struct ax25_protocol *next; - unsigned int pid; - int (*func)(struct sk_buff *, ax25_cb *); -}; - -extern void ax25_register_pid(struct ax25_protocol *ap); +extern int ax25_protocol_register(unsigned int, int (*)(struct sk_buff *, ax25_cb *)); extern void ax25_protocol_release(unsigned int); - -struct ax25_linkfail { - struct hlist_node lf_node; - void (*func)(ax25_cb *, int); -}; - -extern void ax25_linkfail_register(struct ax25_linkfail *lf); -extern void ax25_linkfail_release(struct ax25_linkfail *lf); -extern int __must_check ax25_listen_register(ax25_address *, - struct net_device *); +extern int ax25_linkfail_register(void (*)(ax25_cb *, int)); +extern void ax25_linkfail_release(void (*)(ax25_cb *, int)); +extern int ax25_listen_register(ax25_address *, struct net_device *); extern void ax25_listen_release(ax25_address *, struct net_device *); extern int (*ax25_protocol_function(unsigned int))(struct sk_buff *, ax25_cb *); extern int ax25_listen_mine(ax25_address *, struct net_device *); @@ -429,7 +415,7 @@ extern unsigned long ax25_display_timer(struct timer_list *); /* ax25_uid.c */ extern int ax25_uid_policy; extern ax25_uid_assoc *ax25_findbyuid(uid_t); -extern int __must_check ax25_uid_ioctl(int, struct sockaddr_ax25 *); +extern int ax25_uid_ioctl(int, struct sockaddr_ax25 *); extern struct file_operations ax25_uid_fops; extern void ax25_uid_free(void); diff --git a/trunk/include/net/rose.h b/trunk/include/net/rose.h index 4c05a88b921b..012b09ed2401 100644 --- a/trunk/include/net/rose.h +++ b/trunk/include/net/rose.h @@ -188,13 +188,13 @@ extern void rose_kick(struct sock *); extern void rose_enquiry_response(struct sock *); /* rose_route.c */ -extern struct rose_neigh rose_loopback_neigh; +extern struct rose_neigh *rose_loopback_neigh; extern struct file_operations rose_neigh_fops; extern struct file_operations rose_nodes_fops; extern struct file_operations rose_routes_fops; -extern void rose_add_loopback_neigh(void); -extern int __must_check rose_add_loopback_node(rose_address *); +extern int rose_add_loopback_neigh(void); +extern int rose_add_loopback_node(rose_address *); extern void rose_del_loopback_node(rose_address *); extern void rose_rt_device_down(struct net_device *); extern void rose_link_device_down(struct net_device *); diff --git a/trunk/include/rdma/ib_verbs.h b/trunk/include/rdma/ib_verbs.h index 0bfa3328d686..3c2e10574b23 100644 --- a/trunk/include/rdma/ib_verbs.h +++ b/trunk/include/rdma/ib_verbs.h @@ -1639,14 +1639,7 @@ static inline void *ib_dma_alloc_coherent(struct ib_device *dev, { if (dev->dma_ops) return dev->dma_ops->alloc_coherent(dev, size, dma_handle, flag); - else { - dma_addr_t handle; - void *ret; - - ret = dma_alloc_coherent(dev->dma_device, size, &handle, flag); - *dma_handle = handle; - return ret; - } + return dma_alloc_coherent(dev->dma_device, size, dma_handle, flag); } /** diff --git a/trunk/kernel/Makefile b/trunk/kernel/Makefile index 14f4d45e0ae9..5e3f3b75563a 100644 --- a/trunk/kernel/Makefile +++ b/trunk/kernel/Makefile @@ -31,6 +31,7 @@ obj-$(CONFIG_PROVE_LOCKING) += spinlock.o obj-$(CONFIG_UID16) += uid16.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_KALLSYMS) += kallsyms.o +obj-$(CONFIG_STACK_UNWIND) += unwind.o obj-$(CONFIG_PM) += power/ obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o obj-$(CONFIG_KEXEC) += kexec.o diff --git a/trunk/kernel/unwind.c b/trunk/kernel/unwind.c new file mode 100644 index 000000000000..09c261329249 --- /dev/null +++ b/trunk/kernel/unwind.c @@ -0,0 +1,1305 @@ +/* + * Copyright (C) 2002-2006 Novell, Inc. + * Jan Beulich + * This code is released under version 2 of the GNU GPL. + * + * A simple API for unwinding kernel stacks. This is used for + * debugging and error reporting purposes. The kernel doesn't need + * full-blown stack unwinding with all the bells and whistles, so there + * is not much point in implementing the full Dwarf2 unwind API. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern const char __start_unwind[], __end_unwind[]; +extern const u8 __start_unwind_hdr[], __end_unwind_hdr[]; + +#define MAX_STACK_DEPTH 8 + +#define EXTRA_INFO(f) { \ + BUILD_BUG_ON_ZERO(offsetof(struct unwind_frame_info, f) \ + % FIELD_SIZEOF(struct unwind_frame_info, f)) \ + + offsetof(struct unwind_frame_info, f) \ + / FIELD_SIZEOF(struct unwind_frame_info, f), \ + FIELD_SIZEOF(struct unwind_frame_info, f) \ + } +#define PTREGS_INFO(f) EXTRA_INFO(regs.f) + +static const struct { + unsigned offs:BITS_PER_LONG / 2; + unsigned width:BITS_PER_LONG / 2; +} reg_info[] = { + UNW_REGISTER_INFO +}; + +#undef PTREGS_INFO +#undef EXTRA_INFO + +#ifndef REG_INVALID +#define REG_INVALID(r) (reg_info[r].width == 0) +#endif + +#define DW_CFA_nop 0x00 +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_CFA_offset_extended_sf 0x11 +#define DW_CFA_def_cfa_sf 0x12 +#define DW_CFA_def_cfa_offset_sf 0x13 +#define DW_CFA_val_offset 0x14 +#define DW_CFA_val_offset_sf 0x15 +#define DW_CFA_val_expression 0x16 +#define DW_CFA_lo_user 0x1c +#define DW_CFA_GNU_window_save 0x2d +#define DW_CFA_GNU_args_size 0x2e +#define DW_CFA_GNU_negative_offset_extended 0x2f +#define DW_CFA_hi_user 0x3f + +#define DW_EH_PE_FORM 0x07 +#define DW_EH_PE_native 0x00 +#define DW_EH_PE_leb128 0x01 +#define DW_EH_PE_data2 0x02 +#define DW_EH_PE_data4 0x03 +#define DW_EH_PE_data8 0x04 +#define DW_EH_PE_signed 0x08 +#define DW_EH_PE_ADJUST 0x70 +#define DW_EH_PE_abs 0x00 +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +#define DW_EH_PE_indirect 0x80 +#define DW_EH_PE_omit 0xff + +typedef unsigned long uleb128_t; +typedef signed long sleb128_t; +#define sleb128abs __builtin_labs + +static struct unwind_table { + struct { + unsigned long pc; + unsigned long range; + } core, init; + const void *address; + unsigned long size; + const unsigned char *header; + unsigned long hdrsz; + struct unwind_table *link; + const char *name; +} root_table; + +struct unwind_item { + enum item_location { + Nowhere, + Memory, + Register, + Value + } where; + uleb128_t value; +}; + +struct unwind_state { + uleb128_t loc, org; + const u8 *cieStart, *cieEnd; + uleb128_t codeAlign; + sleb128_t dataAlign; + struct cfa { + uleb128_t reg, offs; + } cfa; + struct unwind_item regs[ARRAY_SIZE(reg_info)]; + unsigned stackDepth:8; + unsigned version:8; + const u8 *label; + const u8 *stack[MAX_STACK_DEPTH]; +}; + +static const struct cfa badCFA = { ARRAY_SIZE(reg_info), 1 }; + +static unsigned unwind_debug; +static int __init unwind_debug_setup(char *s) +{ + unwind_debug = simple_strtoul(s, NULL, 0); + return 1; +} +__setup("unwind_debug=", unwind_debug_setup); +#define dprintk(lvl, fmt, args...) \ + ((void)(lvl > unwind_debug \ + || printk(KERN_DEBUG "unwind: " fmt "\n", ##args))) + +static struct unwind_table *find_table(unsigned long pc) +{ + struct unwind_table *table; + + for (table = &root_table; table; table = table->link) + if ((pc >= table->core.pc + && pc < table->core.pc + table->core.range) + || (pc >= table->init.pc + && pc < table->init.pc + table->init.range)) + break; + + return table; +} + +static unsigned long read_pointer(const u8 **pLoc, + const void *end, + signed ptrType, + unsigned long text_base, + unsigned long data_base); + +static void init_unwind_table(struct unwind_table *table, + const char *name, + const void *core_start, + unsigned long core_size, + const void *init_start, + unsigned long init_size, + const void *table_start, + unsigned long table_size, + const u8 *header_start, + unsigned long header_size) +{ + const u8 *ptr = header_start + 4; + const u8 *end = header_start + header_size; + + table->core.pc = (unsigned long)core_start; + table->core.range = core_size; + table->init.pc = (unsigned long)init_start; + table->init.range = init_size; + table->address = table_start; + table->size = table_size; + /* See if the linker provided table looks valid. */ + if (header_size <= 4 + || header_start[0] != 1 + || (void *)read_pointer(&ptr, end, header_start[1], 0, 0) + != table_start + || !read_pointer(&ptr, end, header_start[2], 0, 0) + || !read_pointer(&ptr, end, header_start[3], 0, + (unsigned long)header_start) + || !read_pointer(&ptr, end, header_start[3], 0, + (unsigned long)header_start)) + header_start = NULL; + table->hdrsz = header_size; + smp_wmb(); + table->header = header_start; + table->link = NULL; + table->name = name; +} + +void __init unwind_init(void) +{ + init_unwind_table(&root_table, "kernel", + _text, _end - _text, + NULL, 0, + __start_unwind, __end_unwind - __start_unwind, + __start_unwind_hdr, __end_unwind_hdr - __start_unwind_hdr); +} + +static const u32 bad_cie, not_fde; +static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *); +static signed fde_pointer_type(const u32 *cie); + +struct eh_frame_hdr_table_entry { + unsigned long start, fde; +}; + +static int cmp_eh_frame_hdr_table_entries(const void *p1, const void *p2) +{ + const struct eh_frame_hdr_table_entry *e1 = p1; + const struct eh_frame_hdr_table_entry *e2 = p2; + + return (e1->start > e2->start) - (e1->start < e2->start); +} + +static void swap_eh_frame_hdr_table_entries(void *p1, void *p2, int size) +{ + struct eh_frame_hdr_table_entry *e1 = p1; + struct eh_frame_hdr_table_entry *e2 = p2; + unsigned long v; + + v = e1->start; + e1->start = e2->start; + e2->start = v; + v = e1->fde; + e1->fde = e2->fde; + e2->fde = v; +} + +static void __init setup_unwind_table(struct unwind_table *table, + void *(*alloc)(unsigned long)) +{ + const u8 *ptr; + unsigned long tableSize = table->size, hdrSize; + unsigned n; + const u32 *fde; + struct { + u8 version; + u8 eh_frame_ptr_enc; + u8 fde_count_enc; + u8 table_enc; + unsigned long eh_frame_ptr; + unsigned int fde_count; + struct eh_frame_hdr_table_entry table[]; + } __attribute__((__packed__)) *header; + + if (table->header) + return; + + if (table->hdrsz) + printk(KERN_WARNING ".eh_frame_hdr for '%s' present but unusable\n", + table->name); + + if (tableSize & (sizeof(*fde) - 1)) + return; + + for (fde = table->address, n = 0; + tableSize > sizeof(*fde) && tableSize - sizeof(*fde) >= *fde; + tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + const u32 *cie = cie_for_fde(fde, table); + signed ptrType; + + if (cie == ¬_fde) + continue; + if (cie == NULL + || cie == &bad_cie + || (ptrType = fde_pointer_type(cie)) < 0) + return; + ptr = (const u8 *)(fde + 2); + if (!read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType, 0, 0)) + return; + ++n; + } + + if (tableSize || !n) + return; + + hdrSize = 4 + sizeof(unsigned long) + sizeof(unsigned int) + + 2 * n * sizeof(unsigned long); + dprintk(2, "Binary lookup table size for %s: %lu bytes", table->name, hdrSize); + header = alloc(hdrSize); + if (!header) + return; + header->version = 1; + header->eh_frame_ptr_enc = DW_EH_PE_abs|DW_EH_PE_native; + header->fde_count_enc = DW_EH_PE_abs|DW_EH_PE_data4; + header->table_enc = DW_EH_PE_abs|DW_EH_PE_native; + put_unaligned((unsigned long)table->address, &header->eh_frame_ptr); + BUILD_BUG_ON(offsetof(typeof(*header), fde_count) + % __alignof(typeof(header->fde_count))); + header->fde_count = n; + + BUILD_BUG_ON(offsetof(typeof(*header), table) + % __alignof(typeof(*header->table))); + for (fde = table->address, tableSize = table->size, n = 0; + tableSize; + tableSize -= sizeof(*fde) + *fde, fde += 1 + *fde / sizeof(*fde)) { + const u32 *cie = fde + 1 - fde[1] / sizeof(*fde); + + if (!fde[1]) + continue; /* this is a CIE */ + ptr = (const u8 *)(fde + 2); + header->table[n].start = read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + fde_pointer_type(cie), 0, 0); + header->table[n].fde = (unsigned long)fde; + ++n; + } + WARN_ON(n != header->fde_count); + + sort(header->table, + n, + sizeof(*header->table), + cmp_eh_frame_hdr_table_entries, + swap_eh_frame_hdr_table_entries); + + table->hdrsz = hdrSize; + smp_wmb(); + table->header = (const void *)header; +} + +static void *__init balloc(unsigned long sz) +{ + return __alloc_bootmem_nopanic(sz, + sizeof(unsigned int), + __pa(MAX_DMA_ADDRESS)); +} + +void __init unwind_setup(void) +{ + setup_unwind_table(&root_table, balloc); +} + +#ifdef CONFIG_MODULES + +static struct unwind_table *last_table; + +/* Must be called with module_mutex held. */ +void *unwind_add_table(struct module *module, + const void *table_start, + unsigned long table_size) +{ + struct unwind_table *table; + + if (table_size <= 0) + return NULL; + + table = kmalloc(sizeof(*table), GFP_KERNEL); + if (!table) + return NULL; + + init_unwind_table(table, module->name, + module->module_core, module->core_size, + module->module_init, module->init_size, + table_start, table_size, + NULL, 0); + + if (last_table) + last_table->link = table; + else + root_table.link = table; + last_table = table; + + return table; +} + +struct unlink_table_info +{ + struct unwind_table *table; + int init_only; +}; + +static int unlink_table(void *arg) +{ + struct unlink_table_info *info = arg; + struct unwind_table *table = info->table, *prev; + + for (prev = &root_table; prev->link && prev->link != table; prev = prev->link) + ; + + if (prev->link) { + if (info->init_only) { + table->init.pc = 0; + table->init.range = 0; + info->table = NULL; + } else { + prev->link = table->link; + if (!prev->link) + last_table = prev; + } + } else + info->table = NULL; + + return 0; +} + +/* Must be called with module_mutex held. */ +void unwind_remove_table(void *handle, int init_only) +{ + struct unwind_table *table = handle; + struct unlink_table_info info; + + if (!table || table == &root_table) + return; + + if (init_only && table == last_table) { + table->init.pc = 0; + table->init.range = 0; + return; + } + + info.table = table; + info.init_only = init_only; + stop_machine_run(unlink_table, &info, NR_CPUS); + + if (info.table) + kfree(table); +} + +#endif /* CONFIG_MODULES */ + +static uleb128_t get_uleb128(const u8 **pcur, const u8 *end) +{ + const u8 *cur = *pcur; + uleb128_t value; + unsigned shift; + + for (shift = 0, value = 0; cur < end; shift += 7) { + if (shift + 7 > 8 * sizeof(value) + && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { + cur = end + 1; + break; + } + value |= (uleb128_t)(*cur & 0x7f) << shift; + if (!(*cur++ & 0x80)) + break; + } + *pcur = cur; + + return value; +} + +static sleb128_t get_sleb128(const u8 **pcur, const u8 *end) +{ + const u8 *cur = *pcur; + sleb128_t value; + unsigned shift; + + for (shift = 0, value = 0; cur < end; shift += 7) { + if (shift + 7 > 8 * sizeof(value) + && (*cur & 0x7fU) >= (1U << (8 * sizeof(value) - shift))) { + cur = end + 1; + break; + } + value |= (sleb128_t)(*cur & 0x7f) << shift; + if (!(*cur & 0x80)) { + value |= -(*cur++ & 0x40) << shift; + break; + } + } + *pcur = cur; + + return value; +} + +static const u32 *cie_for_fde(const u32 *fde, const struct unwind_table *table) +{ + const u32 *cie; + + if (!*fde || (*fde & (sizeof(*fde) - 1))) + return &bad_cie; + if (!fde[1]) + return ¬_fde; /* this is a CIE */ + if ((fde[1] & (sizeof(*fde) - 1)) + || fde[1] > (unsigned long)(fde + 1) - (unsigned long)table->address) + return NULL; /* this is not a valid FDE */ + cie = fde + 1 - fde[1] / sizeof(*fde); + if (*cie <= sizeof(*cie) + 4 + || *cie >= fde[1] - sizeof(*fde) + || (*cie & (sizeof(*cie) - 1)) + || cie[1]) + return NULL; /* this is not a (valid) CIE */ + return cie; +} + +static unsigned long read_pointer(const u8 **pLoc, + const void *end, + signed ptrType, + unsigned long text_base, + unsigned long data_base) +{ + unsigned long value = 0; + union { + const u8 *p8; + const u16 *p16u; + const s16 *p16s; + const u32 *p32u; + const s32 *p32s; + const unsigned long *pul; + } ptr; + + if (ptrType < 0 || ptrType == DW_EH_PE_omit) { + dprintk(1, "Invalid pointer encoding %02X (%p,%p).", ptrType, *pLoc, end); + return 0; + } + ptr.p8 = *pLoc; + switch(ptrType & DW_EH_PE_FORM) { + case DW_EH_PE_data2: + if (end < (const void *)(ptr.p16u + 1)) { + dprintk(1, "Data16 overrun (%p,%p).", ptr.p8, end); + return 0; + } + if(ptrType & DW_EH_PE_signed) + value = get_unaligned(ptr.p16s++); + else + value = get_unaligned(ptr.p16u++); + break; + case DW_EH_PE_data4: +#ifdef CONFIG_64BIT + if (end < (const void *)(ptr.p32u + 1)) { + dprintk(1, "Data32 overrun (%p,%p).", ptr.p8, end); + return 0; + } + if(ptrType & DW_EH_PE_signed) + value = get_unaligned(ptr.p32s++); + else + value = get_unaligned(ptr.p32u++); + break; + case DW_EH_PE_data8: + BUILD_BUG_ON(sizeof(u64) != sizeof(value)); +#else + BUILD_BUG_ON(sizeof(u32) != sizeof(value)); +#endif + case DW_EH_PE_native: + if (end < (const void *)(ptr.pul + 1)) { + dprintk(1, "DataUL overrun (%p,%p).", ptr.p8, end); + return 0; + } + value = get_unaligned(ptr.pul++); + break; + case DW_EH_PE_leb128: + BUILD_BUG_ON(sizeof(uleb128_t) > sizeof(value)); + value = ptrType & DW_EH_PE_signed + ? get_sleb128(&ptr.p8, end) + : get_uleb128(&ptr.p8, end); + if ((const void *)ptr.p8 > end) { + dprintk(1, "DataLEB overrun (%p,%p).", ptr.p8, end); + return 0; + } + break; + default: + dprintk(2, "Cannot decode pointer type %02X (%p,%p).", + ptrType, ptr.p8, end); + return 0; + } + switch(ptrType & DW_EH_PE_ADJUST) { + case DW_EH_PE_abs: + break; + case DW_EH_PE_pcrel: + value += (unsigned long)*pLoc; + break; + case DW_EH_PE_textrel: + if (likely(text_base)) { + value += text_base; + break; + } + dprintk(2, "Text-relative encoding %02X (%p,%p), but zero text base.", + ptrType, *pLoc, end); + return 0; + case DW_EH_PE_datarel: + if (likely(data_base)) { + value += data_base; + break; + } + dprintk(2, "Data-relative encoding %02X (%p,%p), but zero data base.", + ptrType, *pLoc, end); + return 0; + default: + dprintk(2, "Cannot adjust pointer type %02X (%p,%p).", + ptrType, *pLoc, end); + return 0; + } + if ((ptrType & DW_EH_PE_indirect) + && probe_kernel_address((unsigned long *)value, value)) { + dprintk(1, "Cannot read indirect value %lx (%p,%p).", + value, *pLoc, end); + return 0; + } + *pLoc = ptr.p8; + + return value; +} + +static signed fde_pointer_type(const u32 *cie) +{ + const u8 *ptr = (const u8 *)(cie + 2); + unsigned version = *ptr; + + if (version != 1) + return -1; /* unsupported */ + if (*++ptr) { + const char *aug; + const u8 *end = (const u8 *)(cie + 1) + *cie; + uleb128_t len; + + /* check if augmentation size is first (and thus present) */ + if (*ptr != 'z') + return -1; + /* check if augmentation string is nul-terminated */ + if ((ptr = memchr(aug = (const void *)ptr, 0, end - ptr)) == NULL) + return -1; + ++ptr; /* skip terminator */ + get_uleb128(&ptr, end); /* skip code alignment */ + get_sleb128(&ptr, end); /* skip data alignment */ + /* skip return address column */ + version <= 1 ? (void)++ptr : (void)get_uleb128(&ptr, end); + len = get_uleb128(&ptr, end); /* augmentation length */ + if (ptr + len < ptr || ptr + len > end) + return -1; + end = ptr + len; + while (*++aug) { + if (ptr >= end) + return -1; + switch(*aug) { + case 'L': + ++ptr; + break; + case 'P': { + signed ptrType = *ptr++; + + if (!read_pointer(&ptr, end, ptrType, 0, 0) + || ptr > end) + return -1; + } + break; + case 'R': + return *ptr; + default: + return -1; + } + } + } + return DW_EH_PE_native|DW_EH_PE_abs; +} + +static int advance_loc(unsigned long delta, struct unwind_state *state) +{ + state->loc += delta * state->codeAlign; + + return delta > 0; +} + +static void set_rule(uleb128_t reg, + enum item_location where, + uleb128_t value, + struct unwind_state *state) +{ + if (reg < ARRAY_SIZE(state->regs)) { + state->regs[reg].where = where; + state->regs[reg].value = value; + } +} + +static int processCFI(const u8 *start, + const u8 *end, + unsigned long targetLoc, + signed ptrType, + struct unwind_state *state) +{ + union { + const u8 *p8; + const u16 *p16; + const u32 *p32; + } ptr; + int result = 1; + + if (start != state->cieStart) { + state->loc = state->org; + result = processCFI(state->cieStart, state->cieEnd, 0, ptrType, state); + if (targetLoc == 0 && state->label == NULL) + return result; + } + for (ptr.p8 = start; result && ptr.p8 < end; ) { + switch(*ptr.p8 >> 6) { + uleb128_t value; + + case 0: + switch(*ptr.p8++) { + case DW_CFA_nop: + break; + case DW_CFA_set_loc: + state->loc = read_pointer(&ptr.p8, end, ptrType, 0, 0); + if (state->loc == 0) + result = 0; + break; + case DW_CFA_advance_loc1: + result = ptr.p8 < end && advance_loc(*ptr.p8++, state); + break; + case DW_CFA_advance_loc2: + result = ptr.p8 <= end + 2 + && advance_loc(*ptr.p16++, state); + break; + case DW_CFA_advance_loc4: + result = ptr.p8 <= end + 4 + && advance_loc(*ptr.p32++, state); + break; + case DW_CFA_offset_extended: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_val_offset: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Value, get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_offset_extended_sf: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Memory, get_sleb128(&ptr.p8, end), state); + break; + case DW_CFA_val_offset_sf: + value = get_uleb128(&ptr.p8, end); + set_rule(value, Value, get_sleb128(&ptr.p8, end), state); + break; + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_same_value: + set_rule(get_uleb128(&ptr.p8, end), Nowhere, 0, state); + break; + case DW_CFA_register: + value = get_uleb128(&ptr.p8, end); + set_rule(value, + Register, + get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_remember_state: + if (ptr.p8 == state->label) { + state->label = NULL; + return 1; + } + if (state->stackDepth >= MAX_STACK_DEPTH) { + dprintk(1, "State stack overflow (%p,%p).", ptr.p8, end); + return 0; + } + state->stack[state->stackDepth++] = ptr.p8; + break; + case DW_CFA_restore_state: + if (state->stackDepth) { + const uleb128_t loc = state->loc; + const u8 *label = state->label; + + state->label = state->stack[state->stackDepth - 1]; + memcpy(&state->cfa, &badCFA, sizeof(state->cfa)); + memset(state->regs, 0, sizeof(state->regs)); + state->stackDepth = 0; + result = processCFI(start, end, 0, ptrType, state); + state->loc = loc; + state->label = label; + } else { + dprintk(1, "State stack underflow (%p,%p).", ptr.p8, end); + return 0; + } + break; + case DW_CFA_def_cfa: + state->cfa.reg = get_uleb128(&ptr.p8, end); + /*nobreak*/ + case DW_CFA_def_cfa_offset: + state->cfa.offs = get_uleb128(&ptr.p8, end); + break; + case DW_CFA_def_cfa_sf: + state->cfa.reg = get_uleb128(&ptr.p8, end); + /*nobreak*/ + case DW_CFA_def_cfa_offset_sf: + state->cfa.offs = get_sleb128(&ptr.p8, end) + * state->dataAlign; + break; + case DW_CFA_def_cfa_register: + state->cfa.reg = get_uleb128(&ptr.p8, end); + break; + /*todo case DW_CFA_def_cfa_expression: */ + /*todo case DW_CFA_expression: */ + /*todo case DW_CFA_val_expression: */ + case DW_CFA_GNU_args_size: + get_uleb128(&ptr.p8, end); + break; + case DW_CFA_GNU_negative_offset_extended: + value = get_uleb128(&ptr.p8, end); + set_rule(value, + Memory, + (uleb128_t)0 - get_uleb128(&ptr.p8, end), state); + break; + case DW_CFA_GNU_window_save: + default: + dprintk(1, "Unrecognized CFI op %02X (%p,%p).", ptr.p8[-1], ptr.p8 - 1, end); + result = 0; + break; + } + break; + case 1: + result = advance_loc(*ptr.p8++ & 0x3f, state); + break; + case 2: + value = *ptr.p8++ & 0x3f; + set_rule(value, Memory, get_uleb128(&ptr.p8, end), state); + break; + case 3: + set_rule(*ptr.p8++ & 0x3f, Nowhere, 0, state); + break; + } + if (ptr.p8 > end) { + dprintk(1, "Data overrun (%p,%p).", ptr.p8, end); + result = 0; + } + if (result && targetLoc != 0 && targetLoc < state->loc) + return 1; + } + + if (result && ptr.p8 < end) + dprintk(1, "Data underrun (%p,%p).", ptr.p8, end); + + return result + && ptr.p8 == end + && (targetLoc == 0 + || (/*todo While in theory this should apply, gcc in practice omits + everything past the function prolog, and hence the location + never reaches the end of the function. + targetLoc < state->loc &&*/ state->label == NULL)); +} + +/* Unwind to previous to frame. Returns 0 if successful, negative + * number in case of an error. */ +int unwind(struct unwind_frame_info *frame) +{ +#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs]) + const u32 *fde = NULL, *cie = NULL; + const u8 *ptr = NULL, *end = NULL; + unsigned long pc = UNW_PC(frame) - frame->call_frame, sp; + unsigned long startLoc = 0, endLoc = 0, cfa; + unsigned i; + signed ptrType = -1; + uleb128_t retAddrReg = 0; + const struct unwind_table *table; + struct unwind_state state; + + if (UNW_PC(frame) == 0) + return -EINVAL; + if ((table = find_table(pc)) != NULL + && !(table->size & (sizeof(*fde) - 1))) { + const u8 *hdr = table->header; + unsigned long tableSize; + + smp_rmb(); + if (hdr && hdr[0] == 1) { + switch(hdr[3] & DW_EH_PE_FORM) { + case DW_EH_PE_native: tableSize = sizeof(unsigned long); break; + case DW_EH_PE_data2: tableSize = 2; break; + case DW_EH_PE_data4: tableSize = 4; break; + case DW_EH_PE_data8: tableSize = 8; break; + default: tableSize = 0; break; + } + ptr = hdr + 4; + end = hdr + table->hdrsz; + if (tableSize + && read_pointer(&ptr, end, hdr[1], 0, 0) + == (unsigned long)table->address + && (i = read_pointer(&ptr, end, hdr[2], 0, 0)) > 0 + && i == (end - ptr) / (2 * tableSize) + && !((end - ptr) % (2 * tableSize))) { + do { + const u8 *cur = ptr + (i / 2) * (2 * tableSize); + + startLoc = read_pointer(&cur, + cur + tableSize, + hdr[3], 0, + (unsigned long)hdr); + if (pc < startLoc) + i /= 2; + else { + ptr = cur - tableSize; + i = (i + 1) / 2; + } + } while (startLoc && i > 1); + if (i == 1 + && (startLoc = read_pointer(&ptr, + ptr + tableSize, + hdr[3], 0, + (unsigned long)hdr)) != 0 + && pc >= startLoc) + fde = (void *)read_pointer(&ptr, + ptr + tableSize, + hdr[3], 0, + (unsigned long)hdr); + } + } + if(hdr && !fde) + dprintk(3, "Binary lookup for %lx failed.", pc); + + if (fde != NULL) { + cie = cie_for_fde(fde, table); + ptr = (const u8 *)(fde + 2); + if(cie != NULL + && cie != &bad_cie + && cie != ¬_fde + && (ptrType = fde_pointer_type(cie)) >= 0 + && read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType, 0, 0) == startLoc) { + if (!(ptrType & DW_EH_PE_indirect)) + ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed; + endLoc = startLoc + + read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType, 0, 0); + if(pc >= endLoc) + fde = NULL; + } else + fde = NULL; + if(!fde) + dprintk(1, "Binary lookup result for %lx discarded.", pc); + } + if (fde == NULL) { + for (fde = table->address, tableSize = table->size; + cie = NULL, tableSize > sizeof(*fde) + && tableSize - sizeof(*fde) >= *fde; + tableSize -= sizeof(*fde) + *fde, + fde += 1 + *fde / sizeof(*fde)) { + cie = cie_for_fde(fde, table); + if (cie == &bad_cie) { + cie = NULL; + break; + } + if (cie == NULL + || cie == ¬_fde + || (ptrType = fde_pointer_type(cie)) < 0) + continue; + ptr = (const u8 *)(fde + 2); + startLoc = read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType, 0, 0); + if (!startLoc) + continue; + if (!(ptrType & DW_EH_PE_indirect)) + ptrType &= DW_EH_PE_FORM|DW_EH_PE_signed; + endLoc = startLoc + + read_pointer(&ptr, + (const u8 *)(fde + 1) + *fde, + ptrType, 0, 0); + if (pc >= startLoc && pc < endLoc) + break; + } + if(!fde) + dprintk(3, "Linear lookup for %lx failed.", pc); + } + } + if (cie != NULL) { + memset(&state, 0, sizeof(state)); + state.cieEnd = ptr; /* keep here temporarily */ + ptr = (const u8 *)(cie + 2); + end = (const u8 *)(cie + 1) + *cie; + frame->call_frame = 1; + if ((state.version = *ptr) != 1) + cie = NULL; /* unsupported version */ + else if (*++ptr) { + /* check if augmentation size is first (and thus present) */ + if (*ptr == 'z') { + while (++ptr < end && *ptr) { + switch(*ptr) { + /* check for ignorable (or already handled) + * nul-terminated augmentation string */ + case 'L': + case 'P': + case 'R': + continue; + case 'S': + frame->call_frame = 0; + continue; + default: + break; + } + break; + } + } + if (ptr >= end || *ptr) + cie = NULL; + } + if(!cie) + dprintk(1, "CIE unusable (%p,%p).", ptr, end); + ++ptr; + } + if (cie != NULL) { + /* get code aligment factor */ + state.codeAlign = get_uleb128(&ptr, end); + /* get data aligment factor */ + state.dataAlign = get_sleb128(&ptr, end); + if (state.codeAlign == 0 || state.dataAlign == 0 || ptr >= end) + cie = NULL; + else if (UNW_PC(frame) % state.codeAlign + || UNW_SP(frame) % sleb128abs(state.dataAlign)) { + dprintk(1, "Input pointer(s) misaligned (%lx,%lx).", + UNW_PC(frame), UNW_SP(frame)); + return -EPERM; + } else { + retAddrReg = state.version <= 1 ? *ptr++ : get_uleb128(&ptr, end); + /* skip augmentation */ + if (((const char *)(cie + 2))[1] == 'z') { + uleb128_t augSize = get_uleb128(&ptr, end); + + ptr += augSize; + } + if (ptr > end + || retAddrReg >= ARRAY_SIZE(reg_info) + || REG_INVALID(retAddrReg) + || reg_info[retAddrReg].width != sizeof(unsigned long)) + cie = NULL; + } + if(!cie) + dprintk(1, "CIE validation failed (%p,%p).", ptr, end); + } + if (cie != NULL) { + state.cieStart = ptr; + ptr = state.cieEnd; + state.cieEnd = end; + end = (const u8 *)(fde + 1) + *fde; + /* skip augmentation */ + if (((const char *)(cie + 2))[1] == 'z') { + uleb128_t augSize = get_uleb128(&ptr, end); + + if ((ptr += augSize) > end) + fde = NULL; + } + if(!fde) + dprintk(1, "FDE validation failed (%p,%p).", ptr, end); + } + if (cie == NULL || fde == NULL) { +#ifdef CONFIG_FRAME_POINTER + unsigned long top, bottom; + + if ((UNW_SP(frame) | UNW_FP(frame)) % sizeof(unsigned long)) + return -EPERM; + top = STACK_TOP(frame->task); + bottom = STACK_BOTTOM(frame->task); +# if FRAME_RETADDR_OFFSET < 0 + if (UNW_SP(frame) < top + && UNW_FP(frame) <= UNW_SP(frame) + && bottom < UNW_FP(frame) +# else + if (UNW_SP(frame) > top + && UNW_FP(frame) >= UNW_SP(frame) + && bottom > UNW_FP(frame) +# endif + && !((UNW_SP(frame) | UNW_FP(frame)) + & (sizeof(unsigned long) - 1))) { + unsigned long link; + + if (!probe_kernel_address( + (unsigned long *)(UNW_FP(frame) + + FRAME_LINK_OFFSET), + link) +# if FRAME_RETADDR_OFFSET < 0 + && link > bottom && link < UNW_FP(frame) +# else + && link > UNW_FP(frame) && link < bottom +# endif + && !(link & (sizeof(link) - 1)) + && !probe_kernel_address( + (unsigned long *)(UNW_FP(frame) + + FRAME_RETADDR_OFFSET), UNW_PC(frame))) { + UNW_SP(frame) = UNW_FP(frame) + FRAME_RETADDR_OFFSET +# if FRAME_RETADDR_OFFSET < 0 + - +# else + + +# endif + sizeof(UNW_PC(frame)); + UNW_FP(frame) = link; + return 0; + } + } +#endif + return -ENXIO; + } + state.org = startLoc; + memcpy(&state.cfa, &badCFA, sizeof(state.cfa)); + /* process instructions */ + if (!processCFI(ptr, end, pc, ptrType, &state) + || state.loc > endLoc + || state.regs[retAddrReg].where == Nowhere + || state.cfa.reg >= ARRAY_SIZE(reg_info) + || reg_info[state.cfa.reg].width != sizeof(unsigned long) + || FRAME_REG(state.cfa.reg, unsigned long) % sizeof(unsigned long) + || state.cfa.offs % sizeof(unsigned long)) { + dprintk(1, "Unusable unwind info (%p,%p).", ptr, end); + return -EIO; + } + /* update frame */ +#ifndef CONFIG_AS_CFI_SIGNAL_FRAME + if(frame->call_frame + && !UNW_DEFAULT_RA(state.regs[retAddrReg], state.dataAlign)) + frame->call_frame = 0; +#endif + cfa = FRAME_REG(state.cfa.reg, unsigned long) + state.cfa.offs; + startLoc = min((unsigned long)UNW_SP(frame), cfa); + endLoc = max((unsigned long)UNW_SP(frame), cfa); + if (STACK_LIMIT(startLoc) != STACK_LIMIT(endLoc)) { + startLoc = min(STACK_LIMIT(cfa), cfa); + endLoc = max(STACK_LIMIT(cfa), cfa); + } +#ifndef CONFIG_64BIT +# define CASES CASE(8); CASE(16); CASE(32) +#else +# define CASES CASE(8); CASE(16); CASE(32); CASE(64) +#endif + pc = UNW_PC(frame); + sp = UNW_SP(frame); + for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { + if (REG_INVALID(i)) { + if (state.regs[i].where == Nowhere) + continue; + dprintk(1, "Cannot restore register %u (%d).", + i, state.regs[i].where); + return -EIO; + } + switch(state.regs[i].where) { + default: + break; + case Register: + if (state.regs[i].value >= ARRAY_SIZE(reg_info) + || REG_INVALID(state.regs[i].value) + || reg_info[i].width > reg_info[state.regs[i].value].width) { + dprintk(1, "Cannot restore register %u from register %lu.", + i, state.regs[i].value); + return -EIO; + } + switch(reg_info[state.regs[i].value].width) { +#define CASE(n) \ + case sizeof(u##n): \ + state.regs[i].value = FRAME_REG(state.regs[i].value, \ + const u##n); \ + break + CASES; +#undef CASE + default: + dprintk(1, "Unsupported register size %u (%lu).", + reg_info[state.regs[i].value].width, + state.regs[i].value); + return -EIO; + } + break; + } + } + for (i = 0; i < ARRAY_SIZE(state.regs); ++i) { + if (REG_INVALID(i)) + continue; + switch(state.regs[i].where) { + case Nowhere: + if (reg_info[i].width != sizeof(UNW_SP(frame)) + || &FRAME_REG(i, __typeof__(UNW_SP(frame))) + != &UNW_SP(frame)) + continue; + UNW_SP(frame) = cfa; + break; + case Register: + switch(reg_info[i].width) { +#define CASE(n) case sizeof(u##n): \ + FRAME_REG(i, u##n) = state.regs[i].value; \ + break + CASES; +#undef CASE + default: + dprintk(1, "Unsupported register size %u (%u).", + reg_info[i].width, i); + return -EIO; + } + break; + case Value: + if (reg_info[i].width != sizeof(unsigned long)) { + dprintk(1, "Unsupported value size %u (%u).", + reg_info[i].width, i); + return -EIO; + } + FRAME_REG(i, unsigned long) = cfa + state.regs[i].value + * state.dataAlign; + break; + case Memory: { + unsigned long addr = cfa + state.regs[i].value + * state.dataAlign; + + if ((state.regs[i].value * state.dataAlign) + % sizeof(unsigned long) + || addr < startLoc + || addr + sizeof(unsigned long) < addr + || addr + sizeof(unsigned long) > endLoc) { + dprintk(1, "Bad memory location %lx (%lx).", + addr, state.regs[i].value); + return -EIO; + } + switch(reg_info[i].width) { +#define CASE(n) case sizeof(u##n): \ + probe_kernel_address((u##n *)addr, FRAME_REG(i, u##n)); \ + break + CASES; +#undef CASE + default: + dprintk(1, "Unsupported memory size %u (%u).", + reg_info[i].width, i); + return -EIO; + } + } + break; + } + } + + if (UNW_PC(frame) % state.codeAlign + || UNW_SP(frame) % sleb128abs(state.dataAlign)) { + dprintk(1, "Output pointer(s) misaligned (%lx,%lx).", + UNW_PC(frame), UNW_SP(frame)); + return -EIO; + } + if (pc == UNW_PC(frame) && sp == UNW_SP(frame)) { + dprintk(1, "No progress (%lx,%lx).", pc, sp); + return -EIO; + } + + return 0; +#undef CASES +#undef FRAME_REG +} +EXPORT_SYMBOL(unwind); + +int unwind_init_frame_info(struct unwind_frame_info *info, + struct task_struct *tsk, + /*const*/ struct pt_regs *regs) +{ + info->task = tsk; + info->call_frame = 0; + arch_unw_init_frame_info(info, regs); + + return 0; +} +EXPORT_SYMBOL(unwind_init_frame_info); + +/* + * Prepare to unwind a blocked task. + */ +int unwind_init_blocked(struct unwind_frame_info *info, + struct task_struct *tsk) +{ + info->task = tsk; + info->call_frame = 0; + arch_unw_init_blocked(info); + + return 0; +} +EXPORT_SYMBOL(unwind_init_blocked); + +/* + * Prepare to unwind the currently running thread. + */ +int unwind_init_running(struct unwind_frame_info *info, + asmlinkage int (*callback)(struct unwind_frame_info *, + void *arg), + void *arg) +{ + info->task = current; + info->call_frame = 0; + + return arch_unwind_init_running(info, callback, arg); +} +EXPORT_SYMBOL(unwind_init_running); + +/* + * Unwind until the return pointer is in user-land (or until an error + * occurs). Returns 0 if successful, negative number in case of + * error. + */ +int unwind_to_user(struct unwind_frame_info *info) +{ + while (!arch_unw_user_mode(info)) { + int err = unwind(info); + + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL(unwind_to_user); diff --git a/trunk/kernel/workqueue.c b/trunk/kernel/workqueue.c index 742cbbe49bdc..db49886bfae1 100644 --- a/trunk/kernel/workqueue.c +++ b/trunk/kernel/workqueue.c @@ -96,13 +96,13 @@ static inline void set_wq_data(struct work_struct *work, void *wq) BUG_ON(!work_pending(work)); new = (unsigned long) wq | (1UL << WORK_STRUCT_PENDING); - new |= WORK_STRUCT_FLAG_MASK & *work_data_bits(work); - atomic_long_set(&work->data, new); + new |= work->management & WORK_STRUCT_FLAG_MASK; + work->management = new; } static inline void *get_wq_data(struct work_struct *work) { - return (void *) (atomic_long_read(&work->data) & WORK_STRUCT_WQ_DATA_MASK); + return (void *) (work->management & WORK_STRUCT_WQ_DATA_MASK); } static int __run_work(struct cpu_workqueue_struct *cwq, struct work_struct *work) @@ -133,7 +133,7 @@ static int __run_work(struct cpu_workqueue_struct *cwq, struct work_struct *work list_del_init(&work->entry); spin_unlock_irqrestore(&cwq->lock, flags); - if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work))) + if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management)) work_release(work); f(work); @@ -206,7 +206,7 @@ int fastcall queue_work(struct workqueue_struct *wq, struct work_struct *work) { int ret = 0, cpu = get_cpu(); - if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { if (unlikely(is_single_threaded(wq))) cpu = singlethread_cpu; BUG_ON(!list_empty(&work->entry)); @@ -248,7 +248,7 @@ int fastcall queue_delayed_work(struct workqueue_struct *wq, if (delay == 0) return queue_work(wq, work); - if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { BUG_ON(timer_pending(timer)); BUG_ON(!list_empty(&work->entry)); @@ -280,7 +280,7 @@ int queue_delayed_work_on(int cpu, struct workqueue_struct *wq, struct timer_list *timer = &dwork->timer; struct work_struct *work = &dwork->work; - if (!test_and_set_bit(WORK_STRUCT_PENDING, work_data_bits(work))) { + if (!test_and_set_bit(WORK_STRUCT_PENDING, &work->management)) { BUG_ON(timer_pending(timer)); BUG_ON(!list_empty(&work->entry)); @@ -321,7 +321,7 @@ static void run_workqueue(struct cpu_workqueue_struct *cwq) spin_unlock_irqrestore(&cwq->lock, flags); BUG_ON(get_wq_data(work) != cwq); - if (!test_bit(WORK_STRUCT_NOAUTOREL, work_data_bits(work))) + if (!test_bit(WORK_STRUCT_NOAUTOREL, &work->management)) work_release(work); f(work); diff --git a/trunk/lib/Kconfig.debug b/trunk/lib/Kconfig.debug index 5c2681875b9a..818e4589f718 100644 --- a/trunk/lib/Kconfig.debug +++ b/trunk/lib/Kconfig.debug @@ -354,6 +354,24 @@ config FRAME_POINTER some architectures or if you use external debuggers. If you don't debug the kernel, you can say N. +config UNWIND_INFO + bool "Compile the kernel with frame unwind information" + depends on !IA64 && !PARISC && !ARM + depends on !MODULES || !(MIPS || PPC || SUPERH || V850) + help + If you say Y here the resulting kernel image will be slightly larger + but not slower, and it will give very useful debugging information. + If you don't debug the kernel, you can say N, but we may not be able + to solve problems without frame unwind information or frame pointers. + +config STACK_UNWIND + bool "Stack unwind support" + depends on UNWIND_INFO + depends on X86 + help + This enables more precise stack traces, omitting all unrelated + occurrences of pointers into kernel code from the dump. + config FORCED_INLINING bool "Force gcc to inline functions marked 'inline'" depends on DEBUG_KERNEL diff --git a/trunk/lib/fault-inject.c b/trunk/lib/fault-inject.c index b5a90fc056d3..d143c0faf248 100644 --- a/trunk/lib/fault-inject.c +++ b/trunk/lib/fault-inject.c @@ -55,7 +55,37 @@ static bool fail_task(struct fault_attr *attr, struct task_struct *task) #define MAX_STACK_TRACE_DEPTH 32 -#if defined(CONFIG_STACKTRACE) +#ifdef CONFIG_STACK_UNWIND + +static asmlinkage int fail_stacktrace_callback(struct unwind_frame_info *info, + void *arg) +{ + int depth; + struct fault_attr *attr = arg; + bool found = (attr->require_start == 0 && attr->require_end == ULONG_MAX); + + for (depth = 0; depth < attr->stacktrace_depth + && unwind(info) == 0 && UNW_PC(info); depth++) { + if (arch_unw_user_mode(info)) + break; + if (attr->reject_start <= UNW_PC(info) && + UNW_PC(info) < attr->reject_end) + return false; + if (attr->require_start <= UNW_PC(info) && + UNW_PC(info) < attr->require_end) + found = true; + } + return found; +} + +static bool fail_stacktrace(struct fault_attr *attr) +{ + struct unwind_frame_info info; + + return unwind_init_running(&info, fail_stacktrace_callback, attr); +} + +#elif defined(CONFIG_STACKTRACE) static bool fail_stacktrace(struct fault_attr *attr) { diff --git a/trunk/mm/mincore.c b/trunk/mm/mincore.c index 8aca6f7167bb..72890780c1c9 100644 --- a/trunk/mm/mincore.c +++ b/trunk/mm/mincore.c @@ -1,7 +1,7 @@ /* * linux/mm/mincore.c * - * Copyright (C) 1994-2006 Linus Torvalds + * Copyright (C) 1994-1999 Linus Torvalds */ /* @@ -38,51 +38,46 @@ static unsigned char mincore_page(struct vm_area_struct * vma, return present; } -/* - * Do a chunk of "sys_mincore()". We've already checked - * all the arguments, we hold the mmap semaphore: we should - * just return the amount of info we're asked for. - */ -static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pages) +static long mincore_vma(struct vm_area_struct * vma, + unsigned long start, unsigned long end, unsigned char __user * vec) { - unsigned long i, nr, pgoff; - struct vm_area_struct *vma = find_vma(current->mm, addr); - - /* - * find_vma() didn't find anything above us, or we're - * in an unmapped hole in the address space: ENOMEM. - */ - if (!vma || addr < vma->vm_start) - return -ENOMEM; + long error, i, remaining; + unsigned char * tmp; - /* - * Ok, got it. But check whether it's a segment we support - * mincore() on. Right now, we don't do any anonymous mappings. - * - * FIXME: This is just stupid. And returning ENOMEM is - * stupid too. We should just look at the page tables. But - * this is what we've traditionally done, so we'll just - * continue doing it. - */ + error = -ENOMEM; if (!vma->vm_file) - return -ENOMEM; + return error; - /* - * Calculate how many pages there are left in the vma, and - * what the pgoff is for our address. - */ - nr = (vma->vm_end - addr) >> PAGE_SHIFT; - if (nr > pages) - nr = pages; + start = ((start - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; + if (end > vma->vm_end) + end = vma->vm_end; + end = ((end - vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff; - pgoff = (addr - vma->vm_start) >> PAGE_SHIFT; - pgoff += vma->vm_pgoff; + error = -EAGAIN; + tmp = (unsigned char *) __get_free_page(GFP_KERNEL); + if (!tmp) + return error; + + /* (end - start) is # of pages, and also # of bytes in "vec */ + remaining = (end - start), + + error = 0; + for (i = 0; remaining > 0; remaining -= PAGE_SIZE, i++) { + int j = 0; + long thispiece = (remaining < PAGE_SIZE) ? + remaining : PAGE_SIZE; + + while (j < thispiece) + tmp[j++] = mincore_page(vma, start++); - /* And then we just fill the sucker in.. */ - for (i = 0 ; i < nr; i++, pgoff++) - vec[i] = mincore_page(vma, pgoff); + if (copy_to_user(vec + PAGE_SIZE * i, tmp, thispiece)) { + error = -EFAULT; + break; + } + } - return nr; + free_page((unsigned long) tmp); + return error; } /* @@ -112,50 +107,82 @@ static long do_mincore(unsigned long addr, unsigned char *vec, unsigned long pag asmlinkage long sys_mincore(unsigned long start, size_t len, unsigned char __user * vec) { - long retval; - unsigned long pages; - unsigned char *tmp; - - /* Check the start address: needs to be page-aligned.. */ + int index = 0; + unsigned long end, limit; + struct vm_area_struct * vma; + size_t max; + int unmapped_error = 0; + long error; + + /* check the arguments */ if (start & ~PAGE_CACHE_MASK) - return -EINVAL; + goto einval; - /* ..and we need to be passed a valid user-space range */ - if (!access_ok(VERIFY_READ, (void __user *) start, len)) - return -ENOMEM; + limit = TASK_SIZE; + if (start >= limit) + goto enomem; - /* This also avoids any overflows on PAGE_CACHE_ALIGN */ - pages = len >> PAGE_SHIFT; - pages += (len & ~PAGE_MASK) != 0; + if (!len) + return 0; - if (!access_ok(VERIFY_WRITE, vec, pages)) - return -EFAULT; + max = limit - start; + len = PAGE_CACHE_ALIGN(len); + if (len > max || !len) + goto enomem; - tmp = (void *) __get_free_page(GFP_USER); - if (!tmp) - return -EAGAIN; - - retval = 0; - while (pages) { - /* - * Do at most PAGE_SIZE entries per iteration, due to - * the temporary buffer size. - */ - down_read(¤t->mm->mmap_sem); - retval = do_mincore(start, tmp, min(pages, PAGE_SIZE)); - up_read(¤t->mm->mmap_sem); - - if (retval <= 0) - break; - if (copy_to_user(vec, tmp, retval)) { - retval = -EFAULT; - break; + end = start + len; + + /* check the output buffer whilst holding the lock */ + error = -EFAULT; + down_read(¤t->mm->mmap_sem); + + if (!access_ok(VERIFY_WRITE, vec, len >> PAGE_SHIFT)) + goto out; + + /* + * If the interval [start,end) covers some unmapped address + * ranges, just ignore them, but return -ENOMEM at the end. + */ + error = 0; + + vma = find_vma(current->mm, start); + while (vma) { + /* Here start < vma->vm_end. */ + if (start < vma->vm_start) { + unmapped_error = -ENOMEM; + start = vma->vm_start; + } + + /* Here vma->vm_start <= start < vma->vm_end. */ + if (end <= vma->vm_end) { + if (start < end) { + error = mincore_vma(vma, start, end, + &vec[index]); + if (error) + goto out; + } + error = unmapped_error; + goto out; } - pages -= retval; - vec += retval; - start += retval << PAGE_SHIFT; - retval = 0; + + /* Here vma->vm_start <= start < vma->vm_end < end. */ + error = mincore_vma(vma, start, vma->vm_end, &vec[index]); + if (error) + goto out; + index += (vma->vm_end - start) >> PAGE_CACHE_SHIFT; + start = vma->vm_end; + vma = vma->vm_next; } - free_page((unsigned long) tmp); - return retval; + + /* we found a hole in the area queried if we arrive here */ + error = -ENOMEM; + +out: + up_read(¤t->mm->mmap_sem); + return error; + +einval: + return -EINVAL; +enomem: + return -ENOMEM; } diff --git a/trunk/net/ax25/af_ax25.c b/trunk/net/ax25/af_ax25.c index 42233df2b099..6cabf6d8a751 100644 --- a/trunk/net/ax25/af_ax25.c +++ b/trunk/net/ax25/af_ax25.c @@ -1088,8 +1088,8 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) /* * FIXME: nonblock behaviour looks like it may have a bug. */ -static int __must_check ax25_connect(struct socket *sock, - struct sockaddr *uaddr, int addr_len, int flags) +static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, + int addr_len, int flags) { struct sock *sk = sock->sk; ax25_cb *ax25 = ax25_sk(sk), *ax25t; diff --git a/trunk/net/ax25/ax25_iface.c b/trunk/net/ax25/ax25_iface.c index aff3e652c2d1..07ac0207eb69 100644 --- a/trunk/net/ax25/ax25_iface.c +++ b/trunk/net/ax25/ax25_iface.c @@ -29,10 +29,17 @@ #include #include -static struct ax25_protocol *protocol_list; +static struct protocol_struct { + struct protocol_struct *next; + unsigned int pid; + int (*func)(struct sk_buff *, ax25_cb *); +} *protocol_list = NULL; static DEFINE_RWLOCK(protocol_list_lock); -static HLIST_HEAD(ax25_linkfail_list); +static struct linkfail_struct { + struct linkfail_struct *next; + void (*func)(ax25_cb *, int); +} *linkfail_list = NULL; static DEFINE_SPINLOCK(linkfail_lock); static struct listen_struct { @@ -42,23 +49,36 @@ static struct listen_struct { } *listen_list = NULL; static DEFINE_SPINLOCK(listen_lock); -/* - * Do not register the internal protocols AX25_P_TEXT, AX25_P_SEGMENT, - * AX25_P_IP or AX25_P_ARP ... - */ -void ax25_register_pid(struct ax25_protocol *ap) +int ax25_protocol_register(unsigned int pid, + int (*func)(struct sk_buff *, ax25_cb *)) { + struct protocol_struct *protocol; + + if (pid == AX25_P_TEXT || pid == AX25_P_SEGMENT) + return 0; +#ifdef CONFIG_INET + if (pid == AX25_P_IP || pid == AX25_P_ARP) + return 0; +#endif + if ((protocol = kmalloc(sizeof(*protocol), GFP_ATOMIC)) == NULL) + return 0; + + protocol->pid = pid; + protocol->func = func; + write_lock_bh(&protocol_list_lock); - ap->next = protocol_list; - protocol_list = ap; + protocol->next = protocol_list; + protocol_list = protocol; write_unlock_bh(&protocol_list_lock); + + return 1; } -EXPORT_SYMBOL_GPL(ax25_register_pid); +EXPORT_SYMBOL(ax25_protocol_register); void ax25_protocol_release(unsigned int pid) { - struct ax25_protocol *s, *protocol; + struct protocol_struct *s, *protocol; write_lock_bh(&protocol_list_lock); protocol = protocol_list; @@ -90,19 +110,54 @@ void ax25_protocol_release(unsigned int pid) EXPORT_SYMBOL(ax25_protocol_release); -void ax25_linkfail_register(struct ax25_linkfail *lf) +int ax25_linkfail_register(void (*func)(ax25_cb *, int)) { + struct linkfail_struct *linkfail; + + if ((linkfail = kmalloc(sizeof(*linkfail), GFP_ATOMIC)) == NULL) + return 0; + + linkfail->func = func; + spin_lock_bh(&linkfail_lock); - hlist_add_head(&lf->lf_node, &ax25_linkfail_list); + linkfail->next = linkfail_list; + linkfail_list = linkfail; spin_unlock_bh(&linkfail_lock); + + return 1; } EXPORT_SYMBOL(ax25_linkfail_register); -void ax25_linkfail_release(struct ax25_linkfail *lf) +void ax25_linkfail_release(void (*func)(ax25_cb *, int)) { + struct linkfail_struct *s, *linkfail; + spin_lock_bh(&linkfail_lock); - hlist_del_init(&lf->lf_node); + linkfail = linkfail_list; + if (linkfail == NULL) { + spin_unlock_bh(&linkfail_lock); + return; + } + + if (linkfail->func == func) { + linkfail_list = linkfail->next; + spin_unlock_bh(&linkfail_lock); + kfree(linkfail); + return; + } + + while (linkfail != NULL && linkfail->next != NULL) { + if (linkfail->next->func == func) { + s = linkfail->next; + linkfail->next = linkfail->next->next; + spin_unlock_bh(&linkfail_lock); + kfree(s); + return; + } + + linkfail = linkfail->next; + } spin_unlock_bh(&linkfail_lock); } @@ -116,7 +171,7 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev) return 0; if ((listen = kmalloc(sizeof(*listen), GFP_ATOMIC)) == NULL) - return -ENOMEM; + return 0; listen->callsign = *callsign; listen->dev = dev; @@ -126,7 +181,7 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev) listen_list = listen; spin_unlock_bh(&listen_lock); - return 0; + return 1; } EXPORT_SYMBOL(ax25_listen_register); @@ -168,7 +223,7 @@ EXPORT_SYMBOL(ax25_listen_release); int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *) { int (*res)(struct sk_buff *, ax25_cb *) = NULL; - struct ax25_protocol *protocol; + struct protocol_struct *protocol; read_lock(&protocol_list_lock); for (protocol = protocol_list; protocol != NULL; protocol = protocol->next) @@ -187,8 +242,7 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev) spin_lock_bh(&listen_lock); for (listen = listen_list; listen != NULL; listen = listen->next) - if (ax25cmp(&listen->callsign, callsign) == 0 && - (listen->dev == dev || listen->dev == NULL)) { + if (ax25cmp(&listen->callsign, callsign) == 0 && (listen->dev == dev || listen->dev == NULL)) { spin_unlock_bh(&listen_lock); return 1; } @@ -199,18 +253,17 @@ int ax25_listen_mine(ax25_address *callsign, struct net_device *dev) void ax25_link_failed(ax25_cb *ax25, int reason) { - struct ax25_linkfail *lf; - struct hlist_node *node; + struct linkfail_struct *linkfail; spin_lock_bh(&linkfail_lock); - hlist_for_each_entry(lf, node, &ax25_linkfail_list, lf_node) - lf->func(ax25, reason); + for (linkfail = linkfail_list; linkfail != NULL; linkfail = linkfail->next) + (linkfail->func)(ax25, reason); spin_unlock_bh(&linkfail_lock); } int ax25_protocol_is_registered(unsigned int pid) { - struct ax25_protocol *protocol; + struct protocol_struct *protocol; int res = 0; read_lock_bh(&protocol_list_lock); diff --git a/trunk/net/ax25/ax25_route.c b/trunk/net/ax25/ax25_route.c index 0a0381622b1c..8580356ace5c 100644 --- a/trunk/net/ax25/ax25_route.c +++ b/trunk/net/ax25/ax25_route.c @@ -71,7 +71,7 @@ void ax25_rt_device_down(struct net_device *dev) write_unlock(&ax25_route_lock); } -static int __must_check ax25_rt_add(struct ax25_routes_struct *route) +static int ax25_rt_add(struct ax25_routes_struct *route) { ax25_route *ax25_rt; ax25_dev *ax25_dev; diff --git a/trunk/net/ipv4/route.c b/trunk/net/ipv4/route.c index 2daa0dc19d33..1aaff0a2e098 100644 --- a/trunk/net/ipv4/route.c +++ b/trunk/net/ipv4/route.c @@ -1325,8 +1325,7 @@ void ip_rt_send_redirect(struct sk_buff *skb) /* Check for load limit; set rate_last to the latest sent * redirect. */ - if (rt->u.dst.rate_tokens == 0 || - time_after(jiffies, + if (time_after(jiffies, (rt->u.dst.rate_last + (ip_rt_redirect_load << rt->u.dst.rate_tokens)))) { icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, rt->rt_gateway); diff --git a/trunk/net/ipv4/tcp_ipv4.c b/trunk/net/ipv4/tcp_ipv4.c index bf7a22412bcb..a1222d6968c4 100644 --- a/trunk/net/ipv4/tcp_ipv4.c +++ b/trunk/net/ipv4/tcp_ipv4.c @@ -928,7 +928,6 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) if (tp->md5sig_info->entries4 == 0) { kfree(tp->md5sig_info->keys4); tp->md5sig_info->keys4 = NULL; - tp->md5sig_info->alloced4 = 0; } else if (tp->md5sig_info->entries4 != i) { /* Need to do some manipulation */ memcpy(&tp->md5sig_info->keys4[i], @@ -1186,7 +1185,7 @@ static int tcp_v4_inbound_md5_hash(struct sock *sk, struct sk_buff *skb) return 0; if (hash_expected && !hash_location) { - LIMIT_NETDEBUG(KERN_INFO "MD5 Hash expected but NOT found " + LIMIT_NETDEBUG(KERN_INFO "MD5 Hash NOT expected but found " "(" NIPQUAD_FMT ", %d)->(" NIPQUAD_FMT ", %d)\n", NIPQUAD(iph->saddr), ntohs(th->source), NIPQUAD(iph->daddr), ntohs(th->dest)); diff --git a/trunk/net/ipv6/netfilter/Kconfig b/trunk/net/ipv6/netfilter/Kconfig index adcd6131df2a..fc3e5eb4bc3f 100644 --- a/trunk/net/ipv6/netfilter/Kconfig +++ b/trunk/net/ipv6/netfilter/Kconfig @@ -7,7 +7,7 @@ menu "IPv6: Netfilter Configuration (EXPERIMENTAL)" config NF_CONNTRACK_IPV6 tristate "IPv6 connection tracking support (EXPERIMENTAL)" - depends on INET && IPV6 && EXPERIMENTAL && NF_CONNTRACK + depends on EXPERIMENTAL && NF_CONNTRACK ---help--- Connection tracking keeps a record of what packets have passed through your machine, in order to figure out how they are related @@ -21,7 +21,6 @@ config NF_CONNTRACK_IPV6 config IP6_NF_QUEUE tristate "IP6 Userspace queueing via NETLINK (OBSOLETE)" - depends on INET && IPV6 && NETFILTER && EXPERIMENTAL ---help--- This option adds a queue handler to the kernel for IPv6 @@ -42,7 +41,7 @@ config IP6_NF_QUEUE config IP6_NF_IPTABLES tristate "IP6 tables support (required for filtering)" - depends on INET && IPV6 && EXPERIMENTAL && NETFILTER_XTABLES + depends on NETFILTER_XTABLES help ip6tables is a general, extensible packet identification framework. Currently only the packet filtering and packet mangling subsystem diff --git a/trunk/net/netrom/af_netrom.c b/trunk/net/netrom/af_netrom.c index 43bbe2c9e49a..1d50f801f181 100644 --- a/trunk/net/netrom/af_netrom.c +++ b/trunk/net/netrom/af_netrom.c @@ -1377,15 +1377,6 @@ static struct notifier_block nr_dev_notifier = { static struct net_device **dev_nr; -static struct ax25_protocol nr_pid = { - .pid = AX25_P_NETROM, - .func = nr_route_frame -}; - -static struct ax25_linkfail nr_linkfail_notifier = { - .func = nr_link_failed, -}; - static int __init nr_proto_init(void) { int i; @@ -1433,8 +1424,8 @@ static int __init nr_proto_init(void) register_netdevice_notifier(&nr_dev_notifier); - ax25_register_pid(&nr_pid); - ax25_linkfail_register(&nr_linkfail_notifier); + ax25_protocol_register(AX25_P_NETROM, nr_route_frame); + ax25_linkfail_register(nr_link_failed); #ifdef CONFIG_SYSCTL nr_register_sysctl(); @@ -1483,7 +1474,7 @@ static void __exit nr_exit(void) nr_unregister_sysctl(); #endif - ax25_linkfail_release(&nr_linkfail_notifier); + ax25_linkfail_release(nr_link_failed); ax25_protocol_release(AX25_P_NETROM); unregister_netdevice_notifier(&nr_dev_notifier); diff --git a/trunk/net/netrom/nr_dev.c b/trunk/net/netrom/nr_dev.c index 4700d5225b78..9b8eb54971ab 100644 --- a/trunk/net/netrom/nr_dev.c +++ b/trunk/net/netrom/nr_dev.c @@ -128,37 +128,25 @@ static int nr_header(struct sk_buff *skb, struct net_device *dev, unsigned short return -37; } -static int __must_check nr_set_mac_address(struct net_device *dev, void *addr) +static int nr_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *sa = addr; - int err; - - if (!memcmp(dev->dev_addr, sa->sa_data, dev->addr_len)) - return 0; - - if (dev->flags & IFF_UP) { - err = ax25_listen_register((ax25_address *)sa->sa_data, NULL); - if (err) - return err; + if (dev->flags & IFF_UP) ax25_listen_release((ax25_address *)dev->dev_addr, NULL); - } memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); + if (dev->flags & IFF_UP) + ax25_listen_register((ax25_address *)dev->dev_addr, NULL); + return 0; } static int nr_open(struct net_device *dev) { - int err; - - err = ax25_listen_register((ax25_address *)dev->dev_addr, NULL); - if (err) - return err; - netif_start_queue(dev); - + ax25_listen_register((ax25_address *)dev->dev_addr, NULL); return 0; } diff --git a/trunk/net/netrom/nr_route.c b/trunk/net/netrom/nr_route.c index 8f88964099ef..0096105bcd47 100644 --- a/trunk/net/netrom/nr_route.c +++ b/trunk/net/netrom/nr_route.c @@ -87,9 +87,8 @@ static void nr_remove_neigh(struct nr_neigh *); * Add a new route to a node, and in the process add the node and the * neighbour if it is new. */ -static int __must_check nr_add_node(ax25_address *nr, const char *mnemonic, - ax25_address *ax25, ax25_digi *ax25_digi, struct net_device *dev, - int quality, int obs_count) +static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax25, + ax25_digi *ax25_digi, struct net_device *dev, int quality, int obs_count) { struct nr_node *nr_node; struct nr_neigh *nr_neigh; @@ -407,8 +406,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n /* * Lock a neighbour with a quality. */ -static int __must_check nr_add_neigh(ax25_address *callsign, - ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality) +static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality) { struct nr_neigh *nr_neigh; @@ -779,13 +777,9 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) nr_src = (ax25_address *)(skb->data + 0); nr_dest = (ax25_address *)(skb->data + 7); - if (ax25 != NULL) { - ret = nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat, - ax25->ax25_dev->dev, 0, - sysctl_netrom_obsolescence_count_initialiser); - if (ret) - return ret; - } + if (ax25 != NULL) + nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat, + ax25->ax25_dev->dev, 0, sysctl_netrom_obsolescence_count_initialiser); if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */ if (ax25 == NULL) /* Its from me */ @@ -850,7 +844,6 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25) ret = (nr_neigh->ax25 != NULL); nr_node_unlock(nr_node); nr_node_put(nr_node); - return ret; } diff --git a/trunk/net/rose/af_rose.c b/trunk/net/rose/af_rose.c index 9e279464c9d1..08a542855654 100644 --- a/trunk/net/rose/af_rose.c +++ b/trunk/net/rose/af_rose.c @@ -1314,8 +1314,7 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) if (copy_from_user(&rose_callsign, argp, sizeof(ax25_address))) return -EFAULT; if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) - return ax25_listen_register(&rose_callsign, NULL); - + ax25_listen_register(&rose_callsign, NULL); return 0; case SIOCRSGL2CALL: @@ -1482,15 +1481,6 @@ static struct notifier_block rose_dev_notifier = { static struct net_device **dev_rose; -static struct ax25_protocol rose_pid = { - .pid = AX25_P_ROSE, - .func = rose_route_frame -}; - -static struct ax25_linkfail rose_linkfail_notifier = { - .func = rose_link_failed -}; - static int __init rose_proto_init(void) { int i; @@ -1540,8 +1530,8 @@ static int __init rose_proto_init(void) sock_register(&rose_family_ops); register_netdevice_notifier(&rose_dev_notifier); - ax25_register_pid(&rose_pid); - ax25_linkfail_register(&rose_linkfail_notifier); + ax25_protocol_register(AX25_P_ROSE, rose_route_frame); + ax25_linkfail_register(rose_link_failed); #ifdef CONFIG_SYSCTL rose_register_sysctl(); @@ -1589,7 +1579,7 @@ static void __exit rose_exit(void) rose_rt_free(); ax25_protocol_release(AX25_P_ROSE); - ax25_linkfail_release(&rose_linkfail_notifier); + ax25_linkfail_release(rose_link_failed); if (ax25cmp(&rose_callsign, &null_ax25_address) != 0) ax25_listen_release(&rose_callsign, NULL); diff --git a/trunk/net/rose/rose_dev.c b/trunk/net/rose/rose_dev.c index 50824d345fa6..7c279e2659ec 100644 --- a/trunk/net/rose/rose_dev.c +++ b/trunk/net/rose/rose_dev.c @@ -93,34 +93,20 @@ static int rose_rebuild_header(struct sk_buff *skb) static int rose_set_mac_address(struct net_device *dev, void *addr) { struct sockaddr *sa = addr; - int err; - if (!memcpy(dev->dev_addr, sa->sa_data, dev->addr_len)) - return 0; - - if (dev->flags & IFF_UP) { - err = rose_add_loopback_node((rose_address *)dev->dev_addr); - if (err) - return err; - - rose_del_loopback_node((rose_address *)dev->dev_addr); - } + rose_del_loopback_node((rose_address *)dev->dev_addr); memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); + rose_add_loopback_node((rose_address *)dev->dev_addr); + return 0; } static int rose_open(struct net_device *dev) { - int err; - - err = rose_add_loopback_node((rose_address *)dev->dev_addr); - if (err) - return err; - netif_start_queue(dev); - + rose_add_loopback_node((rose_address *)dev->dev_addr); return 0; } diff --git a/trunk/net/rose/rose_loopback.c b/trunk/net/rose/rose_loopback.c index 3e41bd93ab9f..103b4d38f88a 100644 --- a/trunk/net/rose/rose_loopback.c +++ b/trunk/net/rose/rose_loopback.c @@ -79,8 +79,7 @@ static void rose_loopback_timer(unsigned long param) skb->h.raw = skb->data; - sk = rose_find_socket(lci_o, &rose_loopback_neigh); - if (sk) { + if ((sk = rose_find_socket(lci_o, rose_loopback_neigh)) != NULL) { if (rose_process_rx_frame(sk, skb) == 0) kfree_skb(skb); continue; @@ -88,7 +87,7 @@ static void rose_loopback_timer(unsigned long param) if (frametype == ROSE_CALL_REQUEST) { if ((dev = rose_dev_get(dest)) != NULL) { - if (rose_rx_call_request(skb, dev, &rose_loopback_neigh, lci_o) == 0) + if (rose_rx_call_request(skb, dev, rose_loopback_neigh, lci_o) == 0) kfree_skb(skb); } else { kfree_skb(skb); diff --git a/trunk/net/rose/rose_route.c b/trunk/net/rose/rose_route.c index 8028c0d425dc..7252344779a0 100644 --- a/trunk/net/rose/rose_route.c +++ b/trunk/net/rose/rose_route.c @@ -46,13 +46,13 @@ static DEFINE_SPINLOCK(rose_neigh_list_lock); static struct rose_route *rose_route_list; static DEFINE_SPINLOCK(rose_route_list_lock); -struct rose_neigh rose_loopback_neigh; +struct rose_neigh *rose_loopback_neigh; /* * Add a new route to a node, and in the process add the node and the * neighbour if it is new. */ -static int __must_check rose_add_node(struct rose_route_struct *rose_route, +static int rose_add_node(struct rose_route_struct *rose_route, struct net_device *dev) { struct rose_node *rose_node, *rose_tmpn, *rose_tmpp; @@ -361,30 +361,33 @@ static int rose_del_node(struct rose_route_struct *rose_route, /* * Add the loopback neighbour. */ -void rose_add_loopback_neigh(void) +int rose_add_loopback_neigh(void) { - struct rose_neigh *sn = &rose_loopback_neigh; + if ((rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_ATOMIC)) == NULL) + return -ENOMEM; - sn->callsign = null_ax25_address; - sn->digipeat = NULL; - sn->ax25 = NULL; - sn->dev = NULL; - sn->count = 0; - sn->use = 0; - sn->dce_mode = 1; - sn->loopback = 1; - sn->number = rose_neigh_no++; - sn->restarted = 1; + rose_loopback_neigh->callsign = null_ax25_address; + rose_loopback_neigh->digipeat = NULL; + rose_loopback_neigh->ax25 = NULL; + rose_loopback_neigh->dev = NULL; + rose_loopback_neigh->count = 0; + rose_loopback_neigh->use = 0; + rose_loopback_neigh->dce_mode = 1; + rose_loopback_neigh->loopback = 1; + rose_loopback_neigh->number = rose_neigh_no++; + rose_loopback_neigh->restarted = 1; - skb_queue_head_init(&sn->queue); + skb_queue_head_init(&rose_loopback_neigh->queue); - init_timer(&sn->ftimer); - init_timer(&sn->t0timer); + init_timer(&rose_loopback_neigh->ftimer); + init_timer(&rose_loopback_neigh->t0timer); spin_lock_bh(&rose_neigh_list_lock); - sn->next = rose_neigh_list; - rose_neigh_list = sn; + rose_loopback_neigh->next = rose_neigh_list; + rose_neigh_list = rose_loopback_neigh; spin_unlock_bh(&rose_neigh_list_lock); + + return 0; } /* @@ -418,13 +421,13 @@ int rose_add_loopback_node(rose_address *address) rose_node->mask = 10; rose_node->count = 1; rose_node->loopback = 1; - rose_node->neighbour[0] = &rose_loopback_neigh; + rose_node->neighbour[0] = rose_loopback_neigh; /* Insert at the head of list. Address is always mask=10 */ rose_node->next = rose_node_list; rose_node_list = rose_node; - rose_loopback_neigh.count++; + rose_loopback_neigh->count++; out: spin_unlock_bh(&rose_node_list_lock); @@ -455,7 +458,7 @@ void rose_del_loopback_node(rose_address *address) rose_remove_node(rose_node); - rose_loopback_neigh.count--; + rose_loopback_neigh->count--; out: spin_unlock_bh(&rose_node_list_lock); diff --git a/trunk/sound/oss/dmasound/tas3001c.c b/trunk/sound/oss/dmasound/tas3001c.c index 2f21a3c00374..f227c9f688cc 100644 --- a/trunk/sound/oss/dmasound/tas3001c.c +++ b/trunk/sound/oss/dmasound/tas3001c.c @@ -50,7 +50,6 @@ struct tas3001c_data_t { int output_id; int speaker_id; struct tas_drce_t drce_state; - struct work_struct change; }; @@ -668,13 +667,14 @@ tas3001c_update_device_parameters(struct tas3001c_data_t *self) } static void -tas3001c_device_change_handler(struct work_struct *work) +tas3001c_device_change_handler(void *self) { - struct tas3001c_data_t *self; - self = container_of(work, struct tas3001c_data_t, change); - tas3001c_update_device_parameters(self); + if (self) + tas3001c_update_device_parameters(self); } +static struct work_struct device_change; + static int tas3001c_output_device_change( struct tas3001c_data_t *self, int device_id, @@ -685,7 +685,7 @@ tas3001c_output_device_change( struct tas3001c_data_t *self, self->output_id=output_id; self->speaker_id=speaker_id; - schedule_work(&self->change); + schedule_work(&device_change); return 0; } @@ -823,7 +823,7 @@ tas3001c_init(struct i2c_client *client) tas3001c_write_biquad_shadow(self, i, j, &tas3001c_eq_unity); - INIT_WORK(&self->change, tas3001c_device_change_handler); + INIT_WORK(&device_change, tas3001c_device_change_handler, self); return 0; } diff --git a/trunk/sound/oss/dmasound/tas3004.c b/trunk/sound/oss/dmasound/tas3004.c index af34fb39bc29..82eaaca2db9a 100644 --- a/trunk/sound/oss/dmasound/tas3004.c +++ b/trunk/sound/oss/dmasound/tas3004.c @@ -48,7 +48,6 @@ struct tas3004_data_t { int output_id; int speaker_id; struct tas_drce_t drce_state; - struct work_struct change; }; #define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000) @@ -915,13 +914,15 @@ tas3004_update_device_parameters(struct tas3004_data_t *self) } static void -tas3004_device_change_handler(struct work_struct *work) +tas3004_device_change_handler(void *self) { - struct tas3004_data_t *self; - self = container_of(work, struct tas3004_data_t, change); - tas3004_update_device_parameters(self); + if (!self) return; + + tas3004_update_device_parameters((struct tas3004_data_t *)self); } +static struct work_struct device_change; + static int tas3004_output_device_change( struct tas3004_data_t *self, int device_id, @@ -932,7 +933,7 @@ tas3004_output_device_change( struct tas3004_data_t *self, self->output_id=output_id; self->speaker_id=speaker_id; - schedule_work(&self->change); + schedule_work(&device_change); return 0; } @@ -1111,7 +1112,7 @@ tas3004_init(struct i2c_client *client) tas3004_write_register(self, TAS3004_REG_MCR2, &mcr2, WRITE_SHADOW); tas3004_write_register(self, TAS3004_REG_DRC, drce_init, WRITE_SHADOW); - INIT_WORK(&self->change, tas3004_device_change_handler); + INIT_WORK(&device_change, tas3004_device_change_handler, self); return 0; }