From d50e15aa0bdfebf70f796f54f8efebd6950f668c Mon Sep 17 00:00:00 2001 From: Hangbin Liu Date: Thu, 26 Jul 2012 22:52:21 +0000 Subject: [PATCH] --- yaml --- r: 319121 b: refs/heads/master c: 42493570100b91ef663c4c6f0c0fdab238f9d3c2 h: refs/heads/master i: 319119: 5f883d012952b545d41feafcd47bb9c068bdf287 v: v3 --- [refs] | 2 +- .../bindings/tty/serial/of-serial.txt | 1 - .../feature-removal-schedule.txt | 8 + trunk/arch/arm/Kconfig | 22 -- trunk/arch/arm/Kconfig.debug | 9 - trunk/arch/arm/Makefile | 3 - trunk/arch/arm/boot/compressed/atags_to_fdt.c | 62 +--- trunk/arch/arm/include/asm/arch_timer.h | 3 - trunk/arch/arm/include/asm/delay.h | 32 +- trunk/arch/arm/include/asm/kmap_types.h | 26 +- trunk/arch/arm/include/asm/locks.h | 274 +++++++++++++++ trunk/arch/arm/include/asm/memory.h | 2 +- trunk/arch/arm/include/asm/perf_event.h | 17 +- trunk/arch/arm/include/asm/pmu.h | 3 +- trunk/arch/arm/include/asm/spinlock.h | 76 ++--- trunk/arch/arm/include/asm/spinlock_types.h | 17 +- trunk/arch/arm/include/asm/timex.h | 10 +- trunk/arch/arm/include/asm/uaccess.h | 27 +- trunk/arch/arm/include/asm/word-at-a-time.h | 96 ------ trunk/arch/arm/kernel/arch_timer.c | 13 +- trunk/arch/arm/kernel/armksyms.c | 7 +- trunk/arch/arm/kernel/entry-common.S | 20 +- trunk/arch/arm/kernel/head.S | 59 ++-- trunk/arch/arm/kernel/perf_event.c | 15 +- trunk/arch/arm/kernel/perf_event_v6.c | 2 + trunk/arch/arm/kernel/perf_event_v7.c | 5 + trunk/arch/arm/kernel/perf_event_xscale.c | 2 + trunk/arch/arm/kernel/ptrace.c | 34 +- trunk/arch/arm/kernel/smp.c | 2 +- trunk/arch/arm/kernel/topology.c | 239 ++----------- trunk/arch/arm/kernel/traps.c | 78 ++--- trunk/arch/arm/lib/Makefile | 3 +- trunk/arch/arm/lib/{delay-loop.S => delay.S} | 20 +- trunk/arch/arm/lib/delay.c | 71 ---- trunk/arch/arm/lib/strncpy_from_user.S | 43 +++ trunk/arch/arm/lib/strnlen_user.S | 40 +++ trunk/arch/arm/mach-msm/platsmp.c | 2 +- trunk/arch/arm/mach-omap2/omap-smp.c | 2 +- .../arch/arm/mach-pxa/include/mach/regs-ost.h | 22 +- trunk/arch/arm/mach-pxa/reset.c | 7 +- trunk/arch/arm/mach-pxa/time.c | 52 +-- trunk/arch/arm/mach-sa1100/assabet.c | 2 +- trunk/arch/arm/mach-sa1100/cpu-sa1100.c | 1 - trunk/arch/arm/mach-sa1100/cpu-sa1110.c | 1 - .../arm/mach-sa1100/include/mach/SA-1100.h | 16 +- .../arch/arm/mach-sa1100/include/mach/gpio.h | 1 - .../arm/mach-sa1100/include/mach/hardware.h | 6 +- .../arm/mach-sa1100/include/mach/uncompress.h | 2 - trunk/arch/arm/mach-sa1100/irq.c | 1 - trunk/arch/arm/mach-sa1100/jornada720_ssp.c | 1 - trunk/arch/arm/mach-sa1100/leds-cerf.c | 1 - trunk/arch/arm/mach-sa1100/leds-lart.c | 1 - trunk/arch/arm/mach-sa1100/pm.c | 1 - trunk/arch/arm/mach-sa1100/sleep.S | 8 +- trunk/arch/arm/mach-sa1100/time.c | 48 +-- trunk/arch/arm/mm/context.c | 35 -- trunk/arch/arm/mm/dma-mapping.c | 2 +- trunk/arch/arm/mm/init.c | 2 +- trunk/arch/arm/mm/ioremap.c | 2 +- trunk/arch/arm/mm/mmu.c | 8 +- trunk/arch/arm/mm/proc-v6.S | 6 - trunk/arch/arm/mm/proc-v7-2level.S | 5 - trunk/arch/arm/oprofile/common.c | 45 +-- trunk/arch/arm/plat-versatile/platsmp.c | 2 +- trunk/arch/avr32/include/asm/kmap_types.h | 24 +- trunk/arch/frv/include/asm/highmem.h | 34 +- trunk/arch/frv/include/asm/kmap_types.h | 24 +- trunk/arch/frv/mb93090-mb00/pci-dma.c | 4 +- trunk/arch/frv/mm/cache-page.c | 8 +- trunk/arch/frv/mm/highmem.c | 20 +- trunk/arch/powerpc/include/asm/kmap_types.h | 31 +- trunk/arch/tile/include/asm/kmap_types.h | 31 +- trunk/arch/tile/mm/highmem.c | 2 +- trunk/arch/um/include/asm/kmap_types.h | 18 +- trunk/drivers/amba/bus.c | 2 +- .../drivers/input/touchscreen/jornada720_ts.c | 1 - trunk/drivers/net/irda/pxaficp_ir.c | 12 +- trunk/drivers/pcmcia/sa1100_shannon.c | 1 - trunk/drivers/tty/serial/8250/8250.c | 8 - trunk/drivers/tty/serial/amba-pl011.c | 2 +- trunk/drivers/tty/serial/of_serial.c | 1 - trunk/drivers/tty/serial/pch_uart.c | 59 ++-- trunk/drivers/tty/serial/samsung.c | 4 +- trunk/drivers/tty/serial/serial_core.c | 6 +- trunk/drivers/tty/tty_ldisc.c | 2 +- trunk/drivers/tty/vt/vt_ioctl.c | 47 +-- trunk/drivers/watchdog/sa1100_wdt.c | 14 +- trunk/fs/ext4/balloc.c | 3 +- trunk/fs/ext4/bitmap.c | 12 +- trunk/fs/ext4/ext4.h | 26 +- trunk/fs/ext4/ext4_jbd2.c | 8 +- trunk/fs/ext4/ext4_jbd2.h | 25 +- trunk/fs/ext4/extents.c | 51 ++- trunk/fs/ext4/file.c | 121 ++----- trunk/fs/ext4/ialloc.c | 5 +- trunk/fs/ext4/inode.c | 126 ++----- trunk/fs/ext4/mballoc.c | 26 +- trunk/fs/ext4/namei.c | 15 +- trunk/fs/ext4/resize.c | 7 +- trunk/fs/ext4/super.c | 323 ++++-------------- trunk/fs/ext4/xattr.c | 11 +- trunk/fs/jbd2/commit.c | 4 +- trunk/fs/pipe.c | 2 +- trunk/include/asm-generic/kmap_types.h | 34 +- trunk/include/asm-generic/sizes.h | 49 ++- trunk/include/linux/highmem.h | 41 ++- trunk/include/linux/pipe_fs_i.h | 8 +- trunk/include/linux/serial_core.h | 3 +- trunk/include/linux/sizes.h | 47 --- trunk/init/Kconfig | 2 +- trunk/mm/vmalloc.c | 8 +- trunk/net/ipv4/tcp.c | 5 +- 112 files changed, 1276 insertions(+), 1666 deletions(-) create mode 100644 trunk/arch/arm/include/asm/locks.h delete mode 100644 trunk/arch/arm/include/asm/word-at-a-time.h rename trunk/arch/arm/lib/{delay-loop.S => delay.S} (81%) delete mode 100644 trunk/arch/arm/lib/delay.c create mode 100644 trunk/arch/arm/lib/strncpy_from_user.S create mode 100644 trunk/arch/arm/lib/strnlen_user.S delete mode 100644 trunk/include/linux/sizes.h diff --git a/[refs] b/[refs] index efd90b062f97..a4690c16fd1a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 173f8654746c138a08f51a8a0db7747763a896a2 +refs/heads/master: 42493570100b91ef663c4c6f0c0fdab238f9d3c2 diff --git a/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt b/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt index 0847fdeee11a..b8b27b0aca10 100644 --- a/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt +++ b/trunk/Documentation/devicetree/bindings/tty/serial/of-serial.txt @@ -9,7 +9,6 @@ Required properties: - "ns16750" - "ns16850" - "nvidia,tegra20-uart" - - "nxp,lpc3220-uart" - "ibm,qpace-nwp-serial" - "serial" if the port type is unknown. - reg : offset and length of the register set for the device. diff --git a/trunk/Documentation/feature-removal-schedule.txt b/trunk/Documentation/feature-removal-schedule.txt index 76112dac7659..61d1a89baeaf 100644 --- a/trunk/Documentation/feature-removal-schedule.txt +++ b/trunk/Documentation/feature-removal-schedule.txt @@ -512,6 +512,14 @@ Who: Sebastian Andrzej Siewior ---------------------------- +What: kmap_atomic(page, km_type) +When: 3.5 +Why: The old kmap_atomic() with two arguments is deprecated, we only + keep it for backward compatibility for few cycles and then drop it. +Who: Cong Wang + +---------------------------- + What: get_robust_list syscall When: 2013 Why: There appear to be no production users of the get_robust_list syscall, diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index fbdd8533c05d..9124ff75fe53 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -45,9 +45,6 @@ config ARM select GENERIC_SMP_IDLE_THREAD select KTIME_SCALAR select GENERIC_CLOCKEVENTS_BROADCAST if SMP - select GENERIC_STRNCPY_FROM_USER - select GENERIC_STRNLEN_USER - select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN help The ARM series is a line of low-power-consumption RISC chip designs licensed by ARM Ltd and targeted at embedded applications and @@ -2007,25 +2004,6 @@ config ARM_ATAG_DTB_COMPAT bootloaders, this option allows zImage to extract the information from the ATAG list and store it at run time into the appended DTB. -choice - prompt "Kernel command line type" if ARM_ATAG_DTB_COMPAT - default ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER - -config ARM_ATAG_DTB_COMPAT_CMDLINE_FROM_BOOTLOADER - bool "Use bootloader kernel arguments if available" - help - Uses the command-line options passed by the boot loader instead of - the device tree bootargs property. If the boot loader doesn't provide - any, the device tree bootargs property will be used. - -config ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND - bool "Extend with bootloader kernel arguments" - help - The command-line arguments provided by the boot loader will be - appended to the the device tree bootargs property. - -endchoice - config CMDLINE string "Default kernel command string" default "" diff --git a/trunk/arch/arm/Kconfig.debug b/trunk/arch/arm/Kconfig.debug index f15f82bf3a50..a03b5a7059e2 100644 --- a/trunk/arch/arm/Kconfig.debug +++ b/trunk/arch/arm/Kconfig.debug @@ -395,13 +395,4 @@ config ARM_KPROBES_TEST help Perform tests of kprobes API and instruction set simulation. -config PID_IN_CONTEXTIDR - bool "Write the current PID to the CONTEXTIDR register" - depends on CPU_COPY_V6 - help - Enabling this option causes the kernel to write the current PID to - the PROCID field of the CONTEXTIDR register, at the expense of some - additional instructions during context switch. Say Y here only if you - are planning to use hardware trace tools with this kernel. - endmenu diff --git a/trunk/arch/arm/Makefile b/trunk/arch/arm/Makefile index 30eae87ead6d..4d6d31115cf2 100644 --- a/trunk/arch/arm/Makefile +++ b/trunk/arch/arm/Makefile @@ -10,9 +10,6 @@ # # Copyright (C) 1995-2001 by Russell King -# Ensure linker flags are correct -LDFLAGS := - LDFLAGS_vmlinux :=-p --no-undefined -X ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 diff --git a/trunk/arch/arm/boot/compressed/atags_to_fdt.c b/trunk/arch/arm/boot/compressed/atags_to_fdt.c index aabc02a68482..797f04bedb47 100644 --- a/trunk/arch/arm/boot/compressed/atags_to_fdt.c +++ b/trunk/arch/arm/boot/compressed/atags_to_fdt.c @@ -1,12 +1,6 @@ #include #include -#if defined(CONFIG_ARM_ATAG_DTB_COMPAT_CMDLINE_EXTEND) -#define do_extend_cmdline 1 -#else -#define do_extend_cmdline 0 -#endif - static int node_offset(void *fdt, const char *node_path) { int offset = fdt_path_offset(fdt, node_path); @@ -42,48 +36,6 @@ static int setprop_cell(void *fdt, const char *node_path, return fdt_setprop_cell(fdt, offset, property, val); } -static const void *getprop(const void *fdt, const char *node_path, - const char *property, int *len) -{ - int offset = fdt_path_offset(fdt, node_path); - - if (offset == -FDT_ERR_NOTFOUND) - return NULL; - - return fdt_getprop(fdt, offset, property, len); -} - -static void merge_fdt_bootargs(void *fdt, const char *fdt_cmdline) -{ - char cmdline[COMMAND_LINE_SIZE]; - const char *fdt_bootargs; - char *ptr = cmdline; - int len = 0; - - /* copy the fdt command line into the buffer */ - fdt_bootargs = getprop(fdt, "/chosen", "bootargs", &len); - if (fdt_bootargs) - if (len < COMMAND_LINE_SIZE) { - memcpy(ptr, fdt_bootargs, len); - /* len is the length of the string - * including the NULL terminator */ - ptr += len - 1; - } - - /* and append the ATAG_CMDLINE */ - if (fdt_cmdline) { - len = strlen(fdt_cmdline); - if (ptr - cmdline + len + 2 < COMMAND_LINE_SIZE) { - *ptr++ = ' '; - memcpy(ptr, fdt_cmdline, len); - ptr += len; - } - } - *ptr = '\0'; - - setprop_string(fdt, "/chosen", "bootargs", cmdline); -} - /* * Convert and fold provided ATAGs into the provided FDT. * @@ -120,18 +72,8 @@ int atags_to_fdt(void *atag_list, void *fdt, int total_space) for_each_tag(atag, atag_list) { if (atag->hdr.tag == ATAG_CMDLINE) { - /* Append the ATAGS command line to the device tree - * command line. - * NB: This means that if the same parameter is set in - * the device tree and in the tags, the one from the - * tags will be chosen. - */ - if (do_extend_cmdline) - merge_fdt_bootargs(fdt, - atag->u.cmdline.cmdline); - else - setprop_string(fdt, "/chosen", "bootargs", - atag->u.cmdline.cmdline); + setprop_string(fdt, "/chosen", "bootargs", + atag->u.cmdline.cmdline); } else if (atag->hdr.tag == ATAG_MEM) { if (memcount >= sizeof(mem_reg_property)/4) continue; diff --git a/trunk/arch/arm/include/asm/arch_timer.h b/trunk/arch/arm/include/asm/arch_timer.h index 62e75475e57e..ed2e95d46e29 100644 --- a/trunk/arch/arm/include/asm/arch_timer.h +++ b/trunk/arch/arm/include/asm/arch_timer.h @@ -1,10 +1,7 @@ #ifndef __ASMARM_ARCH_TIMER_H #define __ASMARM_ARCH_TIMER_H -#include - #ifdef CONFIG_ARM_ARCH_TIMER -#define ARCH_HAS_READ_CURRENT_TIMER int arch_timer_of_register(void); int arch_timer_sched_clock_init(void); #else diff --git a/trunk/arch/arm/include/asm/delay.h b/trunk/arch/arm/include/asm/delay.h index dc6145120de3..b2deda181549 100644 --- a/trunk/arch/arm/include/asm/delay.h +++ b/trunk/arch/arm/include/asm/delay.h @@ -6,22 +6,9 @@ #ifndef __ASM_ARM_DELAY_H #define __ASM_ARM_DELAY_H -#include #include /* HZ */ -#define MAX_UDELAY_MS 2 -#define UDELAY_MULT ((UL(2199023) * HZ) >> 11) -#define UDELAY_SHIFT 30 - -#ifndef __ASSEMBLY__ - -extern struct arm_delay_ops { - void (*delay)(unsigned long); - void (*const_udelay)(unsigned long); - void (*udelay)(unsigned long); -} arm_delay_ops; - -#define __delay(n) arm_delay_ops.delay(n) +extern void __delay(int loops); /* * This function intentionally does not exist; if you see references to @@ -36,27 +23,22 @@ extern void __bad_udelay(void); * division by multiplication: you don't have to worry about * loss of precision. * - * Use only for very small delays ( < 2 msec). Should probably use a + * Use only for very small delays ( < 1 msec). Should probably use a * lookup table, really, as the multiplications take much too long with * short delays. This is a "reasonable" implementation, though (and the * first constant multiplications gets optimized away if the delay is * a constant) */ -#define __udelay(n) arm_delay_ops.udelay(n) -#define __const_udelay(n) arm_delay_ops.const_udelay(n) +extern void __udelay(unsigned long usecs); +extern void __const_udelay(unsigned long); + +#define MAX_UDELAY_MS 2 #define udelay(n) \ (__builtin_constant_p(n) ? \ ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() : \ - __const_udelay((n) * UDELAY_MULT)) : \ + __const_udelay((n) * ((2199023U*HZ)>>11))) : \ __udelay(n)) -/* Loop-based definitions for assembly code. */ -extern void __loop_delay(unsigned long loops); -extern void __loop_udelay(unsigned long usecs); -extern void __loop_const_udelay(unsigned long); - -#endif /* __ASSEMBLY__ */ - #endif /* defined(_ARM_DELAY_H) */ diff --git a/trunk/arch/arm/include/asm/kmap_types.h b/trunk/arch/arm/include/asm/kmap_types.h index 83eb2f772911..e51b1e81df05 100644 --- a/trunk/arch/arm/include/asm/kmap_types.h +++ b/trunk/arch/arm/include/asm/kmap_types.h @@ -4,6 +4,30 @@ /* * This is the "bare minimum". AIO seems to require this. */ -#define KM_TYPE_NR 16 +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_L1_CACHE, + KM_L2_CACHE, + KM_KDB, + KM_TYPE_NR +}; + +#ifdef CONFIG_DEBUG_HIGHMEM +#define KM_NMI (-1) +#define KM_NMI_PTE (-1) +#define KM_IRQ_PTE (-1) +#endif #endif diff --git a/trunk/arch/arm/include/asm/locks.h b/trunk/arch/arm/include/asm/locks.h new file mode 100644 index 000000000000..ef4c897772d1 --- /dev/null +++ b/trunk/arch/arm/include/asm/locks.h @@ -0,0 +1,274 @@ +/* + * arch/arm/include/asm/locks.h + * + * Copyright (C) 2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Interrupt safe locking assembler. + */ +#ifndef __ASM_PROC_LOCKS_H +#define __ASM_PROC_LOCKS_H + +#if __LINUX_ARM_ARCH__ >= 6 + +#define __down_op(ptr,fail) \ + ({ \ + __asm__ __volatile__( \ + "@ down_op\n" \ +"1: ldrex lr, [%0]\n" \ +" sub lr, lr, %1\n" \ +" strex ip, lr, [%0]\n" \ +" teq ip, #0\n" \ +" bne 1b\n" \ +" teq lr, #0\n" \ +" movmi ip, %0\n" \ +" blmi " #fail \ + : \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + }) + +#define __down_op_ret(ptr,fail) \ + ({ \ + unsigned int ret; \ + __asm__ __volatile__( \ + "@ down_op_ret\n" \ +"1: ldrex lr, [%1]\n" \ +" sub lr, lr, %2\n" \ +" strex ip, lr, [%1]\n" \ +" teq ip, #0\n" \ +" bne 1b\n" \ +" teq lr, #0\n" \ +" movmi ip, %1\n" \ +" movpl ip, #0\n" \ +" blmi " #fail "\n" \ +" mov %0, ip" \ + : "=&r" (ret) \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + ret; \ + }) + +#define __up_op(ptr,wake) \ + ({ \ + smp_mb(); \ + __asm__ __volatile__( \ + "@ up_op\n" \ +"1: ldrex lr, [%0]\n" \ +" add lr, lr, %1\n" \ +" strex ip, lr, [%0]\n" \ +" teq ip, #0\n" \ +" bne 1b\n" \ +" cmp lr, #0\n" \ +" movle ip, %0\n" \ +" blle " #wake \ + : \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + }) + +/* + * The value 0x01000000 supports up to 128 processors and + * lots of processes. BIAS must be chosen such that sub'ing + * BIAS once per CPU will result in the long remaining + * negative. + */ +#define RW_LOCK_BIAS 0x01000000 +#define RW_LOCK_BIAS_STR "0x01000000" + +#define __down_op_write(ptr,fail) \ + ({ \ + __asm__ __volatile__( \ + "@ down_op_write\n" \ +"1: ldrex lr, [%0]\n" \ +" sub lr, lr, %1\n" \ +" strex ip, lr, [%0]\n" \ +" teq ip, #0\n" \ +" bne 1b\n" \ +" teq lr, #0\n" \ +" movne ip, %0\n" \ +" blne " #fail \ + : \ + : "r" (ptr), "I" (RW_LOCK_BIAS) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + }) + +#define __up_op_write(ptr,wake) \ + ({ \ + smp_mb(); \ + __asm__ __volatile__( \ + "@ up_op_write\n" \ +"1: ldrex lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" strex ip, lr, [%0]\n" \ +" teq ip, #0\n" \ +" bne 1b\n" \ +" movcs ip, %0\n" \ +" blcs " #wake \ + : \ + : "r" (ptr), "I" (RW_LOCK_BIAS) \ + : "ip", "lr", "cc"); \ + }) + +#define __down_op_read(ptr,fail) \ + __down_op(ptr, fail) + +#define __up_op_read(ptr,wake) \ + ({ \ + smp_mb(); \ + __asm__ __volatile__( \ + "@ up_op_read\n" \ +"1: ldrex lr, [%0]\n" \ +" add lr, lr, %1\n" \ +" strex ip, lr, [%0]\n" \ +" teq ip, #0\n" \ +" bne 1b\n" \ +" teq lr, #0\n" \ +" moveq ip, %0\n" \ +" bleq " #wake \ + : \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + }) + +#else + +#define __down_op(ptr,fail) \ + ({ \ + __asm__ __volatile__( \ + "@ down_op\n" \ +" mrs ip, cpsr\n" \ +" orr lr, ip, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" subs lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, ip\n" \ +" movmi ip, %0\n" \ +" blmi " #fail \ + : \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + }) + +#define __down_op_ret(ptr,fail) \ + ({ \ + unsigned int ret; \ + __asm__ __volatile__( \ + "@ down_op_ret\n" \ +" mrs ip, cpsr\n" \ +" orr lr, ip, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%1]\n" \ +" subs lr, lr, %2\n" \ +" str lr, [%1]\n" \ +" msr cpsr_c, ip\n" \ +" movmi ip, %1\n" \ +" movpl ip, #0\n" \ +" blmi " #fail "\n" \ +" mov %0, ip" \ + : "=&r" (ret) \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + ret; \ + }) + +#define __up_op(ptr,wake) \ + ({ \ + smp_mb(); \ + __asm__ __volatile__( \ + "@ up_op\n" \ +" mrs ip, cpsr\n" \ +" orr lr, ip, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, ip\n" \ +" movle ip, %0\n" \ +" blle " #wake \ + : \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + }) + +/* + * The value 0x01000000 supports up to 128 processors and + * lots of processes. BIAS must be chosen such that sub'ing + * BIAS once per CPU will result in the long remaining + * negative. + */ +#define RW_LOCK_BIAS 0x01000000 +#define RW_LOCK_BIAS_STR "0x01000000" + +#define __down_op_write(ptr,fail) \ + ({ \ + __asm__ __volatile__( \ + "@ down_op_write\n" \ +" mrs ip, cpsr\n" \ +" orr lr, ip, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" subs lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, ip\n" \ +" movne ip, %0\n" \ +" blne " #fail \ + : \ + : "r" (ptr), "I" (RW_LOCK_BIAS) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + }) + +#define __up_op_write(ptr,wake) \ + ({ \ + __asm__ __volatile__( \ + "@ up_op_write\n" \ +" mrs ip, cpsr\n" \ +" orr lr, ip, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, ip\n" \ +" movcs ip, %0\n" \ +" blcs " #wake \ + : \ + : "r" (ptr), "I" (RW_LOCK_BIAS) \ + : "ip", "lr", "cc"); \ + smp_mb(); \ + }) + +#define __down_op_read(ptr,fail) \ + __down_op(ptr, fail) + +#define __up_op_read(ptr,wake) \ + ({ \ + smp_mb(); \ + __asm__ __volatile__( \ + "@ up_op_read\n" \ +" mrs ip, cpsr\n" \ +" orr lr, ip, #128\n" \ +" msr cpsr_c, lr\n" \ +" ldr lr, [%0]\n" \ +" adds lr, lr, %1\n" \ +" str lr, [%0]\n" \ +" msr cpsr_c, ip\n" \ +" moveq ip, %0\n" \ +" bleq " #wake \ + : \ + : "r" (ptr), "I" (1) \ + : "ip", "lr", "cc"); \ + }) + +#endif + +#endif diff --git a/trunk/arch/arm/include/asm/memory.h b/trunk/arch/arm/include/asm/memory.h index e965f1b560f1..fcb575747e5e 100644 --- a/trunk/arch/arm/include/asm/memory.h +++ b/trunk/arch/arm/include/asm/memory.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #ifdef CONFIG_NEED_MACH_MEMORY_H #include diff --git a/trunk/arch/arm/include/asm/perf_event.h b/trunk/arch/arm/include/asm/perf_event.h index e074948d8143..00cbe10a50e3 100644 --- a/trunk/arch/arm/include/asm/perf_event.h +++ b/trunk/arch/arm/include/asm/perf_event.h @@ -12,6 +12,21 @@ #ifndef __ARM_PERF_EVENT_H__ #define __ARM_PERF_EVENT_H__ -/* Nothing to see here... */ +/* ARM perf PMU IDs for use by internal perf clients. */ +enum arm_perf_pmu_ids { + ARM_PERF_PMU_ID_XSCALE1 = 0, + ARM_PERF_PMU_ID_XSCALE2, + ARM_PERF_PMU_ID_V6, + ARM_PERF_PMU_ID_V6MP, + ARM_PERF_PMU_ID_CA8, + ARM_PERF_PMU_ID_CA9, + ARM_PERF_PMU_ID_CA5, + ARM_PERF_PMU_ID_CA15, + ARM_PERF_PMU_ID_CA7, + ARM_NUM_PMU_IDS, +}; + +extern enum arm_perf_pmu_ids +armpmu_get_pmu_id(void); #endif /* __ARM_PERF_EVENT_H__ */ diff --git a/trunk/arch/arm/include/asm/pmu.h b/trunk/arch/arm/include/asm/pmu.h index 4432305f4a2a..90114faa9f3c 100644 --- a/trunk/arch/arm/include/asm/pmu.h +++ b/trunk/arch/arm/include/asm/pmu.h @@ -103,9 +103,10 @@ struct pmu_hw_events { struct arm_pmu { struct pmu pmu; + enum arm_perf_pmu_ids id; enum arm_pmu_type type; cpumask_t active_irqs; - char *name; + const char *name; irqreturn_t (*handle_irq)(int irq_num, void *dev); void (*enable)(struct hw_perf_event *evt, int idx); void (*disable)(struct hw_perf_event *evt, int idx); diff --git a/trunk/arch/arm/include/asm/spinlock.h b/trunk/arch/arm/include/asm/spinlock.h index b4ca707d0a69..65fa3c88095c 100644 --- a/trunk/arch/arm/include/asm/spinlock.h +++ b/trunk/arch/arm/include/asm/spinlock.h @@ -59,13 +59,18 @@ static inline void dsb_sev(void) } /* - * ARMv6 ticket-based spin-locking. + * ARMv6 Spin-locking. * - * A memory barrier is required after we get a lock, and before we - * release it, because V6 CPUs are assumed to have weakly ordered - * memory. + * We exclusively read the old value. If it is zero, we may have + * won the lock, so we try exclusively storing it. A memory barrier + * is required after we get a lock, and before we release it, because + * V6 CPUs are assumed to have weakly ordered memory. + * + * Unlocked value: 0 + * Locked value: 1 */ +#define arch_spin_is_locked(x) ((x)->lock != 0) #define arch_spin_unlock_wait(lock) \ do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0) @@ -74,39 +79,31 @@ static inline void dsb_sev(void) static inline void arch_spin_lock(arch_spinlock_t *lock) { unsigned long tmp; - u32 newval; - arch_spinlock_t lockval; __asm__ __volatile__( -"1: ldrex %0, [%3]\n" -" add %1, %0, %4\n" -" strex %2, %1, [%3]\n" -" teq %2, #0\n" +"1: ldrex %0, [%1]\n" +" teq %0, #0\n" + WFE("ne") +" strexeq %0, %2, [%1]\n" +" teqeq %0, #0\n" " bne 1b" - : "=&r" (lockval), "=&r" (newval), "=&r" (tmp) - : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) + : "=&r" (tmp) + : "r" (&lock->lock), "r" (1) : "cc"); - while (lockval.tickets.next != lockval.tickets.owner) { - wfe(); - lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner); - } - smp_mb(); } static inline int arch_spin_trylock(arch_spinlock_t *lock) { unsigned long tmp; - u32 slock; __asm__ __volatile__( -" ldrex %0, [%2]\n" -" subs %1, %0, %0, ror #16\n" -" addeq %0, %0, %3\n" -" strexeq %1, %0, [%2]" - : "=&r" (slock), "=&r" (tmp) - : "r" (&lock->slock), "I" (1 << TICKET_SHIFT) +" ldrex %0, [%1]\n" +" teq %0, #0\n" +" strexeq %0, %2, [%1]" + : "=&r" (tmp) + : "r" (&lock->lock), "r" (1) : "cc"); if (tmp == 0) { @@ -119,38 +116,17 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) static inline void arch_spin_unlock(arch_spinlock_t *lock) { - unsigned long tmp; - u32 slock; - smp_mb(); __asm__ __volatile__( -" mov %1, #1\n" -"1: ldrex %0, [%2]\n" -" uadd16 %0, %0, %1\n" -" strex %1, %0, [%2]\n" -" teq %1, #0\n" -" bne 1b" - : "=&r" (slock), "=&r" (tmp) - : "r" (&lock->slock) +" str %1, [%0]\n" + : + : "r" (&lock->lock), "r" (0) : "cc"); dsb_sev(); } -static inline int arch_spin_is_locked(arch_spinlock_t *lock) -{ - struct __raw_tickets tickets = ACCESS_ONCE(lock->tickets); - return tickets.owner != tickets.next; -} - -static inline int arch_spin_is_contended(arch_spinlock_t *lock) -{ - struct __raw_tickets tickets = ACCESS_ONCE(lock->tickets); - return (tickets.next - tickets.owner) > 1; -} -#define arch_spin_is_contended arch_spin_is_contended - /* * RWLOCKS * @@ -182,7 +158,7 @@ static inline int arch_write_trylock(arch_rwlock_t *rw) unsigned long tmp; __asm__ __volatile__( -" ldrex %0, [%1]\n" +"1: ldrex %0, [%1]\n" " teq %0, #0\n" " strexeq %0, %2, [%1]" : "=&r" (tmp) @@ -268,7 +244,7 @@ static inline int arch_read_trylock(arch_rwlock_t *rw) unsigned long tmp, tmp2 = 1; __asm__ __volatile__( -" ldrex %0, [%2]\n" +"1: ldrex %0, [%2]\n" " adds %0, %0, #1\n" " strexpl %1, %0, [%2]\n" : "=&r" (tmp), "+r" (tmp2) diff --git a/trunk/arch/arm/include/asm/spinlock_types.h b/trunk/arch/arm/include/asm/spinlock_types.h index b262d2f8b478..d14d197ae04a 100644 --- a/trunk/arch/arm/include/asm/spinlock_types.h +++ b/trunk/arch/arm/include/asm/spinlock_types.h @@ -5,24 +5,11 @@ # error "please don't include this file directly" #endif -#define TICKET_SHIFT 16 - typedef struct { - union { - u32 slock; - struct __raw_tickets { -#ifdef __ARMEB__ - u16 next; - u16 owner; -#else - u16 owner; - u16 next; -#endif - } tickets; - }; + volatile unsigned int lock; } arch_spinlock_t; -#define __ARCH_SPIN_LOCK_UNLOCKED { { 0 } } +#define __ARCH_SPIN_LOCK_UNLOCKED { 0 } typedef struct { volatile unsigned int lock; diff --git a/trunk/arch/arm/include/asm/timex.h b/trunk/arch/arm/include/asm/timex.h index ce119442277c..3be8de3adaba 100644 --- a/trunk/arch/arm/include/asm/timex.h +++ b/trunk/arch/arm/include/asm/timex.h @@ -12,15 +12,13 @@ #ifndef _ASMARM_TIMEX_H #define _ASMARM_TIMEX_H -#include #include typedef unsigned long cycles_t; -#ifdef ARCH_HAS_READ_CURRENT_TIMER -#define get_cycles() ({ cycles_t c; read_current_timer(&c) ? 0 : c; }) -#else -#define get_cycles() (0) -#endif +static inline cycles_t get_cycles (void) +{ + return 0; +} #endif diff --git a/trunk/arch/arm/include/asm/uaccess.h b/trunk/arch/arm/include/asm/uaccess.h index 479a6352e0b5..71f6536d17ac 100644 --- a/trunk/arch/arm/include/asm/uaccess.h +++ b/trunk/arch/arm/include/asm/uaccess.h @@ -189,9 +189,6 @@ static inline void set_fs(mm_segment_t fs) #define access_ok(type,addr,size) (__range_ok(addr,size) == 0) -#define user_addr_max() \ - (segment_eq(get_fs(), USER_DS) ? TASK_SIZE : ~0UL) - /* * The "__xxx" versions of the user access functions do not verify the * address space - it must have been done previously with a separate @@ -401,6 +398,9 @@ extern unsigned long __must_check __clear_user_std(void __user *addr, unsigned l #define __clear_user(addr,n) (memset((void __force *)addr, 0, n), 0) #endif +extern unsigned long __must_check __strncpy_from_user(char *to, const char __user *from, unsigned long count); +extern unsigned long __must_check __strnlen_user(const char __user *s, long n); + static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { if (access_ok(VERIFY_READ, from, n)) @@ -427,9 +427,24 @@ static inline unsigned long __must_check clear_user(void __user *to, unsigned lo return n; } -extern long strncpy_from_user(char *dest, const char __user *src, long count); +static inline long __must_check strncpy_from_user(char *dst, const char __user *src, long count) +{ + long res = -EFAULT; + if (access_ok(VERIFY_READ, src, 1)) + res = __strncpy_from_user(dst, src, count); + return res; +} + +#define strlen_user(s) strnlen_user(s, ~0UL >> 1) -extern __must_check long strlen_user(const char __user *str); -extern __must_check long strnlen_user(const char __user *str, long n); +static inline long __must_check strnlen_user(const char __user *s, long n) +{ + unsigned long res = 0; + + if (__addr_ok(s)) + res = __strnlen_user(s, n); + + return res; +} #endif /* _ASMARM_UACCESS_H */ diff --git a/trunk/arch/arm/include/asm/word-at-a-time.h b/trunk/arch/arm/include/asm/word-at-a-time.h deleted file mode 100644 index 4d52f92967a6..000000000000 --- a/trunk/arch/arm/include/asm/word-at-a-time.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef __ASM_ARM_WORD_AT_A_TIME_H -#define __ASM_ARM_WORD_AT_A_TIME_H - -#ifndef __ARMEB__ - -/* - * Little-endian word-at-a-time zero byte handling. - * Heavily based on the x86 algorithm. - */ -#include - -struct word_at_a_time { - const unsigned long one_bits, high_bits; -}; - -#define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } - -static inline unsigned long has_zero(unsigned long a, unsigned long *bits, - const struct word_at_a_time *c) -{ - unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; - *bits = mask; - return mask; -} - -#define prep_zero_mask(a, bits, c) (bits) - -static inline unsigned long create_zero_mask(unsigned long bits) -{ - bits = (bits - 1) & ~bits; - return bits >> 7; -} - -static inline unsigned long find_zero(unsigned long mask) -{ - unsigned long ret; - -#if __LINUX_ARM_ARCH__ >= 5 - /* We have clz available. */ - ret = fls(mask) >> 3; -#else - /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ - ret = (0x0ff0001 + mask) >> 23; - /* Fix the 1 for 00 case */ - ret &= mask; -#endif - - return ret; -} - -#ifdef CONFIG_DCACHE_WORD_ACCESS - -#define zero_bytemask(mask) (mask) - -/* - * Load an unaligned word from kernel space. - * - * In the (very unlikely) case of the word being a page-crosser - * and the next page not being mapped, take the exception and - * return zeroes in the non-existing part. - */ -static inline unsigned long load_unaligned_zeropad(const void *addr) -{ - unsigned long ret, offset; - - /* Load word from unaligned pointer addr */ - asm( - "1: ldr %0, [%2]\n" - "2:\n" - " .pushsection .fixup,\"ax\"\n" - " .align 2\n" - "3: and %1, %2, #0x3\n" - " bic %2, %2, #0x3\n" - " ldr %0, [%2]\n" - " lsl %1, %1, #0x3\n" - " lsr %0, %0, %1\n" - " b 2b\n" - " .popsection\n" - " .pushsection __ex_table,\"a\"\n" - " .align 3\n" - " .long 1b, 3b\n" - " .popsection" - : "=&r" (ret), "=&r" (offset) - : "r" (addr), "Qo" (*(unsigned long *)addr)); - - return ret; -} - - -#endif /* DCACHE_WORD_ACCESS */ - -#else /* __ARMEB__ */ -#include -#endif - -#endif /* __ASM_ARM_WORD_AT_A_TIME_H */ diff --git a/trunk/arch/arm/kernel/arch_timer.c b/trunk/arch/arm/kernel/arch_timer.c index cf258807160d..dd58035621f7 100644 --- a/trunk/arch/arm/kernel/arch_timer.c +++ b/trunk/arch/arm/kernel/arch_timer.c @@ -32,8 +32,6 @@ static int arch_timer_ppi2; static struct clock_event_device __percpu **arch_timer_evt; -extern void init_current_timer_delay(unsigned long freq); - /* * Architected system timer support. */ @@ -139,7 +137,7 @@ static int __cpuinit arch_timer_setup(struct clock_event_device *clk) /* Be safe... */ arch_timer_disable(); - clk->features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_C3STOP; + clk->features = CLOCK_EVT_FEAT_ONESHOT; clk->name = "arch_sys_timer"; clk->rating = 450; clk->set_mode = arch_timer_set_mode; @@ -225,14 +223,6 @@ static cycle_t arch_counter_read(struct clocksource *cs) return arch_counter_get_cntpct(); } -int read_current_timer(unsigned long *timer_val) -{ - if (!arch_timer_rate) - return -ENXIO; - *timer_val = arch_counter_get_cntpct(); - return 0; -} - static struct clocksource clocksource_counter = { .name = "arch_sys_counter", .rating = 400, @@ -306,7 +296,6 @@ static int __init arch_timer_register(void) if (err) goto out_free_irq; - init_current_timer_delay(arch_timer_rate); return 0; out_free_irq: diff --git a/trunk/arch/arm/kernel/armksyms.c b/trunk/arch/arm/kernel/armksyms.c index 60d3b738d420..b57c75e0b01f 100644 --- a/trunk/arch/arm/kernel/armksyms.c +++ b/trunk/arch/arm/kernel/armksyms.c @@ -49,7 +49,8 @@ extern void __aeabi_ulcmp(void); extern void fpundefinstr(void); /* platform dependent support */ -EXPORT_SYMBOL(arm_delay_ops); +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__const_udelay); /* networking */ EXPORT_SYMBOL(csum_partial); @@ -86,6 +87,10 @@ EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memchr); EXPORT_SYMBOL(__memzero); + /* user mem (segment) */ +EXPORT_SYMBOL(__strnlen_user); +EXPORT_SYMBOL(__strncpy_from_user); + #ifdef CONFIG_MMU EXPORT_SYMBOL(copy_page); diff --git a/trunk/arch/arm/kernel/entry-common.S b/trunk/arch/arm/kernel/entry-common.S index 49d9f9305247..4afed88d250a 100644 --- a/trunk/arch/arm/kernel/entry-common.S +++ b/trunk/arch/arm/kernel/entry-common.S @@ -95,7 +95,13 @@ ENDPROC(ret_to_user) ENTRY(ret_from_fork) bl schedule_tail get_thread_info tsk + ldr r1, [tsk, #TI_FLAGS] @ check for syscall tracing mov why, #1 + tst r1, #_TIF_SYSCALL_WORK @ are we tracing syscalls? + beq ret_slow_syscall + mov r1, sp + mov r0, #1 @ trace exit [IP = 1] + bl syscall_trace b ret_slow_syscall ENDPROC(ret_from_fork) @@ -442,9 +448,10 @@ ENDPROC(vector_swi) * context switches, and waiting for our parent to respond. */ __sys_trace: - mov r1, scno - add r0, sp, #S_OFF - bl syscall_trace_enter + mov r2, scno + add r1, sp, #S_OFF + mov r0, #0 @ trace entry [IP = 0] + bl syscall_trace adr lr, BSYM(__sys_trace_return) @ return address mov scno, r0 @ syscall number (possibly new) @@ -456,9 +463,10 @@ __sys_trace: __sys_trace_return: str r0, [sp, #S_R0 + S_OFF]! @ save returned r0 - mov r1, scno - mov r0, sp - bl syscall_trace_exit + mov r2, scno + mov r1, sp + mov r0, #1 @ trace exit [IP = 1] + bl syscall_trace b ret_slow_syscall .align 5 diff --git a/trunk/arch/arm/kernel/head.S b/trunk/arch/arm/kernel/head.S index 3db960e20cb8..835898e7d704 100644 --- a/trunk/arch/arm/kernel/head.S +++ b/trunk/arch/arm/kernel/head.S @@ -55,6 +55,14 @@ add \rd, \phys, #TEXT_OFFSET - PG_DIR_SIZE .endm +#ifdef CONFIG_XIP_KERNEL +#define KERNEL_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) +#define KERNEL_END _edata_loc +#else +#define KERNEL_START KERNEL_RAM_VADDR +#define KERNEL_END _end +#endif + /* * Kernel startup entry point. * --------------------------- @@ -210,46 +218,51 @@ __create_page_tables: blo 1b /* - * Map our RAM from the start to the end of the kernel .bss section. + * Now setup the pagetables for our kernel direct + * mapped region. */ - add r0, r4, #PAGE_OFFSET >> (SECTION_SHIFT - PMD_ORDER) - ldr r6, =(_end - 1) - orr r3, r8, r7 + mov r3, pc + mov r3, r3, lsr #SECTION_SHIFT + orr r3, r7, r3, lsl #SECTION_SHIFT + add r0, r4, #(KERNEL_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #((KERNEL_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! + ldr r6, =(KERNEL_END - 1) + add r0, r0, #1 << PMD_ORDER add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) -1: str r3, [r0], #1 << PMD_ORDER +1: cmp r0, r6 add r3, r3, #1 << SECTION_SHIFT - cmp r0, r6 + strls r3, [r0], #1 << PMD_ORDER bls 1b #ifdef CONFIG_XIP_KERNEL /* - * Map the kernel image separately as it is not located in RAM. + * Map some ram to cover our .data and .bss areas. */ -#define XIP_START XIP_VIRT_ADDR(CONFIG_XIP_PHYS_ADDR) - mov r3, pc - mov r3, r3, lsr #SECTION_SHIFT - orr r3, r7, r3, lsl #SECTION_SHIFT - add r0, r4, #(XIP_START & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) - str r3, [r0, #((XIP_START & 0x00f00000) >> SECTION_SHIFT) << PMD_ORDER]! - ldr r6, =(_edata_loc - 1) - add r0, r0, #1 << PMD_ORDER + add r3, r8, #TEXT_OFFSET + orr r3, r3, r7 + add r0, r4, #(KERNEL_RAM_VADDR & 0xff000000) >> (SECTION_SHIFT - PMD_ORDER) + str r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> (SECTION_SHIFT - PMD_ORDER)]! + ldr r6, =(_end - 1) + add r0, r0, #4 add r6, r4, r6, lsr #(SECTION_SHIFT - PMD_ORDER) 1: cmp r0, r6 - add r3, r3, #1 << SECTION_SHIFT - strls r3, [r0], #1 << PMD_ORDER + add r3, r3, #1 << 20 + strls r3, [r0], #4 bls 1b #endif /* - * Then map boot params address in r2 if specified. + * Then map boot params address in r2 or the first 1MB (2MB with LPAE) + * of ram if boot params address is not specified. */ mov r0, r2, lsr #SECTION_SHIFT movs r0, r0, lsl #SECTION_SHIFT - subne r3, r0, r8 - addne r3, r3, #PAGE_OFFSET - addne r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) - orrne r6, r7, r0 - strne r6, [r3] + moveq r0, r8 + sub r3, r0, r8 + add r3, r3, #PAGE_OFFSET + add r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER) + orr r6, r7, r0 + str r6, [r3] #ifdef CONFIG_DEBUG_LL #if !defined(CONFIG_DEBUG_ICEDCC) && !defined(CONFIG_DEBUG_SEMIHOSTING) diff --git a/trunk/arch/arm/kernel/perf_event.c b/trunk/arch/arm/kernel/perf_event.c index ab243b87118d..a02eada3aa5d 100644 --- a/trunk/arch/arm/kernel/perf_event.c +++ b/trunk/arch/arm/kernel/perf_event.c @@ -47,14 +47,17 @@ static DEFINE_PER_CPU(struct pmu_hw_events, cpu_hw_events); /* Set at runtime when we know what CPU type we are. */ static struct arm_pmu *cpu_pmu; -const char *perf_pmu_name(void) +enum arm_perf_pmu_ids +armpmu_get_pmu_id(void) { - if (!cpu_pmu) - return NULL; + int id = -ENODEV; + + if (cpu_pmu != NULL) + id = cpu_pmu->id; - return cpu_pmu->pmu.name; + return id; } -EXPORT_SYMBOL_GPL(perf_pmu_name); +EXPORT_SYMBOL_GPL(armpmu_get_pmu_id); int perf_num_counters(void) { @@ -757,7 +760,7 @@ init_hw_perf_events(void) cpu_pmu->name, cpu_pmu->num_events); cpu_pmu_init(cpu_pmu); register_cpu_notifier(&pmu_cpu_notifier); - armpmu_register(cpu_pmu, cpu_pmu->name, PERF_TYPE_RAW); + armpmu_register(cpu_pmu, "cpu", PERF_TYPE_RAW); } else { pr_info("no hardware support available\n"); } diff --git a/trunk/arch/arm/kernel/perf_event_v6.c b/trunk/arch/arm/kernel/perf_event_v6.c index c90fcb2b6967..ab627a740fa3 100644 --- a/trunk/arch/arm/kernel/perf_event_v6.c +++ b/trunk/arch/arm/kernel/perf_event_v6.c @@ -650,6 +650,7 @@ static int armv6_map_event(struct perf_event *event) } static struct arm_pmu armv6pmu = { + .id = ARM_PERF_PMU_ID_V6, .name = "v6", .handle_irq = armv6pmu_handle_irq, .enable = armv6pmu_enable_event, @@ -684,6 +685,7 @@ static int armv6mpcore_map_event(struct perf_event *event) } static struct arm_pmu armv6mpcore_pmu = { + .id = ARM_PERF_PMU_ID_V6MP, .name = "v6mpcore", .handle_irq = armv6pmu_handle_irq, .enable = armv6pmu_enable_event, diff --git a/trunk/arch/arm/kernel/perf_event_v7.c b/trunk/arch/arm/kernel/perf_event_v7.c index f04070bd2183..d3c536068162 100644 --- a/trunk/arch/arm/kernel/perf_event_v7.c +++ b/trunk/arch/arm/kernel/perf_event_v7.c @@ -1258,6 +1258,7 @@ static u32 __init armv7_read_num_pmnc_events(void) static struct arm_pmu *__init armv7_a8_pmu_init(void) { + armv7pmu.id = ARM_PERF_PMU_ID_CA8; armv7pmu.name = "ARMv7 Cortex-A8"; armv7pmu.map_event = armv7_a8_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1266,6 +1267,7 @@ static struct arm_pmu *__init armv7_a8_pmu_init(void) static struct arm_pmu *__init armv7_a9_pmu_init(void) { + armv7pmu.id = ARM_PERF_PMU_ID_CA9; armv7pmu.name = "ARMv7 Cortex-A9"; armv7pmu.map_event = armv7_a9_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1274,6 +1276,7 @@ static struct arm_pmu *__init armv7_a9_pmu_init(void) static struct arm_pmu *__init armv7_a5_pmu_init(void) { + armv7pmu.id = ARM_PERF_PMU_ID_CA5; armv7pmu.name = "ARMv7 Cortex-A5"; armv7pmu.map_event = armv7_a5_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1282,6 +1285,7 @@ static struct arm_pmu *__init armv7_a5_pmu_init(void) static struct arm_pmu *__init armv7_a15_pmu_init(void) { + armv7pmu.id = ARM_PERF_PMU_ID_CA15; armv7pmu.name = "ARMv7 Cortex-A15"; armv7pmu.map_event = armv7_a15_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); @@ -1291,6 +1295,7 @@ static struct arm_pmu *__init armv7_a15_pmu_init(void) static struct arm_pmu *__init armv7_a7_pmu_init(void) { + armv7pmu.id = ARM_PERF_PMU_ID_CA7; armv7pmu.name = "ARMv7 Cortex-A7"; armv7pmu.map_event = armv7_a7_map_event; armv7pmu.num_events = armv7_read_num_pmnc_events(); diff --git a/trunk/arch/arm/kernel/perf_event_xscale.c b/trunk/arch/arm/kernel/perf_event_xscale.c index f759fe0bab63..e34e7254e652 100644 --- a/trunk/arch/arm/kernel/perf_event_xscale.c +++ b/trunk/arch/arm/kernel/perf_event_xscale.c @@ -435,6 +435,7 @@ static int xscale_map_event(struct perf_event *event) } static struct arm_pmu xscale1pmu = { + .id = ARM_PERF_PMU_ID_XSCALE1, .name = "xscale1", .handle_irq = xscale1pmu_handle_irq, .enable = xscale1pmu_enable_event, @@ -802,6 +803,7 @@ xscale2pmu_write_counter(int counter, u32 val) } static struct arm_pmu xscale2pmu = { + .id = ARM_PERF_PMU_ID_XSCALE2, .name = "xscale2", .handle_irq = xscale2pmu_handle_irq, .enable = xscale2pmu_enable_event, diff --git a/trunk/arch/arm/kernel/ptrace.c b/trunk/arch/arm/kernel/ptrace.c index dab711e6e1ca..14e38261cd31 100644 --- a/trunk/arch/arm/kernel/ptrace.c +++ b/trunk/arch/arm/kernel/ptrace.c @@ -907,16 +907,16 @@ long arch_ptrace(struct task_struct *child, long request, return ret; } -enum ptrace_syscall_dir { - PTRACE_SYSCALL_ENTER = 0, - PTRACE_SYSCALL_EXIT, -}; - -static int ptrace_syscall_trace(struct pt_regs *regs, int scno, - enum ptrace_syscall_dir dir) +asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno) { unsigned long ip; + if (why) + audit_syscall_exit(regs); + else + audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, + regs->ARM_r1, regs->ARM_r2, regs->ARM_r3); + if (!test_thread_flag(TIF_SYSCALL_TRACE)) return scno; @@ -927,28 +927,14 @@ static int ptrace_syscall_trace(struct pt_regs *regs, int scno, * IP = 0 -> entry, =1 -> exit */ ip = regs->ARM_ip; - regs->ARM_ip = dir; + regs->ARM_ip = why; - if (dir == PTRACE_SYSCALL_EXIT) + if (why) tracehook_report_syscall_exit(regs, 0); else if (tracehook_report_syscall_entry(regs)) current_thread_info()->syscall = -1; regs->ARM_ip = ip; - return current_thread_info()->syscall; -} -asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno) -{ - int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_ENTER); - audit_syscall_entry(AUDIT_ARCH_ARM, scno, regs->ARM_r0, regs->ARM_r1, - regs->ARM_r2, regs->ARM_r3); - return ret; -} - -asmlinkage int syscall_trace_exit(struct pt_regs *regs, int scno) -{ - int ret = ptrace_syscall_trace(regs, scno, PTRACE_SYSCALL_EXIT); - audit_syscall_exit(regs); - return ret; + return current_thread_info()->syscall; } diff --git a/trunk/arch/arm/kernel/smp.c b/trunk/arch/arm/kernel/smp.c index aea74f5bc34a..2c7217d971db 100644 --- a/trunk/arch/arm/kernel/smp.c +++ b/trunk/arch/arm/kernel/smp.c @@ -179,7 +179,7 @@ void __ref cpu_die(void) mb(); /* Tell __cpu_die() that this CPU is now safe to dispose of */ - RCU_NONIDLE(complete(&cpu_died)); + complete(&cpu_died); /* * actual CPU shutdown procedure is at least platform (if not diff --git a/trunk/arch/arm/kernel/topology.c b/trunk/arch/arm/kernel/topology.c index 198b08456e90..8200deaa14f6 100644 --- a/trunk/arch/arm/kernel/topology.c +++ b/trunk/arch/arm/kernel/topology.c @@ -17,190 +17,11 @@ #include #include #include -#include #include -#include #include #include -/* - * cpu power scale management - */ - -/* - * cpu power table - * This per cpu data structure describes the relative capacity of each core. - * On a heteregenous system, cores don't have the same computation capacity - * and we reflect that difference in the cpu_power field so the scheduler can - * take this difference into account during load balance. A per cpu structure - * is preferred because each CPU updates its own cpu_power field during the - * load balance except for idle cores. One idle core is selected to run the - * rebalance_domains for all idle cores and the cpu_power can be updated - * during this sequence. - */ -static DEFINE_PER_CPU(unsigned long, cpu_scale); - -unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu) -{ - return per_cpu(cpu_scale, cpu); -} - -static void set_power_scale(unsigned int cpu, unsigned long power) -{ - per_cpu(cpu_scale, cpu) = power; -} - -#ifdef CONFIG_OF -struct cpu_efficiency { - const char *compatible; - unsigned long efficiency; -}; - -/* - * Table of relative efficiency of each processors - * The efficiency value must fit in 20bit and the final - * cpu_scale value must be in the range - * 0 < cpu_scale < 3*SCHED_POWER_SCALE/2 - * in order to return at most 1 when DIV_ROUND_CLOSEST - * is used to compute the capacity of a CPU. - * Processors that are not defined in the table, - * use the default SCHED_POWER_SCALE value for cpu_scale. - */ -struct cpu_efficiency table_efficiency[] = { - {"arm,cortex-a15", 3891}, - {"arm,cortex-a7", 2048}, - {NULL, }, -}; - -struct cpu_capacity { - unsigned long hwid; - unsigned long capacity; -}; - -struct cpu_capacity *cpu_capacity; - -unsigned long middle_capacity = 1; - -/* - * Iterate all CPUs' descriptor in DT and compute the efficiency - * (as per table_efficiency). Also calculate a middle efficiency - * as close as possible to (max{eff_i} - min{eff_i}) / 2 - * This is later used to scale the cpu_power field such that an - * 'average' CPU is of middle power. Also see the comments near - * table_efficiency[] and update_cpu_power(). - */ -static void __init parse_dt_topology(void) -{ - struct cpu_efficiency *cpu_eff; - struct device_node *cn = NULL; - unsigned long min_capacity = (unsigned long)(-1); - unsigned long max_capacity = 0; - unsigned long capacity = 0; - int alloc_size, cpu = 0; - - alloc_size = nr_cpu_ids * sizeof(struct cpu_capacity); - cpu_capacity = (struct cpu_capacity *)kzalloc(alloc_size, GFP_NOWAIT); - - while ((cn = of_find_node_by_type(cn, "cpu"))) { - const u32 *rate, *reg; - int len; - - if (cpu >= num_possible_cpus()) - break; - - for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++) - if (of_device_is_compatible(cn, cpu_eff->compatible)) - break; - - if (cpu_eff->compatible == NULL) - continue; - - rate = of_get_property(cn, "clock-frequency", &len); - if (!rate || len != 4) { - pr_err("%s missing clock-frequency property\n", - cn->full_name); - continue; - } - - reg = of_get_property(cn, "reg", &len); - if (!reg || len != 4) { - pr_err("%s missing reg property\n", cn->full_name); - continue; - } - - capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency; - - /* Save min capacity of the system */ - if (capacity < min_capacity) - min_capacity = capacity; - - /* Save max capacity of the system */ - if (capacity > max_capacity) - max_capacity = capacity; - - cpu_capacity[cpu].capacity = capacity; - cpu_capacity[cpu++].hwid = be32_to_cpup(reg); - } - - if (cpu < num_possible_cpus()) - cpu_capacity[cpu].hwid = (unsigned long)(-1); - - /* If min and max capacities are equals, we bypass the update of the - * cpu_scale because all CPUs have the same capacity. Otherwise, we - * compute a middle_capacity factor that will ensure that the capacity - * of an 'average' CPU of the system will be as close as possible to - * SCHED_POWER_SCALE, which is the default value, but with the - * constraint explained near table_efficiency[]. - */ - if (min_capacity == max_capacity) - cpu_capacity[0].hwid = (unsigned long)(-1); - else if (4*max_capacity < (3*(max_capacity + min_capacity))) - middle_capacity = (min_capacity + max_capacity) - >> (SCHED_POWER_SHIFT+1); - else - middle_capacity = ((max_capacity / 3) - >> (SCHED_POWER_SHIFT-1)) + 1; - -} - -/* - * Look for a customed capacity of a CPU in the cpu_capacity table during the - * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the - * function returns directly for SMP system. - */ -void update_cpu_power(unsigned int cpu, unsigned long hwid) -{ - unsigned int idx = 0; - - /* look for the cpu's hwid in the cpu capacity table */ - for (idx = 0; idx < num_possible_cpus(); idx++) { - if (cpu_capacity[idx].hwid == hwid) - break; - - if (cpu_capacity[idx].hwid == -1) - return; - } - - if (idx == num_possible_cpus()) - return; - - set_power_scale(cpu, cpu_capacity[idx].capacity / middle_capacity); - - printk(KERN_INFO "CPU%u: update cpu_power %lu\n", - cpu, arch_scale_freq_power(NULL, cpu)); -} - -#else -static inline void parse_dt_topology(void) {} -static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {} -#endif - - -/* - * cpu topology management - */ - #define MPIDR_SMP_BITMASK (0x3 << 30) #define MPIDR_SMP_VALUE (0x2 << 30) @@ -210,7 +31,6 @@ static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {} * These masks reflect the current use of the affinity levels. * The affinity level can be up to 16 bits according to ARM ARM */ -#define MPIDR_HWID_BITMASK 0xFFFFFF #define MPIDR_LEVEL0_MASK 0x3 #define MPIDR_LEVEL0_SHIFT 0 @@ -221,9 +41,6 @@ static inline void update_cpu_power(unsigned int cpuid, unsigned int mpidr) {} #define MPIDR_LEVEL2_MASK 0xFF #define MPIDR_LEVEL2_SHIFT 16 -/* - * cpu topology table - */ struct cputopo_arm cpu_topology[NR_CPUS]; const struct cpumask *cpu_coregroup_mask(int cpu) @@ -231,32 +48,6 @@ const struct cpumask *cpu_coregroup_mask(int cpu) return &cpu_topology[cpu].core_sibling; } -void update_siblings_masks(unsigned int cpuid) -{ - struct cputopo_arm *cpu_topo, *cpuid_topo = &cpu_topology[cpuid]; - int cpu; - - /* update core and thread sibling masks */ - for_each_possible_cpu(cpu) { - cpu_topo = &cpu_topology[cpu]; - - if (cpuid_topo->socket_id != cpu_topo->socket_id) - continue; - - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, &cpuid_topo->core_sibling); - - if (cpuid_topo->core_id != cpu_topo->core_id) - continue; - - cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling); - } - smp_wmb(); -} - /* * store_cpu_topology is called at boot when only one cpu is running * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, @@ -266,6 +57,7 @@ void store_cpu_topology(unsigned int cpuid) { struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; unsigned int mpidr; + unsigned int cpu; /* If the cpu topology has been already set, just return */ if (cpuid_topo->core_id != -1) @@ -307,9 +99,26 @@ void store_cpu_topology(unsigned int cpuid) cpuid_topo->socket_id = -1; } - update_siblings_masks(cpuid); - - update_cpu_power(cpuid, mpidr & MPIDR_HWID_BITMASK); + /* update core and thread sibling masks */ + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if (cpuid_topo->socket_id == cpu_topo->socket_id) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", cpuid, cpu_topology[cpuid].thread_id, @@ -325,7 +134,7 @@ void init_cpu_topology(void) { unsigned int cpu; - /* init core mask and power*/ + /* init core mask */ for_each_possible_cpu(cpu) { struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); @@ -334,10 +143,6 @@ void init_cpu_topology(void) cpu_topo->socket_id = -1; cpumask_clear(&cpu_topo->core_sibling); cpumask_clear(&cpu_topo->thread_sibling); - - set_power_scale(cpu, SCHED_POWER_SCALE); } smp_wmb(); - - parse_dt_topology(); } diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index 8b97d739b17b..3647170e9a16 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -233,9 +233,9 @@ void show_stack(struct task_struct *tsk, unsigned long *sp) #define S_ISA " ARM" #endif -static int __die(const char *str, int err, struct pt_regs *regs) +static int __die(const char *str, int err, struct thread_info *thread, struct pt_regs *regs) { - struct task_struct *tsk = current; + struct task_struct *tsk = thread->task; static int die_counter; int ret; @@ -245,12 +245,12 @@ static int __die(const char *str, int err, struct pt_regs *regs) /* trap and error numbers are mostly meaningless on ARM */ ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, SIGSEGV); if (ret == NOTIFY_STOP) - return 1; + return ret; print_modules(); __show_regs(regs); printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n", - TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), end_of_stack(tsk)); + TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1); if (!user_mode(regs) || in_interrupt()) { dump_mem(KERN_EMERG, "Stack: ", regs->ARM_sp, @@ -259,77 +259,45 @@ static int __die(const char *str, int err, struct pt_regs *regs) dump_instr(KERN_EMERG, regs); } - return 0; + return ret; } -static arch_spinlock_t die_lock = __ARCH_SPIN_LOCK_UNLOCKED; -static int die_owner = -1; -static unsigned int die_nest_count; +static DEFINE_RAW_SPINLOCK(die_lock); -static unsigned long oops_begin(void) +/* + * This function is protected against re-entrancy. + */ +void die(const char *str, struct pt_regs *regs, int err) { - int cpu; - unsigned long flags; + struct thread_info *thread = current_thread_info(); + int ret; + enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; oops_enter(); - /* racy, but better than risking deadlock. */ - raw_local_irq_save(flags); - cpu = smp_processor_id(); - if (!arch_spin_trylock(&die_lock)) { - if (cpu == die_owner) - /* nested oops. should stop eventually */; - else - arch_spin_lock(&die_lock); - } - die_nest_count++; - die_owner = cpu; + raw_spin_lock_irq(&die_lock); console_verbose(); bust_spinlocks(1); - return flags; -} + if (!user_mode(regs)) + bug_type = report_bug(regs->ARM_pc, regs); + if (bug_type != BUG_TRAP_TYPE_NONE) + str = "Oops - BUG"; + ret = __die(str, err, thread, regs); -static void oops_end(unsigned long flags, struct pt_regs *regs, int signr) -{ - if (regs && kexec_should_crash(current)) + if (regs && kexec_should_crash(thread->task)) crash_kexec(regs); bust_spinlocks(0); - die_owner = -1; add_taint(TAINT_DIE); - die_nest_count--; - if (!die_nest_count) - /* Nest count reaches zero, release the lock. */ - arch_spin_unlock(&die_lock); - raw_local_irq_restore(flags); + raw_spin_unlock_irq(&die_lock); oops_exit(); if (in_interrupt()) panic("Fatal exception in interrupt"); if (panic_on_oops) panic("Fatal exception"); - if (signr) - do_exit(signr); -} - -/* - * This function is protected against re-entrancy. - */ -void die(const char *str, struct pt_regs *regs, int err) -{ - enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; - unsigned long flags = oops_begin(); - int sig = SIGSEGV; - - if (!user_mode(regs)) - bug_type = report_bug(regs->ARM_pc, regs); - if (bug_type != BUG_TRAP_TYPE_NONE) - str = "Oops - BUG"; - - if (__die(str, err, regs)) - sig = 0; - - oops_end(flags, regs, sig); + if (ret != NOTIFY_STOP) + do_exit(SIGSEGV); } void arm_notify_die(const char *str, struct pt_regs *regs, diff --git a/trunk/arch/arm/lib/Makefile b/trunk/arch/arm/lib/Makefile index 2473fd1fd51c..992769ae2599 100644 --- a/trunk/arch/arm/lib/Makefile +++ b/trunk/arch/arm/lib/Makefile @@ -6,8 +6,9 @@ lib-y := backtrace.o changebit.o csumipv6.o csumpartial.o \ csumpartialcopy.o csumpartialcopyuser.o clearbit.o \ - delay.o delay-loop.o findbit.o memchr.o memcpy.o \ + delay.o findbit.o memchr.o memcpy.o \ memmove.o memset.o memzero.o setbit.o \ + strncpy_from_user.o strnlen_user.o \ strchr.o strrchr.o \ testchangebit.o testclearbit.o testsetbit.o \ ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \ diff --git a/trunk/arch/arm/lib/delay-loop.S b/trunk/arch/arm/lib/delay.S similarity index 81% rename from trunk/arch/arm/lib/delay-loop.S rename to trunk/arch/arm/lib/delay.S index 36b668d8e121..3c9a05c8d20b 100644 --- a/trunk/arch/arm/lib/delay-loop.S +++ b/trunk/arch/arm/lib/delay.S @@ -9,11 +9,11 @@ */ #include #include -#include +#include .text .LC0: .word loops_per_jiffy -.LC1: .word UDELAY_MULT +.LC1: .word (2199023*HZ)>>11 /* * r0 <= 2000 @@ -21,10 +21,10 @@ * HZ <= 1000 */ -ENTRY(__loop_udelay) +ENTRY(__udelay) ldr r2, .LC1 mul r0, r2, r0 -ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0x7fffff06 +ENTRY(__const_udelay) @ 0 <= r0 <= 0x7fffff06 mov r1, #-1 ldr r2, .LC0 ldr r2, [r2] @ max = 0x01ffffff @@ -39,10 +39,12 @@ ENTRY(__loop_const_udelay) @ 0 <= r0 <= 0x7fffff06 /* * loops = r0 * HZ * loops_per_jiffy / 1000000 + * + * Oh, if only we had a cycle counter... */ @ Delay routine -ENTRY(__loop_delay) +ENTRY(__delay) subs r0, r0, #1 #if 0 movls pc, lr @@ -60,8 +62,8 @@ ENTRY(__loop_delay) movls pc, lr subs r0, r0, #1 #endif - bhi __loop_delay + bhi __delay mov pc, lr -ENDPROC(__loop_udelay) -ENDPROC(__loop_const_udelay) -ENDPROC(__loop_delay) +ENDPROC(__udelay) +ENDPROC(__const_udelay) +ENDPROC(__delay) diff --git a/trunk/arch/arm/lib/delay.c b/trunk/arch/arm/lib/delay.c deleted file mode 100644 index d6dacc69254e..000000000000 --- a/trunk/arch/arm/lib/delay.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Delay loops based on the OpenRISC implementation. - * - * Copyright (C) 2012 ARM Limited - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Author: Will Deacon - */ - -#include -#include -#include -#include -#include - -/* - * Default to the loop-based delay implementation. - */ -struct arm_delay_ops arm_delay_ops = { - .delay = __loop_delay, - .const_udelay = __loop_const_udelay, - .udelay = __loop_udelay, -}; - -#ifdef ARCH_HAS_READ_CURRENT_TIMER -static void __timer_delay(unsigned long cycles) -{ - cycles_t start = get_cycles(); - - while ((get_cycles() - start) < cycles) - cpu_relax(); -} - -static void __timer_const_udelay(unsigned long xloops) -{ - unsigned long long loops = xloops; - loops *= loops_per_jiffy; - __timer_delay(loops >> UDELAY_SHIFT); -} - -static void __timer_udelay(unsigned long usecs) -{ - __timer_const_udelay(usecs * UDELAY_MULT); -} - -void __init init_current_timer_delay(unsigned long freq) -{ - pr_info("Switching to timer-based delay loop\n"); - lpj_fine = freq / HZ; - arm_delay_ops.delay = __timer_delay; - arm_delay_ops.const_udelay = __timer_const_udelay; - arm_delay_ops.udelay = __timer_udelay; -} - -unsigned long __cpuinit calibrate_delay_is_known(void) -{ - return lpj_fine; -} -#endif diff --git a/trunk/arch/arm/lib/strncpy_from_user.S b/trunk/arch/arm/lib/strncpy_from_user.S new file mode 100644 index 000000000000..f202d7bd1647 --- /dev/null +++ b/trunk/arch/arm/lib/strncpy_from_user.S @@ -0,0 +1,43 @@ +/* + * linux/arch/arm/lib/strncpy_from_user.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + + .text + .align 5 + +/* + * Copy a string from user space to kernel space. + * r0 = dst, r1 = src, r2 = byte length + * returns the number of characters copied (strlen of copied string), + * -EFAULT on exception, or "len" if we fill the whole buffer + */ +ENTRY(__strncpy_from_user) + mov ip, r1 +1: subs r2, r2, #1 + ldrusr r3, r1, 1, pl + bmi 2f + strb r3, [r0], #1 + teq r3, #0 + bne 1b + sub r1, r1, #1 @ take NUL character out of count +2: sub r0, r1, ip + mov pc, lr +ENDPROC(__strncpy_from_user) + + .pushsection .fixup,"ax" + .align 0 +9001: mov r3, #0 + strb r3, [r0, #0] @ null terminate + mov r0, #-EFAULT + mov pc, lr + .popsection + diff --git a/trunk/arch/arm/lib/strnlen_user.S b/trunk/arch/arm/lib/strnlen_user.S new file mode 100644 index 000000000000..0ecbb459c4f1 --- /dev/null +++ b/trunk/arch/arm/lib/strnlen_user.S @@ -0,0 +1,40 @@ +/* + * linux/arch/arm/lib/strnlen_user.S + * + * Copyright (C) 1995-2000 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include + + .text + .align 5 + +/* Prototype: unsigned long __strnlen_user(const char *str, long n) + * Purpose : get length of a string in user memory + * Params : str - address of string in user memory + * Returns : length of string *including terminator* + * or zero on exception, or n + 1 if too long + */ +ENTRY(__strnlen_user) + mov r2, r0 +1: + ldrusr r3, r0, 1 + teq r3, #0 + beq 2f + subs r1, r1, #1 + bne 1b + add r0, r0, #1 +2: sub r0, r0, r2 + mov pc, lr +ENDPROC(__strnlen_user) + + .pushsection .fixup,"ax" + .align 0 +9001: mov r0, #0 + mov pc, lr + .popsection diff --git a/trunk/arch/arm/mach-msm/platsmp.c b/trunk/arch/arm/mach-msm/platsmp.c index e012dc8391cf..db0117ec55f4 100644 --- a/trunk/arch/arm/mach-msm/platsmp.c +++ b/trunk/arch/arm/mach-msm/platsmp.c @@ -127,7 +127,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 0); + gic_raise_softirq(cpumask_of(cpu), 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/trunk/arch/arm/mach-omap2/omap-smp.c b/trunk/arch/arm/mach-omap2/omap-smp.c index 9a35adf91232..7d118b9bdd5f 100644 --- a/trunk/arch/arm/mach-omap2/omap-smp.c +++ b/trunk/arch/arm/mach-omap2/omap-smp.c @@ -125,7 +125,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) booted = true; } - gic_raise_softirq(cpumask_of(cpu), 0); + gic_raise_softirq(cpumask_of(cpu), 1); /* * Now the secondary core is starting up let it run its diff --git a/trunk/arch/arm/mach-pxa/include/mach/regs-ost.h b/trunk/arch/arm/mach-pxa/include/mach/regs-ost.h index 628819995c52..a3e5f86ef67e 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/regs-ost.h +++ b/trunk/arch/arm/mach-pxa/include/mach/regs-ost.h @@ -7,17 +7,17 @@ * OS Timer & Match Registers */ -#define OSMR0 io_p2v(0x40A00000) /* */ -#define OSMR1 io_p2v(0x40A00004) /* */ -#define OSMR2 io_p2v(0x40A00008) /* */ -#define OSMR3 io_p2v(0x40A0000C) /* */ -#define OSMR4 io_p2v(0x40A00080) /* */ -#define OSCR io_p2v(0x40A00010) /* OS Timer Counter Register */ -#define OSCR4 io_p2v(0x40A00040) /* OS Timer Counter Register */ -#define OMCR4 io_p2v(0x40A000C0) /* */ -#define OSSR io_p2v(0x40A00014) /* OS Timer Status Register */ -#define OWER io_p2v(0x40A00018) /* OS Timer Watchdog Enable Register */ -#define OIER io_p2v(0x40A0001C) /* OS Timer Interrupt Enable Register */ +#define OSMR0 __REG(0x40A00000) /* */ +#define OSMR1 __REG(0x40A00004) /* */ +#define OSMR2 __REG(0x40A00008) /* */ +#define OSMR3 __REG(0x40A0000C) /* */ +#define OSMR4 __REG(0x40A00080) /* */ +#define OSCR __REG(0x40A00010) /* OS Timer Counter Register */ +#define OSCR4 __REG(0x40A00040) /* OS Timer Counter Register */ +#define OMCR4 __REG(0x40A000C0) /* */ +#define OSSR __REG(0x40A00014) /* OS Timer Status Register */ +#define OWER __REG(0x40A00018) /* OS Timer Watchdog Enable Register */ +#define OIER __REG(0x40A0001C) /* OS Timer Interrupt Enable Register */ #define OSSR_M3 (1 << 3) /* Match status channel 3 */ #define OSSR_M2 (1 << 2) /* Match status channel 2 */ diff --git a/trunk/arch/arm/mach-pxa/reset.c b/trunk/arch/arm/mach-pxa/reset.c index 3fab583755d4..b4528899ef08 100644 --- a/trunk/arch/arm/mach-pxa/reset.c +++ b/trunk/arch/arm/mach-pxa/reset.c @@ -77,10 +77,9 @@ static void do_gpio_reset(void) static void do_hw_reset(void) { /* Initialize the watchdog and let it fire */ - writel_relaxed(OWER_WME, OWER); - writel_relaxed(OSSR_M3, OSSR); - /* ... in 100 ms */ - writel_relaxed(readl_relaxed(OSCR) + 368640, OSMR3); + OWER = OWER_WME; + OSSR = OSSR_M3; + OSMR3 = OSCR + 368640; /* ... in 100 ms */ } void pxa_restart(char mode, const char *cmd) diff --git a/trunk/arch/arm/mach-pxa/time.c b/trunk/arch/arm/mach-pxa/time.c index 4bc47d63698b..3d6c9bd90de6 100644 --- a/trunk/arch/arm/mach-pxa/time.c +++ b/trunk/arch/arm/mach-pxa/time.c @@ -35,7 +35,7 @@ static u32 notrace pxa_read_sched_clock(void) { - return readl_relaxed(OSCR); + return OSCR; } @@ -47,8 +47,8 @@ pxa_ost0_interrupt(int irq, void *dev_id) struct clock_event_device *c = dev_id; /* Disarm the compare/match, signal the event. */ - writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); - writel_relaxed(OSSR_M0, OSSR); + OIER &= ~OIER_E0; + OSSR = OSSR_M0; c->event_handler(c); return IRQ_HANDLED; @@ -59,10 +59,10 @@ pxa_osmr0_set_next_event(unsigned long delta, struct clock_event_device *dev) { unsigned long next, oscr; - writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER); - next = readl_relaxed(OSCR) + delta; - writel_relaxed(next, OSMR0); - oscr = readl_relaxed(OSCR); + OIER |= OIER_E0; + next = OSCR + delta; + OSMR0 = next; + oscr = OSCR; return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; } @@ -72,15 +72,15 @@ pxa_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *dev) { switch (mode) { case CLOCK_EVT_MODE_ONESHOT: - writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); - writel_relaxed(OSSR_M0, OSSR); + OIER &= ~OIER_E0; + OSSR = OSSR_M0; break; case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: /* initializing, released, or preparing for suspend */ - writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); - writel_relaxed(OSSR_M0, OSSR); + OIER &= ~OIER_E0; + OSSR = OSSR_M0; break; case CLOCK_EVT_MODE_RESUME: @@ -108,8 +108,8 @@ static void __init pxa_timer_init(void) { unsigned long clock_tick_rate = get_clock_tick_rate(); - writel_relaxed(0, OIER); - writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); + OIER = 0; + OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate); @@ -122,7 +122,7 @@ static void __init pxa_timer_init(void) setup_irq(IRQ_OST0, &pxa_ost0_irq); - clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32, + clocksource_mmio_init(&OSCR, "oscr0", clock_tick_rate, 200, 32, clocksource_mmio_readl_up); clockevents_register_device(&ckevt_pxa_osmr0); } @@ -132,12 +132,12 @@ static unsigned long osmr[4], oier, oscr; static void pxa_timer_suspend(void) { - osmr[0] = readl_relaxed(OSMR0); - osmr[1] = readl_relaxed(OSMR1); - osmr[2] = readl_relaxed(OSMR2); - osmr[3] = readl_relaxed(OSMR3); - oier = readl_relaxed(OIER); - oscr = readl_relaxed(OSCR); + osmr[0] = OSMR0; + osmr[1] = OSMR1; + osmr[2] = OSMR2; + osmr[3] = OSMR3; + oier = OIER; + oscr = OSCR; } static void pxa_timer_resume(void) @@ -151,12 +151,12 @@ static void pxa_timer_resume(void) if (osmr[0] - oscr < MIN_OSCR_DELTA) osmr[0] += MIN_OSCR_DELTA; - writel_relaxed(osmr[0], OSMR0); - writel_relaxed(osmr[1], OSMR1); - writel_relaxed(osmr[2], OSMR2); - writel_relaxed(osmr[3], OSMR3); - writel_relaxed(oier, OIER); - writel_relaxed(oscr, OSCR); + OSMR0 = osmr[0]; + OSMR1 = osmr[1]; + OSMR2 = osmr[2]; + OSMR3 = osmr[3]; + OIER = oier; + OSCR = oscr; } #else #define pxa_timer_suspend NULL diff --git a/trunk/arch/arm/mach-sa1100/assabet.c b/trunk/arch/arm/mach-sa1100/assabet.c index d673211f121c..d1dc7f1a239c 100644 --- a/trunk/arch/arm/mach-sa1100/assabet.c +++ b/trunk/arch/arm/mach-sa1100/assabet.c @@ -362,7 +362,7 @@ static void __init assabet_init(void) static void __init map_sa1100_gpio_regs( void ) { unsigned long phys = __PREG(GPLR) & PMD_MASK; - unsigned long virt = (unsigned long)io_p2v(phys); + unsigned long virt = io_p2v(phys); int prot = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_DOMAIN(DOMAIN_IO); pmd_t *pmd; diff --git a/trunk/arch/arm/mach-sa1100/cpu-sa1100.c b/trunk/arch/arm/mach-sa1100/cpu-sa1100.c index e8f4d1e19233..19b2053f5af4 100644 --- a/trunk/arch/arm/mach-sa1100/cpu-sa1100.c +++ b/trunk/arch/arm/mach-sa1100/cpu-sa1100.c @@ -87,7 +87,6 @@ #include #include #include -#include #include diff --git a/trunk/arch/arm/mach-sa1100/cpu-sa1110.c b/trunk/arch/arm/mach-sa1100/cpu-sa1110.c index 48c45b0c92bb..675bf8ef97e8 100644 --- a/trunk/arch/arm/mach-sa1100/cpu-sa1110.c +++ b/trunk/arch/arm/mach-sa1100/cpu-sa1110.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/arch/arm/mach-sa1100/include/mach/SA-1100.h b/trunk/arch/arm/mach-sa1100/include/mach/SA-1100.h index 0ac6cc08a19c..3f2d1b60188c 100644 --- a/trunk/arch/arm/mach-sa1100/include/mach/SA-1100.h +++ b/trunk/arch/arm/mach-sa1100/include/mach/SA-1100.h @@ -830,14 +830,14 @@ * (read/write). */ -#define OSMR0 io_p2v(0x90000000) /* OS timer Match Reg. 0 */ -#define OSMR1 io_p2v(0x90000004) /* OS timer Match Reg. 1 */ -#define OSMR2 io_p2v(0x90000008) /* OS timer Match Reg. 2 */ -#define OSMR3 io_p2v(0x9000000c) /* OS timer Match Reg. 3 */ -#define OSCR io_p2v(0x90000010) /* OS timer Counter Reg. */ -#define OSSR io_p2v(0x90000014) /* OS timer Status Reg. */ -#define OWER io_p2v(0x90000018) /* OS timer Watch-dog Enable Reg. */ -#define OIER io_p2v(0x9000001C) /* OS timer Interrupt Enable Reg. */ +#define OSMR0 __REG(0x90000000) /* OS timer Match Reg. 0 */ +#define OSMR1 __REG(0x90000004) /* OS timer Match Reg. 1 */ +#define OSMR2 __REG(0x90000008) /* OS timer Match Reg. 2 */ +#define OSMR3 __REG(0x9000000c) /* OS timer Match Reg. 3 */ +#define OSCR __REG(0x90000010) /* OS timer Counter Reg. */ +#define OSSR __REG(0x90000014 ) /* OS timer Status Reg. */ +#define OWER __REG(0x90000018 ) /* OS timer Watch-dog Enable Reg. */ +#define OIER __REG(0x9000001C ) /* OS timer Interrupt Enable Reg. */ #define OSSR_M(Nb) /* Match detected [0..3] */ \ (0x00000001 << (Nb)) diff --git a/trunk/arch/arm/mach-sa1100/include/mach/gpio.h b/trunk/arch/arm/mach-sa1100/include/mach/gpio.h index 6a9eecf3137e..a38fc4f54241 100644 --- a/trunk/arch/arm/mach-sa1100/include/mach/gpio.h +++ b/trunk/arch/arm/mach-sa1100/include/mach/gpio.h @@ -24,7 +24,6 @@ #ifndef __ASM_ARCH_SA1100_GPIO_H #define __ASM_ARCH_SA1100_GPIO_H -#include #include #include #include diff --git a/trunk/arch/arm/mach-sa1100/include/mach/hardware.h b/trunk/arch/arm/mach-sa1100/include/mach/hardware.h index cbedd75a9d65..99f5856d8de4 100644 --- a/trunk/arch/arm/mach-sa1100/include/mach/hardware.h +++ b/trunk/arch/arm/mach-sa1100/include/mach/hardware.h @@ -32,7 +32,7 @@ #define PIO_START 0x80000000 /* physical start of IO space */ #define io_p2v( x ) \ - IOMEM( (((x)&0x00ffffff) | (((x)&0x30000000)>>VIO_SHIFT)) + VIO_BASE ) + ( (((x)&0x00ffffff) | (((x)&0x30000000)>>VIO_SHIFT)) + VIO_BASE ) #define io_v2p( x ) \ ( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))< @@ -58,7 +56,7 @@ #define cpu_is_sa1100() ((read_cpuid_id() & CPU_SA1100_MASK) == CPU_SA1100_ID) #define cpu_is_sa1110() ((read_cpuid_id() & CPU_SA1110_MASK) == CPU_SA1110_ID) -# define __REG(x) (*((volatile unsigned long __iomem *)io_p2v(x))) +# define __REG(x) (*((volatile unsigned long *)io_p2v(x))) # define __PREG(x) (io_v2p((unsigned long)&(x))) static inline unsigned long get_clock_tick_rate(void) diff --git a/trunk/arch/arm/mach-sa1100/include/mach/uncompress.h b/trunk/arch/arm/mach-sa1100/include/mach/uncompress.h index 5cf71da60e42..6cb39ddde656 100644 --- a/trunk/arch/arm/mach-sa1100/include/mach/uncompress.h +++ b/trunk/arch/arm/mach-sa1100/include/mach/uncompress.h @@ -8,8 +8,6 @@ #include "hardware.h" -#define IOMEM(x) (x) - /* * The following code assumes the serial port has already been * initialized by the bootloader. We search for the first enabled diff --git a/trunk/arch/arm/mach-sa1100/irq.c b/trunk/arch/arm/mach-sa1100/irq.c index 2124f1fc2fbe..516ccc25d7fd 100644 --- a/trunk/arch/arm/mach-sa1100/irq.c +++ b/trunk/arch/arm/mach-sa1100/irq.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include diff --git a/trunk/arch/arm/mach-sa1100/jornada720_ssp.c b/trunk/arch/arm/mach-sa1100/jornada720_ssp.c index 7f07f08d8968..b412fc09c80c 100644 --- a/trunk/arch/arm/mach-sa1100/jornada720_ssp.c +++ b/trunk/arch/arm/mach-sa1100/jornada720_ssp.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/arm/mach-sa1100/leds-cerf.c b/trunk/arch/arm/mach-sa1100/leds-cerf.c index 30fc3b2bf555..040540fb7d8a 100644 --- a/trunk/arch/arm/mach-sa1100/leds-cerf.c +++ b/trunk/arch/arm/mach-sa1100/leds-cerf.c @@ -4,7 +4,6 @@ * Author: ??? */ #include -#include #include #include diff --git a/trunk/arch/arm/mach-sa1100/leds-lart.c b/trunk/arch/arm/mach-sa1100/leds-lart.c index 50a5b143b460..a51830c60e53 100644 --- a/trunk/arch/arm/mach-sa1100/leds-lart.c +++ b/trunk/arch/arm/mach-sa1100/leds-lart.c @@ -10,7 +10,6 @@ * pace of the LED. */ #include -#include #include #include diff --git a/trunk/arch/arm/mach-sa1100/pm.c b/trunk/arch/arm/mach-sa1100/pm.c index 6645d1e31f14..690cf0ce5c0c 100644 --- a/trunk/arch/arm/mach-sa1100/pm.c +++ b/trunk/arch/arm/mach-sa1100/pm.c @@ -23,7 +23,6 @@ * Storage is local on the stack now. */ #include -#include #include #include #include diff --git a/trunk/arch/arm/mach-sa1100/sleep.S b/trunk/arch/arm/mach-sa1100/sleep.S index 85863741ef8b..30cc6721665b 100644 --- a/trunk/arch/arm/mach-sa1100/sleep.S +++ b/trunk/arch/arm/mach-sa1100/sleep.S @@ -38,9 +38,9 @@ ENTRY(sa1100_finish_suspend) orr r4, r4, #MDREFR_K1DB2 ldr r5, =PPCR - @ Pre-load __loop_udelay into the I-cache + @ Pre-load __udelay into the I-cache mov r0, #1 - bl __loop_udelay + bl __udelay mov r0, r0 @ The following must all exist in a single cache line to @@ -53,11 +53,11 @@ ENTRY(sa1100_finish_suspend) @ delay 90us and set CPU PLL to lowest speed @ fixes resume problem on high speed SA1110 mov r0, #90 - bl __loop_udelay + bl __udelay mov r1, #0 str r1, [r5] mov r0, #90 - bl __loop_udelay + bl __udelay /* * SA1110 SDRAM controller workaround. register values: diff --git a/trunk/arch/arm/mach-sa1100/time.c b/trunk/arch/arm/mach-sa1100/time.c index 80702c9ecc77..6af26e8d55e6 100644 --- a/trunk/arch/arm/mach-sa1100/time.c +++ b/trunk/arch/arm/mach-sa1100/time.c @@ -22,7 +22,7 @@ static u32 notrace sa1100_read_sched_clock(void) { - return readl_relaxed(OSCR); + return OSCR; } #define MIN_OSCR_DELTA 2 @@ -32,8 +32,8 @@ static irqreturn_t sa1100_ost0_interrupt(int irq, void *dev_id) struct clock_event_device *c = dev_id; /* Disarm the compare/match, signal the event. */ - writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); - writel_relaxed(OSSR_M0, OSSR); + OIER &= ~OIER_E0; + OSSR = OSSR_M0; c->event_handler(c); return IRQ_HANDLED; @@ -44,10 +44,10 @@ sa1100_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c) { unsigned long next, oscr; - writel_relaxed(readl_relaxed(OIER) | OIER_E0, OIER); - next = readl_relaxed(OSCR) + delta; - writel_relaxed(next, OSMR0); - oscr = readl_relaxed(OSCR); + OIER |= OIER_E0; + next = OSCR + delta; + OSMR0 = next; + oscr = OSCR; return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0; } @@ -59,8 +59,8 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c) case CLOCK_EVT_MODE_ONESHOT: case CLOCK_EVT_MODE_UNUSED: case CLOCK_EVT_MODE_SHUTDOWN: - writel_relaxed(readl_relaxed(OIER) & ~OIER_E0, OIER); - writel_relaxed(OSSR_M0, OSSR); + OIER &= ~OIER_E0; + OSSR = OSSR_M0; break; case CLOCK_EVT_MODE_RESUME: @@ -86,8 +86,8 @@ static struct irqaction sa1100_timer_irq = { static void __init sa1100_timer_init(void) { - writel_relaxed(0, OIER); - writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR); + OIER = 0; + OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3; setup_sched_clock(sa1100_read_sched_clock, 32, 3686400); @@ -100,7 +100,7 @@ static void __init sa1100_timer_init(void) setup_irq(IRQ_OST0, &sa1100_timer_irq); - clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, + clocksource_mmio_init(&OSCR, "oscr", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up); clockevents_register_device(&ckevt_sa1100_osmr0); } @@ -110,26 +110,26 @@ unsigned long osmr[4], oier; static void sa1100_timer_suspend(void) { - osmr[0] = readl_relaxed(OSMR0); - osmr[1] = readl_relaxed(OSMR1); - osmr[2] = readl_relaxed(OSMR2); - osmr[3] = readl_relaxed(OSMR3); - oier = readl_relaxed(OIER); + osmr[0] = OSMR0; + osmr[1] = OSMR1; + osmr[2] = OSMR2; + osmr[3] = OSMR3; + oier = OIER; } static void sa1100_timer_resume(void) { - writel_relaxed(0x0f, OSSR); - writel_relaxed(osmr[0], OSMR0); - writel_relaxed(osmr[1], OSMR1); - writel_relaxed(osmr[2], OSMR2); - writel_relaxed(osmr[3], OSMR3); - writel_relaxed(oier, OIER); + OSSR = 0x0f; + OSMR0 = osmr[0]; + OSMR1 = osmr[1]; + OSMR2 = osmr[2]; + OSMR3 = osmr[3]; + OIER = oier; /* * OSMR0 is the system timer: make sure OSCR is sufficiently behind */ - writel_relaxed(OSMR0 - LATCH, OSCR); + OSCR = OSMR0 - LATCH; } #else #define sa1100_timer_suspend NULL diff --git a/trunk/arch/arm/mm/context.c b/trunk/arch/arm/mm/context.c index 119bc52ab93e..806cc4f63516 100644 --- a/trunk/arch/arm/mm/context.c +++ b/trunk/arch/arm/mm/context.c @@ -14,7 +14,6 @@ #include #include -#include #include static DEFINE_RAW_SPINLOCK(cpu_asid_lock); @@ -49,40 +48,6 @@ void cpu_set_reserved_ttbr0(void) } #endif -#ifdef CONFIG_PID_IN_CONTEXTIDR -static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd, - void *t) -{ - u32 contextidr; - pid_t pid; - struct thread_info *thread = t; - - if (cmd != THREAD_NOTIFY_SWITCH) - return NOTIFY_DONE; - - pid = task_pid_nr(thread->task) << ASID_BITS; - asm volatile( - " mrc p15, 0, %0, c13, c0, 1\n" - " bfi %1, %0, #0, %2\n" - " mcr p15, 0, %1, c13, c0, 1\n" - : "=r" (contextidr), "+r" (pid) - : "I" (ASID_BITS)); - isb(); - - return NOTIFY_OK; -} - -static struct notifier_block contextidr_notifier_block = { - .notifier_call = contextidr_notifier, -}; - -static int __init contextidr_notifier_init(void) -{ - return thread_register_notifier(&contextidr_notifier_block); -} -arch_initcall(contextidr_notifier_init); -#endif - /* * We fork()ed a process, and we need a new context for the child * to run in. diff --git a/trunk/arch/arm/mm/dma-mapping.c b/trunk/arch/arm/mm/dma-mapping.c index 5cfc98994076..655878bcc96d 100644 --- a/trunk/arch/arm/mm/dma-mapping.c +++ b/trunk/arch/arm/mm/dma-mapping.c @@ -23,12 +23,12 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include diff --git a/trunk/arch/arm/mm/init.c b/trunk/arch/arm/mm/init.c index 9aec41fa80ae..f54d59219764 100644 --- a/trunk/arch/arm/mm/init.c +++ b/trunk/arch/arm/mm/init.c @@ -21,13 +21,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include diff --git a/trunk/arch/arm/mm/ioremap.c b/trunk/arch/arm/mm/ioremap.c index 566750fa57d4..4f55f5062ab7 100644 --- a/trunk/arch/arm/mm/ioremap.c +++ b/trunk/arch/arm/mm/ioremap.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include @@ -33,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/trunk/arch/arm/mm/mmu.c b/trunk/arch/arm/mm/mmu.c index 4c2d0451e84a..cf4528d51774 100644 --- a/trunk/arch/arm/mm/mmu.c +++ b/trunk/arch/arm/mm/mmu.c @@ -16,13 +16,13 @@ #include #include #include -#include #include #include #include #include #include +#include #include #include #include @@ -421,6 +421,12 @@ static void __init build_mem_type_table(void) cp = &cache_policies[cachepolicy]; vecs_pgprot = kern_pgprot = user_pgprot = cp->pte; + /* + * Only use write-through for non-SMP systems + */ + if (!is_smp() && cpu_arch >= CPU_ARCH_ARMv5 && cachepolicy > CPOLICY_WRITETHROUGH) + vecs_pgprot = cache_policies[CPOLICY_WRITETHROUGH].pte; + /* * Enable CPU-specific coherency if supported. * (Only available on XSC3 at the moment.) diff --git a/trunk/arch/arm/mm/proc-v6.S b/trunk/arch/arm/mm/proc-v6.S index 86b8b480634f..5900cd520e84 100644 --- a/trunk/arch/arm/mm/proc-v6.S +++ b/trunk/arch/arm/mm/proc-v6.S @@ -107,12 +107,6 @@ ENTRY(cpu_v6_switch_mm) mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB mcr p15, 0, r2, c7, c10, 4 @ drain write buffer mcr p15, 0, r0, c2, c0, 0 @ set TTB 0 -#ifdef CONFIG_PID_IN_CONTEXTIDR - mrc p15, 0, r2, c13, c0, 1 @ read current context ID - bic r2, r2, #0xff @ extract the PID - and r1, r1, #0xff - orr r1, r1, r2 @ insert into new context ID -#endif mcr p15, 0, r1, c13, c0, 1 @ set context ID #endif mov pc, lr diff --git a/trunk/arch/arm/mm/proc-v7-2level.S b/trunk/arch/arm/mm/proc-v7-2level.S index fd045e706390..42ac069c8012 100644 --- a/trunk/arch/arm/mm/proc-v7-2level.S +++ b/trunk/arch/arm/mm/proc-v7-2level.S @@ -46,11 +46,6 @@ ENTRY(cpu_v7_switch_mm) #ifdef CONFIG_ARM_ERRATA_430973 mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB #endif -#ifdef CONFIG_PID_IN_CONTEXTIDR - mrc p15, 0, r2, c13, c0, 1 @ read current context ID - lsr r2, r2, #8 @ extract the PID - bfi r1, r2, #8, #24 @ insert into new context ID -#endif #ifdef CONFIG_ARM_ERRATA_754322 dsb #endif diff --git a/trunk/arch/arm/oprofile/common.c b/trunk/arch/arm/oprofile/common.c index 99c63d4b6af8..4e0a371630b3 100644 --- a/trunk/arch/arm/oprofile/common.c +++ b/trunk/arch/arm/oprofile/common.c @@ -23,37 +23,26 @@ #include #ifdef CONFIG_HW_PERF_EVENTS - -/* - * OProfile has a curious naming scheme for the ARM PMUs, but they are - * part of the user ABI so we need to map from the perf PMU name for - * supported PMUs. - */ -static struct op_perf_name { - char *perf_name; - char *op_name; -} op_perf_name_map[] = { - { "xscale1", "arm/xscale1" }, - { "xscale1", "arm/xscale2" }, - { "v6", "arm/armv6" }, - { "v6mpcore", "arm/mpcore" }, - { "ARMv7 Cortex-A8", "arm/armv7" }, - { "ARMv7 Cortex-A9", "arm/armv7-ca9" }, -}; - char *op_name_from_perf_id(void) { - int i; - struct op_perf_name names; - const char *perf_name = perf_pmu_name(); - - for (i = 0; i < ARRAY_SIZE(op_perf_name_map); ++i) { - names = op_perf_name_map[i]; - if (!strcmp(names.perf_name, perf_name)) - return names.op_name; + enum arm_perf_pmu_ids id = armpmu_get_pmu_id(); + + switch (id) { + case ARM_PERF_PMU_ID_XSCALE1: + return "arm/xscale1"; + case ARM_PERF_PMU_ID_XSCALE2: + return "arm/xscale2"; + case ARM_PERF_PMU_ID_V6: + return "arm/armv6"; + case ARM_PERF_PMU_ID_V6MP: + return "arm/mpcore"; + case ARM_PERF_PMU_ID_CA8: + return "arm/armv7"; + case ARM_PERF_PMU_ID_CA9: + return "arm/armv7-ca9"; + default: + return NULL; } - - return NULL; } #endif diff --git a/trunk/arch/arm/plat-versatile/platsmp.c b/trunk/arch/arm/plat-versatile/platsmp.c index d7c5c171f5aa..49c7db48c7f1 100644 --- a/trunk/arch/arm/plat-versatile/platsmp.c +++ b/trunk/arch/arm/plat-versatile/platsmp.c @@ -85,7 +85,7 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle) * the boot monitor to read the system wide flags register, * and branch to the address found there. */ - gic_raise_softirq(cpumask_of(cpu), 0); + gic_raise_softirq(cpumask_of(cpu), 1); timeout = jiffies + (1 * HZ); while (time_before(jiffies, timeout)) { diff --git a/trunk/arch/avr32/include/asm/kmap_types.h b/trunk/arch/avr32/include/asm/kmap_types.h index 479330b89796..b7f5c6870107 100644 --- a/trunk/arch/avr32/include/asm/kmap_types.h +++ b/trunk/arch/avr32/include/asm/kmap_types.h @@ -2,9 +2,29 @@ #define __ASM_AVR32_KMAP_TYPES_H #ifdef CONFIG_DEBUG_HIGHMEM -# define KM_TYPE_NR 29 +# define D(n) __KM_FENCE_##n , #else -# define KM_TYPE_NR 14 +# define D(n) #endif +enum km_type { +D(0) KM_BOUNCE_READ, +D(1) KM_SKB_SUNRPC_DATA, +D(2) KM_SKB_DATA_SOFTIRQ, +D(3) KM_USER0, +D(4) KM_USER1, +D(5) KM_BIO_SRC_IRQ, +D(6) KM_BIO_DST_IRQ, +D(7) KM_PTE0, +D(8) KM_PTE1, +D(9) KM_PTE2, +D(10) KM_IRQ0, +D(11) KM_IRQ1, +D(12) KM_SOFTIRQ0, +D(13) KM_SOFTIRQ1, +D(14) KM_TYPE_NR +}; + +#undef D + #endif /* __ASM_AVR32_KMAP_TYPES_H */ diff --git a/trunk/arch/frv/include/asm/highmem.h b/trunk/arch/frv/include/asm/highmem.h index b3adc93611f3..716956a5317b 100644 --- a/trunk/arch/frv/include/asm/highmem.h +++ b/trunk/arch/frv/include/asm/highmem.h @@ -76,16 +76,15 @@ extern struct page *kmap_atomic_to_page(void *ptr); #ifndef __ASSEMBLY__ -#define __kmap_atomic_primary(cached, paddr, ampr) \ +#define __kmap_atomic_primary(type, paddr, ampr) \ ({ \ unsigned long damlr, dampr; \ \ dampr = paddr | xAMPRx_L | xAMPRx_M | xAMPRx_S | xAMPRx_SS_16Kb | xAMPRx_V; \ \ - if (!cached) \ + if (type != __KM_CACHE) \ asm volatile("movgs %0,dampr"#ampr :: "r"(dampr) : "memory"); \ else \ - /* cache flush page attachment point */ \ asm volatile("movgs %0,iampr"#ampr"\n" \ "movgs %0,dampr"#ampr"\n" \ :: "r"(dampr) : "memory" \ @@ -113,20 +112,29 @@ extern struct page *kmap_atomic_to_page(void *ptr); (void *) damlr; \ }) -static inline void *kmap_atomic_primary(struct page *page) +static inline void *kmap_atomic_primary(struct page *page, enum km_type type) { unsigned long paddr; pagefault_disable(); paddr = page_to_phys(page); - return __kmap_atomic_primary(1, paddr, 2); + switch (type) { + case 0: return __kmap_atomic_primary(0, paddr, 2); + case 1: return __kmap_atomic_primary(1, paddr, 3); + case 2: return __kmap_atomic_primary(2, paddr, 4); + case 3: return __kmap_atomic_primary(3, paddr, 5); + + default: + BUG(); + return NULL; + } } -#define __kunmap_atomic_primary(cached, ampr) \ +#define __kunmap_atomic_primary(type, ampr) \ do { \ asm volatile("movgs gr0,dampr"#ampr"\n" ::: "memory"); \ - if (cached) \ + if (type == __KM_CACHE) \ asm volatile("movgs gr0,iampr"#ampr"\n" ::: "memory"); \ } while(0) @@ -135,9 +143,17 @@ do { \ asm volatile("tlbpr %0,gr0,#4,#1" : : "r"(vaddr) : "memory"); \ } while(0) -static inline void kunmap_atomic_primary(void *kvaddr) +static inline void kunmap_atomic_primary(void *kvaddr, enum km_type type) { - __kunmap_atomic_primary(1, 2); + switch (type) { + case 0: __kunmap_atomic_primary(0, 2); break; + case 1: __kunmap_atomic_primary(1, 3); break; + case 2: __kunmap_atomic_primary(2, 4); break; + case 3: __kunmap_atomic_primary(3, 5); break; + + default: + BUG(); + } pagefault_enable(); } diff --git a/trunk/arch/frv/include/asm/kmap_types.h b/trunk/arch/frv/include/asm/kmap_types.h index 43901f220963..f8e16b2a5804 100644 --- a/trunk/arch/frv/include/asm/kmap_types.h +++ b/trunk/arch/frv/include/asm/kmap_types.h @@ -2,6 +2,28 @@ #ifndef _ASM_KMAP_TYPES_H #define _ASM_KMAP_TYPES_H -#define KM_TYPE_NR 17 +enum km_type { + /* arch specific kmaps - change the numbers attached to these at your peril */ + __KM_CACHE, /* cache flush page attachment point */ + __KM_PGD, /* current page directory */ + __KM_ITLB_PTD, /* current instruction TLB miss page table lookup */ + __KM_DTLB_PTD, /* current data TLB miss page table lookup */ + + /* general kmaps */ + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; #endif diff --git a/trunk/arch/frv/mb93090-mb00/pci-dma.c b/trunk/arch/frv/mb93090-mb00/pci-dma.c index 82478979ac9a..4f8d8bcdc7de 100644 --- a/trunk/arch/frv/mb93090-mb00/pci-dma.c +++ b/trunk/arch/frv/mb93090-mb00/pci-dma.c @@ -62,14 +62,14 @@ int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, dampr2 = __get_DAMPR(2); for (i = 0; i < nents; i++) { - vaddr = kmap_atomic_primary(sg_page(&sg[i])); + vaddr = kmap_atomic_primary(sg_page(&sg[i]), __KM_CACHE); frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE); } - kunmap_atomic_primary(vaddr); + kunmap_atomic_primary(vaddr, __KM_CACHE); if (dampr2) { __set_DAMPR(2, dampr2); __set_IAMPR(2, dampr2); diff --git a/trunk/arch/frv/mm/cache-page.c b/trunk/arch/frv/mm/cache-page.c index 8e09dae0ec3f..b24ade27a0f0 100644 --- a/trunk/arch/frv/mm/cache-page.c +++ b/trunk/arch/frv/mm/cache-page.c @@ -26,11 +26,11 @@ void flush_dcache_page(struct page *page) dampr2 = __get_DAMPR(2); - vaddr = kmap_atomic_primary(page); + vaddr = kmap_atomic_primary(page, __KM_CACHE); frv_dcache_writeback((unsigned long) vaddr, (unsigned long) vaddr + PAGE_SIZE); - kunmap_atomic_primary(vaddr); + kunmap_atomic_primary(vaddr, __KM_CACHE); if (dampr2) { __set_DAMPR(2, dampr2); @@ -54,12 +54,12 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page, dampr2 = __get_DAMPR(2); - vaddr = kmap_atomic_primary(page); + vaddr = kmap_atomic_primary(page, __KM_CACHE); start = (start & ~PAGE_MASK) | (unsigned long) vaddr; frv_cache_wback_inv(start, start + len); - kunmap_atomic_primary(vaddr); + kunmap_atomic_primary(vaddr, __KM_CACHE); if (dampr2) { __set_DAMPR(2, dampr2); diff --git a/trunk/arch/frv/mm/highmem.c b/trunk/arch/frv/mm/highmem.c index bed9a9bd3c10..31902c9d5be5 100644 --- a/trunk/arch/frv/mm/highmem.c +++ b/trunk/arch/frv/mm/highmem.c @@ -50,11 +50,11 @@ void *kmap_atomic(struct page *page) /* * The first 4 primary maps are reserved for architecture code */ - case 0: return __kmap_atomic_primary(0, paddr, 6); - case 1: return __kmap_atomic_primary(0, paddr, 7); - case 2: return __kmap_atomic_primary(0, paddr, 8); - case 3: return __kmap_atomic_primary(0, paddr, 9); - case 4: return __kmap_atomic_primary(0, paddr, 10); + case 0: return __kmap_atomic_primary(4, paddr, 6); + case 1: return __kmap_atomic_primary(5, paddr, 7); + case 2: return __kmap_atomic_primary(6, paddr, 8); + case 3: return __kmap_atomic_primary(7, paddr, 9); + case 4: return __kmap_atomic_primary(8, paddr, 10); case 5 ... 5 + NR_TLB_LINES - 1: return __kmap_atomic_secondary(type - 5, paddr); @@ -70,11 +70,11 @@ void __kunmap_atomic(void *kvaddr) { int type = kmap_atomic_idx(); switch (type) { - case 0: __kunmap_atomic_primary(0, 6); break; - case 1: __kunmap_atomic_primary(0, 7); break; - case 2: __kunmap_atomic_primary(0, 8); break; - case 3: __kunmap_atomic_primary(0, 9); break; - case 4: __kunmap_atomic_primary(0, 10); break; + case 0: __kunmap_atomic_primary(4, 6); break; + case 1: __kunmap_atomic_primary(5, 7); break; + case 2: __kunmap_atomic_primary(6, 8); break; + case 3: __kunmap_atomic_primary(7, 9); break; + case 4: __kunmap_atomic_primary(8, 10); break; case 5 ... 5 + NR_TLB_LINES - 1: __kunmap_atomic_secondary(type - 5, kvaddr); diff --git a/trunk/arch/powerpc/include/asm/kmap_types.h b/trunk/arch/powerpc/include/asm/kmap_types.h index 5acabbd7ac6f..bca8fdcd2542 100644 --- a/trunk/arch/powerpc/include/asm/kmap_types.h +++ b/trunk/arch/powerpc/include/asm/kmap_types.h @@ -10,7 +10,36 @@ * 2 of the License, or (at your option) any later version. */ -#define KM_TYPE_NR 16 +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_PPC_SYNC_PAGE, + KM_PPC_SYNC_ICACHE, + KM_KDB, + KM_TYPE_NR +}; + +/* + * This is a temporary build fix that (so they say on lkml....) should no longer + * be required after 2.6.33, because of changes planned to the kmap code. + * Let's try to remove this cruft then. + */ +#ifdef CONFIG_DEBUG_HIGHMEM +#define KM_NMI (-1) +#define KM_NMI_PTE (-1) +#define KM_IRQ_PTE (-1) +#endif #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_KMAP_TYPES_H */ diff --git a/trunk/arch/tile/include/asm/kmap_types.h b/trunk/arch/tile/include/asm/kmap_types.h index 92b28e3e9972..3d0f20246260 100644 --- a/trunk/arch/tile/include/asm/kmap_types.h +++ b/trunk/arch/tile/include/asm/kmap_types.h @@ -23,6 +23,35 @@ * adds 4MB of required address-space. For now we leave KM_TYPE_NR * set to depth 8. */ -#define KM_TYPE_NR 8 +enum km_type { + KM_TYPE_NR = 8 +}; + +/* + * We provide dummy definitions of all the stray values that used to be + * required for kmap_atomic() and no longer are. + */ +enum { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_SYNC_ICACHE, + KM_SYNC_DCACHE, + KM_UML_USERCOPY, + KM_IRQ_PTE, + KM_NMI, + KM_NMI_PTE, + KM_KDB +}; #endif /* _ASM_TILE_KMAP_TYPES_H */ diff --git a/trunk/arch/tile/mm/highmem.c b/trunk/arch/tile/mm/highmem.c index 347d123b14be..ef8e5a62b6e3 100644 --- a/trunk/arch/tile/mm/highmem.c +++ b/trunk/arch/tile/mm/highmem.c @@ -93,7 +93,7 @@ static DEFINE_PER_CPU(struct kmap_amps, amps); * If we examine it earlier we are exposed to a race where it looks * writable earlier, but becomes immutable before we write the PTE. */ -static void kmap_atomic_register(struct page *page, int type, +static void kmap_atomic_register(struct page *page, enum km_type type, unsigned long va, pte_t *ptep, pte_t pteval) { unsigned long flags; diff --git a/trunk/arch/um/include/asm/kmap_types.h b/trunk/arch/um/include/asm/kmap_types.h index 2e0a6b1d8300..6c03acdb4405 100644 --- a/trunk/arch/um/include/asm/kmap_types.h +++ b/trunk/arch/um/include/asm/kmap_types.h @@ -8,6 +8,22 @@ /* No more #include "asm/arch/kmap_types.h" ! */ -#define KM_TYPE_NR 14 +enum km_type { + KM_BOUNCE_READ, + KM_SKB_SUNRPC_DATA, + KM_SKB_DATA_SOFTIRQ, + KM_USER0, + KM_USER1, + KM_UML_USERCOPY, /* UML specific, for copy_*_user - used in do_op_one_page */ + KM_BIO_SRC_IRQ, + KM_BIO_DST_IRQ, + KM_PTE0, + KM_PTE1, + KM_IRQ0, + KM_IRQ1, + KM_SOFTIRQ0, + KM_SOFTIRQ1, + KM_TYPE_NR +}; #endif diff --git a/trunk/drivers/amba/bus.c b/trunk/drivers/amba/bus.c index e8eb91bd0d28..b7e728517284 100644 --- a/trunk/drivers/amba/bus.c +++ b/trunk/drivers/amba/bus.c @@ -16,9 +16,9 @@ #include #include #include -#include #include +#include #define to_amba_driver(d) container_of(d, struct amba_driver, drv) diff --git a/trunk/drivers/input/touchscreen/jornada720_ts.c b/trunk/drivers/input/touchscreen/jornada720_ts.c index 7f03d1bd916e..d9be6eac99b1 100644 --- a/trunk/drivers/input/touchscreen/jornada720_ts.c +++ b/trunk/drivers/input/touchscreen/jornada720_ts.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include diff --git a/trunk/drivers/net/irda/pxaficp_ir.c b/trunk/drivers/net/irda/pxaficp_ir.c index 8d5476707912..ff16daf33ae1 100644 --- a/trunk/drivers/net/irda/pxaficp_ir.c +++ b/trunk/drivers/net/irda/pxaficp_ir.c @@ -289,7 +289,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) } lsr = STLSR; } - si->last_oscr = readl_relaxed(OSCR); + si->last_oscr = OSCR; break; case 0x04: /* Received Data Available */ @@ -300,7 +300,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) dev->stats.rx_bytes++; async_unwrap_char(dev, &dev->stats, &si->rx_buff, STRBR); } while (STLSR & LSR_DR); - si->last_oscr = readl_relaxed(OSCR); + si->last_oscr = OSCR; break; case 0x02: /* Transmit FIFO Data Request */ @@ -316,7 +316,7 @@ static irqreturn_t pxa_irda_sir_irq(int irq, void *dev_id) /* We need to ensure that the transmitter has finished. */ while ((STLSR & LSR_TEMT) == 0) cpu_relax(); - si->last_oscr = readl_relaxed(OSCR); + si->last_oscr = OSCR; /* * Ok, we've finished transmitting. Now enable @@ -370,7 +370,7 @@ static void pxa_irda_fir_dma_tx_irq(int channel, void *data) while (ICSR1 & ICSR1_TBY) cpu_relax(); - si->last_oscr = readl_relaxed(OSCR); + si->last_oscr = OSCR; /* * HACK: It looks like the TBY bit is dropped too soon. @@ -470,7 +470,7 @@ static irqreturn_t pxa_irda_fir_irq(int irq, void *dev_id) /* stop RX DMA */ DCSR(si->rxdma) &= ~DCSR_RUN; - si->last_oscr = readl_relaxed(OSCR); + si->last_oscr = OSCR; icsr0 = ICSR0; if (icsr0 & (ICSR0_FRE | ICSR0_RAB)) { @@ -546,7 +546,7 @@ static int pxa_irda_hard_xmit(struct sk_buff *skb, struct net_device *dev) skb_copy_from_linear_data(skb, si->dma_tx_buff, skb->len); if (mtt) - while ((unsigned)(readl_relaxed(OSCR) - si->last_oscr)/4 < mtt) + while ((unsigned)(OSCR - si->last_oscr)/4 < mtt) cpu_relax(); /* stop RX DMA, disable FICP */ diff --git a/trunk/drivers/pcmcia/sa1100_shannon.c b/trunk/drivers/pcmcia/sa1100_shannon.c index 56ab73915602..decb34730bcf 100644 --- a/trunk/drivers/pcmcia/sa1100_shannon.c +++ b/trunk/drivers/pcmcia/sa1100_shannon.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff --git a/trunk/drivers/tty/serial/8250/8250.c b/trunk/drivers/tty/serial/8250/8250.c index 8123f784bcda..6e1958a325bd 100644 --- a/trunk/drivers/tty/serial/8250/8250.c +++ b/trunk/drivers/tty/serial/8250/8250.c @@ -282,14 +282,6 @@ static const struct serial8250_config uart_config[] = { .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, .flags = UART_CAP_FIFO | UART_CAP_AFE | UART_CAP_EFR, }, - [PORT_LPC3220] = { - .name = "LPC3220", - .fifo_size = 64, - .tx_loadsz = 32, - .fcr = UART_FCR_DMA_SELECT | UART_FCR_ENABLE_FIFO | - UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, - .flags = UART_CAP_FIFO, - }, }; /* Uart divisor latch read */ diff --git a/trunk/drivers/tty/serial/amba-pl011.c b/trunk/drivers/tty/serial/amba-pl011.c index d3553b5d3fca..c17923ec6e95 100644 --- a/trunk/drivers/tty/serial/amba-pl011.c +++ b/trunk/drivers/tty/serial/amba-pl011.c @@ -53,9 +53,9 @@ #include #include #include -#include #include +#include #define UART_NR 14 diff --git a/trunk/drivers/tty/serial/of_serial.c b/trunk/drivers/tty/serial/of_serial.c index 34e71874a892..5410c0637266 100644 --- a/trunk/drivers/tty/serial/of_serial.c +++ b/trunk/drivers/tty/serial/of_serial.c @@ -208,7 +208,6 @@ static struct of_device_id __devinitdata of_platform_serial_table[] = { { .compatible = "ns16750", .data = (void *)PORT_16750, }, { .compatible = "ns16850", .data = (void *)PORT_16850, }, { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, - { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL { .compatible = "ibm,qpace-nwp-serial", .data = (void *)PORT_NWPSERIAL, }, diff --git a/trunk/drivers/tty/serial/pch_uart.c b/trunk/drivers/tty/serial/pch_uart.c index 558ce8509a9a..4fdec6a6b758 100644 --- a/trunk/drivers/tty/serial/pch_uart.c +++ b/trunk/drivers/tty/serial/pch_uart.c @@ -253,9 +253,6 @@ struct eg20t_port { dma_addr_t rx_buf_dma; struct dentry *debugfs; - - /* protect the eg20t_port private structure and io access to membase */ - spinlock_t lock; }; /** @@ -757,8 +754,7 @@ static void pch_dma_rx_complete(void *arg) tty_flip_buffer_push(tty); tty_kref_put(tty); async_tx_ack(priv->desc_rx); - pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | - PCH_UART_HAL_RX_ERR_INT); + pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); } static void pch_dma_tx_complete(void *arg) @@ -813,8 +809,7 @@ static int handle_rx_to(struct eg20t_port *priv) int rx_size; int ret; if (!priv->start_rx) { - pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | - PCH_UART_HAL_RX_ERR_INT); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); return 0; } buf = &priv->rxbuf; @@ -1063,7 +1058,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) int next = 1; u8 msr; - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&priv->port.lock, flags); handled = 0; while (next) { iid = pch_uart_hal_get_iid(priv); @@ -1083,13 +1078,11 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) case PCH_UART_IID_RDR: /* Received Data Ready */ if (priv->use_dma) { pch_uart_hal_disable_interrupt(priv, - PCH_UART_HAL_RX_INT | - PCH_UART_HAL_RX_ERR_INT); + PCH_UART_HAL_RX_INT); ret = dma_handle_rx(priv); if (!ret) pch_uart_hal_enable_interrupt(priv, - PCH_UART_HAL_RX_INT | - PCH_UART_HAL_RX_ERR_INT); + PCH_UART_HAL_RX_INT); } else { ret = handle_rx(priv); } @@ -1123,7 +1116,7 @@ static irqreturn_t pch_uart_interrupt(int irq, void *dev_id) handled |= (unsigned int)ret; } - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&priv->port.lock, flags); return IRQ_RETVAL(handled); } @@ -1215,8 +1208,7 @@ static void pch_uart_stop_rx(struct uart_port *port) struct eg20t_port *priv; priv = container_of(port, struct eg20t_port, port); priv->start_rx = 0; - pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT | - PCH_UART_HAL_RX_ERR_INT); + pch_uart_hal_disable_interrupt(priv, PCH_UART_HAL_RX_INT); } /* Enable the modem status interrupts. */ @@ -1234,9 +1226,9 @@ static void pch_uart_break_ctl(struct uart_port *port, int ctl) unsigned long flags; priv = container_of(port, struct eg20t_port, port); - spin_lock_irqsave(&priv->lock, flags); + spin_lock_irqsave(&port->lock, flags); pch_uart_hal_set_break(priv, ctl); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } /* Grab any interrupt resources and initialise any low level driver state. */ @@ -1271,7 +1263,6 @@ static int pch_uart_startup(struct uart_port *port) break; case 16: fifo_size = PCH_UART_HAL_FIFO16; - break; case 1: default: fifo_size = PCH_UART_HAL_FIFO_DIS; @@ -1309,8 +1300,7 @@ static int pch_uart_startup(struct uart_port *port) pch_request_dma(port); priv->start_rx = 1; - pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT | - PCH_UART_HAL_RX_ERR_INT); + pch_uart_hal_enable_interrupt(priv, PCH_UART_HAL_RX_INT); uart_update_timeout(port, CS8, default_baud); return 0; @@ -1368,7 +1358,7 @@ static void pch_uart_set_termios(struct uart_port *port, stb = PCH_UART_HAL_STB1; if (termios->c_cflag & PARENB) { - if (termios->c_cflag & PARODD) + if (!(termios->c_cflag & PARODD)) parity = PCH_UART_HAL_PARITY_ODD; else parity = PCH_UART_HAL_PARITY_EVEN; @@ -1386,8 +1376,7 @@ static void pch_uart_set_termios(struct uart_port *port, baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); - spin_lock_irqsave(&priv->lock, flags); - spin_lock(&port->lock); + spin_lock_irqsave(&port->lock, flags); uart_update_timeout(port, termios->c_cflag, baud); rtn = pch_uart_hal_set_line(priv, baud, parity, bits, stb); @@ -1400,8 +1389,7 @@ static void pch_uart_set_termios(struct uart_port *port, tty_termios_encode_baud_rate(termios, baud, baud); out: - spin_unlock(&port->lock); - spin_unlock_irqrestore(&priv->lock, flags); + spin_unlock_irqrestore(&port->lock, flags); } static const char *pch_uart_type(struct uart_port *port) @@ -1550,9 +1538,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count) { struct eg20t_port *priv; unsigned long flags; - int priv_locked = 1; - int port_locked = 1; u8 ier; + int locked = 1; priv = pch_uart_ports[co->index]; @@ -1560,16 +1547,12 @@ pch_console_write(struct console *co, const char *s, unsigned int count) local_irq_save(flags); if (priv->port.sysrq) { - spin_lock(&priv->lock); - /* serial8250_handle_port() already took the port lock */ - port_locked = 0; + /* serial8250_handle_port() already took the lock */ + locked = 0; } else if (oops_in_progress) { - priv_locked = spin_trylock(&priv->lock); - port_locked = spin_trylock(&priv->port.lock); - } else { - spin_lock(&priv->lock); + locked = spin_trylock(&priv->port.lock); + } else spin_lock(&priv->port.lock); - } /* * First save the IER then disable the interrupts @@ -1587,10 +1570,8 @@ pch_console_write(struct console *co, const char *s, unsigned int count) wait_for_xmitr(priv, BOTH_EMPTY); iowrite8(ier, priv->membase + UART_IER); - if (port_locked) + if (locked) spin_unlock(&priv->port.lock); - if (priv_locked) - spin_unlock(&priv->lock); local_irq_restore(flags); } @@ -1688,8 +1669,6 @@ static struct eg20t_port *pch_uart_init_port(struct pci_dev *pdev, pci_enable_msi(pdev); pci_set_master(pdev); - spin_lock_init(&priv->lock); - iobase = pci_resource_start(pdev, 0); mapbase = pci_resource_start(pdev, 1); priv->mapbase = mapbase; diff --git a/trunk/drivers/tty/serial/samsung.c b/trunk/drivers/tty/serial/samsung.c index 02d07bfcfa8a..d8b0aee35632 100644 --- a/trunk/drivers/tty/serial/samsung.c +++ b/trunk/drivers/tty/serial/samsung.c @@ -1014,10 +1014,10 @@ static int s3c24xx_serial_cpufreq_transition(struct notifier_block *nb, * a disturbance in the clock-rate over the change. */ - if (IS_ERR(port->baudclk)) + if (IS_ERR(port->clk)) goto exit; - if (port->baudclk_rate == clk_get_rate(port->baudclk)) + if (port->baudclk_rate == clk_get_rate(port->clk)) goto exit; if (val == CPUFREQ_PRECHANGE) { diff --git a/trunk/drivers/tty/serial/serial_core.c b/trunk/drivers/tty/serial/serial_core.c index a21dc8e3b7c0..246b823c1b27 100644 --- a/trunk/drivers/tty/serial/serial_core.c +++ b/trunk/drivers/tty/serial/serial_core.c @@ -2527,16 +2527,14 @@ void uart_insert_char(struct uart_port *port, unsigned int status, struct tty_struct *tty = port->state->port.tty; if ((status & port->ignore_status_mask & ~overrun) == 0) - if (tty_insert_flip_char(tty, ch, flag) == 0) - ++port->icount.buf_overrun; + tty_insert_flip_char(tty, ch, flag); /* * Overrun is special. Since it's reported immediately, * it doesn't affect the current character. */ if (status & ~port->ignore_status_mask & overrun) - if (tty_insert_flip_char(tty, 0, TTY_OVERRUN) == 0) - ++port->icount.buf_overrun; + tty_insert_flip_char(tty, 0, TTY_OVERRUN); } EXPORT_SYMBOL_GPL(uart_insert_char); diff --git a/trunk/drivers/tty/tty_ldisc.c b/trunk/drivers/tty/tty_ldisc.c index 6f99c9959f0c..9911eb6b34cd 100644 --- a/trunk/drivers/tty/tty_ldisc.c +++ b/trunk/drivers/tty/tty_ldisc.c @@ -659,7 +659,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) goto enable; } - if (test_bit(TTY_HUPPING, &tty->flags)) { + if (test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ clear_bit(TTY_LDISC_CHANGING, &tty->flags); diff --git a/trunk/drivers/tty/vt/vt_ioctl.c b/trunk/drivers/tty/vt/vt_ioctl.c index b841f56d2e66..64618547be11 100644 --- a/trunk/drivers/tty/vt/vt_ioctl.c +++ b/trunk/drivers/tty/vt/vt_ioctl.c @@ -110,7 +110,16 @@ void vt_event_post(unsigned int event, unsigned int old, unsigned int new) wake_up_interruptible(&vt_event_waitqueue); } -static void __vt_event_queue(struct vt_event_wait *vw) +/** + * vt_event_wait - wait for an event + * @vw: our event + * + * Waits for an event to occur which completes our vt_event_wait + * structure. On return the structure has wv->done set to 1 for success + * or 0 if some event such as a signal ended the wait. + */ + +static void vt_event_wait(struct vt_event_wait *vw) { unsigned long flags; /* Prepare the event */ @@ -120,40 +129,14 @@ static void __vt_event_queue(struct vt_event_wait *vw) spin_lock_irqsave(&vt_event_lock, flags); list_add(&vw->list, &vt_events); spin_unlock_irqrestore(&vt_event_lock, flags); -} - -static void __vt_event_wait(struct vt_event_wait *vw) -{ /* Wait for it to pass */ wait_event_interruptible(vt_event_waitqueue, vw->done); -} - -static void __vt_event_dequeue(struct vt_event_wait *vw) -{ - unsigned long flags; - /* Dequeue it */ spin_lock_irqsave(&vt_event_lock, flags); list_del(&vw->list); spin_unlock_irqrestore(&vt_event_lock, flags); } -/** - * vt_event_wait - wait for an event - * @vw: our event - * - * Waits for an event to occur which completes our vt_event_wait - * structure. On return the structure has wv->done set to 1 for success - * or 0 if some event such as a signal ended the wait. - */ - -static void vt_event_wait(struct vt_event_wait *vw) -{ - __vt_event_queue(vw); - __vt_event_wait(vw); - __vt_event_dequeue(vw); -} - /** * vt_event_wait_ioctl - event ioctl handler * @arg: argument to ioctl @@ -194,14 +177,10 @@ int vt_waitactive(int n) { struct vt_event_wait vw; do { - vw.event.event = VT_EVENT_SWITCH; - __vt_event_queue(&vw); - if (n == fg_console + 1) { - __vt_event_dequeue(&vw); + if (n == fg_console + 1) break; - } - __vt_event_wait(&vw); - __vt_event_dequeue(&vw); + vw.event.event = VT_EVENT_SWITCH; + vt_event_wait(&vw); if (vw.done == 0) return -EINTR; } while (vw.event.newev != n); diff --git a/trunk/drivers/watchdog/sa1100_wdt.c b/trunk/drivers/watchdog/sa1100_wdt.c index ccd6b29e21bf..54984deb8561 100644 --- a/trunk/drivers/watchdog/sa1100_wdt.c +++ b/trunk/drivers/watchdog/sa1100_wdt.c @@ -54,10 +54,10 @@ static int sa1100dog_open(struct inode *inode, struct file *file) return -EBUSY; /* Activate SA1100 Watchdog timer */ - writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); - writel_relaxed(OSSR_M3, OSSR); - writel_relaxed(OWER_WME, OWER); - writel_relaxed(readl_relaxed(OIER) | OIER_E3, OIER); + OSMR3 = OSCR + pre_margin; + OSSR = OSSR_M3; + OWER = OWER_WME; + OIER |= OIER_E3; return nonseekable_open(inode, file); } @@ -80,7 +80,7 @@ static ssize_t sa1100dog_write(struct file *file, const char __user *data, { if (len) /* Refresh OSMR3 timer. */ - writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); + OSMR3 = OSCR + pre_margin; return len; } @@ -114,7 +114,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, break; case WDIOC_KEEPALIVE: - writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); + OSMR3 = OSCR + pre_margin; ret = 0; break; @@ -129,7 +129,7 @@ static long sa1100dog_ioctl(struct file *file, unsigned int cmd, } pre_margin = oscr_freq * time; - writel_relaxed(readl_relaxed(OSCR) + pre_margin, OSMR3); + OSMR3 = OSCR + pre_margin; /*fall through*/ case WDIOC_GETTIMEOUT: diff --git a/trunk/fs/ext4/balloc.c b/trunk/fs/ext4/balloc.c index d23b31ca9d7a..cee7812cc3cf 100644 --- a/trunk/fs/ext4/balloc.c +++ b/trunk/fs/ext4/balloc.c @@ -609,8 +609,7 @@ ext4_fsblk_t ext4_count_free_clusters(struct super_block *sb) if (bitmap_bh == NULL) continue; - x = ext4_count_free(bitmap_bh->b_data, - EXT4_BLOCKS_PER_GROUP(sb) / 8); + x = ext4_count_free(bitmap_bh, sb->s_blocksize); printk(KERN_DEBUG "group %u: stored = %d, counted = %u\n", i, ext4_free_group_clusters(sb, gdp), x); bitmap_count += x; diff --git a/trunk/fs/ext4/bitmap.c b/trunk/fs/ext4/bitmap.c index a94b9c63ee5c..b319721da26a 100644 --- a/trunk/fs/ext4/bitmap.c +++ b/trunk/fs/ext4/bitmap.c @@ -11,18 +11,24 @@ #include #include "ext4.h" +#ifdef EXT4FS_DEBUG + static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; -unsigned int ext4_count_free(char *bitmap, unsigned int numchars) +unsigned int ext4_count_free(struct buffer_head *map, unsigned int numchars) { unsigned int i, sum = 0; + if (!map) + return 0; for (i = 0; i < numchars; i++) - sum += nibblemap[bitmap[i] & 0xf] + - nibblemap[(bitmap[i] >> 4) & 0xf]; + sum += nibblemap[map->b_data[i] & 0xf] + + nibblemap[(map->b_data[i] >> 4) & 0xf]; return sum; } +#endif /* EXT4FS_DEBUG */ + int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, struct buffer_head *bh, int sz) diff --git a/trunk/fs/ext4/ext4.h b/trunk/fs/ext4/ext4.h index c3411d4ce2da..cfc4e01b3c83 100644 --- a/trunk/fs/ext4/ext4.h +++ b/trunk/fs/ext4/ext4.h @@ -571,8 +571,6 @@ enum { #define EXT4_GET_BLOCKS_NO_NORMALIZE 0x0040 /* Request will not result in inode size update (user for fallocate) */ #define EXT4_GET_BLOCKS_KEEP_SIZE 0x0080 - /* Do not take i_data_sem locking in ext4_map_blocks */ -#define EXT4_GET_BLOCKS_NO_LOCK 0x0100 /* * Flags used by ext4_free_blocks @@ -1163,7 +1161,8 @@ struct ext4_sb_info { unsigned long s_desc_per_block; /* Number of group descriptors per block */ ext4_group_t s_groups_count; /* Number of groups in the fs */ ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ - unsigned long s_overhead; /* # of fs overhead clusters */ + unsigned long s_overhead_last; /* Last calculated overhead */ + unsigned long s_blocks_last; /* Last seen block count */ unsigned int s_cluster_ratio; /* Number of blocks per cluster */ unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */ loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ @@ -1315,8 +1314,6 @@ static inline struct timespec ext4_current_time(struct inode *inode) static inline int ext4_valid_inum(struct super_block *sb, unsigned long ino) { return ino == EXT4_ROOT_INO || - ino == EXT4_USR_QUOTA_INO || - ino == EXT4_GRP_QUOTA_INO || ino == EXT4_JOURNAL_INO || ino == EXT4_RESIZE_INO || (ino >= EXT4_FIRST_INO(sb) && @@ -1499,8 +1496,7 @@ static inline void ext4_clear_state_flags(struct ext4_inode_info *ei) EXT4_FEATURE_RO_COMPAT_BTREE_DIR |\ EXT4_FEATURE_RO_COMPAT_HUGE_FILE |\ EXT4_FEATURE_RO_COMPAT_BIGALLOC |\ - EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|\ - EXT4_FEATURE_RO_COMPAT_QUOTA) + EXT4_FEATURE_RO_COMPAT_METADATA_CSUM) /* * Default values for user and/or group using reserved blocks @@ -1667,12 +1663,10 @@ static inline u32 ext4_chksum(struct ext4_sb_info *sbi, u32 crc, { struct { struct shash_desc shash; - char ctx[4]; + char ctx[crypto_shash_descsize(sbi->s_chksum_driver)]; } desc; int err; - BUG_ON(crypto_shash_descsize(sbi->s_chksum_driver)!=sizeof(desc.ctx)); - desc.shash.tfm = sbi->s_chksum_driver; desc.shash.flags = 0; *(u32 *)desc.ctx = crc; @@ -1858,7 +1852,7 @@ struct mmpd_data { # define NORET_AND noreturn, /* bitmap.c */ -extern unsigned int ext4_count_free(char *bitmap, unsigned numchars); +extern unsigned int ext4_count_free(struct buffer_head *, unsigned); void ext4_inode_bitmap_csum_set(struct super_block *sb, ext4_group_t group, struct ext4_group_desc *gdp, struct buffer_head *bh, int sz); @@ -2043,7 +2037,6 @@ extern int ext4_group_extend(struct super_block *sb, extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); /* super.c */ -extern int ext4_calculate_overhead(struct super_block *sb); extern int ext4_superblock_csum_verify(struct super_block *sb, struct ext4_super_block *es); extern void ext4_superblock_csum_set(struct super_block *sb, @@ -2328,6 +2321,15 @@ static inline void ext4_unlock_group(struct super_block *sb, spin_unlock(ext4_group_lock_ptr(sb, group)); } +static inline void ext4_mark_super_dirty(struct super_block *sb) +{ + struct ext4_super_block *es = EXT4_SB(sb)->s_es; + + ext4_superblock_csum_set(sb, es); + if (EXT4_SB(sb)->s_journal == NULL) + sb->s_dirt =1; +} + /* * Block validity checking */ diff --git a/trunk/fs/ext4/ext4_jbd2.c b/trunk/fs/ext4/ext4_jbd2.c index bfa65b49d424..90f7c2e84db1 100644 --- a/trunk/fs/ext4/ext4_jbd2.c +++ b/trunk/fs/ext4/ext4_jbd2.c @@ -138,7 +138,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, } int __ext4_handle_dirty_super(const char *where, unsigned int line, - handle_t *handle, struct super_block *sb) + handle_t *handle, struct super_block *sb, + int now) { struct buffer_head *bh = EXT4_SB(sb)->s_sbh; int err = 0; @@ -150,10 +151,11 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line, if (err) ext4_journal_abort_handle(where, line, __func__, bh, handle, err); - } else { + } else if (now) { ext4_superblock_csum_set(sb, (struct ext4_super_block *)bh->b_data); mark_buffer_dirty(bh); - } + } else + sb->s_dirt = 1; return err; } diff --git a/trunk/fs/ext4/ext4_jbd2.h b/trunk/fs/ext4/ext4_jbd2.h index 56d258c18303..f440e8f1841f 100644 --- a/trunk/fs/ext4/ext4_jbd2.h +++ b/trunk/fs/ext4/ext4_jbd2.h @@ -87,20 +87,14 @@ #ifdef CONFIG_QUOTA /* Amount of blocks needed for quota update - we know that the structure was * allocated so we need to update only data block */ -#define EXT4_QUOTA_TRANS_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ - EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\ - 1 : 0) +#define EXT4_QUOTA_TRANS_BLOCKS(sb) (test_opt(sb, QUOTA) ? 1 : 0) /* Amount of blocks needed for quota insert/delete - we do some block writes * but inode, sb and group updates are done only once */ -#define EXT4_QUOTA_INIT_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ - EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\ - (DQUOT_INIT_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\ - +3+DQUOT_INIT_REWRITE) : 0) - -#define EXT4_QUOTA_DEL_BLOCKS(sb) ((test_opt(sb, QUOTA) ||\ - EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) ?\ - (DQUOT_DEL_ALLOC*(EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)\ - +3+DQUOT_DEL_REWRITE) : 0) +#define EXT4_QUOTA_INIT_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_INIT_ALLOC*\ + (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_INIT_REWRITE) : 0) + +#define EXT4_QUOTA_DEL_BLOCKS(sb) (test_opt(sb, QUOTA) ? (DQUOT_DEL_ALLOC*\ + (EXT4_SINGLEDATA_TRANS_BLOCKS(sb)-3)+3+DQUOT_DEL_REWRITE) : 0) #else #define EXT4_QUOTA_TRANS_BLOCKS(sb) 0 #define EXT4_QUOTA_INIT_BLOCKS(sb) 0 @@ -219,7 +213,8 @@ int __ext4_handle_dirty_metadata(const char *where, unsigned int line, struct buffer_head *bh); int __ext4_handle_dirty_super(const char *where, unsigned int line, - handle_t *handle, struct super_block *sb); + handle_t *handle, struct super_block *sb, + int now); #define ext4_journal_get_write_access(handle, bh) \ __ext4_journal_get_write_access(__func__, __LINE__, (handle), (bh)) @@ -231,8 +226,10 @@ int __ext4_handle_dirty_super(const char *where, unsigned int line, #define ext4_handle_dirty_metadata(handle, inode, bh) \ __ext4_handle_dirty_metadata(__func__, __LINE__, (handle), (inode), \ (bh)) +#define ext4_handle_dirty_super_now(handle, sb) \ + __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb), 1) #define ext4_handle_dirty_super(handle, sb) \ - __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb)) + __ext4_handle_dirty_super(__func__, __LINE__, (handle), (sb), 0) handle_t *ext4_journal_start_sb(struct super_block *sb, int nblocks); int __ext4_journal_stop(const char *where, unsigned int line, handle_t *handle); diff --git a/trunk/fs/ext4/extents.c b/trunk/fs/ext4/extents.c index cd0c7ed06772..91341ec6e06a 100644 --- a/trunk/fs/ext4/extents.c +++ b/trunk/fs/ext4/extents.c @@ -1891,10 +1891,11 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode, nearex->ee_len = newext->ee_len; merge: - /* try to merge extents */ + /* try to merge extents to the right */ if (!(flag & EXT4_GET_BLOCKS_PRE_IO)) ext4_ext_try_to_merge(inode, path, nearex); + /* try to merge extents to the left */ /* time to correct all indexes above */ err = ext4_ext_correct_indexes(handle, inode, path); @@ -2569,10 +2570,10 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, { struct super_block *sb = inode->i_sb; int depth = ext_depth(inode); - struct ext4_ext_path *path = NULL; + struct ext4_ext_path *path; ext4_fsblk_t partial_cluster = 0; handle_t *handle; - int i = 0, err; + int i, err; ext_debug("truncate since %u to %u\n", start, end); @@ -2605,12 +2606,8 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, } depth = ext_depth(inode); ex = path[depth].p_ext; - if (!ex) { - ext4_ext_drop_refs(path); - kfree(path); - path = NULL; + if (!ex) goto cont; - } ee_block = le32_to_cpu(ex->ee_block); @@ -2640,6 +2637,8 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, if (err < 0) goto out; } + ext4_ext_drop_refs(path); + kfree(path); } cont: @@ -2648,27 +2647,19 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, * after i_size and walking into the tree depth-wise. */ depth = ext_depth(inode); - if (path) { - int k = i = depth; - while (--k > 0) - path[k].p_block = - le16_to_cpu(path[k].p_hdr->eh_entries)+1; - } else { - path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), - GFP_NOFS); - if (path == NULL) { - ext4_journal_stop(handle); - return -ENOMEM; - } - path[0].p_depth = depth; - path[0].p_hdr = ext_inode_hdr(inode); + path = kzalloc(sizeof(struct ext4_ext_path) * (depth + 1), GFP_NOFS); + if (path == NULL) { + ext4_journal_stop(handle); + return -ENOMEM; + } + path[0].p_depth = depth; + path[0].p_hdr = ext_inode_hdr(inode); - if (ext4_ext_check(inode, path[0].p_hdr, depth)) { - err = -EIO; - goto out; - } + if (ext4_ext_check(inode, path[0].p_hdr, depth)) { + err = -EIO; + goto out; } - err = 0; + i = err = 0; while (i >= 0 && err == 0) { if (i == depth) { @@ -2782,10 +2773,8 @@ static int ext4_ext_remove_space(struct inode *inode, ext4_lblk_t start, out: ext4_ext_drop_refs(path); kfree(path); - if (err == -EAGAIN) { - path = NULL; + if (err == -EAGAIN) goto again; - } ext4_journal_stop(handle); return err; @@ -4431,8 +4420,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len) ext4_falloc_update_inode(inode, mode, new_size, (map.m_flags & EXT4_MAP_NEW)); ext4_mark_inode_dirty(handle, inode); - if ((file->f_flags & O_SYNC) && ret >= max_blocks) - ext4_handle_sync(handle); ret2 = ext4_journal_stop(handle); if (ret2) break; diff --git a/trunk/fs/ext4/file.c b/trunk/fs/ext4/file.c index 3b0e3bdaabfc..782eecb57e43 100644 --- a/trunk/fs/ext4/file.c +++ b/trunk/fs/ext4/file.c @@ -89,92 +89,12 @@ ext4_unaligned_aio(struct inode *inode, const struct iovec *iov, return 0; } -static ssize_t -ext4_file_dio_write(struct kiocb *iocb, const struct iovec *iov, - unsigned long nr_segs, loff_t pos) -{ - struct file *file = iocb->ki_filp; - struct inode *inode = file->f_mapping->host; - struct blk_plug plug; - int unaligned_aio = 0; - ssize_t ret; - int overwrite = 0; - size_t length = iov_length(iov, nr_segs); - - if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS) && - !is_sync_kiocb(iocb)) - unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos); - - /* Unaligned direct AIO must be serialized; see comment above */ - if (unaligned_aio) { - static unsigned long unaligned_warn_time; - - /* Warn about this once per day */ - if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ)) - ext4_msg(inode->i_sb, KERN_WARNING, - "Unaligned AIO/DIO on inode %ld by %s; " - "performance will be poor.", - inode->i_ino, current->comm); - mutex_lock(ext4_aio_mutex(inode)); - ext4_aiodio_wait(inode); - } - - BUG_ON(iocb->ki_pos != pos); - - mutex_lock(&inode->i_mutex); - blk_start_plug(&plug); - - iocb->private = &overwrite; - - /* check whether we do a DIO overwrite or not */ - if (ext4_should_dioread_nolock(inode) && !unaligned_aio && - !file->f_mapping->nrpages && pos + length <= i_size_read(inode)) { - struct ext4_map_blocks map; - unsigned int blkbits = inode->i_blkbits; - int err, len; - - map.m_lblk = pos >> blkbits; - map.m_len = (EXT4_BLOCK_ALIGN(pos + length, blkbits) >> blkbits) - - map.m_lblk; - len = map.m_len; - - err = ext4_map_blocks(NULL, inode, &map, 0); - /* - * 'err==len' means that all of blocks has been preallocated no - * matter they are initialized or not. For excluding - * uninitialized extents, we need to check m_flags. There are - * two conditions that indicate for initialized extents. - * 1) If we hit extent cache, EXT4_MAP_MAPPED flag is returned; - * 2) If we do a real lookup, non-flags are returned. - * So we should check these two conditions. - */ - if (err == len && (map.m_flags & EXT4_MAP_MAPPED)) - overwrite = 1; - } - - ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos); - mutex_unlock(&inode->i_mutex); - - if (ret > 0 || ret == -EIOCBQUEUED) { - ssize_t err; - - err = generic_write_sync(file, pos, ret); - if (err < 0 && ret > 0) - ret = err; - } - blk_finish_plug(&plug); - - if (unaligned_aio) - mutex_unlock(ext4_aio_mutex(inode)); - - return ret; -} - static ssize_t ext4_file_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos) { struct inode *inode = iocb->ki_filp->f_path.dentry->d_inode; + int unaligned_aio = 0; ssize_t ret; /* @@ -194,12 +114,29 @@ ext4_file_write(struct kiocb *iocb, const struct iovec *iov, nr_segs = iov_shorten((struct iovec *)iov, nr_segs, sbi->s_bitmap_maxbytes - pos); } + } else if (unlikely((iocb->ki_filp->f_flags & O_DIRECT) && + !is_sync_kiocb(iocb))) { + unaligned_aio = ext4_unaligned_aio(inode, iov, nr_segs, pos); } - if (unlikely(iocb->ki_filp->f_flags & O_DIRECT)) - ret = ext4_file_dio_write(iocb, iov, nr_segs, pos); - else - ret = generic_file_aio_write(iocb, iov, nr_segs, pos); + /* Unaligned direct AIO must be serialized; see comment above */ + if (unaligned_aio) { + static unsigned long unaligned_warn_time; + + /* Warn about this once per day */ + if (printk_timed_ratelimit(&unaligned_warn_time, 60*60*24*HZ)) + ext4_msg(inode->i_sb, KERN_WARNING, + "Unaligned AIO/DIO on inode %ld by %s; " + "performance will be poor.", + inode->i_ino, current->comm); + mutex_lock(ext4_aio_mutex(inode)); + ext4_aiodio_wait(inode); + } + + ret = generic_file_aio_write(iocb, iov, nr_segs, pos); + + if (unaligned_aio) + mutex_unlock(ext4_aio_mutex(inode)); return ret; } @@ -244,21 +181,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp) path.dentry = mnt->mnt_root; cp = d_path(&path, buf, sizeof(buf)); if (!IS_ERR(cp)) { - handle_t *handle; - int err; - - handle = ext4_journal_start_sb(sb, 1); - if (IS_ERR(handle)) - return PTR_ERR(handle); - err = ext4_journal_get_write_access(handle, sbi->s_sbh); - if (err) { - ext4_journal_stop(handle); - return err; - } strlcpy(sbi->s_es->s_last_mounted, cp, sizeof(sbi->s_es->s_last_mounted)); - ext4_handle_dirty_super(handle, sb); - ext4_journal_stop(handle); + ext4_mark_super_dirty(sb); } } /* diff --git a/trunk/fs/ext4/ialloc.c b/trunk/fs/ext4/ialloc.c index 26154b81b836..d48e8b14928c 100644 --- a/trunk/fs/ext4/ialloc.c +++ b/trunk/fs/ext4/ialloc.c @@ -315,6 +315,7 @@ void ext4_free_inode(handle_t *handle, struct inode *inode) err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh); if (!fatal) fatal = err; + ext4_mark_super_dirty(sb); } else ext4_error(sb, "bit already cleared for inode %lu", ino); @@ -829,6 +830,7 @@ struct inode *ext4_new_inode(handle_t *handle, struct inode *dir, umode_t mode, percpu_counter_dec(&sbi->s_freeinodes_counter); if (S_ISDIR(mode)) percpu_counter_inc(&sbi->s_dirs_counter); + ext4_mark_super_dirty(sb); if (sbi->s_log_groups_per_flex) { flex_group = ext4_flex_group(sbi, group); @@ -1052,8 +1054,7 @@ unsigned long ext4_count_free_inodes(struct super_block *sb) if (!bitmap_bh) continue; - x = ext4_count_free(bitmap_bh->b_data, - EXT4_INODES_PER_GROUP(sb) / 8); + x = ext4_count_free(bitmap_bh, EXT4_INODES_PER_GROUP(sb) / 8); printk(KERN_DEBUG "group %lu: stored = %d, counted = %lu\n", (unsigned long) i, ext4_free_inodes_count(sb, gdp), x); bitmap_count += x; diff --git a/trunk/fs/ext4/inode.c b/trunk/fs/ext4/inode.c index 89b59cb7f9b8..02bc8cbe7281 100644 --- a/trunk/fs/ext4/inode.c +++ b/trunk/fs/ext4/inode.c @@ -346,15 +346,6 @@ void ext4_da_update_reserve_space(struct inode *inode, used = ei->i_reserved_data_blocks; } - if (unlikely(ei->i_allocated_meta_blocks > ei->i_reserved_meta_blocks)) { - ext4_msg(inode->i_sb, KERN_NOTICE, "%s: ino %lu, allocated %d " - "with only %d reserved metadata blocks\n", __func__, - inode->i_ino, ei->i_allocated_meta_blocks, - ei->i_reserved_meta_blocks); - WARN_ON(1); - ei->i_allocated_meta_blocks = ei->i_reserved_meta_blocks; - } - /* Update per-inode reservations */ ei->i_reserved_data_blocks -= used; ei->i_reserved_meta_blocks -= ei->i_allocated_meta_blocks; @@ -553,8 +544,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, * Try to see if we can get the block without requesting a new * file system block. */ - if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) - down_read((&EXT4_I(inode)->i_data_sem)); + down_read((&EXT4_I(inode)->i_data_sem)); if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) { retval = ext4_ext_map_blocks(handle, inode, map, flags & EXT4_GET_BLOCKS_KEEP_SIZE); @@ -562,8 +552,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode, retval = ext4_ind_map_blocks(handle, inode, map, flags & EXT4_GET_BLOCKS_KEEP_SIZE); } - if (!(flags & EXT4_GET_BLOCKS_NO_LOCK)) - up_read((&EXT4_I(inode)->i_data_sem)); + up_read((&EXT4_I(inode)->i_data_sem)); if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) { int ret = check_block_validity(inode, map); @@ -1182,17 +1171,6 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) struct ext4_inode_info *ei = EXT4_I(inode); unsigned int md_needed; int ret; - ext4_lblk_t save_last_lblock; - int save_len; - - /* - * We will charge metadata quota at writeout time; this saves - * us from metadata over-estimation, though we may go over by - * a small amount in the end. Here we just reserve for data. - */ - ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); - if (ret) - return ret; /* * recalculate the amount of metadata blocks to reserve @@ -1201,31 +1179,32 @@ static int ext4_da_reserve_space(struct inode *inode, ext4_lblk_t lblock) */ repeat: spin_lock(&ei->i_block_reservation_lock); - /* - * ext4_calc_metadata_amount() has side effects, which we have - * to be prepared undo if we fail to claim space. - */ - save_len = ei->i_da_metadata_calc_len; - save_last_lblock = ei->i_da_metadata_calc_last_lblock; md_needed = EXT4_NUM_B2C(sbi, ext4_calc_metadata_amount(inode, lblock)); trace_ext4_da_reserve_space(inode, md_needed); + spin_unlock(&ei->i_block_reservation_lock); + /* + * We will charge metadata quota at writeout time; this saves + * us from metadata over-estimation, though we may go over by + * a small amount in the end. Here we just reserve for data. + */ + ret = dquot_reserve_block(inode, EXT4_C2B(sbi, 1)); + if (ret) + return ret; /* * We do still charge estimated metadata to the sb though; * we cannot afford to run out of free blocks. */ if (ext4_claim_free_clusters(sbi, md_needed + 1, 0)) { - ei->i_da_metadata_calc_len = save_len; - ei->i_da_metadata_calc_last_lblock = save_last_lblock; - spin_unlock(&ei->i_block_reservation_lock); + dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); if (ext4_should_retry_alloc(inode->i_sb, &retries)) { yield(); goto repeat; } - dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1)); return -ENOSPC; } + spin_lock(&ei->i_block_reservation_lock); ei->i_reserved_data_blocks++; ei->i_reserved_meta_blocks += md_needed; spin_unlock(&ei->i_block_reservation_lock); @@ -2839,32 +2818,6 @@ static int ext4_get_block_write(struct inode *inode, sector_t iblock, EXT4_GET_BLOCKS_IO_CREATE_EXT); } -static int ext4_get_block_write_nolock(struct inode *inode, sector_t iblock, - struct buffer_head *bh_result, int flags) -{ - handle_t *handle = ext4_journal_current_handle(); - struct ext4_map_blocks map; - int ret = 0; - - ext4_debug("ext4_get_block_write_nolock: inode %lu, flag %d\n", - inode->i_ino, flags); - - flags = EXT4_GET_BLOCKS_NO_LOCK; - - map.m_lblk = iblock; - map.m_len = bh_result->b_size >> inode->i_blkbits; - - ret = ext4_map_blocks(handle, inode, &map, flags); - if (ret > 0) { - map_bh(bh_result, inode->i_sb, map.m_pblk); - bh_result->b_state = (bh_result->b_state & ~EXT4_MAP_FLAGS) | - map.m_flags; - bh_result->b_size = inode->i_sb->s_blocksize * map.m_len; - ret = 0; - } - return ret; -} - static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, ssize_t size, void *private, int ret, bool is_async) @@ -3013,18 +2966,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, loff_t final_size = offset + count; if (rw == WRITE && final_size <= inode->i_size) { - int overwrite = 0; - - BUG_ON(iocb->private == NULL); - - /* If we do a overwrite dio, i_mutex locking can be released */ - overwrite = *((int *)iocb->private); - - if (overwrite) { - down_read(&EXT4_I(inode)->i_data_sem); - mutex_unlock(&inode->i_mutex); - } - /* * We could direct write to holes and fallocate. * @@ -3050,10 +2991,8 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, if (!is_sync_kiocb(iocb)) { ext4_io_end_t *io_end = ext4_init_io_end(inode, GFP_NOFS); - if (!io_end) { - ret = -ENOMEM; - goto retake_lock; - } + if (!io_end) + return -ENOMEM; io_end->flag |= EXT4_IO_END_DIRECT; iocb->private = io_end; /* @@ -3066,22 +3005,13 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, EXT4_I(inode)->cur_aio_dio = iocb->private; } - if (overwrite) - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, - ext4_get_block_write_nolock, - ext4_end_io_dio, - NULL, - 0); - else - ret = __blockdev_direct_IO(rw, iocb, inode, - inode->i_sb->s_bdev, iov, - offset, nr_segs, - ext4_get_block_write, - ext4_end_io_dio, - NULL, - DIO_LOCKING); + ret = __blockdev_direct_IO(rw, iocb, inode, + inode->i_sb->s_bdev, iov, + offset, nr_segs, + ext4_get_block_write, + ext4_end_io_dio, + NULL, + DIO_LOCKING); if (iocb->private) EXT4_I(inode)->cur_aio_dio = NULL; /* @@ -3101,7 +3031,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, if (ret != -EIOCBQUEUED && ret <= 0 && iocb->private) { ext4_free_io_end(iocb->private); iocb->private = NULL; - } else if (ret > 0 && !overwrite && ext4_test_inode_state(inode, + } else if (ret > 0 && ext4_test_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN)) { int err; /* @@ -3114,14 +3044,6 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb, ret = err; ext4_clear_inode_state(inode, EXT4_STATE_DIO_UNWRITTEN); } - - retake_lock: - /* take i_mutex locking again if we do a ovewrite dio */ - if (overwrite) { - up_read(&EXT4_I(inode)->i_data_sem); - mutex_lock(&inode->i_mutex); - } - return ret; } @@ -4112,7 +4034,7 @@ static int ext4_do_update_inode(handle_t *handle, EXT4_SET_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_LARGE_FILE); ext4_handle_sync(handle); - err = ext4_handle_dirty_super(handle, sb); + err = ext4_handle_dirty_super_now(handle, sb); } } raw_inode->i_generation = cpu_to_le32(inode->i_generation); diff --git a/trunk/fs/ext4/mballoc.c b/trunk/fs/ext4/mballoc.c index 8eae94771c45..1cd6994fc446 100644 --- a/trunk/fs/ext4/mballoc.c +++ b/trunk/fs/ext4/mballoc.c @@ -969,6 +969,7 @@ static int ext4_mb_get_buddy_page_lock(struct super_block *sb, block++; pnum = block / blocks_per_page; + poff = block % blocks_per_page; page = find_or_create_page(inode->i_mapping, pnum, GFP_NOFS); if (!page) return -EIO; @@ -2076,9 +2077,8 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) struct super_block *sb = seq->private; ext4_group_t group = (ext4_group_t) ((unsigned long) v); int i; - int err, buddy_loaded = 0; + int err; struct ext4_buddy e4b; - struct ext4_group_info *grinfo; struct sg { struct ext4_group_info info; ext4_grpblk_t counters[16]; @@ -2095,21 +2095,15 @@ static int ext4_mb_seq_groups_show(struct seq_file *seq, void *v) i = (sb->s_blocksize_bits + 2) * sizeof(sg.info.bb_counters[0]) + sizeof(struct ext4_group_info); - grinfo = ext4_get_group_info(sb, group); - /* Load the group info in memory only if not already loaded. */ - if (unlikely(EXT4_MB_GRP_NEED_INIT(grinfo))) { - err = ext4_mb_load_buddy(sb, group, &e4b); - if (err) { - seq_printf(seq, "#%-5u: I/O error\n", group); - return 0; - } - buddy_loaded = 1; + err = ext4_mb_load_buddy(sb, group, &e4b); + if (err) { + seq_printf(seq, "#%-5u: I/O error\n", group); + return 0; } - + ext4_lock_group(sb, group); memcpy(&sg, ext4_get_group_info(sb, group), i); - - if (buddy_loaded) - ext4_mb_unload_buddy(&e4b); + ext4_unlock_group(sb, group); + ext4_mb_unload_buddy(&e4b); seq_printf(seq, "#%-5u: %-5u %-5u %-5u [", group, sg.info.bb_free, sg.info.bb_fragments, sg.info.bb_first_free); @@ -2831,6 +2825,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, err = ext4_handle_dirty_metadata(handle, NULL, gdp_bh); out_err: + ext4_mark_super_dirty(sb); brelse(bitmap_bh); return err; } @@ -4699,6 +4694,7 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode, put_bh(bitmap_bh); goto do_more; } + ext4_mark_super_dirty(sb); error_return: brelse(bitmap_bh); ext4_std_error(sb, err); diff --git a/trunk/fs/ext4/namei.c b/trunk/fs/ext4/namei.c index 2a42cc04466f..d0d3f0e87f99 100644 --- a/trunk/fs/ext4/namei.c +++ b/trunk/fs/ext4/namei.c @@ -2397,7 +2397,7 @@ int ext4_orphan_add(handle_t *handle, struct inode *inode) /* Insert this inode at the head of the on-disk orphan list... */ NEXT_ORPHAN(inode) = le32_to_cpu(EXT4_SB(sb)->s_es->s_last_orphan); EXT4_SB(sb)->s_es->s_last_orphan = cpu_to_le32(inode->i_ino); - err = ext4_handle_dirty_super(handle, sb); + err = ext4_handle_dirty_super_now(handle, sb); rc = ext4_mark_iloc_dirty(handle, inode, &iloc); if (!err) err = rc; @@ -2470,7 +2470,7 @@ int ext4_orphan_del(handle_t *handle, struct inode *inode) if (err) goto out_brelse; sbi->s_es->s_last_orphan = cpu_to_le32(ino_next); - err = ext4_handle_dirty_super(handle, inode->i_sb); + err = ext4_handle_dirty_super_now(handle, inode->i_sb); } else { struct ext4_iloc iloc2; struct inode *i_prev = @@ -2918,15 +2918,8 @@ static int ext4_rename(struct inode *old_dir, struct dentry *old_dentry, PARENT_INO(dir_bh->b_data, new_dir->i_sb->s_blocksize) = cpu_to_le32(new_dir->i_ino); BUFFER_TRACE(dir_bh, "call ext4_handle_dirty_metadata"); - if (is_dx(old_inode)) { - retval = ext4_handle_dirty_dx_node(handle, - old_inode, - dir_bh); - } else { - retval = ext4_handle_dirty_dirent_node(handle, - old_inode, - dir_bh); - } + retval = ext4_handle_dirty_dirent_node(handle, old_inode, + dir_bh); if (retval) { ext4_std_error(old_dir->i_sb, retval); goto end_rename; diff --git a/trunk/fs/ext4/resize.c b/trunk/fs/ext4/resize.c index 41f6ef68e2e1..7ea6cbb44121 100644 --- a/trunk/fs/ext4/resize.c +++ b/trunk/fs/ext4/resize.c @@ -798,7 +798,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, ext4_kvfree(o_group_desc); le16_add_cpu(&es->s_reserved_gdt_blocks, -1); - err = ext4_handle_dirty_super(handle, sb); + err = ext4_handle_dirty_super_now(handle, sb); if (err) ext4_std_error(sb, err); @@ -1272,11 +1272,6 @@ static void ext4_update_super(struct super_block *sb, &sbi->s_flex_groups[flex_group].free_inodes); } - /* - * Update the fs overhead information - */ - ext4_calculate_overhead(sb); - if (test_opt(sb, DEBUG)) printk(KERN_DEBUG "EXT4-fs: added group %u:" "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, diff --git a/trunk/fs/ext4/super.c b/trunk/fs/ext4/super.c index 2d51cd9af225..d8759401ecae 100644 --- a/trunk/fs/ext4/super.c +++ b/trunk/fs/ext4/super.c @@ -74,6 +74,7 @@ static const char *ext4_decode_error(struct super_block *sb, int errno, static int ext4_remount(struct super_block *sb, int *flags, char *data); static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); static int ext4_unfreeze(struct super_block *sb); +static void ext4_write_super(struct super_block *sb); static int ext4_freeze(struct super_block *sb); static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data); @@ -895,7 +896,7 @@ static void ext4_put_super(struct super_block *sb) EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); es->s_state = cpu_to_le16(sbi->s_mount_state); } - if (!(sb->s_flags & MS_RDONLY)) + if (sb->s_dirt || !(sb->s_flags & MS_RDONLY)) ext4_commit_super(sb, 1); if (sbi->s_proc) { @@ -1136,18 +1137,12 @@ static int ext4_mark_dquot_dirty(struct dquot *dquot); static int ext4_write_info(struct super_block *sb, int type); static int ext4_quota_on(struct super_block *sb, int type, int format_id, struct path *path); -static int ext4_quota_on_sysfile(struct super_block *sb, int type, - int format_id); static int ext4_quota_off(struct super_block *sb, int type); -static int ext4_quota_off_sysfile(struct super_block *sb, int type); static int ext4_quota_on_mount(struct super_block *sb, int type); static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off); static ssize_t ext4_quota_write(struct super_block *sb, int type, const char *data, size_t len, loff_t off); -static int ext4_quota_enable(struct super_block *sb, int type, int format_id, - unsigned int flags); -static int ext4_enable_quotas(struct super_block *sb); static const struct dquot_operations ext4_quota_operations = { .get_reserved_space = ext4_get_reserved_space, @@ -1169,16 +1164,6 @@ static const struct quotactl_ops ext4_qctl_operations = { .get_dqblk = dquot_get_dqblk, .set_dqblk = dquot_set_dqblk }; - -static const struct quotactl_ops ext4_qctl_sysfile_operations = { - .quota_on_meta = ext4_quota_on_sysfile, - .quota_off = ext4_quota_off_sysfile, - .quota_sync = dquot_quota_sync, - .get_info = dquot_get_dqinfo, - .set_info = dquot_set_dqinfo, - .get_dqblk = dquot_get_dqblk, - .set_dqblk = dquot_set_dqblk -}; #endif static const struct super_operations ext4_sops = { @@ -1209,6 +1194,7 @@ static const struct super_operations ext4_nojournal_sops = { .dirty_inode = ext4_dirty_inode, .drop_inode = ext4_drop_inode, .evict_inode = ext4_evict_inode, + .write_super = ext4_write_super, .put_super = ext4_put_super, .statfs = ext4_statfs, .remount_fs = ext4_remount, @@ -2675,16 +2661,6 @@ static int ext4_feature_set_ok(struct super_block *sb, int readonly) "extents feature\n"); return 0; } - -#ifndef CONFIG_QUOTA - if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && - !readonly) { - ext4_msg(sb, KERN_ERR, - "Filesystem with quota feature cannot be mounted RDWR " - "without CONFIG_QUOTA"); - return 0; - } -#endif /* CONFIG_QUOTA */ return 1; } @@ -3109,114 +3085,6 @@ static int set_journal_csum_feature_set(struct super_block *sb) return ret; } -/* - * Note: calculating the overhead so we can be compatible with - * historical BSD practice is quite difficult in the face of - * clusters/bigalloc. This is because multiple metadata blocks from - * different block group can end up in the same allocation cluster. - * Calculating the exact overhead in the face of clustered allocation - * requires either O(all block bitmaps) in memory or O(number of block - * groups**2) in time. We will still calculate the superblock for - * older file systems --- and if we come across with a bigalloc file - * system with zero in s_overhead_clusters the estimate will be close to - * correct especially for very large cluster sizes --- but for newer - * file systems, it's better to calculate this figure once at mkfs - * time, and store it in the superblock. If the superblock value is - * present (even for non-bigalloc file systems), we will use it. - */ -static int count_overhead(struct super_block *sb, ext4_group_t grp, - char *buf) -{ - struct ext4_sb_info *sbi = EXT4_SB(sb); - struct ext4_group_desc *gdp; - ext4_fsblk_t first_block, last_block, b; - ext4_group_t i, ngroups = ext4_get_groups_count(sb); - int s, j, count = 0; - - first_block = le32_to_cpu(sbi->s_es->s_first_data_block) + - (grp * EXT4_BLOCKS_PER_GROUP(sb)); - last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1; - for (i = 0; i < ngroups; i++) { - gdp = ext4_get_group_desc(sb, i, NULL); - b = ext4_block_bitmap(sb, gdp); - if (b >= first_block && b <= last_block) { - ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); - count++; - } - b = ext4_inode_bitmap(sb, gdp); - if (b >= first_block && b <= last_block) { - ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf); - count++; - } - b = ext4_inode_table(sb, gdp); - if (b >= first_block && b + sbi->s_itb_per_group <= last_block) - for (j = 0; j < sbi->s_itb_per_group; j++, b++) { - int c = EXT4_B2C(sbi, b - first_block); - ext4_set_bit(c, buf); - count++; - } - if (i != grp) - continue; - s = 0; - if (ext4_bg_has_super(sb, grp)) { - ext4_set_bit(s++, buf); - count++; - } - for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) { - ext4_set_bit(EXT4_B2C(sbi, s++), buf); - count++; - } - } - if (!count) - return 0; - return EXT4_CLUSTERS_PER_GROUP(sb) - - ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8); -} - -/* - * Compute the overhead and stash it in sbi->s_overhead - */ -int ext4_calculate_overhead(struct super_block *sb) -{ - struct ext4_sb_info *sbi = EXT4_SB(sb); - struct ext4_super_block *es = sbi->s_es; - ext4_group_t i, ngroups = ext4_get_groups_count(sb); - ext4_fsblk_t overhead = 0; - char *buf = (char *) get_zeroed_page(GFP_KERNEL); - - memset(buf, 0, PAGE_SIZE); - if (!buf) - return -ENOMEM; - - /* - * Compute the overhead (FS structures). This is constant - * for a given filesystem unless the number of block groups - * changes so we cache the previous value until it does. - */ - - /* - * All of the blocks before first_data_block are overhead - */ - overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); - - /* - * Add the overhead found in each block group - */ - for (i = 0; i < ngroups; i++) { - int blks; - - blks = count_overhead(sb, i, buf); - overhead += blks; - if (blks) - memset(buf, 0, PAGE_SIZE); - cond_resched(); - } - sbi->s_overhead = overhead; - smp_wmb(); - free_page((unsigned long) buf); - return 0; -} - static int ext4_fill_super(struct super_block *sb, void *data, int silent) { char *orig_data = kstrdup(data, GFP_KERNEL); @@ -3772,11 +3640,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) #ifdef CONFIG_QUOTA sb->s_qcop = &ext4_qctl_operations; sb->dq_op = &ext4_quota_operations; - - if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) { - /* Use qctl operations for hidden quota files. */ - sb->s_qcop = &ext4_qctl_sysfile_operations; - } #endif memcpy(sb->s_uuid, es->s_uuid, sizeof(es->s_uuid)); @@ -3871,18 +3734,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) percpu_counter_set(&sbi->s_dirtyclusters_counter, 0); no_journal: - /* - * Get the # of file system overhead blocks from the - * superblock if present. - */ - if (es->s_overhead_clusters) - sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters); - else { - ret = ext4_calculate_overhead(sb); - if (ret) - goto failed_mount_wq; - } - /* * The maximum number of concurrent works can be high and * concurrency isn't really necessary. Limit it to 1. @@ -3989,16 +3840,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) } else descr = "out journal"; -#ifdef CONFIG_QUOTA - /* Enable quota usage during mount. */ - if (EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA) && - !(sb->s_flags & MS_RDONLY)) { - ret = ext4_enable_quotas(sb); - if (ret) - goto failed_mount7; - } -#endif /* CONFIG_QUOTA */ - ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " "Opts: %s%s%s", descr, sbi->s_es->s_mount_opts, *sbi->s_es->s_mount_opts ? "; " : "", orig_data); @@ -4362,6 +4203,7 @@ static int ext4_commit_super(struct super_block *sb, int sync) es->s_free_inodes_count = cpu_to_le32(percpu_counter_sum_positive( &EXT4_SB(sb)->s_freeinodes_counter)); + sb->s_dirt = 0; BUFFER_TRACE(sbh, "marking dirty"); ext4_superblock_csum_set(sb, es); mark_buffer_dirty(sbh); @@ -4468,6 +4310,13 @@ int ext4_force_commit(struct super_block *sb) return ret; } +static void ext4_write_super(struct super_block *sb) +{ + lock_super(sb); + ext4_commit_super(sb, 1); + unlock_super(sb); +} + static int ext4_sync_fs(struct super_block *sb, int wait) { int ret = 0; @@ -4718,26 +4567,16 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) if (sbi->s_journal == NULL) ext4_commit_super(sb, 1); - unlock_super(sb); #ifdef CONFIG_QUOTA /* Release old quota file names */ for (i = 0; i < MAXQUOTAS; i++) if (old_opts.s_qf_names[i] && old_opts.s_qf_names[i] != sbi->s_qf_names[i]) kfree(old_opts.s_qf_names[i]); - if (enable_quota) { - if (sb_any_quota_suspended(sb)) - dquot_resume(sb, -1); - else if (EXT4_HAS_RO_COMPAT_FEATURE(sb, - EXT4_FEATURE_RO_COMPAT_QUOTA)) { - err = ext4_enable_quotas(sb); - if (err) { - lock_super(sb); - goto restore_opts; - } - } - } #endif + unlock_super(sb); + if (enable_quota) + dquot_resume(sb, -1); ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s", orig_data); kfree(orig_data); @@ -4766,21 +4605,67 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) return err; } +/* + * Note: calculating the overhead so we can be compatible with + * historical BSD practice is quite difficult in the face of + * clusters/bigalloc. This is because multiple metadata blocks from + * different block group can end up in the same allocation cluster. + * Calculating the exact overhead in the face of clustered allocation + * requires either O(all block bitmaps) in memory or O(number of block + * groups**2) in time. We will still calculate the superblock for + * older file systems --- and if we come across with a bigalloc file + * system with zero in s_overhead_clusters the estimate will be close to + * correct especially for very large cluster sizes --- but for newer + * file systems, it's better to calculate this figure once at mkfs + * time, and store it in the superblock. If the superblock value is + * present (even for non-bigalloc file systems), we will use it. + */ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) { struct super_block *sb = dentry->d_sb; struct ext4_sb_info *sbi = EXT4_SB(sb); struct ext4_super_block *es = sbi->s_es; - ext4_fsblk_t overhead = 0; + struct ext4_group_desc *gdp; u64 fsid; s64 bfree; - if (!test_opt(sb, MINIX_DF)) - overhead = sbi->s_overhead; + if (test_opt(sb, MINIX_DF)) { + sbi->s_overhead_last = 0; + } else if (es->s_overhead_clusters) { + sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters); + } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { + ext4_group_t i, ngroups = ext4_get_groups_count(sb); + ext4_fsblk_t overhead = 0; + + /* + * Compute the overhead (FS structures). This is constant + * for a given filesystem unless the number of block groups + * changes so we cache the previous value until it does. + */ + + /* + * All of the blocks before first_data_block are + * overhead + */ + overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); + + /* + * Add the overhead found in each block group + */ + for (i = 0; i < ngroups; i++) { + gdp = ext4_get_group_desc(sb, i, NULL); + overhead += ext4_num_overhead_clusters(sb, i, gdp); + cond_resched(); + } + sbi->s_overhead_last = overhead; + smp_wmb(); + sbi->s_blocks_last = ext4_blocks_count(es); + } buf->f_type = EXT4_SUPER_MAGIC; buf->f_bsize = sb->s_blocksize; - buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead); + buf->f_blocks = (ext4_blocks_count(es) - + EXT4_C2B(sbi, sbi->s_overhead_last)); bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); /* prevent underflow in case that few free space is available */ @@ -4950,74 +4835,6 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, return dquot_quota_on(sb, type, format_id, path); } -static int ext4_quota_enable(struct super_block *sb, int type, int format_id, - unsigned int flags) -{ - int err; - struct inode *qf_inode; - unsigned long qf_inums[MAXQUOTAS] = { - le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), - le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) - }; - - BUG_ON(!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)); - - if (!qf_inums[type]) - return -EPERM; - - qf_inode = ext4_iget(sb, qf_inums[type]); - if (IS_ERR(qf_inode)) { - ext4_error(sb, "Bad quota inode # %lu", qf_inums[type]); - return PTR_ERR(qf_inode); - } - - err = dquot_enable(qf_inode, type, format_id, flags); - iput(qf_inode); - - return err; -} - -/* Enable usage tracking for all quota types. */ -static int ext4_enable_quotas(struct super_block *sb) -{ - int type, err = 0; - unsigned long qf_inums[MAXQUOTAS] = { - le32_to_cpu(EXT4_SB(sb)->s_es->s_usr_quota_inum), - le32_to_cpu(EXT4_SB(sb)->s_es->s_grp_quota_inum) - }; - - sb_dqopt(sb)->flags |= DQUOT_QUOTA_SYS_FILE; - for (type = 0; type < MAXQUOTAS; type++) { - if (qf_inums[type]) { - err = ext4_quota_enable(sb, type, QFMT_VFS_V1, - DQUOT_USAGE_ENABLED); - if (err) { - ext4_warning(sb, - "Failed to enable quota (type=%d) " - "tracking. Please run e2fsck to fix.", - type); - return err; - } - } - } - return 0; -} - -/* - * quota_on function that is used when QUOTA feature is set. - */ -static int ext4_quota_on_sysfile(struct super_block *sb, int type, - int format_id) -{ - if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) - return -EINVAL; - - /* - * USAGE was enabled at mount time. Only need to enable LIMITS now. - */ - return ext4_quota_enable(sb, type, format_id, DQUOT_LIMITS_ENABLED); -} - static int ext4_quota_off(struct super_block *sb, int type) { struct inode *inode = sb_dqopt(sb)->files[type]; @@ -5044,18 +4861,6 @@ static int ext4_quota_off(struct super_block *sb, int type) return dquot_quota_off(sb, type); } -/* - * quota_off function that is used when QUOTA feature is set. - */ -static int ext4_quota_off_sysfile(struct super_block *sb, int type) -{ - if (!EXT4_HAS_RO_COMPAT_FEATURE(sb, EXT4_FEATURE_RO_COMPAT_QUOTA)) - return -EINVAL; - - /* Disable only the limits. */ - return dquot_disable(sb, type, DQUOT_LIMITS_ENABLED); -} - /* Read data from quotafile - avoid pagecache and such because we cannot afford * acquiring the locks... As quota files are never truncated and quota code * itself serializes the operations (and no one else should touch the files) diff --git a/trunk/fs/ext4/xattr.c b/trunk/fs/ext4/xattr.c index 2cdb98d62980..e56c9ed7d6e3 100644 --- a/trunk/fs/ext4/xattr.c +++ b/trunk/fs/ext4/xattr.c @@ -127,16 +127,19 @@ static __le32 ext4_xattr_block_csum(struct inode *inode, struct ext4_xattr_header *hdr) { struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); + struct ext4_inode_info *ei = EXT4_I(inode); __u32 csum, old; old = hdr->h_checksum; hdr->h_checksum = 0; - block_nr = cpu_to_le64(block_nr); - csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&block_nr, - sizeof(block_nr)); + if (le32_to_cpu(hdr->h_refcount) != 1) { + block_nr = cpu_to_le64(block_nr); + csum = ext4_chksum(sbi, sbi->s_csum_seed, (__u8 *)&block_nr, + sizeof(block_nr)); + } else + csum = ei->i_csum_seed; csum = ext4_chksum(sbi, csum, (__u8 *)hdr, EXT4_BLOCK_SIZE(inode->i_sb)); - hdr->h_checksum = old; return cpu_to_le32(csum); } diff --git a/trunk/fs/jbd2/commit.c b/trunk/fs/jbd2/commit.c index af5280fb579b..216f4299f65e 100644 --- a/trunk/fs/jbd2/commit.c +++ b/trunk/fs/jbd2/commit.c @@ -349,12 +349,12 @@ static void jbd2_block_tag_csum_set(journal_t *j, journal_block_tag_t *tag, return; sequence = cpu_to_be32(sequence); - addr = kmap_atomic(page); + addr = kmap_atomic(page, KM_USER0); csum = jbd2_chksum(j, j->j_csum_seed, (__u8 *)&sequence, sizeof(sequence)); csum = jbd2_chksum(j, csum, addr + offset_in_page(bh->b_data), bh->b_size); - kunmap_atomic(addr); + kunmap_atomic(addr, KM_USER0); tag->t_checksum = cpu_to_be32(csum); } diff --git a/trunk/fs/pipe.c b/trunk/fs/pipe.c index 95cbd6b227e6..49c1065256fd 100644 --- a/trunk/fs/pipe.c +++ b/trunk/fs/pipe.c @@ -224,7 +224,7 @@ static void anon_pipe_buf_release(struct pipe_inode_info *pipe, * and the caller has to be careful not to fault before calling * the unmap function. * - * Note that this function calls kmap_atomic() if @atomic != 0. + * Note that this function occupies KM_USER0 if @atomic != 0. */ void *generic_pipe_buf_map(struct pipe_inode_info *pipe, struct pipe_buffer *buf, int atomic) diff --git a/trunk/include/asm-generic/kmap_types.h b/trunk/include/asm-generic/kmap_types.h index 90f99c74dd38..0232ccb76f2b 100644 --- a/trunk/include/asm-generic/kmap_types.h +++ b/trunk/include/asm-generic/kmap_types.h @@ -2,9 +2,39 @@ #define _ASM_GENERIC_KMAP_TYPES_H #ifdef __WITH_KM_FENCE -# define KM_TYPE_NR 41 +# define KMAP_D(n) __KM_FENCE_##n , #else -# define KM_TYPE_NR 20 +# define KMAP_D(n) #endif +enum km_type { +KMAP_D(0) KM_BOUNCE_READ, +KMAP_D(1) KM_SKB_SUNRPC_DATA, +KMAP_D(2) KM_SKB_DATA_SOFTIRQ, +KMAP_D(3) KM_USER0, +KMAP_D(4) KM_USER1, +KMAP_D(5) KM_BIO_SRC_IRQ, +KMAP_D(6) KM_BIO_DST_IRQ, +KMAP_D(7) KM_PTE0, +KMAP_D(8) KM_PTE1, +KMAP_D(9) KM_IRQ0, +KMAP_D(10) KM_IRQ1, +KMAP_D(11) KM_SOFTIRQ0, +KMAP_D(12) KM_SOFTIRQ1, +KMAP_D(13) KM_SYNC_ICACHE, +KMAP_D(14) KM_SYNC_DCACHE, +/* UML specific, for copy_*_user - used in do_op_one_page */ +KMAP_D(15) KM_UML_USERCOPY, +KMAP_D(16) KM_IRQ_PTE, +KMAP_D(17) KM_NMI, +KMAP_D(18) KM_NMI_PTE, +KMAP_D(19) KM_KDB, +/* + * Remember to update debug_kmap_atomic() when adding new kmap types! + */ +KMAP_D(20) KM_TYPE_NR +}; + +#undef KMAP_D + #endif diff --git a/trunk/include/asm-generic/sizes.h b/trunk/include/asm-generic/sizes.h index 1dcfad9629ef..ea5d4ef81061 100644 --- a/trunk/include/asm-generic/sizes.h +++ b/trunk/include/asm-generic/sizes.h @@ -1,2 +1,47 @@ -/* This is a placeholder, to be removed over time */ -#include +/* + * linux/include/asm-generic/sizes.h + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ASM_GENERIC_SIZES_H__ +#define __ASM_GENERIC_SIZES_H__ + +#define SZ_1 0x00000001 +#define SZ_2 0x00000002 +#define SZ_4 0x00000004 +#define SZ_8 0x00000008 +#define SZ_16 0x00000010 +#define SZ_32 0x00000020 +#define SZ_64 0x00000040 +#define SZ_128 0x00000080 +#define SZ_256 0x00000100 +#define SZ_512 0x00000200 + +#define SZ_1K 0x00000400 +#define SZ_2K 0x00000800 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_32K 0x00008000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 + +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 + +#define SZ_1G 0x40000000 +#define SZ_2G 0x80000000 + +#endif /* __ASM_GENERIC_SIZES_H__ */ diff --git a/trunk/include/linux/highmem.h b/trunk/include/linux/highmem.h index 774fa47b3b5b..d3999b4e26cc 100644 --- a/trunk/include/linux/highmem.h +++ b/trunk/include/linux/highmem.h @@ -109,16 +109,55 @@ static inline void kmap_atomic_idx_pop(void) #endif +/* + * NOTE: + * kmap_atomic() and kunmap_atomic() with two arguments are deprecated. + * We only keep them for backward compatibility, any usage of them + * are now warned. + */ + +#define PASTE(a, b) a ## b +#define PASTE2(a, b) PASTE(a, b) + +#define NARG_(_2, _1, n, ...) n +#define NARG(...) NARG_(__VA_ARGS__, 2, 1, :) + +static inline void __deprecated *kmap_atomic_deprecated(struct page *page, + enum km_type km) +{ + return kmap_atomic(page); +} + +#define kmap_atomic1(...) kmap_atomic(__VA_ARGS__) +#define kmap_atomic2(...) kmap_atomic_deprecated(__VA_ARGS__) +#define kmap_atomic(...) PASTE2(kmap_atomic, NARG(__VA_ARGS__)(__VA_ARGS__)) + +static inline void __deprecated __kunmap_atomic_deprecated(void *addr, + enum km_type km) +{ + __kunmap_atomic(addr); +} + /* * Prevent people trying to call kunmap_atomic() as if it were kunmap() * kunmap_atomic() should get the return value of kmap_atomic, not the page. */ -#define kunmap_atomic(addr) \ +#define kunmap_atomic_deprecated(addr, km) \ +do { \ + BUILD_BUG_ON(__same_type((addr), struct page *)); \ + __kunmap_atomic_deprecated(addr, km); \ +} while (0) + +#define kunmap_atomic_withcheck(addr) \ do { \ BUILD_BUG_ON(__same_type((addr), struct page *)); \ __kunmap_atomic(addr); \ } while (0) +#define kunmap_atomic1(...) kunmap_atomic_withcheck(__VA_ARGS__) +#define kunmap_atomic2(...) kunmap_atomic_deprecated(__VA_ARGS__) +#define kunmap_atomic(...) PASTE2(kunmap_atomic, NARG(__VA_ARGS__)(__VA_ARGS__)) +/**** End of C pre-processor tricks for deprecated macros ****/ /* when CONFIG_HIGHMEM is not set these will be plain clear/copy_page */ #ifndef clear_user_highpage diff --git a/trunk/include/linux/pipe_fs_i.h b/trunk/include/linux/pipe_fs_i.h index e11d1c0fc60f..e1ac1ce16fb0 100644 --- a/trunk/include/linux/pipe_fs_i.h +++ b/trunk/include/linux/pipe_fs_i.h @@ -86,9 +86,11 @@ struct pipe_buf_operations { * mapping or not. The atomic map is faster, however you can't take * page faults before calling ->unmap() again. So if you need to eg * access user data through copy_to/from_user(), then you must get - * a non-atomic map. ->map() uses the kmap_atomic slot for - * atomic maps, you have to be careful if mapping another page as - * source or destination for a copy. + * a non-atomic map. ->map() uses the KM_USER0 atomic slot for + * atomic maps, so you can't map more than one pipe_buffer at once + * and you have to be careful if mapping another page as source + * or destination for a copy (IOW, it has to use something else + * than KM_USER0). */ void * (*map)(struct pipe_inode_info *, struct pipe_buffer *, int); diff --git a/trunk/include/linux/serial_core.h b/trunk/include/linux/serial_core.h index 0253c2022e53..65db9928e15f 100644 --- a/trunk/include/linux/serial_core.h +++ b/trunk/include/linux/serial_core.h @@ -47,8 +47,7 @@ #define PORT_U6_16550A 19 /* ST-Ericsson U6xxx internal UART */ #define PORT_TEGRA 20 /* NVIDIA Tegra internal UART */ #define PORT_XR17D15X 21 /* Exar XR17D15x UART */ -#define PORT_LPC3220 22 /* NXP LPC32xx SoC "Standard" UART */ -#define PORT_MAX_8250 22 /* max port ID */ +#define PORT_MAX_8250 21 /* max port ID */ /* * ARM specific type numbers. These are not currently guaranteed diff --git a/trunk/include/linux/sizes.h b/trunk/include/linux/sizes.h deleted file mode 100644 index ce3e8150c174..000000000000 --- a/trunk/include/linux/sizes.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * include/linux/sizes.h - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#ifndef __LINUX_SIZES_H__ -#define __LINUX_SIZES_H__ - -#define SZ_1 0x00000001 -#define SZ_2 0x00000002 -#define SZ_4 0x00000004 -#define SZ_8 0x00000008 -#define SZ_16 0x00000010 -#define SZ_32 0x00000020 -#define SZ_64 0x00000040 -#define SZ_128 0x00000080 -#define SZ_256 0x00000100 -#define SZ_512 0x00000200 - -#define SZ_1K 0x00000400 -#define SZ_2K 0x00000800 -#define SZ_4K 0x00001000 -#define SZ_8K 0x00002000 -#define SZ_16K 0x00004000 -#define SZ_32K 0x00008000 -#define SZ_64K 0x00010000 -#define SZ_128K 0x00020000 -#define SZ_256K 0x00040000 -#define SZ_512K 0x00080000 - -#define SZ_1M 0x00100000 -#define SZ_2M 0x00200000 -#define SZ_4M 0x00400000 -#define SZ_8M 0x00800000 -#define SZ_16M 0x01000000 -#define SZ_32M 0x02000000 -#define SZ_64M 0x04000000 -#define SZ_128M 0x08000000 -#define SZ_256M 0x10000000 -#define SZ_512M 0x20000000 - -#define SZ_1G 0x40000000 -#define SZ_2G 0x80000000 - -#endif /* __LINUX_SIZES_H__ */ diff --git a/trunk/init/Kconfig b/trunk/init/Kconfig index b3f55f15e107..d07dcf9fc8a9 100644 --- a/trunk/init/Kconfig +++ b/trunk/init/Kconfig @@ -357,7 +357,7 @@ config AUDIT config AUDITSYSCALL bool "Enable system-call auditing support" - depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT)) + depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || ARM) default y if SECURITY_SELINUX help Enable low-overhead system-call auditing infrastructure that diff --git a/trunk/mm/vmalloc.c b/trunk/mm/vmalloc.c index c7ac8e1b3ac7..2aad49981b57 100644 --- a/trunk/mm/vmalloc.c +++ b/trunk/mm/vmalloc.c @@ -1975,7 +1975,9 @@ static int aligned_vwrite(char *buf, char *addr, unsigned long count) * IOREMAP area is treated as memory hole and no copy is done. * * If [addr...addr+count) doesn't includes any intersects with alive - * vm_struct area, returns 0. @buf should be kernel's buffer. + * vm_struct area, returns 0. + * @buf should be kernel's buffer. Because this function uses KM_USER0, + * the caller should guarantee KM_USER0 is not used. * * Note: In usual ops, vread() is never necessary because the caller * should know vmalloc() area is valid and can use memcpy(). @@ -2049,7 +2051,9 @@ long vread(char *buf, char *addr, unsigned long count) * IOREMAP area is treated as memory hole and no copy is done. * * If [addr...addr+count) doesn't includes any intersects with alive - * vm_struct area, returns 0. @buf should be kernel's buffer. + * vm_struct area, returns 0. + * @buf should be kernel's buffer. Because this function uses KM_USER0, + * the caller should guarantee KM_USER0 is not used. * * Note: In usual ops, vwrite() is never necessary because the caller * should know vmalloc() area is valid and can use memcpy(). diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 581ecf02c6b5..e7e6eeae49c0 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -2681,7 +2681,10 @@ static int do_tcp_setsockopt(struct sock *sk, int level, /* Cap the max timeout in ms TCP will retry/retrans * before giving up and aborting (ETIMEDOUT) a connection. */ - icsk->icsk_user_timeout = msecs_to_jiffies(val); + if (val < 0) + err = -EINVAL; + else + icsk->icsk_user_timeout = msecs_to_jiffies(val); break; default: err = -ENOPROTOOPT;