diff --git a/[refs] b/[refs] index 0634fdde8e61..8be25e7a0b5e 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: a7d6e4ecdb7648478ddec76d30d87d03d6e22b31 +refs/heads/master: a628e7b87e100befac9702aa0c3b9848a7685e49 diff --git a/trunk/Documentation/arm/Booting b/trunk/Documentation/arm/Booting index 76850295af8f..4e686a2ed91e 100644 --- a/trunk/Documentation/arm/Booting +++ b/trunk/Documentation/arm/Booting @@ -65,13 +65,19 @@ looks at the connected hardware is beyond the scope of this document. The boot loader must ultimately be able to provide a MACH_TYPE_xxx value to the kernel. (see linux/arch/arm/tools/mach-types). - -4. Setup the kernel tagged list -------------------------------- +4. Setup boot data +------------------ Existing boot loaders: OPTIONAL, HIGHLY RECOMMENDED New boot loaders: MANDATORY +The boot loader must provide either a tagged list or a dtb image for +passing configuration data to the kernel. The physical address of the +boot data is passed to the kernel in register r2. + +4a. Setup the kernel tagged list +-------------------------------- + The boot loader must create and initialise the kernel tagged list. A valid tagged list starts with ATAG_CORE and ends with ATAG_NONE. The ATAG_CORE tag may or may not be empty. An empty ATAG_CORE tag @@ -101,6 +107,24 @@ The tagged list must be placed in a region of memory where neither the kernel decompressor nor initrd 'bootp' program will overwrite it. The recommended placement is in the first 16KiB of RAM. +4b. Setup the device tree +------------------------- + +The boot loader must load a device tree image (dtb) into system ram +at a 64bit aligned address and initialize it with the boot data. The +dtb format is documented in Documentation/devicetree/booting-without-of.txt. +The kernel will look for the dtb magic value of 0xd00dfeed at the dtb +physical address to determine if a dtb has been passed instead of a +tagged list. + +The boot loader must pass at a minimum the size and location of the +system memory, and the root filesystem location. The dtb must be +placed in a region of memory where the kernel decompressor will not +overwrite it. The recommended placement is in the first 16KiB of RAM +with the caveat that it may not be located at physical address 0 since +the kernel interprets a value of 0 in r2 to mean neither a tagged list +nor a dtb were passed. + 5. Calling the kernel image --------------------------- @@ -125,7 +149,8 @@ In either case, the following conditions must be met: - CPU register settings r0 = 0, r1 = machine type number discovered in (3) above. - r2 = physical address of tagged list in system RAM. + r2 = physical address of tagged list in system RAM, or + physical address of device tree block (dtb) in system RAM - CPU mode All forms of interrupts must be disabled (IRQs and FIQs) diff --git a/trunk/Documentation/devicetree/booting-without-of.txt b/trunk/Documentation/devicetree/booting-without-of.txt index 28b1c9d3d351..9381a1481027 100644 --- a/trunk/Documentation/devicetree/booting-without-of.txt +++ b/trunk/Documentation/devicetree/booting-without-of.txt @@ -13,6 +13,7 @@ Table of Contents I - Introduction 1) Entry point for arch/powerpc + 2) Entry point for arch/arm II - The DT block format 1) Header @@ -225,6 +226,45 @@ it with special cases. cannot support both configurations with Book E and configurations with classic Powerpc architectures. +2) Entry point for arch/arm +--------------------------- + + There is one single entry point to the kernel, at the start + of the kernel image. That entry point supports two calling + conventions. A summary of the interface is described here. A full + description of the boot requirements is documented in + Documentation/arm/Booting + + a) ATAGS interface. Minimal information is passed from firmware + to the kernel with a tagged list of predefined parameters. + + r0 : 0 + + r1 : Machine type number + + r2 : Physical address of tagged list in system RAM + + b) Entry with a flattened device-tree block. Firmware loads the + physical address of the flattened device tree block (dtb) into r2, + r1 is not used, but it is considered good practise to use a valid + machine number as described in Documentation/arm/Booting. + + r0 : 0 + + r1 : Valid machine type number. When using a device tree, + a single machine type number will often be assigned to + represent a class or family of SoCs. + + r2 : physical pointer to the device-tree block + (defined in chapter II) in RAM. Device tree can be located + anywhere in system RAM, but it should be aligned on a 32 bit + boundary. + + The kernel will differentiate between ATAGS and device tree booting by + reading the memory pointed to by r1 and looking for either the flattened + device tree block magic value (0xd00dfeed) or the ATAG_CORE value at + offset 0x4 from r2 (0x54410001). + II - The DT block format ======================== diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 5dd6c751e6a6..4837907a4eda 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -2126,7 +2126,6 @@ S: Supported F: fs/dlm/ DMA GENERIC OFFLOAD ENGINE SUBSYSTEM -M: Vinod Koul M: Dan Williams S: Supported F: drivers/dma/ diff --git a/trunk/arch/arm/Kconfig b/trunk/arch/arm/Kconfig index 26d45e5b636b..5cff165b7eb0 100644 --- a/trunk/arch/arm/Kconfig +++ b/trunk/arch/arm/Kconfig @@ -1391,7 +1391,7 @@ config AEABI config OABI_COMPAT bool "Allow old ABI binaries to run with this kernel (EXPERIMENTAL)" - depends on AEABI && EXPERIMENTAL && !THUMB2_KERNEL + depends on AEABI && EXPERIMENTAL default y help This option preserves the old syscall interface along with the diff --git a/trunk/arch/arm/kernel/head.S b/trunk/arch/arm/kernel/head.S index f06ff9feb0db..c0225da3fb21 100644 --- a/trunk/arch/arm/kernel/head.S +++ b/trunk/arch/arm/kernel/head.S @@ -391,7 +391,6 @@ ENDPROC(__turn_mmu_on) #ifdef CONFIG_SMP_ON_UP - __INIT __fixup_smp: and r3, r9, #0x000f0000 @ architecture version teq r3, #0x000f0000 @ CPU ID supported? @@ -416,7 +415,18 @@ __fixup_smp_on_up: sub r3, r0, r3 add r4, r4, r3 add r5, r5, r3 - b __do_fixup_smp_on_up +2: cmp r4, r5 + movhs pc, lr + ldmia r4!, {r0, r6} + ARM( str r6, [r0, r3] ) + THUMB( add r0, r0, r3 ) +#ifdef __ARMEB__ + THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. +#endif + THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords + THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. + THUMB( strh r6, [r0] ) + b 2b ENDPROC(__fixup_smp) .align @@ -430,31 +440,7 @@ smp_on_up: ALT_SMP(.long 1) ALT_UP(.long 0) .popsection -#endif - .text -__do_fixup_smp_on_up: - cmp r4, r5 - movhs pc, lr - ldmia r4!, {r0, r6} - ARM( str r6, [r0, r3] ) - THUMB( add r0, r0, r3 ) -#ifdef __ARMEB__ - THUMB( mov r6, r6, ror #16 ) @ Convert word order for big-endian. #endif - THUMB( strh r6, [r0], #2 ) @ For Thumb-2, store as two halfwords - THUMB( mov r6, r6, lsr #16 ) @ to be robust against misaligned r3. - THUMB( strh r6, [r0] ) - b __do_fixup_smp_on_up -ENDPROC(__do_fixup_smp_on_up) - -ENTRY(fixup_smp) - stmfd sp!, {r4 - r6, lr} - mov r4, r0 - add r5, r0, r1 - mov r3, #0 - bl __do_fixup_smp_on_up - ldmfd sp!, {r4 - r6, pc} -ENDPROC(fixup_smp) #include "head-common.S" diff --git a/trunk/arch/arm/kernel/hw_breakpoint.c b/trunk/arch/arm/kernel/hw_breakpoint.c index d600bd350704..c9f3f0467570 100644 --- a/trunk/arch/arm/kernel/hw_breakpoint.c +++ b/trunk/arch/arm/kernel/hw_breakpoint.c @@ -137,10 +137,11 @@ static u8 get_debug_arch(void) u32 didr; /* Do we implement the extended CPUID interface? */ - if (WARN_ONCE((((read_cpuid_id() >> 16) & 0xf) != 0xf), - "CPUID feature registers not supported. " - "Assuming v6 debug is present.\n")) + if (((read_cpuid_id() >> 16) & 0xf) != 0xf) { + pr_warning("CPUID feature registers not supported. " + "Assuming v6 debug is present.\n"); return ARM_DEBUG_ARCH_V6; + } ARM_DBG_READ(c0, 0, didr); return (didr >> 16) & 0xf; @@ -151,12 +152,6 @@ u8 arch_get_debug_arch(void) return debug_arch; } -static int debug_arch_supported(void) -{ - u8 arch = get_debug_arch(); - return arch >= ARM_DEBUG_ARCH_V6 && arch <= ARM_DEBUG_ARCH_V7_ECP14; -} - /* Determine number of BRP register available. */ static int get_num_brp_resources(void) { @@ -273,9 +268,6 @@ static int enable_monitor_mode(void) int hw_breakpoint_slots(int type) { - if (!debug_arch_supported()) - return 0; - /* * We can be called early, so don't rely on * our static variables being initialised. @@ -842,11 +834,11 @@ static void reset_ctrl_regs(void *unused) /* * v7 debug contains save and restore registers so that debug state - * can be maintained across low-power modes without leaving the debug - * logic powered up. It is IMPLEMENTATION DEFINED whether we can access - * the debug registers out of reset, so we must unlock the OS Lock - * Access Register to avoid taking undefined instruction exceptions - * later on. + * can be maintained across low-power modes without leaving + * the debug logic powered up. It is IMPLEMENTATION DEFINED whether + * we can write to the debug registers out of reset, so we must + * unlock the OS Lock Access Register to avoid taking undefined + * instruction exceptions later on. */ if (debug_arch >= ARM_DEBUG_ARCH_V7_ECP14) { /* @@ -890,7 +882,7 @@ static int __init arch_hw_breakpoint_init(void) debug_arch = get_debug_arch(); - if (!debug_arch_supported()) { + if (debug_arch > ARM_DEBUG_ARCH_V7_ECP14) { pr_info("debug architecture 0x%x unsupported.\n", debug_arch); return 0; } @@ -907,18 +899,18 @@ static int __init arch_hw_breakpoint_init(void) pr_info("%d breakpoint(s) reserved for watchpoint " "single-step.\n", core_num_reserved_brps); - /* - * Reset the breakpoint resources. We assume that a halting - * debugger will leave the world in a nice state for us. - */ - on_each_cpu(reset_ctrl_regs, NULL, 1); - ARM_DBG_READ(c1, 0, dscr); if (dscr & ARM_DSCR_HDBGEN) { - max_watchpoint_len = 4; pr_warning("halting debug mode enabled. Assuming maximum " - "watchpoint size of %u bytes.", max_watchpoint_len); + "watchpoint size of 4 bytes."); } else { + /* + * Reset the breakpoint resources. We assume that a halting + * debugger will leave the world in a nice state for us. + */ + smp_call_function(reset_ctrl_regs, NULL, 1); + reset_ctrl_regs(NULL); + /* Work out the maximum supported watchpoint length. */ max_watchpoint_len = get_max_wp_len(); pr_info("maximum watchpoint size is %u bytes.\n", diff --git a/trunk/arch/arm/kernel/module.c b/trunk/arch/arm/kernel/module.c index 6d4105e6872f..2cfe8161b478 100644 --- a/trunk/arch/arm/kernel/module.c +++ b/trunk/arch/arm/kernel/module.c @@ -22,7 +22,6 @@ #include #include -#include #include #ifdef CONFIG_XIP_KERNEL @@ -269,28 +268,12 @@ struct mod_unwind_map { const Elf_Shdr *txt_sec; }; -static const Elf_Shdr *find_mod_section(const Elf32_Ehdr *hdr, - const Elf_Shdr *sechdrs, const char *name) -{ - const Elf_Shdr *s, *se; - const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - - for (s = sechdrs, se = sechdrs + hdr->e_shnum; s < se; s++) - if (strcmp(name, secstrs + s->sh_name) == 0) - return s; - - return NULL; -} - -extern void fixup_smp(const void *, unsigned long); - int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *mod) { - const Elf_Shdr * __maybe_unused s = NULL; #ifdef CONFIG_ARM_UNWIND const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum; + const Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum; struct mod_unwind_map maps[ARM_SEC_MAX]; int i; @@ -332,9 +315,6 @@ int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs, maps[i].txt_sec->sh_addr, maps[i].txt_sec->sh_size); #endif - s = find_mod_section(hdr, sechdrs, ".alt.smp.init"); - if (s && !is_smp()) - fixup_smp((void *)s->sh_addr, s->sh_size); return 0; } diff --git a/trunk/arch/arm/kernel/perf_event.c b/trunk/arch/arm/kernel/perf_event.c index d150ad1ccb5d..5efa2647a2fb 100644 --- a/trunk/arch/arm/kernel/perf_event.c +++ b/trunk/arch/arm/kernel/perf_event.c @@ -700,7 +700,7 @@ user_backtrace(struct frame_tail __user *tail, * Frame pointers should strictly progress back up the stack * (towards higher addresses). */ - if (tail + 1 >= buftail.fp) + if (tail >= buftail.fp) return NULL; return buftail.fp - 1; diff --git a/trunk/arch/arm/mach-pxa/colibri-evalboard.c b/trunk/arch/arm/mach-pxa/colibri-evalboard.c index 28f667e52ef9..6b2c800a1133 100644 --- a/trunk/arch/arm/mach-pxa/colibri-evalboard.c +++ b/trunk/arch/arm/mach-pxa/colibri-evalboard.c @@ -50,7 +50,7 @@ static void __init colibri_mmc_init(void) GPIO0_COLIBRI_PXA270_SD_DETECT; if (machine_is_colibri300()) /* PXA300 Colibri */ colibri_mci_platform_data.gpio_card_detect = - GPIO13_COLIBRI_PXA300_SD_DETECT; + GPIO39_COLIBRI_PXA300_SD_DETECT; else /* PXA320 Colibri */ colibri_mci_platform_data.gpio_card_detect = GPIO28_COLIBRI_PXA320_SD_DETECT; diff --git a/trunk/arch/arm/mach-pxa/colibri-pxa300.c b/trunk/arch/arm/mach-pxa/colibri-pxa300.c index 66dd81cbc8a0..fddb16d07eb0 100644 --- a/trunk/arch/arm/mach-pxa/colibri-pxa300.c +++ b/trunk/arch/arm/mach-pxa/colibri-pxa300.c @@ -41,7 +41,7 @@ static mfp_cfg_t colibri_pxa300_evalboard_pin_config[] __initdata = { GPIO4_MMC1_DAT1, GPIO5_MMC1_DAT2, GPIO6_MMC1_DAT3, - GPIO13_GPIO, /* GPIO13_COLIBRI_PXA300_SD_DETECT */ + GPIO39_GPIO, /* SD detect */ /* UHC */ GPIO0_2_USBH_PEN, diff --git a/trunk/arch/arm/mach-pxa/include/mach/colibri.h b/trunk/arch/arm/mach-pxa/include/mach/colibri.h index cb4236e98a0f..388a96f1ef93 100644 --- a/trunk/arch/arm/mach-pxa/include/mach/colibri.h +++ b/trunk/arch/arm/mach-pxa/include/mach/colibri.h @@ -60,7 +60,7 @@ static inline void colibri_pxa3xx_init_nand(void) {} #define GPIO113_COLIBRI_PXA270_TS_IRQ 113 /* GPIO definitions for Colibri PXA300/310 */ -#define GPIO13_COLIBRI_PXA300_SD_DETECT 13 +#define GPIO39_COLIBRI_PXA300_SD_DETECT 39 /* GPIO definitions for Colibri PXA320 */ #define GPIO28_COLIBRI_PXA320_SD_DETECT 28 diff --git a/trunk/arch/arm/mach-pxa/palm27x.c b/trunk/arch/arm/mach-pxa/palm27x.c index 35572c427fa8..405b92a29793 100644 --- a/trunk/arch/arm/mach-pxa/palm27x.c +++ b/trunk/arch/arm/mach-pxa/palm27x.c @@ -323,7 +323,7 @@ static struct platform_pwm_backlight_data palm27x_backlight_data = { .pwm_id = 0, .max_brightness = 0xfe, .dft_brightness = 0x7e, - .pwm_period_ns = 3500 * 1024, + .pwm_period_ns = 3500, .init = palm27x_backlight_init, .notify = palm27x_backlight_notify, .exit = palm27x_backlight_exit, diff --git a/trunk/arch/arm/mach-pxa/pm.c b/trunk/arch/arm/mach-pxa/pm.c index 1807c9abdde0..978e1b289544 100644 --- a/trunk/arch/arm/mach-pxa/pm.c +++ b/trunk/arch/arm/mach-pxa/pm.c @@ -33,7 +33,7 @@ int pxa_pm_enter(suspend_state_t state) #endif /* skip registers saving for standby */ - if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->save) { + if (state != PM_SUSPEND_STANDBY) { pxa_cpu_pm_fns->save(sleep_save); /* before sleeping, calculate and save a checksum */ for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++) @@ -44,7 +44,7 @@ int pxa_pm_enter(suspend_state_t state) pxa_cpu_pm_fns->enter(state); cpu_init(); - if (state != PM_SUSPEND_STANDBY && pxa_cpu_pm_fns->restore) { + if (state != PM_SUSPEND_STANDBY) { /* after sleeping, validate the checksum */ for (i = 0; i < pxa_cpu_pm_fns->save_count - 1; i++) checksum += sleep_save[i]; diff --git a/trunk/arch/arm/mach-sa1100/collie.c b/trunk/arch/arm/mach-sa1100/collie.c index bd3e1bfdd6aa..d43c5ef58eb6 100644 --- a/trunk/arch/arm/mach-sa1100/collie.c +++ b/trunk/arch/arm/mach-sa1100/collie.c @@ -241,9 +241,6 @@ static struct locomo_platform_data locomo_info = { struct platform_device collie_locomo_device = { .name = "locomo", .id = 0, - .dev = { - .platform_data = &locomo_info, - }, .num_resources = ARRAY_SIZE(locomo_resources), .resource = locomo_resources, }; diff --git a/trunk/arch/arm/mm/Kconfig b/trunk/arch/arm/mm/Kconfig index e4509bae8fc4..9d30c6f804b9 100644 --- a/trunk/arch/arm/mm/Kconfig +++ b/trunk/arch/arm/mm/Kconfig @@ -405,7 +405,7 @@ config CPU_V6 config CPU_32v6K bool "Support ARM V6K processor extensions" if !SMP depends on CPU_V6 || CPU_V7 - default y if SMP + default y if SMP && !(ARCH_MX3 || ARCH_OMAP2) help Say Y here if your ARMv6 processor supports the 'K' extension. This enables the kernel to use some instructions not present @@ -416,7 +416,7 @@ config CPU_32v6K # ARMv7 config CPU_V7 bool "Support ARM V7 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX - select CPU_32v6K + select CPU_32v6K if !ARCH_OMAP2 select CPU_32v7 select CPU_ABRT_EV7 select CPU_PABRT_V7 @@ -644,7 +644,7 @@ config ARM_THUMBEE config SWP_EMULATE bool "Emulate SWP/SWPB instructions" - depends on !CPU_USE_DOMAINS && CPU_V7 && !CPU_V6 + depends on CPU_V7 && !CPU_V6 select HAVE_PROC_CPU if PROC_FS default y if SMP help diff --git a/trunk/arch/arm/oprofile/common.c b/trunk/arch/arm/oprofile/common.c index c074e66ad224..8aa974491dfc 100644 --- a/trunk/arch/arm/oprofile/common.c +++ b/trunk/arch/arm/oprofile/common.c @@ -10,6 +10,8 @@ */ #include +#include +#include #include #include #include @@ -44,7 +46,6 @@ char *op_name_from_perf_id(void) return NULL; } } -#endif static int report_trace(struct stackframe *frame, void *d) { @@ -84,7 +85,7 @@ static struct frame_tail* user_backtrace(struct frame_tail *tail) /* frame pointers should strictly progress back up the stack * (towards higher addresses) */ - if (tail + 1 >= buftail[0].fp) + if (tail >= buftail[0].fp) return NULL; return buftail[0].fp-1; @@ -110,7 +111,6 @@ static void arm_backtrace(struct pt_regs * const regs, unsigned int depth) int __init oprofile_arch_init(struct oprofile_operations *ops) { - /* provide backtrace support also in timer mode: */ ops->backtrace = arm_backtrace; return oprofile_perf_init(ops); @@ -120,3 +120,11 @@ void __exit oprofile_arch_exit(void) { oprofile_perf_exit(); } +#else +int __init oprofile_arch_init(struct oprofile_operations *ops) +{ + pr_info("oprofile: hardware counters not available\n"); + return -ENODEV; +} +void __exit oprofile_arch_exit(void) {} +#endif /* CONFIG_HW_PERF_EVENTS */ diff --git a/trunk/arch/arm/plat-pxa/mfp.c b/trunk/arch/arm/plat-pxa/mfp.c index a9aa5ad3f4eb..b77e018d36c1 100644 --- a/trunk/arch/arm/plat-pxa/mfp.c +++ b/trunk/arch/arm/plat-pxa/mfp.c @@ -139,11 +139,10 @@ static const unsigned long mfpr_edge[] = { #define mfp_configured(p) ((p)->config != -1) /* - * perform a read-back of any valid MFPR register to make sure the + * perform a read-back of any MFPR register to make sure the * previous writings are finished */ -static unsigned long mfpr_off_readback; -#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + mfpr_off_readback) +#define mfpr_sync() (void)__raw_readl(mfpr_mmio_base + 0) static inline void __mfp_config_run(struct mfp_pin *p) { @@ -249,9 +248,6 @@ void __init mfp_init_addr(struct mfp_addr_map *map) spin_lock_irqsave(&mfp_spin_lock, flags); - /* mfp offset for readback */ - mfpr_off_readback = map[0].offset; - for (p = map; p->start != MFP_PIN_INVALID; p++) { offset = p->offset; i = p->start; diff --git a/trunk/arch/s390/include/asm/processor.h b/trunk/arch/s390/include/asm/processor.h index 2c79b6416271..bf3de04170a7 100644 --- a/trunk/arch/s390/include/asm/processor.h +++ b/trunk/arch/s390/include/asm/processor.h @@ -148,6 +148,11 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); */ extern unsigned long thread_saved_pc(struct task_struct *t); +/* + * Print register of task into buffer. Used in fs/proc/array.c. + */ +extern void task_show_regs(struct seq_file *m, struct task_struct *task); + extern void show_code(struct pt_regs *regs); unsigned long get_wchan(struct task_struct *p); diff --git a/trunk/arch/s390/kernel/traps.c b/trunk/arch/s390/kernel/traps.c index b5a4a739b477..5eb78dd584ce 100644 --- a/trunk/arch/s390/kernel/traps.c +++ b/trunk/arch/s390/kernel/traps.c @@ -237,6 +237,43 @@ void show_regs(struct pt_regs *regs) show_last_breaking_event(regs); } +/* This is called from fs/proc/array.c */ +void task_show_regs(struct seq_file *m, struct task_struct *task) +{ + struct pt_regs *regs; + + regs = task_pt_regs(task); + seq_printf(m, "task: %p, ksp: %p\n", + task, (void *)task->thread.ksp); + seq_printf(m, "User PSW : %p %p\n", + (void *) regs->psw.mask, (void *)regs->psw.addr); + + seq_printf(m, "User GPRS: " FOURLONG, + regs->gprs[0], regs->gprs[1], + regs->gprs[2], regs->gprs[3]); + seq_printf(m, " " FOURLONG, + regs->gprs[4], regs->gprs[5], + regs->gprs[6], regs->gprs[7]); + seq_printf(m, " " FOURLONG, + regs->gprs[8], regs->gprs[9], + regs->gprs[10], regs->gprs[11]); + seq_printf(m, " " FOURLONG, + regs->gprs[12], regs->gprs[13], + regs->gprs[14], regs->gprs[15]); + seq_printf(m, "User ACRS: %08x %08x %08x %08x\n", + task->thread.acrs[0], task->thread.acrs[1], + task->thread.acrs[2], task->thread.acrs[3]); + seq_printf(m, " %08x %08x %08x %08x\n", + task->thread.acrs[4], task->thread.acrs[5], + task->thread.acrs[6], task->thread.acrs[7]); + seq_printf(m, " %08x %08x %08x %08x\n", + task->thread.acrs[8], task->thread.acrs[9], + task->thread.acrs[10], task->thread.acrs[11]); + seq_printf(m, " %08x %08x %08x %08x\n", + task->thread.acrs[12], task->thread.acrs[13], + task->thread.acrs[14], task->thread.acrs[15]); +} + static DEFINE_SPINLOCK(die_lock); void die(const char * str, struct pt_regs * regs, long err) diff --git a/trunk/arch/x86/include/asm/apic.h b/trunk/arch/x86/include/asm/apic.h index 3c896946f4cc..5e3969c36d7f 100644 --- a/trunk/arch/x86/include/asm/apic.h +++ b/trunk/arch/x86/include/asm/apic.h @@ -233,7 +233,6 @@ extern void sync_Arb_IDs(void); extern void init_bsp_APIC(void); extern void setup_local_APIC(void); extern void end_local_APIC_setup(void); -extern void bsp_end_local_APIC_setup(void); extern void init_apic_mappings(void); void register_lapic_address(unsigned long address); extern void setup_boot_APIC_clock(void); diff --git a/trunk/arch/x86/include/asm/cpu.h b/trunk/arch/x86/include/asm/cpu.h index 4564c8e28a33..6e6e7558e702 100644 --- a/trunk/arch/x86/include/asm/cpu.h +++ b/trunk/arch/x86/include/asm/cpu.h @@ -32,6 +32,6 @@ extern void arch_unregister_cpu(int); DECLARE_PER_CPU(int, cpu_state); -int mwait_usable(const struct cpuinfo_x86 *); +int __cpuinit mwait_usable(const struct cpuinfo_x86 *); #endif /* _ASM_X86_CPU_H */ diff --git a/trunk/arch/x86/kernel/alternative.c b/trunk/arch/x86/kernel/alternative.c index 7038b95d363f..123608531c8f 100644 --- a/trunk/arch/x86/kernel/alternative.c +++ b/trunk/arch/x86/kernel/alternative.c @@ -671,7 +671,7 @@ void __kprobes text_poke_smp_batch(struct text_poke_param *params, int n) atomic_set(&stop_machine_first, 1); wrote_text = 0; - __stop_machine(stop_machine_text_poke, (void *)&tpp, NULL); + stop_machine(stop_machine_text_poke, (void *)&tpp, NULL); } #if defined(CONFIG_DYNAMIC_FTRACE) || defined(HAVE_JUMP_LABEL) diff --git a/trunk/arch/x86/kernel/apic/apic.c b/trunk/arch/x86/kernel/apic/apic.c index 76b96d74978a..06c196d7e59c 100644 --- a/trunk/arch/x86/kernel/apic/apic.c +++ b/trunk/arch/x86/kernel/apic/apic.c @@ -1381,17 +1381,12 @@ void __cpuinit end_local_APIC_setup(void) #endif apic_pm_activate(); -} - -void __init bsp_end_local_APIC_setup(void) -{ - end_local_APIC_setup(); /* * Now that local APIC setup is completed for BP, configure the fault * handling for interrupt remapping. */ - if (intr_remapping_enabled) + if (!smp_processor_id() && intr_remapping_enabled) enable_drhd_fault_handling(); } @@ -1761,7 +1756,7 @@ int __init APIC_init_uniprocessor(void) enable_IO_APIC(); #endif - bsp_end_local_APIC_setup(); + end_local_APIC_setup(); #ifdef CONFIG_X86_IO_APIC if (smp_found_config && !skip_ioapic_setup && nr_ioapics) diff --git a/trunk/arch/x86/kernel/apic/io_apic.c b/trunk/arch/x86/kernel/apic/io_apic.c index ca9e2a3545a9..697dc34b7b87 100644 --- a/trunk/arch/x86/kernel/apic/io_apic.c +++ b/trunk/arch/x86/kernel/apic/io_apic.c @@ -4002,9 +4002,6 @@ int mp_find_ioapic(u32 gsi) { int i = 0; - if (nr_ioapics == 0) - return -1; - /* Find the IOAPIC that manages this GSI. */ for (i = 0; i < nr_ioapics; i++) { if ((gsi >= mp_gsi_routing[i].gsi_base) diff --git a/trunk/arch/x86/kernel/irq.c b/trunk/arch/x86/kernel/irq.c index 387b6a0c9e81..52945da52a94 100644 --- a/trunk/arch/x86/kernel/irq.c +++ b/trunk/arch/x86/kernel/irq.c @@ -367,8 +367,7 @@ void fixup_irqs(void) if (irr & (1 << (vector % 32))) { irq = __this_cpu_read(vector_irq[vector]); - desc = irq_to_desc(irq); - data = &desc->irq_data; + data = irq_get_irq_data(irq); raw_spin_lock(&desc->lock); if (data->chip->irq_retrigger) data->chip->irq_retrigger(data); diff --git a/trunk/arch/x86/kernel/process.c b/trunk/arch/x86/kernel/process.c index ff4554198981..e764fc05d700 100644 --- a/trunk/arch/x86/kernel/process.c +++ b/trunk/arch/x86/kernel/process.c @@ -92,31 +92,21 @@ void show_regs(struct pt_regs *regs) void show_regs_common(void) { - const char *vendor, *product, *board; + const char *board, *product; - vendor = dmi_get_system_info(DMI_SYS_VENDOR); - if (!vendor) - vendor = ""; + board = dmi_get_system_info(DMI_BOARD_NAME); + if (!board) + board = ""; product = dmi_get_system_info(DMI_PRODUCT_NAME); if (!product) product = ""; - /* Board Name is optional */ - board = dmi_get_system_info(DMI_BOARD_NAME); - printk(KERN_CONT "\n"); - printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s", + printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s/%s\n", current->pid, current->comm, print_tainted(), init_utsname()->release, (int)strcspn(init_utsname()->version, " "), - init_utsname()->version); - printk(KERN_CONT " "); - printk(KERN_CONT "%s %s", vendor, product); - if (board) { - printk(KERN_CONT "/"); - printk(KERN_CONT "%s", board); - } - printk(KERN_CONT "\n"); + init_utsname()->version, board, product); } void flush_thread(void) @@ -516,7 +506,7 @@ static void poll_idle(void) #define MWAIT_ECX_EXTENDED_INFO 0x01 #define MWAIT_EDX_C1 0xf0 -int mwait_usable(const struct cpuinfo_x86 *c) +int __cpuinit mwait_usable(const struct cpuinfo_x86 *c) { u32 eax, ebx, ecx, edx; diff --git a/trunk/arch/x86/kernel/smpboot.c b/trunk/arch/x86/kernel/smpboot.c index 08776a953487..03273b6c272c 100644 --- a/trunk/arch/x86/kernel/smpboot.c +++ b/trunk/arch/x86/kernel/smpboot.c @@ -1060,7 +1060,7 @@ static int __init smp_sanity_check(unsigned max_cpus) connect_bsp_APIC(); setup_local_APIC(); - bsp_end_local_APIC_setup(); + end_local_APIC_setup(); return -1; } @@ -1137,7 +1137,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus) if (!skip_ioapic_setup && nr_ioapics) enable_IO_APIC(); - bsp_end_local_APIC_setup(); + end_local_APIC_setup(); map_cpu_to_logical_apicid(); diff --git a/trunk/drivers/acpi/acpica/evxfgpe.c b/trunk/drivers/acpi/acpica/evxfgpe.c index 3b20a3401b64..e9562a7cb2f9 100644 --- a/trunk/drivers/acpi/acpica/evxfgpe.c +++ b/trunk/drivers/acpi/acpica/evxfgpe.c @@ -212,40 +212,37 @@ acpi_setup_gpe_for_wake(acpi_handle wake_device, return_ACPI_STATUS(AE_BAD_PARAMETER); } - flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - - /* Ensure that we have a valid GPE number */ + /* Validate wake_device is of type Device */ - gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); - if (!gpe_event_info) { - goto unlock_and_exit; + device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device); + if (device_node->type != ACPI_TYPE_DEVICE) { + return_ACPI_STATUS(AE_BAD_PARAMETER); } - /* - * If there is no method or handler for this GPE, then the - * wake_device will be notified whenever this GPE fires (aka - * "implicit notify") Note: The GPE is assumed to be - * level-triggered (for windows compatibility). - */ - if (((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == - ACPI_GPE_DISPATCH_NONE) && (wake_device != ACPI_ROOT_OBJECT)) { + flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); - /* Validate wake_device is of type Device */ + /* Ensure that we have a valid GPE number */ - device_node = ACPI_CAST_PTR(struct acpi_namespace_node, - wake_device); - if (device_node->type != ACPI_TYPE_DEVICE) { - goto unlock_and_exit; + gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); + if (gpe_event_info) { + /* + * If there is no method or handler for this GPE, then the + * wake_device will be notified whenever this GPE fires (aka + * "implicit notify") Note: The GPE is assumed to be + * level-triggered (for windows compatibility). + */ + if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == + ACPI_GPE_DISPATCH_NONE) { + gpe_event_info->flags = + (ACPI_GPE_DISPATCH_NOTIFY | + ACPI_GPE_LEVEL_TRIGGERED); + gpe_event_info->dispatch.device_node = device_node; } - gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY | - ACPI_GPE_LEVEL_TRIGGERED); - gpe_event_info->dispatch.device_node = device_node; - } - gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; - status = AE_OK; + gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; + status = AE_OK; + } - unlock_and_exit: acpi_os_release_lock(acpi_gbl_gpe_lock, flags); return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index c90c76aa7f8b..b0931818cf98 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -636,21 +636,17 @@ EXPORT_SYMBOL(acpi_os_write_port); acpi_status acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) { - void __iomem *virt_addr; - unsigned int size = width / 8; - bool unmap = false; u32 dummy; + void __iomem *virt_addr; + int size = width / 8, unmap = 0; rcu_read_lock(); virt_addr = acpi_map_vaddr_lookup(phys_addr, size); + rcu_read_unlock(); if (!virt_addr) { - rcu_read_unlock(); virt_addr = acpi_os_ioremap(phys_addr, size); - if (!virt_addr) - return AE_BAD_ADDRESS; - unmap = true; + unmap = 1; } - if (!value) value = &dummy; @@ -670,8 +666,6 @@ acpi_os_read_memory(acpi_physical_address phys_addr, u32 * value, u32 width) if (unmap) iounmap(virt_addr); - else - rcu_read_unlock(); return AE_OK; } @@ -680,17 +674,14 @@ acpi_status acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) { void __iomem *virt_addr; - unsigned int size = width / 8; - bool unmap = false; + int size = width / 8, unmap = 0; rcu_read_lock(); virt_addr = acpi_map_vaddr_lookup(phys_addr, size); + rcu_read_unlock(); if (!virt_addr) { - rcu_read_unlock(); virt_addr = acpi_os_ioremap(phys_addr, size); - if (!virt_addr) - return AE_BAD_ADDRESS; - unmap = true; + unmap = 1; } switch (width) { @@ -709,8 +700,6 @@ acpi_os_write_memory(acpi_physical_address phys_addr, u32 value, u32 width) if (unmap) iounmap(virt_addr); - else - rcu_read_unlock(); return AE_OK; } diff --git a/trunk/drivers/acpi/video_detect.c b/trunk/drivers/acpi/video_detect.c index 5af3479714f6..42d3d72dae85 100644 --- a/trunk/drivers/acpi/video_detect.c +++ b/trunk/drivers/acpi/video_detect.c @@ -82,11 +82,6 @@ long acpi_is_video_device(struct acpi_device *device) if (!device) return 0; - /* Is this device able to support video switching ? */ - if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOD", &h_dummy)) || - ACPI_SUCCESS(acpi_get_handle(device->handle, "_DOS", &h_dummy))) - video_caps |= ACPI_VIDEO_OUTPUT_SWITCHING; - /* Is this device able to retrieve a video ROM ? */ if (ACPI_SUCCESS(acpi_get_handle(device->handle, "_ROM", &h_dummy))) video_caps |= ACPI_VIDEO_ROM_AVAILABLE; diff --git a/trunk/drivers/acpi/wakeup.c b/trunk/drivers/acpi/wakeup.c index 7bfbe40bc43b..ed6501452507 100644 --- a/trunk/drivers/acpi/wakeup.c +++ b/trunk/drivers/acpi/wakeup.c @@ -86,12 +86,8 @@ int __init acpi_wakeup_device_init(void) struct acpi_device *dev = container_of(node, struct acpi_device, wakeup_list); - if (device_can_wakeup(&dev->dev)) { - /* Button GPEs are supposed to be always enabled. */ - acpi_enable_gpe(dev->wakeup.gpe_device, - dev->wakeup.gpe_number); + if (device_can_wakeup(&dev->dev)) device_set_wakeup_enable(&dev->dev, true); - } } mutex_unlock(&acpi_device_lock); return 0; diff --git a/trunk/drivers/dma/amba-pl08x.c b/trunk/drivers/dma/amba-pl08x.c index 07bca4970e50..297f48b0cba9 100644 --- a/trunk/drivers/dma/amba-pl08x.c +++ b/trunk/drivers/dma/amba-pl08x.c @@ -79,7 +79,6 @@ #include #include #include -#include #include #include #include @@ -236,19 +235,16 @@ static void pl08x_start_txd(struct pl08x_dma_chan *plchan, } /* - * Pause the channel by setting the HALT bit. + * Overall DMAC remains enabled always. * - * For M->P transfers, pause the DMAC first and then stop the peripheral - - * the FIFO can only drain if the peripheral is still requesting data. - * (note: this can still timeout if the DMAC FIFO never drains of data.) + * Disabling individual channels could lose data. * - * For P->M transfers, disable the peripheral first to stop it filling - * the DMAC FIFO, and then pause the DMAC. + * Disable the peripheral DMA after disabling the DMAC in order to allow + * the DMAC FIFO to drain, and hence allow the channel to show inactive */ static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch) { u32 val; - int timeout; /* Set the HALT bit and wait for the FIFO to drain */ val = readl(ch->base + PL080_CH_CONFIG); @@ -256,13 +252,8 @@ static void pl08x_pause_phy_chan(struct pl08x_phy_chan *ch) writel(val, ch->base + PL080_CH_CONFIG); /* Wait for channel inactive */ - for (timeout = 1000; timeout; timeout--) { - if (!pl08x_phy_channel_busy(ch)) - break; - udelay(1); - } - if (pl08x_phy_channel_busy(ch)) - pr_err("pl08x: channel%u timeout waiting for pause\n", ch->id); + while (pl08x_phy_channel_busy(ch)) + cpu_relax(); } static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch) @@ -276,24 +267,19 @@ static void pl08x_resume_phy_chan(struct pl08x_phy_chan *ch) } -/* - * pl08x_terminate_phy_chan() stops the channel, clears the FIFO and - * clears any pending interrupt status. This should not be used for - * an on-going transfer, but as a method of shutting down a channel - * (eg, when it's no longer used) or terminating a transfer. - */ -static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x, - struct pl08x_phy_chan *ch) +/* Stops the channel */ +static void pl08x_stop_phy_chan(struct pl08x_phy_chan *ch) { - u32 val = readl(ch->base + PL080_CH_CONFIG); + u32 val; - val &= ~(PL080_CONFIG_ENABLE | PL080_CONFIG_ERR_IRQ_MASK | - PL080_CONFIG_TC_IRQ_MASK); + pl08x_pause_phy_chan(ch); + /* Disable channel */ + val = readl(ch->base + PL080_CH_CONFIG); + val &= ~PL080_CONFIG_ENABLE; + val &= ~PL080_CONFIG_ERR_IRQ_MASK; + val &= ~PL080_CONFIG_TC_IRQ_MASK; writel(val, ch->base + PL080_CH_CONFIG); - - writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR); - writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR); } static inline u32 get_bytes_in_cctl(u32 cctl) @@ -418,12 +404,13 @@ static inline void pl08x_put_phy_channel(struct pl08x_driver_data *pl08x, { unsigned long flags; - spin_lock_irqsave(&ch->lock, flags); - /* Stop the channel and clear its interrupts */ - pl08x_terminate_phy_chan(pl08x, ch); + pl08x_stop_phy_chan(ch); + writel((1 << ch->id), pl08x->base + PL080_ERR_CLEAR); + writel((1 << ch->id), pl08x->base + PL080_TC_CLEAR); /* Mark it as free */ + spin_lock_irqsave(&ch->lock, flags); ch->serving = NULL; spin_unlock_irqrestore(&ch->lock, flags); } @@ -1462,7 +1449,7 @@ static int pl08x_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, plchan->state = PL08X_CHAN_IDLE; if (plchan->phychan) { - pl08x_terminate_phy_chan(pl08x, plchan->phychan); + pl08x_stop_phy_chan(plchan->phychan); /* * Mark physical channel as free and free any slave diff --git a/trunk/drivers/dma/imx-dma.c b/trunk/drivers/dma/imx-dma.c index e18eaabe92b9..e53d438142bb 100644 --- a/trunk/drivers/dma/imx-dma.c +++ b/trunk/drivers/dma/imx-dma.c @@ -49,7 +49,6 @@ struct imxdma_channel { struct imxdma_engine { struct device *dev; - struct device_dma_parameters dma_parms; struct dma_device dma_device; struct imxdma_channel channel[MAX_DMA_CHANNELS]; }; @@ -243,21 +242,6 @@ static struct dma_async_tx_descriptor *imxdma_prep_slave_sg( else dmamode = DMA_MODE_WRITE; - switch (imxdmac->word_size) { - case DMA_SLAVE_BUSWIDTH_4_BYTES: - if (sgl->length & 3 || sgl->dma_address & 3) - return NULL; - break; - case DMA_SLAVE_BUSWIDTH_2_BYTES: - if (sgl->length & 1 || sgl->dma_address & 1) - return NULL; - break; - case DMA_SLAVE_BUSWIDTH_1_BYTE: - break; - default: - return NULL; - } - ret = imx_dma_setup_sg(imxdmac->imxdma_channel, sgl, sg_len, dma_length, imxdmac->per_address, dmamode); if (ret) @@ -345,9 +329,6 @@ static int __init imxdma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&imxdma->dma_device.channels); - dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask); - dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask); - /* Initialize channel parameters */ for (i = 0; i < MAX_DMA_CHANNELS; i++) { struct imxdma_channel *imxdmac = &imxdma->channel[i]; @@ -365,7 +346,11 @@ static int __init imxdma_probe(struct platform_device *pdev) imxdmac->imxdma = imxdma; spin_lock_init(&imxdmac->lock); + dma_cap_set(DMA_SLAVE, imxdma->dma_device.cap_mask); + dma_cap_set(DMA_CYCLIC, imxdma->dma_device.cap_mask); + imxdmac->chan.device = &imxdma->dma_device; + imxdmac->chan.chan_id = i; imxdmac->channel = i; /* Add the channel to the DMAC list */ @@ -385,9 +370,6 @@ static int __init imxdma_probe(struct platform_device *pdev) platform_set_drvdata(pdev, imxdma); - imxdma->dma_device.dev->dma_parms = &imxdma->dma_parms; - dma_set_max_seg_size(imxdma->dma_device.dev, 0xffffff); - ret = dma_async_device_register(&imxdma->dma_device); if (ret) { dev_err(&pdev->dev, "unable to register\n"); diff --git a/trunk/drivers/dma/imx-sdma.c b/trunk/drivers/dma/imx-sdma.c index b6d1455fa936..d5a5d4d9c19b 100644 --- a/trunk/drivers/dma/imx-sdma.c +++ b/trunk/drivers/dma/imx-sdma.c @@ -230,7 +230,7 @@ struct sdma_engine; * struct sdma_channel - housekeeping for a SDMA channel * * @sdma pointer to the SDMA engine for this channel - * @channel the channel number, matches dmaengine chan_id + 1 + * @channel the channel number, matches dmaengine chan_id * @direction transfer type. Needed for setting SDMA script * @peripheral_type Peripheral type. Needed for setting SDMA script * @event_id0 aka dma request line @@ -301,7 +301,6 @@ struct sdma_firmware_header { struct sdma_engine { struct device *dev; - struct device_dma_parameters dma_parms; struct sdma_channel channel[MAX_DMA_CHANNELS]; struct sdma_channel_control *channel_control; void __iomem *regs; @@ -450,7 +449,7 @@ static void sdma_handle_channel_loop(struct sdma_channel *sdmac) if (bd->mode.status & BD_RROR) sdmac->status = DMA_ERROR; else - sdmac->status = DMA_IN_PROGRESS; + sdmac->status = DMA_SUCCESS; bd->mode.status |= BD_DONE; sdmac->buf_tail++; @@ -771,15 +770,15 @@ static void sdma_enable_channel(struct sdma_engine *sdma, int channel) __raw_writel(1 << channel, sdma->regs + SDMA_H_START); } -static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdmac) +static dma_cookie_t sdma_assign_cookie(struct sdma_channel *sdma) { - dma_cookie_t cookie = sdmac->chan.cookie; + dma_cookie_t cookie = sdma->chan.cookie; if (++cookie < 0) cookie = 1; - sdmac->chan.cookie = cookie; - sdmac->desc.cookie = cookie; + sdma->chan.cookie = cookie; + sdma->desc.cookie = cookie; return cookie; } @@ -799,7 +798,7 @@ static dma_cookie_t sdma_tx_submit(struct dma_async_tx_descriptor *tx) cookie = sdma_assign_cookie(sdmac); - sdma_enable_channel(sdma, sdmac->channel); + sdma_enable_channel(sdma, tx->chan->chan_id); spin_unlock_irq(&sdmac->lock); @@ -812,6 +811,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan) struct imx_dma_data *data = chan->private; int prio, ret; + /* No need to execute this for internal channel 0 */ + if (chan->chan_id == 0) + return 0; + if (!data) return -EINVAL; @@ -876,7 +879,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; int ret, i, count; - int channel = sdmac->channel; + int channel = chan->chan_id; struct scatterlist *sg; if (sdmac->status == DMA_IN_PROGRESS) @@ -921,33 +924,22 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( ret = -EINVAL; goto err_out; } - - switch (sdmac->word_size) { - case DMA_SLAVE_BUSWIDTH_4_BYTES: + if (sdmac->word_size == DMA_SLAVE_BUSWIDTH_4_BYTES) bd->mode.command = 0; - if (count & 3 || sg->dma_address & 3) - return NULL; - break; - case DMA_SLAVE_BUSWIDTH_2_BYTES: - bd->mode.command = 2; - if (count & 1 || sg->dma_address & 1) - return NULL; - break; - case DMA_SLAVE_BUSWIDTH_1_BYTE: - bd->mode.command = 1; - break; - default: - return NULL; - } + else + bd->mode.command = sdmac->word_size; param = BD_DONE | BD_EXTD | BD_CONT; - if (i + 1 == sg_len) { + if (sdmac->flags & IMX_DMA_SG_LOOP) { param |= BD_INTR; - param |= BD_LAST; - param &= ~BD_CONT; + if (i + 1 == sg_len) + param |= BD_WRAP; } + if (i + 1 == sg_len) + param |= BD_INTR; + dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n", i, count, sg->dma_address, param & BD_WRAP ? "wrap" : "", @@ -961,7 +953,6 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( return &sdmac->desc; err_out: - sdmac->status = DMA_ERROR; return NULL; } @@ -972,7 +963,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic( struct sdma_channel *sdmac = to_sdma_chan(chan); struct sdma_engine *sdma = sdmac->sdma; int num_periods = buf_len / period_len; - int channel = sdmac->channel; + int channel = chan->chan_id; int ret, i = 0, buf = 0; dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel); @@ -1075,12 +1066,14 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan, { struct sdma_channel *sdmac = to_sdma_chan(chan); dma_cookie_t last_used; + enum dma_status ret; last_used = chan->cookie; + ret = dma_async_is_complete(cookie, sdmac->last_completed, last_used); dma_set_tx_state(txstate, sdmac->last_completed, last_used, 0); - return sdmac->status; + return ret; } static void sdma_issue_pending(struct dma_chan *chan) @@ -1142,7 +1135,7 @@ static int __init sdma_get_firmware(struct sdma_engine *sdma, /* download the RAM image for SDMA */ sdma_load_script(sdma, ram_code, header->ram_code_size, - addr->ram_code_start_addr); + sdma->script_addrs->ram_code_start_addr); clk_disable(sdma->clk); sdma_add_scripts(sdma, addr); @@ -1244,6 +1237,7 @@ static int __init sdma_probe(struct platform_device *pdev) struct resource *iores; struct sdma_platform_data *pdata = pdev->dev.platform_data; int i; + dma_cap_mask_t mask; struct sdma_engine *sdma; sdma = kzalloc(sizeof(*sdma), GFP_KERNEL); @@ -1286,9 +1280,6 @@ static int __init sdma_probe(struct platform_device *pdev) sdma->version = pdata->sdma_version; - dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask); - dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask); - INIT_LIST_HEAD(&sdma->dma_device.channels); /* Initialize channel parameters */ for (i = 0; i < MAX_DMA_CHANNELS; i++) { @@ -1297,17 +1288,15 @@ static int __init sdma_probe(struct platform_device *pdev) sdmac->sdma = sdma; spin_lock_init(&sdmac->lock); + dma_cap_set(DMA_SLAVE, sdma->dma_device.cap_mask); + dma_cap_set(DMA_CYCLIC, sdma->dma_device.cap_mask); + sdmac->chan.device = &sdma->dma_device; + sdmac->chan.chan_id = i; sdmac->channel = i; - /* - * Add the channel to the DMAC list. Do not add channel 0 though - * because we need it internally in the SDMA driver. This also means - * that channel 0 in dmaengine counting matches sdma channel 1. - */ - if (i) - list_add_tail(&sdmac->chan.device_node, - &sdma->dma_device.channels); + /* Add the channel to the DMAC list */ + list_add_tail(&sdmac->chan.device_node, &sdma->dma_device.channels); } ret = sdma_init(sdma); @@ -1328,8 +1317,6 @@ static int __init sdma_probe(struct platform_device *pdev) sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic; sdma->dma_device.device_control = sdma_control; sdma->dma_device.device_issue_pending = sdma_issue_pending; - sdma->dma_device.dev->dma_parms = &sdma->dma_parms; - dma_set_max_seg_size(sdma->dma_device.dev, 65535); ret = dma_async_device_register(&sdma->dma_device); if (ret) { @@ -1337,6 +1324,13 @@ static int __init sdma_probe(struct platform_device *pdev) goto err_init; } + /* request channel 0. This is an internal control channel + * to the SDMA engine and not available to clients. + */ + dma_cap_zero(mask); + dma_cap_set(DMA_SLAVE, mask); + dma_request_channel(mask, NULL, NULL); + dev_info(sdma->dev, "initialized\n"); return 0; @@ -1354,7 +1348,7 @@ static int __init sdma_probe(struct platform_device *pdev) err_request_region: err_irq: kfree(sdma); - return ret; + return 0; } static int __exit sdma_remove(struct platform_device *pdev) diff --git a/trunk/drivers/dma/ipu/ipu_idmac.c b/trunk/drivers/dma/ipu/ipu_idmac.c index c1a125e7d1df..cb26ee9773d6 100644 --- a/trunk/drivers/dma/ipu/ipu_idmac.c +++ b/trunk/drivers/dma/ipu/ipu_idmac.c @@ -1145,6 +1145,29 @@ static int ipu_disable_channel(struct idmac *idmac, struct idmac_channel *ichan, reg = idmac_read_icreg(ipu, IDMAC_CHA_EN); idmac_write_icreg(ipu, reg & ~chan_mask, IDMAC_CHA_EN); + /* + * Problem (observed with channel DMAIC_7): after enabling the channel + * and initialising buffers, there comes an interrupt with current still + * pointing at buffer 0, whereas it should use buffer 0 first and only + * generate an interrupt when it is done, then current should already + * point to buffer 1. This spurious interrupt also comes on channel + * DMASDC_0. With DMAIC_7 normally, is we just leave the ISR after the + * first interrupt, there comes the second with current correctly + * pointing to buffer 1 this time. But sometimes this second interrupt + * doesn't come and the channel hangs. Clearing BUFx_RDY when disabling + * the channel seems to prevent the channel from hanging, but it doesn't + * prevent the spurious interrupt. This might also be unsafe. Think + * about the IDMAC controller trying to switch to a buffer, when we + * clear the ready bit, and re-enable it a moment later. + */ + reg = idmac_read_ipureg(ipu, IPU_CHA_BUF0_RDY); + idmac_write_ipureg(ipu, 0, IPU_CHA_BUF0_RDY); + idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF0_RDY); + + reg = idmac_read_ipureg(ipu, IPU_CHA_BUF1_RDY); + idmac_write_ipureg(ipu, 0, IPU_CHA_BUF1_RDY); + idmac_write_ipureg(ipu, reg & ~(1UL << channel), IPU_CHA_BUF1_RDY); + spin_unlock_irqrestore(&ipu->lock, flags); return 0; @@ -1223,6 +1246,33 @@ static irqreturn_t idmac_interrupt(int irq, void *dev_id) /* Other interrupts do not interfere with this channel */ spin_lock(&ichan->lock); + if (unlikely(chan_id != IDMAC_SDC_0 && chan_id != IDMAC_SDC_1 && + ((curbuf >> chan_id) & 1) == ichan->active_buffer && + !list_is_last(ichan->queue.next, &ichan->queue))) { + int i = 100; + + /* This doesn't help. See comment in ipu_disable_channel() */ + while (--i) { + curbuf = idmac_read_ipureg(&ipu_data, IPU_CHA_CUR_BUF); + if (((curbuf >> chan_id) & 1) != ichan->active_buffer) + break; + cpu_relax(); + } + + if (!i) { + spin_unlock(&ichan->lock); + dev_dbg(dev, + "IRQ on active buffer on channel %x, active " + "%d, ready %x, %x, current %x!\n", chan_id, + ichan->active_buffer, ready0, ready1, curbuf); + return IRQ_NONE; + } else + dev_dbg(dev, + "Buffer deactivated on channel %x, active " + "%d, ready %x, %x, current %x, rest %d!\n", chan_id, + ichan->active_buffer, ready0, ready1, curbuf, i); + } + if (unlikely((ichan->active_buffer && (ready1 >> chan_id) & 1) || (!ichan->active_buffer && (ready0 >> chan_id) & 1) )) { diff --git a/trunk/drivers/firmware/dmi_scan.c b/trunk/drivers/firmware/dmi_scan.c index bcb1126e3d00..e28e41668177 100644 --- a/trunk/drivers/firmware/dmi_scan.c +++ b/trunk/drivers/firmware/dmi_scan.c @@ -378,17 +378,10 @@ static void __init print_filtered(const char *info) static void __init dmi_dump_ids(void) { - const char *board; /* Board Name is optional */ - printk(KERN_DEBUG "DMI: "); - print_filtered(dmi_get_system_info(DMI_SYS_VENDOR)); - printk(KERN_CONT " "); + print_filtered(dmi_get_system_info(DMI_BOARD_NAME)); + printk(KERN_CONT "/"); print_filtered(dmi_get_system_info(DMI_PRODUCT_NAME)); - board = dmi_get_system_info(DMI_BOARD_NAME); - if (board) { - printk(KERN_CONT "/"); - print_filtered(board); - } printk(KERN_CONT ", BIOS "); print_filtered(dmi_get_system_info(DMI_BIOS_VERSION)); printk(KERN_CONT " "); diff --git a/trunk/drivers/input/input.c b/trunk/drivers/input/input.c index 11905b6a3023..7985114beac7 100644 --- a/trunk/drivers/input/input.c +++ b/trunk/drivers/input/input.c @@ -75,6 +75,7 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) * dev->event_lock held and interrupts disabled. */ static void input_pass_event(struct input_dev *dev, + struct input_handler *src_handler, unsigned int type, unsigned int code, int value) { struct input_handler *handler; @@ -93,6 +94,15 @@ static void input_pass_event(struct input_dev *dev, continue; handler = handle->handler; + + /* + * If this is the handler that injected this + * particular event we want to skip it to avoid + * filters firing again and again. + */ + if (handler == src_handler) + continue; + if (!handler->filter) { if (filtered) break; @@ -122,7 +132,7 @@ static void input_repeat_key(unsigned long data) if (test_bit(dev->repeat_key, dev->key) && is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { - input_pass_event(dev, EV_KEY, dev->repeat_key, 2); + input_pass_event(dev, NULL, EV_KEY, dev->repeat_key, 2); if (dev->sync) { /* @@ -131,7 +141,7 @@ static void input_repeat_key(unsigned long data) * Otherwise assume that the driver will send * SYN_REPORT once it's done. */ - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); } if (dev->rep[REP_PERIOD]) @@ -164,6 +174,7 @@ static void input_stop_autorepeat(struct input_dev *dev) #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) static int input_handle_abs_event(struct input_dev *dev, + struct input_handler *src_handler, unsigned int code, int *pval) { bool is_mt_event; @@ -207,13 +218,15 @@ static int input_handle_abs_event(struct input_dev *dev, /* Flush pending "slot" event */ if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); - input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); + input_pass_event(dev, src_handler, + EV_ABS, ABS_MT_SLOT, dev->slot); } return INPUT_PASS_TO_HANDLERS; } static void input_handle_event(struct input_dev *dev, + struct input_handler *src_handler, unsigned int type, unsigned int code, int value) { int disposition = INPUT_IGNORE_EVENT; @@ -266,7 +279,8 @@ static void input_handle_event(struct input_dev *dev, case EV_ABS: if (is_event_supported(code, dev->absbit, ABS_MAX)) - disposition = input_handle_abs_event(dev, code, &value); + disposition = input_handle_abs_event(dev, src_handler, + code, &value); break; @@ -324,7 +338,7 @@ static void input_handle_event(struct input_dev *dev, dev->event(dev, type, code, value); if (disposition & INPUT_PASS_TO_HANDLERS) - input_pass_event(dev, type, code, value); + input_pass_event(dev, src_handler, type, code, value); } /** @@ -353,7 +367,7 @@ void input_event(struct input_dev *dev, spin_lock_irqsave(&dev->event_lock, flags); add_input_randomness(type, code, value); - input_handle_event(dev, type, code, value); + input_handle_event(dev, NULL, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); } } @@ -383,7 +397,8 @@ void input_inject_event(struct input_handle *handle, rcu_read_lock(); grab = rcu_dereference(dev->grab); if (!grab || grab == handle) - input_handle_event(dev, type, code, value); + input_handle_event(dev, handle->handler, + type, code, value); rcu_read_unlock(); spin_unlock_irqrestore(&dev->event_lock, flags); @@ -596,10 +611,10 @@ static void input_dev_release_keys(struct input_dev *dev) for (code = 0; code <= KEY_MAX; code++) { if (is_event_supported(code, dev->keybit, KEY_MAX) && __test_and_clear_bit(code, dev->key)) { - input_pass_event(dev, EV_KEY, code, 0); + input_pass_event(dev, NULL, EV_KEY, code, 0); } } - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); } } @@ -874,9 +889,9 @@ int input_set_keycode(struct input_dev *dev, !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && __test_and_clear_bit(old_keycode, dev->key)) { - input_pass_event(dev, EV_KEY, old_keycode, 0); + input_pass_event(dev, NULL, EV_KEY, old_keycode, 0); if (dev->sync) - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + input_pass_event(dev, NULL, EV_SYN, SYN_REPORT, 1); } out: diff --git a/trunk/drivers/input/misc/rotary_encoder.c b/trunk/drivers/input/misc/rotary_encoder.c index 7e64d01da2be..1f8e0108962e 100644 --- a/trunk/drivers/input/misc/rotary_encoder.c +++ b/trunk/drivers/input/misc/rotary_encoder.c @@ -176,7 +176,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) /* request the IRQs */ err = request_irq(encoder->irq_a, &rotary_encoder_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, DRV_NAME, encoder); if (err) { dev_err(&pdev->dev, "unable to request IRQ %d\n", @@ -185,7 +185,7 @@ static int __devinit rotary_encoder_probe(struct platform_device *pdev) } err = request_irq(encoder->irq_b, &rotary_encoder_irq, - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_LOWEDGE, DRV_NAME, encoder); if (err) { dev_err(&pdev->dev, "unable to request IRQ %d\n", diff --git a/trunk/drivers/input/serio/serio.c b/trunk/drivers/input/serio/serio.c index 7c38d1fbabf2..db5b0bca1a1a 100644 --- a/trunk/drivers/input/serio/serio.c +++ b/trunk/drivers/input/serio/serio.c @@ -188,8 +188,7 @@ static void serio_free_event(struct serio_event *event) kfree(event); } -static void serio_remove_duplicate_events(void *object, - enum serio_event_type type) +static void serio_remove_duplicate_events(struct serio_event *event) { struct serio_event *e, *next; unsigned long flags; @@ -197,13 +196,13 @@ static void serio_remove_duplicate_events(void *object, spin_lock_irqsave(&serio_event_lock, flags); list_for_each_entry_safe(e, next, &serio_event_list, node) { - if (object == e->object) { + if (event->object == e->object) { /* * If this event is of different type we should not * look further - we only suppress duplicate events * that were sent back-to-back. */ - if (type != e->type) + if (event->type != e->type) break; list_del_init(&e->node); @@ -246,7 +245,7 @@ static void serio_handle_event(struct work_struct *work) break; } - serio_remove_duplicate_events(event->object, event->type); + serio_remove_duplicate_events(event); serio_free_event(event); } @@ -437,12 +436,10 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute * } else if (!strncmp(buf, "rescan", count)) { serio_disconnect_port(serio); serio_find_driver(serio); - serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); } else if ((drv = driver_find(buf, &serio_bus)) != NULL) { serio_disconnect_port(serio); error = serio_bind_driver(serio, to_serio_driver(drv)); put_driver(drv); - serio_remove_duplicate_events(serio, SERIO_RESCAN_PORT); } else { error = -EINVAL; } diff --git a/trunk/drivers/input/tablet/wacom_sys.c b/trunk/drivers/input/tablet/wacom_sys.c index cf8fb9f5d4a8..fc381498b798 100644 --- a/trunk/drivers/input/tablet/wacom_sys.c +++ b/trunk/drivers/input/tablet/wacom_sys.c @@ -519,7 +519,7 @@ static int wacom_probe(struct usb_interface *intf, const struct usb_device_id *i /* Retrieve the physical and logical size for OEM devices */ error = wacom_retrieve_hid_descriptor(intf, features); if (error) - goto fail3; + goto fail2; wacom_setup_device_quirks(features); diff --git a/trunk/drivers/input/touchscreen/ads7846.c b/trunk/drivers/input/touchscreen/ads7846.c index 4bf2316e3284..14ea54b78e46 100644 --- a/trunk/drivers/input/touchscreen/ads7846.c +++ b/trunk/drivers/input/touchscreen/ads7846.c @@ -941,30 +941,29 @@ static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads784 struct ads7846_platform_data *pdata = spi->dev.platform_data; int err; - /* - * REVISIT when the irq can be triggered active-low, or if for some + /* REVISIT when the irq can be triggered active-low, or if for some * reason the touchscreen isn't hooked up, we don't need to access * the pendown state. */ + if (!pdata->get_pendown_state && !gpio_is_valid(pdata->gpio_pendown)) { + dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); + return -EINVAL; + } if (pdata->get_pendown_state) { ts->get_pendown_state = pdata->get_pendown_state; - } else if (gpio_is_valid(pdata->gpio_pendown)) { - - err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); - if (err) { - dev_err(&spi->dev, "failed to request pendown GPIO%d\n", - pdata->gpio_pendown); - return err; - } - - ts->gpio_pendown = pdata->gpio_pendown; + return 0; + } - } else { - dev_err(&spi->dev, "no get_pendown_state nor gpio_pendown?\n"); - return -EINVAL; + err = gpio_request(pdata->gpio_pendown, "ads7846_pendown"); + if (err) { + dev_err(&spi->dev, "failed to request pendown GPIO%d\n", + pdata->gpio_pendown); + return err; } + ts->gpio_pendown = pdata->gpio_pendown; + return 0; } @@ -1354,7 +1353,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) err_put_regulator: regulator_put(ts->reg); err_free_gpio: - if (!ts->get_pendown_state) + if (ts->gpio_pendown != -1) gpio_free(ts->gpio_pendown); err_cleanup_filter: if (ts->filter_cleanup) @@ -1384,13 +1383,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) regulator_disable(ts->reg); regulator_put(ts->reg); - if (!ts->get_pendown_state) { - /* - * If we are not using specialized pendown method we must - * have been relying on gpio we set up ourselves. - */ + if (ts->gpio_pendown != -1) gpio_free(ts->gpio_pendown); - } if (ts->filter_cleanup) ts->filter_cleanup(ts->filter_data); diff --git a/trunk/drivers/input/touchscreen/wacom_w8001.c b/trunk/drivers/input/touchscreen/wacom_w8001.c index c14412ef4648..5cb8449c909d 100644 --- a/trunk/drivers/input/touchscreen/wacom_w8001.c +++ b/trunk/drivers/input/touchscreen/wacom_w8001.c @@ -51,10 +51,6 @@ MODULE_LICENSE("GPL"); #define W8001_PKTLEN_TPCCTL 11 /* control packet */ #define W8001_PKTLEN_TOUCH2FG 13 -/* resolution in points/mm */ -#define W8001_PEN_RESOLUTION 100 -#define W8001_TOUCH_RESOLUTION 10 - struct w8001_coord { u8 rdy; u8 tsw; @@ -202,7 +198,7 @@ static void parse_touchquery(u8 *data, struct w8001_touch_query *query) query->y = 1024; if (query->panel_res) query->x = query->y = (1 << query->panel_res); - query->panel_res = W8001_TOUCH_RESOLUTION; + query->panel_res = 10; } } @@ -398,8 +394,6 @@ static int w8001_setup(struct w8001 *w8001) input_set_abs_params(dev, ABS_X, 0, coord.x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, coord.y, 0, 0); - input_abs_set_res(dev, ABS_X, W8001_PEN_RESOLUTION); - input_abs_set_res(dev, ABS_Y, W8001_PEN_RESOLUTION); input_set_abs_params(dev, ABS_PRESSURE, 0, coord.pen_pressure, 0, 0); if (coord.tilt_x && coord.tilt_y) { input_set_abs_params(dev, ABS_TILT_X, 0, coord.tilt_x, 0, 0); @@ -424,17 +418,14 @@ static int w8001_setup(struct w8001 *w8001) w8001->max_touch_x = touch.x; w8001->max_touch_y = touch.y; + /* scale to pen maximum */ if (w8001->max_pen_x && w8001->max_pen_y) { - /* if pen is supported scale to pen maximum */ touch.x = w8001->max_pen_x; touch.y = w8001->max_pen_y; - touch.panel_res = W8001_PEN_RESOLUTION; } input_set_abs_params(dev, ABS_X, 0, touch.x, 0, 0); input_set_abs_params(dev, ABS_Y, 0, touch.y, 0, 0); - input_abs_set_res(dev, ABS_X, touch.panel_res); - input_abs_set_res(dev, ABS_Y, touch.panel_res); switch (touch.sensor_id) { case 0: diff --git a/trunk/drivers/pci/pci-sysfs.c b/trunk/drivers/pci/pci-sysfs.c index 8ecaac983923..ea25e5bfcf23 100644 --- a/trunk/drivers/pci/pci-sysfs.c +++ b/trunk/drivers/pci/pci-sysfs.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include "pci.h" @@ -368,7 +369,7 @@ pci_read_config(struct file *filp, struct kobject *kobj, u8 *data = (u8*) buf; /* Several chips lock up trying to read undefined config space */ - if (cap_raised(filp->f_cred->cap_effective, CAP_SYS_ADMIN)) { + if (security_capable(filp->f_cred, CAP_SYS_ADMIN) == 0) { size = dev->cfg_size; } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { size = 128; diff --git a/trunk/drivers/rtc/rtc-at32ap700x.c b/trunk/drivers/rtc/rtc-at32ap700x.c index e725d51e773d..b2752b6e7a2f 100644 --- a/trunk/drivers/rtc/rtc-at32ap700x.c +++ b/trunk/drivers/rtc/rtc-at32ap700x.c @@ -134,29 +134,36 @@ static int at32_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) return ret; } -static int at32_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +static int at32_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) { struct rtc_at32ap700x *rtc = dev_get_drvdata(dev); int ret = 0; spin_lock_irq(&rtc->lock); - if(enabled) { + switch (cmd) { + case RTC_AIE_ON: if (rtc_readl(rtc, VAL) > rtc->alarm_time) { ret = -EINVAL; - goto out; + break; } rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) | RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); rtc_writel(rtc, IER, RTC_BIT(IER_TOPI)); - } else { + break; + case RTC_AIE_OFF: rtc_writel(rtc, CTRL, rtc_readl(rtc, CTRL) & ~RTC_BIT(CTRL_TOPEN)); rtc_writel(rtc, IDR, RTC_BIT(IDR_TOPI)); rtc_writel(rtc, ICR, RTC_BIT(ICR_TOPI)); + break; + default: + ret = -ENOIOCTLCMD; + break; } -out: + spin_unlock_irq(&rtc->lock); return ret; @@ -188,11 +195,11 @@ static irqreturn_t at32_rtc_interrupt(int irq, void *dev_id) } static struct rtc_class_ops at32_rtc_ops = { + .ioctl = at32_rtc_ioctl, .read_time = at32_rtc_readtime, .set_time = at32_rtc_settime, .read_alarm = at32_rtc_readalarm, .set_alarm = at32_rtc_setalarm, - .alarm_irq_enable = at32_rtc_alarm_irq_enable, }; static int __init at32_rtc_probe(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-at91rm9200.c b/trunk/drivers/rtc/rtc-at91rm9200.c index 26d1cf5d19ae..bc8bbca9a2e2 100644 --- a/trunk/drivers/rtc/rtc-at91rm9200.c +++ b/trunk/drivers/rtc/rtc-at91rm9200.c @@ -195,6 +195,13 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, /* important: scrub old status before enabling IRQs */ switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ + at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); + break; + case RTC_AIE_ON: /* alarm on */ + at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); + at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); + break; case RTC_UIE_OFF: /* update off */ at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV); break; @@ -210,18 +217,6 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, return ret; } -static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - pr_debug("%s(): cmd=%08x\n", __func__, enabled); - - if (enabled) { - at91_sys_write(AT91_RTC_SCCR, AT91_RTC_ALARM); - at91_sys_write(AT91_RTC_IER, AT91_RTC_ALARM); - } else - at91_sys_write(AT91_RTC_IDR, AT91_RTC_ALARM); - - return 0; -} /* * Provide additional RTC information in /proc/driver/rtc */ @@ -275,7 +270,6 @@ static const struct rtc_class_ops at91_rtc_ops = { .read_alarm = at91_rtc_readalarm, .set_alarm = at91_rtc_setalarm, .proc = at91_rtc_proc, - .alarm_irq_enable = at91_rtc_alarm_irq_enable, }; /* diff --git a/trunk/drivers/rtc/rtc-at91sam9.c b/trunk/drivers/rtc/rtc-at91sam9.c index c36749e4c926..f677e0710ca1 100644 --- a/trunk/drivers/rtc/rtc-at91sam9.c +++ b/trunk/drivers/rtc/rtc-at91sam9.c @@ -229,6 +229,12 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr); switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ + rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); + break; + case RTC_AIE_ON: /* alarm on */ + rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); + break; case RTC_UIE_OFF: /* update off */ rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN); break; @@ -243,19 +249,6 @@ static int at91_rtc_ioctl(struct device *dev, unsigned int cmd, return ret; } -static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct sam9_rtc *rtc = dev_get_drvdata(dev); - u32 mr = rtt_readl(rtc, MR); - - dev_dbg(dev, "alarm_irq_enable: enabled=%08x, mr %08x\n", enabled, mr); - if (enabled) - rtt_writel(rtc, MR, mr | AT91_RTT_ALMIEN); - else - rtt_writel(rtc, MR, mr & ~AT91_RTT_ALMIEN); - return 0; -} - /* * Provide additional RTC information in /proc/driver/rtc */ @@ -309,7 +302,6 @@ static const struct rtc_class_ops at91_rtc_ops = { .read_alarm = at91_rtc_readalarm, .set_alarm = at91_rtc_setalarm, .proc = at91_rtc_proc, - .alarm_irq_enabled = at91_rtc_alarm_irq_enable, }; /* diff --git a/trunk/drivers/rtc/rtc-bfin.c b/trunk/drivers/rtc/rtc-bfin.c index 17971d93354d..b4b6087f2234 100644 --- a/trunk/drivers/rtc/rtc-bfin.c +++ b/trunk/drivers/rtc/rtc-bfin.c @@ -259,6 +259,15 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar bfin_rtc_int_clear(~RTC_ISTAT_SEC); break; + case RTC_AIE_ON: + dev_dbg_stamp(dev); + bfin_rtc_int_set_alarm(rtc); + break; + case RTC_AIE_OFF: + dev_dbg_stamp(dev); + bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); + break; + default: dev_dbg_stamp(dev); ret = -ENOIOCTLCMD; @@ -267,17 +276,6 @@ static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long ar return ret; } -static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct bfin_rtc *rtc = dev_get_drvdata(dev); - - dev_dbg_stamp(dev); - if (enabled) - bfin_rtc_int_set_alarm(rtc); - else - bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY)); -} - static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct bfin_rtc *rtc = dev_get_drvdata(dev); @@ -364,7 +362,6 @@ static struct rtc_class_ops bfin_rtc_ops = { .read_alarm = bfin_rtc_read_alarm, .set_alarm = bfin_rtc_set_alarm, .proc = bfin_rtc_proc, - .alarm_irq_enable = bfin_rtc_alarm_irq_enable, }; static int __devinit bfin_rtc_probe(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-dev.c b/trunk/drivers/rtc/rtc-dev.c index 37c3cc1b3dd5..212b16edafc0 100644 --- a/trunk/drivers/rtc/rtc-dev.c +++ b/trunk/drivers/rtc/rtc-dev.c @@ -154,7 +154,19 @@ static long rtc_dev_ioctl(struct file *file, if (err) goto done; - /* + /* try the driver's ioctl interface */ + if (ops->ioctl) { + err = ops->ioctl(rtc->dev.parent, cmd, arg); + if (err != -ENOIOCTLCMD) { + mutex_unlock(&rtc->ops_lock); + return err; + } + } + + /* if the driver does not provide the ioctl interface + * or if that particular ioctl was not implemented + * (-ENOIOCTLCMD), we will try to emulate here. + * * Drivers *SHOULD NOT* provide ioctl implementations * for these requests. Instead, provide methods to * support the following code, so that the RTC's main @@ -317,12 +329,7 @@ static long rtc_dev_ioctl(struct file *file, return err; default: - /* Finally try the driver's ioctl interface */ - if (ops->ioctl) { - err = ops->ioctl(rtc->dev.parent, cmd, arg); - if (err == -ENOIOCTLCMD) - err = -ENOTTY; - } + err = -ENOTTY; break; } diff --git a/trunk/drivers/rtc/rtc-ds1286.c b/trunk/drivers/rtc/rtc-ds1286.c index 60ce69600828..bf430f9091ed 100644 --- a/trunk/drivers/rtc/rtc-ds1286.c +++ b/trunk/drivers/rtc/rtc-ds1286.c @@ -40,26 +40,6 @@ static inline void ds1286_rtc_write(struct ds1286_priv *priv, u8 data, int reg) __raw_writel(data, &priv->rtcregs[reg]); } - -static int ds1286_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct ds1286_priv *priv = dev_get_drvdata(dev); - unsigned long flags; - unsigned char val; - - /* Allow or mask alarm interrupts */ - spin_lock_irqsave(&priv->lock, flags); - val = ds1286_rtc_read(priv, RTC_CMD); - if (enabled) - val &= ~RTC_TDM; - else - val |= RTC_TDM; - ds1286_rtc_write(priv, val, RTC_CMD); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - #ifdef CONFIG_RTC_INTF_DEV static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) @@ -69,6 +49,22 @@ static int ds1286_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) unsigned char val; switch (cmd) { + case RTC_AIE_OFF: + /* Mask alarm int. enab. bit */ + spin_lock_irqsave(&priv->lock, flags); + val = ds1286_rtc_read(priv, RTC_CMD); + val |= RTC_TDM; + ds1286_rtc_write(priv, val, RTC_CMD); + spin_unlock_irqrestore(&priv->lock, flags); + break; + case RTC_AIE_ON: + /* Allow alarm interrupts. */ + spin_lock_irqsave(&priv->lock, flags); + val = ds1286_rtc_read(priv, RTC_CMD); + val &= ~RTC_TDM; + ds1286_rtc_write(priv, val, RTC_CMD); + spin_unlock_irqrestore(&priv->lock, flags); + break; case RTC_WIE_OFF: /* Mask watchdog int. enab. bit */ spin_lock_irqsave(&priv->lock, flags); @@ -320,13 +316,12 @@ static int ds1286_set_alarm(struct device *dev, struct rtc_wkalrm *alm) } static const struct rtc_class_ops ds1286_ops = { - .ioctl = ds1286_ioctl, - .proc = ds1286_proc, + .ioctl = ds1286_ioctl, + .proc = ds1286_proc, .read_time = ds1286_read_time, .set_time = ds1286_set_time, .read_alarm = ds1286_read_alarm, .set_alarm = ds1286_set_alarm, - .alarm_irq_enable = ds1286_alarm_irq_enable, }; static int __devinit ds1286_probe(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-ds1305.c b/trunk/drivers/rtc/rtc-ds1305.c index 57fbcc149ba7..077af1d7b9e4 100644 --- a/trunk/drivers/rtc/rtc-ds1305.c +++ b/trunk/drivers/rtc/rtc-ds1305.c @@ -139,32 +139,49 @@ static u8 hour2bcd(bool hr12, int hour) * Interface to RTC framework */ -static int ds1305_alarm_irq_enable(struct device *dev, unsigned int enabled) +#ifdef CONFIG_RTC_INTF_DEV + +/* + * Context: caller holds rtc->ops_lock (to protect ds1305->ctrl) + */ +static int ds1305_ioctl(struct device *dev, unsigned cmd, unsigned long arg) { struct ds1305 *ds1305 = dev_get_drvdata(dev); u8 buf[2]; - long err = -EINVAL; + int status = -ENOIOCTLCMD; buf[0] = DS1305_WRITE | DS1305_CONTROL; buf[1] = ds1305->ctrl[0]; - if (enabled) { - if (ds1305->ctrl[0] & DS1305_AEI0) - goto done; - buf[1] |= DS1305_AEI0; - } else { + switch (cmd) { + case RTC_AIE_OFF: + status = 0; if (!(buf[1] & DS1305_AEI0)) goto done; buf[1] &= ~DS1305_AEI0; + break; + + case RTC_AIE_ON: + status = 0; + if (ds1305->ctrl[0] & DS1305_AEI0) + goto done; + buf[1] |= DS1305_AEI0; + break; + } + if (status == 0) { + status = spi_write_then_read(ds1305->spi, buf, sizeof buf, + NULL, 0); + if (status >= 0) + ds1305->ctrl[0] = buf[1]; } - err = spi_write_then_read(ds1305->spi, buf, sizeof buf, NULL, 0); - if (err >= 0) - ds1305->ctrl[0] = buf[1]; -done: - return err; +done: + return status; } +#else +#define ds1305_ioctl NULL +#endif /* * Get/set of date and time is pretty normal. @@ -443,12 +460,12 @@ static int ds1305_proc(struct device *dev, struct seq_file *seq) #endif static const struct rtc_class_ops ds1305_ops = { + .ioctl = ds1305_ioctl, .read_time = ds1305_get_time, .set_time = ds1305_set_time, .read_alarm = ds1305_get_alarm, .set_alarm = ds1305_set_alarm, .proc = ds1305_proc, - .alarm_irq_enable = ds1305_alarm_irq_enable, }; static void ds1305_work(struct work_struct *work) diff --git a/trunk/drivers/rtc/rtc-ds1307.c b/trunk/drivers/rtc/rtc-ds1307.c index 4724ba3acf1a..0d559b6416dd 100644 --- a/trunk/drivers/rtc/rtc-ds1307.c +++ b/trunk/drivers/rtc/rtc-ds1307.c @@ -495,27 +495,50 @@ static int ds1337_set_alarm(struct device *dev, struct rtc_wkalrm *t) return 0; } -static int ds1307_alarm_irq_enable(struct device *dev, unsigned int enabled) +static int ds1307_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct i2c_client *client = to_i2c_client(dev); struct ds1307 *ds1307 = i2c_get_clientdata(client); int ret; - if (!test_bit(HAS_ALARM, &ds1307->flags)) - return -ENOTTY; + switch (cmd) { + case RTC_AIE_OFF: + if (!test_bit(HAS_ALARM, &ds1307->flags)) + return -ENOTTY; - ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); - if (ret < 0) - return ret; + ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); + if (ret < 0) + return ret; - if (enabled) - ret |= DS1337_BIT_A1IE; - else ret &= ~DS1337_BIT_A1IE; - ret = i2c_smbus_write_byte_data(client, DS1337_REG_CONTROL, ret); - if (ret < 0) - return ret; + ret = i2c_smbus_write_byte_data(client, + DS1337_REG_CONTROL, ret); + if (ret < 0) + return ret; + + break; + + case RTC_AIE_ON: + if (!test_bit(HAS_ALARM, &ds1307->flags)) + return -ENOTTY; + + ret = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL); + if (ret < 0) + return ret; + + ret |= DS1337_BIT_A1IE; + + ret = i2c_smbus_write_byte_data(client, + DS1337_REG_CONTROL, ret); + if (ret < 0) + return ret; + + break; + + default: + return -ENOIOCTLCMD; + } return 0; } @@ -525,7 +548,7 @@ static const struct rtc_class_ops ds13xx_rtc_ops = { .set_time = ds1307_set_time, .read_alarm = ds1337_read_alarm, .set_alarm = ds1337_set_alarm, - .alarm_irq_enable = ds1307_alarm_irq_enable, + .ioctl = ds1307_ioctl, }; /*----------------------------------------------------------------------*/ diff --git a/trunk/drivers/rtc/rtc-ds1374.c b/trunk/drivers/rtc/rtc-ds1374.c index d834a63ec4b0..47fb6357c346 100644 --- a/trunk/drivers/rtc/rtc-ds1374.c +++ b/trunk/drivers/rtc/rtc-ds1374.c @@ -307,25 +307,42 @@ static void ds1374_work(struct work_struct *work) mutex_unlock(&ds1374->mutex); } -static int ds1374_alarm_irq_enable(struct device *dev, unsigned int enabled) +static int ds1374_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct i2c_client *client = to_i2c_client(dev); struct ds1374 *ds1374 = i2c_get_clientdata(client); - int ret; + int ret = -ENOIOCTLCMD; mutex_lock(&ds1374->mutex); - ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); - if (ret < 0) - goto out; + switch (cmd) { + case RTC_AIE_OFF: + ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); + if (ret < 0) + goto out; + + ret &= ~DS1374_REG_CR_WACE; + + ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); + if (ret < 0) + goto out; + + break; + + case RTC_AIE_ON: + ret = i2c_smbus_read_byte_data(client, DS1374_REG_CR); + if (ret < 0) + goto out; - if (enabled) { ret |= DS1374_REG_CR_WACE | DS1374_REG_CR_AIE; ret &= ~DS1374_REG_CR_WDALM; - } else { - ret &= ~DS1374_REG_CR_WACE; + + ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); + if (ret < 0) + goto out; + + break; } - ret = i2c_smbus_write_byte_data(client, DS1374_REG_CR, ret); out: mutex_unlock(&ds1374->mutex); @@ -337,7 +354,7 @@ static const struct rtc_class_ops ds1374_rtc_ops = { .set_time = ds1374_set_time, .read_alarm = ds1374_read_alarm, .set_alarm = ds1374_set_alarm, - .alarm_irq_enable = ds1374_alarm_irq_enable, + .ioctl = ds1374_ioctl, }; static int ds1374_probe(struct i2c_client *client, diff --git a/trunk/drivers/rtc/rtc-m41t80.c b/trunk/drivers/rtc/rtc-m41t80.c index 69fe664a2228..5a8daa358066 100644 --- a/trunk/drivers/rtc/rtc-m41t80.c +++ b/trunk/drivers/rtc/rtc-m41t80.c @@ -213,27 +213,41 @@ static int m41t80_rtc_set_time(struct device *dev, struct rtc_time *tm) return m41t80_set_datetime(to_i2c_client(dev), tm); } -static int m41t80_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) +static int +m41t80_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct i2c_client *client = to_i2c_client(dev); int rc; + switch (cmd) { + case RTC_AIE_OFF: + case RTC_AIE_ON: + break; + default: + return -ENOIOCTLCMD; + } + rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_MON); if (rc < 0) goto err; - - if (enabled) - rc |= M41T80_ALMON_AFE; - else + switch (cmd) { + case RTC_AIE_OFF: rc &= ~M41T80_ALMON_AFE; - + break; + case RTC_AIE_ON: + rc |= M41T80_ALMON_AFE; + break; + } if (i2c_smbus_write_byte_data(client, M41T80_REG_ALARM_MON, rc) < 0) goto err; - return 0; err: return -EIO; } +#else +#define m41t80_rtc_ioctl NULL +#endif static int m41t80_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t) { @@ -360,7 +374,7 @@ static struct rtc_class_ops m41t80_rtc_ops = { .read_alarm = m41t80_rtc_read_alarm, .set_alarm = m41t80_rtc_set_alarm, .proc = m41t80_rtc_proc, - .alarm_irq_enable = m41t80_rtc_alarm_irq_enable, + .ioctl = m41t80_rtc_ioctl, }; #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) diff --git a/trunk/drivers/rtc/rtc-m48t59.c b/trunk/drivers/rtc/rtc-m48t59.c index 3978f4caf724..a99a0b554eb8 100644 --- a/trunk/drivers/rtc/rtc-m48t59.c +++ b/trunk/drivers/rtc/rtc-m48t59.c @@ -263,21 +263,30 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) /* * Handle commands from user-space */ -static int m48t59_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +static int m48t59_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) { struct platform_device *pdev = to_platform_device(dev); struct m48t59_plat_data *pdata = pdev->dev.platform_data; struct m48t59_private *m48t59 = platform_get_drvdata(pdev); unsigned long flags; + int ret = 0; spin_lock_irqsave(&m48t59->lock, flags); - if (enabled) - M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); - else + switch (cmd) { + case RTC_AIE_OFF: /* alarm interrupt off */ M48T59_WRITE(0x00, M48T59_INTR); + break; + case RTC_AIE_ON: /* alarm interrupt on */ + M48T59_WRITE(M48T59_INTR_AFE, M48T59_INTR); + break; + default: + ret = -ENOIOCTLCMD; + break; + } spin_unlock_irqrestore(&m48t59->lock, flags); - return 0; + return ret; } static int m48t59_rtc_proc(struct device *dev, struct seq_file *seq) @@ -321,12 +330,12 @@ static irqreturn_t m48t59_rtc_interrupt(int irq, void *dev_id) } static const struct rtc_class_ops m48t59_rtc_ops = { + .ioctl = m48t59_rtc_ioctl, .read_time = m48t59_rtc_read_time, .set_time = m48t59_rtc_set_time, .read_alarm = m48t59_rtc_readalarm, .set_alarm = m48t59_rtc_setalarm, .proc = m48t59_rtc_proc, - .alarm_irq_enable = m48t59_rtc_alarm_irq_enable, }; static const struct rtc_class_ops m48t02_rtc_ops = { diff --git a/trunk/drivers/rtc/rtc-mrst.c b/trunk/drivers/rtc/rtc-mrst.c index 1db62db8469d..bcd0cf63eb16 100644 --- a/trunk/drivers/rtc/rtc-mrst.c +++ b/trunk/drivers/rtc/rtc-mrst.c @@ -255,21 +255,42 @@ static int mrst_irq_set_state(struct device *dev, int enabled) return 0; } +#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE) + /* Currently, the vRTC doesn't support UIE ON/OFF */ -static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +static int +mrst_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct mrst_rtc *mrst = dev_get_drvdata(dev); unsigned long flags; + switch (cmd) { + case RTC_AIE_OFF: + case RTC_AIE_ON: + if (!mrst->irq) + return -EINVAL; + break; + default: + /* PIE ON/OFF is handled by mrst_irq_set_state() */ + return -ENOIOCTLCMD; + } + spin_lock_irqsave(&rtc_lock, flags); - if (enabled) - mrst_irq_enable(mrst, RTC_AIE); - else + switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ mrst_irq_disable(mrst, RTC_AIE); + break; + case RTC_AIE_ON: /* alarm on */ + mrst_irq_enable(mrst, RTC_AIE); + break; + } spin_unlock_irqrestore(&rtc_lock, flags); return 0; } +#else +#define mrst_rtc_ioctl NULL +#endif #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE) @@ -296,13 +317,13 @@ static int mrst_procfs(struct device *dev, struct seq_file *seq) #endif static const struct rtc_class_ops mrst_rtc_ops = { + .ioctl = mrst_rtc_ioctl, .read_time = mrst_read_time, .set_time = mrst_set_time, .read_alarm = mrst_read_alarm, .set_alarm = mrst_set_alarm, .proc = mrst_procfs, .irq_set_state = mrst_irq_set_state, - .alarm_irq_enable = mrst_rtc_alarm_irq_enable, }; static struct mrst_rtc mrst_rtc; diff --git a/trunk/drivers/rtc/rtc-msm6242.c b/trunk/drivers/rtc/rtc-msm6242.c index 67820626e18f..b2fff0ca49f8 100644 --- a/trunk/drivers/rtc/rtc-msm6242.c +++ b/trunk/drivers/rtc/rtc-msm6242.c @@ -82,7 +82,7 @@ static inline unsigned int msm6242_read(struct msm6242_priv *priv, static inline void msm6242_write(struct msm6242_priv *priv, unsigned int val, unsigned int reg) { - __raw_writel(val, &priv->regs[reg]); + return __raw_writel(val, &priv->regs[reg]); } static inline void msm6242_set(struct msm6242_priv *priv, unsigned int val, diff --git a/trunk/drivers/rtc/rtc-mv.c b/trunk/drivers/rtc/rtc-mv.c index 60627a764514..bcca47298554 100644 --- a/trunk/drivers/rtc/rtc-mv.c +++ b/trunk/drivers/rtc/rtc-mv.c @@ -169,19 +169,25 @@ static int mv_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) return 0; } -static int mv_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) +static int mv_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) { struct platform_device *pdev = to_platform_device(dev); struct rtc_plat_data *pdata = platform_get_drvdata(pdev); void __iomem *ioaddr = pdata->ioaddr; if (pdata->irq < 0) - return -EINVAL; /* fall back into rtc-dev's emulation */ - - if (enabled) - writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); - else + return -ENOIOCTLCMD; /* fall back into rtc-dev's emulation */ + switch (cmd) { + case RTC_AIE_OFF: writel(0, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); + break; + case RTC_AIE_ON: + writel(1, ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); + break; + default: + return -ENOIOCTLCMD; + } return 0; } @@ -210,7 +216,7 @@ static const struct rtc_class_ops mv_rtc_alarm_ops = { .set_time = mv_rtc_set_time, .read_alarm = mv_rtc_read_alarm, .set_alarm = mv_rtc_set_alarm, - .alarm_irq_enable = mv_rtc_alarm_irq_enable, + .ioctl = mv_rtc_ioctl, }; static int __devinit mv_rtc_probe(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-omap.c b/trunk/drivers/rtc/rtc-omap.c index b4dbf3a319b3..e72b523c79a5 100644 --- a/trunk/drivers/rtc/rtc-omap.c +++ b/trunk/drivers/rtc/rtc-omap.c @@ -143,6 +143,8 @@ omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) u8 reg; switch (cmd) { + case RTC_AIE_OFF: + case RTC_AIE_ON: case RTC_UIE_OFF: case RTC_UIE_ON: break; @@ -154,6 +156,13 @@ omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) rtc_wait_not_busy(); reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); switch (cmd) { + /* AIE = Alarm Interrupt Enable */ + case RTC_AIE_OFF: + reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; + break; + case RTC_AIE_ON: + reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; + break; /* UIE = Update Interrupt Enable (1/second) */ case RTC_UIE_OFF: reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER; @@ -173,24 +182,6 @@ omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) #define omap_rtc_ioctl NULL #endif -static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - u8 reg; - - local_irq_disable(); - rtc_wait_not_busy(); - reg = rtc_read(OMAP_RTC_INTERRUPTS_REG); - if (enabled) - reg |= OMAP_RTC_INTERRUPTS_IT_ALARM; - else - reg &= ~OMAP_RTC_INTERRUPTS_IT_ALARM; - rtc_wait_not_busy(); - rtc_write(reg, OMAP_RTC_INTERRUPTS_REG); - local_irq_enable(); - - return 0; -} - /* this hardware doesn't support "don't care" alarm fields */ static int tm2bcd(struct rtc_time *tm) { @@ -318,7 +309,6 @@ static struct rtc_class_ops omap_rtc_ops = { .set_time = omap_rtc_set_time, .read_alarm = omap_rtc_read_alarm, .set_alarm = omap_rtc_set_alarm, - .alarm_irq_enable = omap_rtc_alarm_irq_enable, }; static int omap_rtc_alarm; diff --git a/trunk/drivers/rtc/rtc-rp5c01.c b/trunk/drivers/rtc/rtc-rp5c01.c index 694da39b6dd2..36eb66184461 100644 --- a/trunk/drivers/rtc/rtc-rp5c01.c +++ b/trunk/drivers/rtc/rtc-rp5c01.c @@ -76,7 +76,7 @@ static inline unsigned int rp5c01_read(struct rp5c01_priv *priv, static inline void rp5c01_write(struct rp5c01_priv *priv, unsigned int val, unsigned int reg) { - __raw_writel(val, &priv->regs[reg]); + return __raw_writel(val, &priv->regs[reg]); } static void rp5c01_lock(struct rp5c01_priv *priv) diff --git a/trunk/drivers/rtc/rtc-rs5c372.c b/trunk/drivers/rtc/rtc-rs5c372.c index 6aaa1550e3b1..dd14e202c2c8 100644 --- a/trunk/drivers/rtc/rtc-rs5c372.c +++ b/trunk/drivers/rtc/rtc-rs5c372.c @@ -299,6 +299,14 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) if (rs5c->type == rtc_rs5c372a && (buf & RS5C372A_CTRL1_SL1)) return -ENOIOCTLCMD; + case RTC_AIE_OFF: + case RTC_AIE_ON: + /* these irq management calls only make sense for chips + * which are wired up to an IRQ. + */ + if (!rs5c->has_irq) + return -ENOIOCTLCMD; + break; default: return -ENOIOCTLCMD; } @@ -309,6 +317,12 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) addr = RS5C_ADDR(RS5C_REG_CTRL1); switch (cmd) { + case RTC_AIE_OFF: /* alarm off */ + buf &= ~RS5C_CTRL1_AALE; + break; + case RTC_AIE_ON: /* alarm on */ + buf |= RS5C_CTRL1_AALE; + break; case RTC_UIE_OFF: /* update off */ buf &= ~RS5C_CTRL1_CT_MASK; break; @@ -333,39 +347,6 @@ rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) #endif -static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct i2c_client *client = to_i2c_client(dev); - struct rs5c372 *rs5c = i2c_get_clientdata(client); - unsigned char buf; - int status, addr; - - buf = rs5c->regs[RS5C_REG_CTRL1]; - - if (!rs5c->has_irq) - return -EINVAL; - - status = rs5c_get_regs(rs5c); - if (status < 0) - return status; - - addr = RS5C_ADDR(RS5C_REG_CTRL1); - if (enabled) - buf |= RS5C_CTRL1_AALE; - else - buf &= ~RS5C_CTRL1_AALE; - - if (i2c_smbus_write_byte_data(client, addr, buf) < 0) { - printk(KERN_WARNING "%s: can't update alarm\n", - rs5c->rtc->name); - status = -EIO; - } else - rs5c->regs[RS5C_REG_CTRL1] = buf; - - return status; -} - - /* NOTE: Since RTC_WKALM_{RD,SET} were originally defined for EFI, * which only exposes a polled programming interface; and since * these calls map directly to those EFI requests; we don't demand @@ -485,7 +466,6 @@ static const struct rtc_class_ops rs5c372_rtc_ops = { .set_time = rs5c372_rtc_set_time, .read_alarm = rs5c_read_alarm, .set_alarm = rs5c_set_alarm, - .alarm_irq_enable = rs5c_rtc_alarm_irq_enable, }; #if defined(CONFIG_RTC_INTF_SYSFS) || defined(CONFIG_RTC_INTF_SYSFS_MODULE) diff --git a/trunk/drivers/rtc/rtc-sa1100.c b/trunk/drivers/rtc/rtc-sa1100.c index 5dfe5ffcb0d3..88ea52b8647a 100644 --- a/trunk/drivers/rtc/rtc-sa1100.c +++ b/trunk/drivers/rtc/rtc-sa1100.c @@ -314,6 +314,16 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { switch (cmd) { + case RTC_AIE_OFF: + spin_lock_irq(&sa1100_rtc_lock); + RTSR &= ~RTSR_ALE; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; + case RTC_AIE_ON: + spin_lock_irq(&sa1100_rtc_lock); + RTSR |= RTSR_ALE; + spin_unlock_irq(&sa1100_rtc_lock); + return 0; case RTC_UIE_OFF: spin_lock_irq(&sa1100_rtc_lock); RTSR &= ~RTSR_HZE; @@ -328,17 +338,6 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, return -ENOIOCTLCMD; } -static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - spin_lock_irq(&sa1100_rtc_lock); - if (enabled) - RTSR |= RTSR_ALE; - else - RTSR &= ~RTSR_ALE; - spin_unlock_irq(&sa1100_rtc_lock); - return 0; -} - static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) { rtc_time_to_tm(RCNR, tm); @@ -411,7 +410,6 @@ static const struct rtc_class_ops sa1100_rtc_ops = { .proc = sa1100_rtc_proc, .irq_set_freq = sa1100_irq_set_freq, .irq_set_state = sa1100_irq_set_state, - .alarm_irq_enable = sa1100_rtc_alarm_irq_enable, }; static int sa1100_rtc_probe(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-sh.c b/trunk/drivers/rtc/rtc-sh.c index 93314a9e7fa9..06e41ed93230 100644 --- a/trunk/drivers/rtc/rtc-sh.c +++ b/trunk/drivers/rtc/rtc-sh.c @@ -350,6 +350,10 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) unsigned int ret = 0; switch (cmd) { + case RTC_AIE_OFF: + case RTC_AIE_ON: + sh_rtc_setaie(dev, cmd == RTC_AIE_ON); + break; case RTC_UIE_OFF: rtc->periodic_freq &= ~PF_OXS; sh_rtc_setcie(dev, 0); @@ -365,12 +369,6 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) return ret; } -static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - sh_rtc_setaie(dev, enabled); - return 0; -} - static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) { struct platform_device *pdev = to_platform_device(dev); @@ -606,7 +604,6 @@ static struct rtc_class_ops sh_rtc_ops = { .irq_set_state = sh_rtc_irq_set_state, .irq_set_freq = sh_rtc_irq_set_freq, .proc = sh_rtc_proc, - .alarm_irq_enable = sh_rtc_alarm_irq_enable, }; static int __init sh_rtc_probe(struct platform_device *pdev) diff --git a/trunk/drivers/rtc/rtc-test.c b/trunk/drivers/rtc/rtc-test.c index a82d6fe97076..51725f7755b0 100644 --- a/trunk/drivers/rtc/rtc-test.c +++ b/trunk/drivers/rtc/rtc-test.c @@ -50,9 +50,24 @@ static int test_rtc_proc(struct device *dev, struct seq_file *seq) return 0; } -static int test_rtc_alarm_irq_enable(struct device *dev, unsigned int enable) +static int test_rtc_ioctl(struct device *dev, unsigned int cmd, + unsigned long arg) { - return 0; + /* We do support interrupts, they're generated + * using the sysfs interface. + */ + switch (cmd) { + case RTC_PIE_ON: + case RTC_PIE_OFF: + case RTC_UIE_ON: + case RTC_UIE_OFF: + case RTC_AIE_ON: + case RTC_AIE_OFF: + return 0; + + default: + return -ENOIOCTLCMD; + } } static const struct rtc_class_ops test_rtc_ops = { @@ -61,7 +76,7 @@ static const struct rtc_class_ops test_rtc_ops = { .read_alarm = test_rtc_read_alarm, .set_alarm = test_rtc_set_alarm, .set_mmss = test_rtc_set_mmss, - .alarm_irq_enable = test_rtc_alarm_irq_enable, + .ioctl = test_rtc_ioctl, }; static ssize_t test_irq_show(struct device *dev, diff --git a/trunk/drivers/rtc/rtc-vr41xx.c b/trunk/drivers/rtc/rtc-vr41xx.c index 769190ac6d11..c3244244e8cf 100644 --- a/trunk/drivers/rtc/rtc-vr41xx.c +++ b/trunk/drivers/rtc/rtc-vr41xx.c @@ -240,6 +240,26 @@ static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled) static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { switch (cmd) { + case RTC_AIE_ON: + spin_lock_irq(&rtc_lock); + + if (!alarm_enabled) { + enable_irq(aie_irq); + alarm_enabled = 1; + } + + spin_unlock_irq(&rtc_lock); + break; + case RTC_AIE_OFF: + spin_lock_irq(&rtc_lock); + + if (alarm_enabled) { + disable_irq(aie_irq); + alarm_enabled = 0; + } + + spin_unlock_irq(&rtc_lock); + break; case RTC_EPOCH_READ: return put_user(epoch, (unsigned long __user *)arg); case RTC_EPOCH_SET: @@ -255,24 +275,6 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long return 0; } -static int vr41xx_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - spin_lock_irq(&rtc_lock); - if (enabled) { - if (!alarm_enabled) { - enable_irq(aie_irq); - alarm_enabled = 1; - } - } else { - if (alarm_enabled) { - disable_irq(aie_irq); - alarm_enabled = 0; - } - } - spin_unlock_irq(&rtc_lock); - return 0; -} - static irqreturn_t elapsedtime_interrupt(int irq, void *dev_id) { struct platform_device *pdev = (struct platform_device *)dev_id; diff --git a/trunk/drivers/tty/sysrq.c b/trunk/drivers/tty/sysrq.c index 81f13958e751..8e0dd254eb11 100644 --- a/trunk/drivers/tty/sysrq.c +++ b/trunk/drivers/tty/sysrq.c @@ -571,7 +571,6 @@ struct sysrq_state { unsigned int alt_use; bool active; bool need_reinject; - bool reinjecting; }; static void sysrq_reinject_alt_sysrq(struct work_struct *work) @@ -582,10 +581,6 @@ static void sysrq_reinject_alt_sysrq(struct work_struct *work) unsigned int alt_code = sysrq->alt_use; if (sysrq->need_reinject) { - /* we do not want the assignment to be reordered */ - sysrq->reinjecting = true; - mb(); - /* Simulate press and release of Alt + SysRq */ input_inject_event(handle, EV_KEY, alt_code, 1); input_inject_event(handle, EV_KEY, KEY_SYSRQ, 1); @@ -594,9 +589,6 @@ static void sysrq_reinject_alt_sysrq(struct work_struct *work) input_inject_event(handle, EV_KEY, KEY_SYSRQ, 0); input_inject_event(handle, EV_KEY, alt_code, 0); input_inject_event(handle, EV_SYN, SYN_REPORT, 1); - - mb(); - sysrq->reinjecting = false; } } @@ -607,13 +599,6 @@ static bool sysrq_filter(struct input_handle *handle, bool was_active = sysrq->active; bool suppress; - /* - * Do not filter anything if we are in the process of re-injecting - * Alt+SysRq combination. - */ - if (sysrq->reinjecting) - return false; - switch (type) { case EV_SYN: @@ -644,7 +629,7 @@ static bool sysrq_filter(struct input_handle *handle, sysrq->alt_use = sysrq->alt; /* * If nothing else will be pressed we'll need - * to re-inject Alt-SysRq keysroke. + * to * re-inject Alt-SysRq keysroke. */ sysrq->need_reinject = true; } diff --git a/trunk/fs/btrfs/disk-io.c b/trunk/fs/btrfs/disk-io.c index e1aa8d607bc7..fdce8799b98d 100644 --- a/trunk/fs/btrfs/disk-io.c +++ b/trunk/fs/btrfs/disk-io.c @@ -359,14 +359,10 @@ static int csum_dirty_buffer(struct btrfs_root *root, struct page *page) tree = &BTRFS_I(page->mapping->host)->io_tree; - if (page->private == EXTENT_PAGE_PRIVATE) { - WARN_ON(1); + if (page->private == EXTENT_PAGE_PRIVATE) goto out; - } - if (!page->private) { - WARN_ON(1); + if (!page->private) goto out; - } len = page->private >> 2; WARN_ON(len == 0); diff --git a/trunk/fs/btrfs/extent-tree.c b/trunk/fs/btrfs/extent-tree.c index f3c96fc01439..4e7e012ad667 100644 --- a/trunk/fs/btrfs/extent-tree.c +++ b/trunk/fs/btrfs/extent-tree.c @@ -6583,7 +6583,7 @@ static noinline int relocate_data_extent(struct inode *reloc_inode, u64 end = start + extent_key->offset - 1; em = alloc_extent_map(GFP_NOFS); - BUG_ON(!em); + BUG_ON(!em || IS_ERR(em)); em->start = start; em->len = extent_key->offset; diff --git a/trunk/fs/btrfs/extent_io.c b/trunk/fs/btrfs/extent_io.c index 92ac5192c518..5e76a474cb7e 100644 --- a/trunk/fs/btrfs/extent_io.c +++ b/trunk/fs/btrfs/extent_io.c @@ -1946,7 +1946,6 @@ void set_page_extent_mapped(struct page *page) static void set_page_extent_head(struct page *page, unsigned long len) { - WARN_ON(!PagePrivate(page)); set_page_private(page, EXTENT_PAGE_PRIVATE_FIRST_PAGE | len << 2); } @@ -2822,17 +2821,9 @@ int try_release_extent_state(struct extent_map_tree *map, * at this point we can safely clear everything except the * locked bit and the nodatasum bit */ - ret = clear_extent_bit(tree, start, end, + clear_extent_bit(tree, start, end, ~(EXTENT_LOCKED | EXTENT_NODATASUM), 0, 0, NULL, mask); - - /* if clear_extent_bit failed for enomem reasons, - * we can't allow the release to continue. - */ - if (ret < 0) - ret = 0; - else - ret = 1; } return ret; } @@ -3203,13 +3194,7 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, } if (!PageUptodate(p)) uptodate = 0; - - /* - * see below about how we avoid a nasty race with release page - * and why we unlock later - */ - if (i != 0) - unlock_page(p); + unlock_page(p); } if (uptodate) set_bit(EXTENT_BUFFER_UPTODATE, &eb->bflags); @@ -3233,26 +3218,9 @@ struct extent_buffer *alloc_extent_buffer(struct extent_io_tree *tree, atomic_inc(&eb->refs); spin_unlock(&tree->buffer_lock); radix_tree_preload_end(); - - /* - * there is a race where release page may have - * tried to find this extent buffer in the radix - * but failed. It will tell the VM it is safe to - * reclaim the, and it will clear the page private bit. - * We must make sure to set the page private bit properly - * after the extent buffer is in the radix tree so - * it doesn't get lost - */ - set_page_extent_mapped(eb->first_page); - set_page_extent_head(eb->first_page, eb->len); - if (!page0) - unlock_page(eb->first_page); return eb; free_eb: - if (eb->first_page && !page0) - unlock_page(eb->first_page); - if (!atomic_dec_and_test(&eb->refs)) return exists; btrfs_release_extent_buffer(eb); @@ -3303,11 +3271,10 @@ int clear_extent_buffer_dirty(struct extent_io_tree *tree, continue; lock_page(page); - WARN_ON(!PagePrivate(page)); - - set_page_extent_mapped(page); if (i == 0) set_page_extent_head(page, eb->len); + else + set_page_private(page, EXTENT_PAGE_PRIVATE); clear_page_dirty_for_io(page); spin_lock_irq(&page->mapping->tree_lock); @@ -3497,13 +3464,6 @@ int read_extent_buffer_pages(struct extent_io_tree *tree, for (i = start_i; i < num_pages; i++) { page = extent_buffer_page(eb, i); - - WARN_ON(!PagePrivate(page)); - - set_page_extent_mapped(page); - if (i == 0) - set_page_extent_head(page, eb->len); - if (inc_all_pages) page_cache_get(page); if (!PageUptodate(page)) { diff --git a/trunk/fs/btrfs/extent_map.c b/trunk/fs/btrfs/extent_map.c index 2b6c12e983b3..b0e1fce12530 100644 --- a/trunk/fs/btrfs/extent_map.c +++ b/trunk/fs/btrfs/extent_map.c @@ -51,8 +51,8 @@ struct extent_map *alloc_extent_map(gfp_t mask) { struct extent_map *em; em = kmem_cache_alloc(extent_map_cache, mask); - if (!em) - return NULL; + if (!em || IS_ERR(em)) + return em; em->in_tree = 0; em->flags = 0; em->compress_type = BTRFS_COMPRESS_NONE; diff --git a/trunk/fs/btrfs/file.c b/trunk/fs/btrfs/file.c index 7084140d5940..c1d3a818731a 100644 --- a/trunk/fs/btrfs/file.c +++ b/trunk/fs/btrfs/file.c @@ -186,7 +186,6 @@ int btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end, split = alloc_extent_map(GFP_NOFS); if (!split2) split2 = alloc_extent_map(GFP_NOFS); - BUG_ON(!split || !split2); write_lock(&em_tree->lock); em = lookup_extent_mapping(em_tree, start, len); diff --git a/trunk/fs/btrfs/inode.c b/trunk/fs/btrfs/inode.c index fb9bd7832b6d..bcc461a9695f 100644 --- a/trunk/fs/btrfs/inode.c +++ b/trunk/fs/btrfs/inode.c @@ -644,7 +644,6 @@ static noinline int submit_compressed_extents(struct inode *inode, async_extent->ram_size - 1, 0); em = alloc_extent_map(GFP_NOFS); - BUG_ON(!em); em->start = async_extent->start; em->len = async_extent->ram_size; em->orig_start = em->start; @@ -821,7 +820,6 @@ static noinline int cow_file_range(struct inode *inode, BUG_ON(ret); em = alloc_extent_map(GFP_NOFS); - BUG_ON(!em); em->start = start; em->orig_start = em->start; ram_size = ins.offset; @@ -1171,7 +1169,6 @@ static noinline int run_delalloc_nocow(struct inode *inode, struct extent_map_tree *em_tree; em_tree = &BTRFS_I(inode)->extent_tree; em = alloc_extent_map(GFP_NOFS); - BUG_ON(!em); em->start = cur_offset; em->orig_start = em->start; em->len = num_bytes; diff --git a/trunk/fs/btrfs/ioctl.c b/trunk/fs/btrfs/ioctl.c index be2d4f6aaa5e..02d224e8c83f 100644 --- a/trunk/fs/btrfs/ioctl.c +++ b/trunk/fs/btrfs/ioctl.c @@ -2208,7 +2208,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) int num_types = 4; int alloc_size; int ret = 0; - u64 slot_count = 0; + int slot_count = 0; int i, c; if (copy_from_user(&space_args, @@ -2247,7 +2247,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) goto out; } - slot_count = min_t(u64, space_args.space_slots, slot_count); + slot_count = min_t(int, space_args.space_slots, slot_count); alloc_size = sizeof(*dest) * slot_count; @@ -2267,9 +2267,6 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) for (i = 0; i < num_types; i++) { struct btrfs_space_info *tmp; - if (!slot_count) - break; - info = NULL; rcu_read_lock(); list_for_each_entry_rcu(tmp, &root->fs_info->space_info, @@ -2291,10 +2288,7 @@ long btrfs_ioctl_space_info(struct btrfs_root *root, void __user *arg) memcpy(dest, &space, sizeof(space)); dest++; space_args.total_spaces++; - slot_count--; } - if (!slot_count) - break; } up_read(&info->groups_sem); } diff --git a/trunk/fs/btrfs/relocation.c b/trunk/fs/btrfs/relocation.c index 0825e4ed9447..1f5556acb530 100644 --- a/trunk/fs/btrfs/relocation.c +++ b/trunk/fs/btrfs/relocation.c @@ -1157,7 +1157,6 @@ static int clone_backref_node(struct btrfs_trans_handle *trans, new_node->bytenr = dest->node->start; new_node->level = node->level; new_node->lowest = node->lowest; - new_node->checked = 1; new_node->root = dest; if (!node->lowest) { diff --git a/trunk/fs/btrfs/volumes.c b/trunk/fs/btrfs/volumes.c index af7dbca15276..2636a051e4b2 100644 --- a/trunk/fs/btrfs/volumes.c +++ b/trunk/fs/btrfs/volumes.c @@ -1605,14 +1605,12 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path) ret = find_next_devid(root, &device->devid); if (ret) { - kfree(device->name); kfree(device); goto error; } trans = btrfs_start_transaction(root, 0); if (IS_ERR(trans)) { - kfree(device->name); kfree(device); ret = PTR_ERR(trans); goto error; diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 9e701e28a329..ec4b2d0190a8 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -455,6 +455,14 @@ static int nameidata_dentry_drop_rcu(struct nameidata *nd, struct dentry *dentry struct fs_struct *fs = current->fs; struct dentry *parent = nd->path.dentry; + /* + * It can be possible to revalidate the dentry that we started + * the path walk with. force_reval_path may also revalidate the + * dentry already committed to the nameidata. + */ + if (unlikely(parent == dentry)) + return nameidata_drop_rcu(nd); + BUG_ON(!(nd->flags & LOOKUP_RCU)); if (nd->root.mnt) { spin_lock(&fs->lock); @@ -563,15 +571,33 @@ void release_open_intent(struct nameidata *nd) } } -static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd) +/* + * Call d_revalidate and handle filesystems that request rcu-walk + * to be dropped. This may be called and return in rcu-walk mode, + * regardless of success or error. If -ECHILD is returned, the caller + * must return -ECHILD back up the path walk stack so path walk may + * be restarted in ref-walk mode. + */ +static int d_revalidate(struct dentry *dentry, struct nameidata *nd) { - return dentry->d_op->d_revalidate(dentry, nd); + int status; + + status = dentry->d_op->d_revalidate(dentry, nd); + if (status == -ECHILD) { + if (nameidata_dentry_drop_rcu(nd, dentry)) + return status; + status = dentry->d_op->d_revalidate(dentry, nd); + } + + return status; } -static struct dentry * +static inline struct dentry * do_revalidate(struct dentry *dentry, struct nameidata *nd) { - int status = d_revalidate(dentry, nd); + int status; + + status = d_revalidate(dentry, nd); if (unlikely(status <= 0)) { /* * The dentry failed validation. @@ -580,35 +606,20 @@ do_revalidate(struct dentry *dentry, struct nameidata *nd) * to return a fail status. */ if (status < 0) { - dput(dentry); + /* If we're in rcu-walk, we don't have a ref */ + if (!(nd->flags & LOOKUP_RCU)) + dput(dentry); dentry = ERR_PTR(status); - } else if (!d_invalidate(dentry)) { - dput(dentry); - dentry = NULL; - } - } - return dentry; -} -static inline struct dentry * -do_revalidate_rcu(struct dentry *dentry, struct nameidata *nd) -{ - int status = d_revalidate(dentry, nd); - if (likely(status > 0)) - return dentry; - if (status == -ECHILD) { - if (nameidata_dentry_drop_rcu(nd, dentry)) - return ERR_PTR(-ECHILD); - return do_revalidate(dentry, nd); - } - if (status < 0) - return ERR_PTR(status); - /* Don't d_invalidate in rcu-walk mode */ - if (nameidata_dentry_drop_rcu(nd, dentry)) - return ERR_PTR(-ECHILD); - if (!d_invalidate(dentry)) { - dput(dentry); - dentry = NULL; + } else { + /* Don't d_invalidate in rcu-walk mode */ + if (nameidata_dentry_drop_rcu_maybe(nd, dentry)) + return ERR_PTR(-ECHILD); + if (!d_invalidate(dentry)) { + dput(dentry); + dentry = NULL; + } + } } return dentry; } @@ -657,6 +668,9 @@ force_reval_path(struct path *path, struct nameidata *nd) return 0; if (!status) { + /* Don't d_invalidate in rcu-walk mode */ + if (nameidata_drop_rcu(nd)) + return -ECHILD; d_invalidate(dentry); status = -ESTALE; } @@ -763,8 +777,6 @@ __do_follow_link(const struct path *link, struct nameidata *nd, void **p) int error; struct dentry *dentry = link->dentry; - BUG_ON(nd->flags & LOOKUP_RCU); - touch_atime(link->mnt, dentry); nd_set_link(nd, NULL); @@ -799,11 +811,6 @@ static inline int do_follow_link(struct path *path, struct nameidata *nd) { void *cookie; int err = -ELOOP; - - /* We drop rcu-walk here */ - if (nameidata_dentry_drop_rcu_maybe(nd, path->dentry)) - return -ECHILD; - if (current->link_count >= MAX_NESTED_LINKS) goto loop; if (current->total_link_count >= 40) @@ -1248,15 +1255,9 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, return -ECHILD; nd->seq = seq; - if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { - dentry = do_revalidate_rcu(dentry, nd); - if (!dentry) - goto need_lookup; - if (IS_ERR(dentry)) - goto fail; - if (!(nd->flags & LOOKUP_RCU)) - goto done; - } + if (dentry->d_flags & DCACHE_OP_REVALIDATE) + goto need_revalidate; +done2: path->mnt = mnt; path->dentry = dentry; if (likely(__follow_mount_rcu(nd, path, inode, false))) @@ -1269,13 +1270,8 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, if (!dentry) goto need_lookup; found: - if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) { - dentry = do_revalidate(dentry, nd); - if (!dentry) - goto need_lookup; - if (IS_ERR(dentry)) - goto fail; - } + if (dentry->d_flags & DCACHE_OP_REVALIDATE) + goto need_revalidate; done: path->mnt = mnt; path->dentry = dentry; @@ -1317,6 +1313,16 @@ static int do_lookup(struct nameidata *nd, struct qstr *name, mutex_unlock(&dir->i_mutex); goto found; +need_revalidate: + dentry = do_revalidate(dentry, nd); + if (!dentry) + goto need_lookup; + if (IS_ERR(dentry)) + goto fail; + if (nd->flags & LOOKUP_RCU) + goto done2; + goto done; + fail: return PTR_ERR(dentry); } @@ -1413,6 +1419,9 @@ static int link_path_walk(const char *name, struct nameidata *nd) goto out_dput; if (inode->i_op->follow_link) { + /* We commonly drop rcu-walk here */ + if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry)) + return -ECHILD; BUG_ON(inode != next.dentry->d_inode); err = do_follow_link(&next, nd); if (err) @@ -1458,6 +1467,8 @@ static int link_path_walk(const char *name, struct nameidata *nd) break; if (inode && unlikely(inode->i_op->follow_link) && (lookup_flags & LOOKUP_FOLLOW)) { + if (nameidata_dentry_drop_rcu_maybe(nd, next.dentry)) + return -ECHILD; BUG_ON(inode != next.dentry->d_inode); err = do_follow_link(&next, nd); if (err) @@ -1493,15 +1504,12 @@ static int link_path_walk(const char *name, struct nameidata *nd) * We may need to check the cached dentry for staleness. */ if (need_reval_dot(nd->path.dentry)) { - if (nameidata_drop_rcu_last_maybe(nd)) - return -ECHILD; /* Note: we do not d_invalidate() */ err = d_revalidate(nd->path.dentry, nd); if (!err) err = -ESTALE; if (err < 0) break; - return 0; } return_base: if (nameidata_drop_rcu_last_maybe(nd)) diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index cde36cb0f348..3be975e18919 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -484,7 +484,7 @@ static int decode_cb_sequence4res(struct xdr_stream *xdr, out: return status; out_default: - return nfs_cb_stat_to_errno(nfserr); + return nfs_cb_stat_to_errno(status); } /* @@ -564,9 +564,11 @@ static int nfs4_xdr_dec_cb_recall(struct rpc_rqst *rqstp, if (unlikely(status)) goto out; if (unlikely(nfserr != NFS4_OK)) - status = nfs_cb_stat_to_errno(nfserr); + goto out_default; out: return status; +out_default: + return nfs_cb_stat_to_errno(status); } /* diff --git a/trunk/fs/nfsd/nfs4state.c b/trunk/fs/nfsd/nfs4state.c index 54b60bfceb8d..d98d0213285d 100644 --- a/trunk/fs/nfsd/nfs4state.c +++ b/trunk/fs/nfsd/nfs4state.c @@ -230,6 +230,9 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f dp->dl_client = clp; get_nfs4_file(fp); dp->dl_file = fp; + dp->dl_vfs_file = find_readable_file(fp); + get_file(dp->dl_vfs_file); + dp->dl_flock = NULL; dp->dl_type = type; dp->dl_stateid.si_boot = boot_time; dp->dl_stateid.si_stateownerid = current_delegid++; @@ -238,6 +241,8 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f fh_copy_shallow(&dp->dl_fh, ¤t_fh->fh_handle); dp->dl_time = 0; atomic_set(&dp->dl_count, 1); + list_add(&dp->dl_perfile, &fp->fi_delegations); + list_add(&dp->dl_perclnt, &clp->cl_delegations); INIT_WORK(&dp->dl_recall.cb_work, nfsd4_do_callback_rpc); return dp; } @@ -248,30 +253,36 @@ nfs4_put_delegation(struct nfs4_delegation *dp) if (atomic_dec_and_test(&dp->dl_count)) { dprintk("NFSD: freeing dp %p\n",dp); put_nfs4_file(dp->dl_file); + fput(dp->dl_vfs_file); kmem_cache_free(deleg_slab, dp); num_delegations--; } } -static void nfs4_put_deleg_lease(struct nfs4_file *fp) +/* Remove the associated file_lock first, then remove the delegation. + * lease_modify() is called to remove the FS_LEASE file_lock from + * the i_flock list, eventually calling nfsd's lock_manager + * fl_release_callback. + */ +static void +nfs4_close_delegation(struct nfs4_delegation *dp) { - if (atomic_dec_and_test(&fp->fi_delegees)) { - vfs_setlease(fp->fi_deleg_file, F_UNLCK, &fp->fi_lease); - fp->fi_lease = NULL; - fp->fi_deleg_file = NULL; - } + dprintk("NFSD: close_delegation dp %p\n",dp); + /* XXX: do we even need this check?: */ + if (dp->dl_flock) + vfs_setlease(dp->dl_vfs_file, F_UNLCK, &dp->dl_flock); } /* Called under the state lock. */ static void unhash_delegation(struct nfs4_delegation *dp) { + list_del_init(&dp->dl_perfile); list_del_init(&dp->dl_perclnt); spin_lock(&recall_lock); - list_del_init(&dp->dl_perfile); list_del_init(&dp->dl_recall_lru); spin_unlock(&recall_lock); - nfs4_put_deleg_lease(dp->dl_file); + nfs4_close_delegation(dp); nfs4_put_delegation(dp); } @@ -947,6 +958,8 @@ expire_client(struct nfs4_client *clp) spin_lock(&recall_lock); while (!list_empty(&clp->cl_delegations)) { dp = list_entry(clp->cl_delegations.next, struct nfs4_delegation, dl_perclnt); + dprintk("NFSD: expire client. dp %p, fp %p\n", dp, + dp->dl_flock); list_del_init(&dp->dl_perclnt); list_move(&dp->dl_recall_lru, &reaplist); } @@ -2065,7 +2078,6 @@ alloc_init_file(struct inode *ino) fp->fi_inode = igrab(ino); fp->fi_id = current_fileid++; fp->fi_had_conflict = false; - fp->fi_lease = NULL; memset(fp->fi_fds, 0, sizeof(fp->fi_fds)); memset(fp->fi_access, 0, sizeof(fp->fi_access)); spin_lock(&recall_lock); @@ -2317,8 +2329,23 @@ nfs4_file_downgrade(struct nfs4_file *fp, unsigned int share_access) nfs4_file_put_access(fp, O_RDONLY); } -static void nfsd_break_one_deleg(struct nfs4_delegation *dp) +/* + * Spawn a thread to perform a recall on the delegation represented + * by the lease (file_lock) + * + * Called from break_lease() with lock_flocks() held. + * Note: we assume break_lease will only call this *once* for any given + * lease. + */ +static +void nfsd_break_deleg_cb(struct file_lock *fl) { + struct nfs4_delegation *dp = (struct nfs4_delegation *)fl->fl_owner; + + dprintk("NFSD nfsd_break_deleg_cb: dp %p fl %p\n",dp,fl); + if (!dp) + return; + /* We're assuming the state code never drops its reference * without first removing the lease. Since we're in this lease * callback (and since the lease code is serialized by the kernel @@ -2326,35 +2353,22 @@ static void nfsd_break_one_deleg(struct nfs4_delegation *dp) * it's safe to take a reference: */ atomic_inc(&dp->dl_count); + spin_lock(&recall_lock); list_add_tail(&dp->dl_recall_lru, &del_recall_lru); + spin_unlock(&recall_lock); /* only place dl_time is set. protected by lock_flocks*/ dp->dl_time = get_seconds(); - nfsd4_cb_recall(dp); -} - -/* Called from break_lease() with lock_flocks() held. */ -static void nfsd_break_deleg_cb(struct file_lock *fl) -{ - struct nfs4_file *fp = (struct nfs4_file *)fl->fl_owner; - struct nfs4_delegation *dp; - - BUG_ON(!fp); - /* We assume break_lease is only called once per lease: */ - BUG_ON(fp->fi_had_conflict); /* * We don't want the locks code to timeout the lease for us; - * we'll remove it ourself if a delegation isn't returned - * in time: + * we'll remove it ourself if the delegation isn't returned + * in time. */ fl->fl_break_time = 0; - spin_lock(&recall_lock); - fp->fi_had_conflict = true; - list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) - nfsd_break_one_deleg(dp); - spin_unlock(&recall_lock); + dp->dl_file->fi_had_conflict = true; + nfsd4_cb_recall(dp); } static @@ -2445,15 +2459,13 @@ nfs4_check_delegmode(struct nfs4_delegation *dp, int flags) static struct nfs4_delegation * find_delegation_file(struct nfs4_file *fp, stateid_t *stid) { - struct nfs4_delegation *dp = NULL; + struct nfs4_delegation *dp; - spin_lock(&recall_lock); list_for_each_entry(dp, &fp->fi_delegations, dl_perfile) { if (dp->dl_stateid.si_stateownerid == stid->si_stateownerid) - break; + return dp; } - spin_unlock(&recall_lock); - return dp; + return NULL; } int share_access_to_flags(u32 share_access) @@ -2629,66 +2641,6 @@ static bool nfsd4_cb_channel_good(struct nfs4_client *clp) return clp->cl_minorversion && clp->cl_cb_state == NFSD4_CB_UNKNOWN; } -static struct file_lock *nfs4_alloc_init_lease(struct nfs4_delegation *dp, int flag) -{ - struct file_lock *fl; - - fl = locks_alloc_lock(); - if (!fl) - return NULL; - locks_init_lock(fl); - fl->fl_lmops = &nfsd_lease_mng_ops; - fl->fl_flags = FL_LEASE; - fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; - fl->fl_end = OFFSET_MAX; - fl->fl_owner = (fl_owner_t)(dp->dl_file); - fl->fl_pid = current->tgid; - return fl; -} - -static int nfs4_setlease(struct nfs4_delegation *dp, int flag) -{ - struct nfs4_file *fp = dp->dl_file; - struct file_lock *fl; - int status; - - fl = nfs4_alloc_init_lease(dp, flag); - if (!fl) - return -ENOMEM; - fl->fl_file = find_readable_file(fp); - list_add(&dp->dl_perclnt, &dp->dl_client->cl_delegations); - status = vfs_setlease(fl->fl_file, fl->fl_type, &fl); - if (status) { - list_del_init(&dp->dl_perclnt); - locks_free_lock(fl); - return -ENOMEM; - } - fp->fi_lease = fl; - fp->fi_deleg_file = fl->fl_file; - get_file(fp->fi_deleg_file); - atomic_set(&fp->fi_delegees, 1); - list_add(&dp->dl_perfile, &fp->fi_delegations); - return 0; -} - -static int nfs4_set_delegation(struct nfs4_delegation *dp, int flag) -{ - struct nfs4_file *fp = dp->dl_file; - - if (!fp->fi_lease) - return nfs4_setlease(dp, flag); - spin_lock(&recall_lock); - if (fp->fi_had_conflict) { - spin_unlock(&recall_lock); - return -EAGAIN; - } - atomic_inc(&fp->fi_delegees); - list_add(&dp->dl_perfile, &fp->fi_delegations); - spin_unlock(&recall_lock); - list_add(&dp->dl_perclnt, &dp->dl_client->cl_delegations); - return 0; -} - /* * Attempt to hand out a delegation. */ @@ -2698,6 +2650,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta struct nfs4_delegation *dp; struct nfs4_stateowner *sop = stp->st_stateowner; int cb_up; + struct file_lock *fl; int status, flag = 0; cb_up = nfsd4_cb_channel_good(sop->so_client); @@ -2728,11 +2681,36 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta } dp = alloc_init_deleg(sop->so_client, stp, fh, flag); - if (dp == NULL) - goto out_no_deleg; - status = nfs4_set_delegation(dp, flag); - if (status) - goto out_free; + if (dp == NULL) { + flag = NFS4_OPEN_DELEGATE_NONE; + goto out; + } + status = -ENOMEM; + fl = locks_alloc_lock(); + if (!fl) + goto out; + locks_init_lock(fl); + fl->fl_lmops = &nfsd_lease_mng_ops; + fl->fl_flags = FL_LEASE; + fl->fl_type = flag == NFS4_OPEN_DELEGATE_READ? F_RDLCK: F_WRLCK; + fl->fl_end = OFFSET_MAX; + fl->fl_owner = (fl_owner_t)dp; + fl->fl_file = find_readable_file(stp->st_file); + BUG_ON(!fl->fl_file); + fl->fl_pid = current->tgid; + dp->dl_flock = fl; + + /* vfs_setlease checks to see if delegation should be handed out. + * the lock_manager callback fl_change is used + */ + if ((status = vfs_setlease(fl->fl_file, fl->fl_type, &fl))) { + dprintk("NFSD: setlease failed [%d], no delegation\n", status); + dp->dl_flock = NULL; + locks_free_lock(fl); + unhash_delegation(dp); + flag = NFS4_OPEN_DELEGATE_NONE; + goto out; + } memcpy(&open->op_delegate_stateid, &dp->dl_stateid, sizeof(dp->dl_stateid)); @@ -2744,12 +2722,6 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) dprintk("NFSD: WARNING: refusing delegation reclaim\n"); open->op_delegate_type = flag; - return; -out_free: - nfs4_put_delegation(dp); -out_no_deleg: - flag = NFS4_OPEN_DELEGATE_NONE; - goto out; } /* @@ -2944,6 +2916,8 @@ nfs4_laundromat(void) test_val = u; break; } + dprintk("NFSD: purging unused delegation dp %p, fp %p\n", + dp, dp->dl_flock); list_move(&dp->dl_recall_lru, &reaplist); } spin_unlock(&recall_lock); @@ -3154,7 +3128,7 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate, goto out; renew_client(dp->dl_client); if (filpp) { - *filpp = dp->dl_file->fi_deleg_file; + *filpp = find_readable_file(dp->dl_file); BUG_ON(!*filpp); } } else { /* open or lock stateid */ diff --git a/trunk/fs/nfsd/state.h b/trunk/fs/nfsd/state.h index 2d31224b07bf..3074656ba7bf 100644 --- a/trunk/fs/nfsd/state.h +++ b/trunk/fs/nfsd/state.h @@ -83,6 +83,8 @@ struct nfs4_delegation { atomic_t dl_count; /* ref count */ struct nfs4_client *dl_client; struct nfs4_file *dl_file; + struct file *dl_vfs_file; + struct file_lock *dl_flock; u32 dl_type; time_t dl_time; /* For recall: */ @@ -377,9 +379,6 @@ struct nfs4_file { */ atomic_t fi_readers; atomic_t fi_writers; - struct file *fi_deleg_file; - struct file_lock *fi_lease; - atomic_t fi_delegees; struct inode *fi_inode; u32 fi_id; /* used with stateowner->so_id * for stateid_hashtbl hash */ diff --git a/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index da1d9701f8e4..641117f2188d 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -808,7 +808,7 @@ nfsd_get_raparms(dev_t dev, ino_t ino) if (ra->p_count == 0) frap = rap; } - depth = nfsdstats.ra_size; + depth = nfsdstats.ra_size*11/10; if (!frap) { spin_unlock(&rab->pb_lock); return NULL; @@ -1742,13 +1742,6 @@ nfsd_rename(struct svc_rqst *rqstp, struct svc_fh *ffhp, char *fname, int flen, goto out_dput_new; host_err = nfsd_break_lease(odentry->d_inode); - if (host_err) - goto out_drop_write; - if (ndentry->d_inode) { - host_err = nfsd_break_lease(ndentry->d_inode); - if (host_err) - goto out_drop_write; - } if (host_err) goto out_drop_write; host_err = vfs_rename(fdir, odentry, tdir, ndentry); @@ -1819,22 +1812,22 @@ nfsd_unlink(struct svc_rqst *rqstp, struct svc_fh *fhp, int type, host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); if (host_err) - goto out_put; + goto out_nfserr; host_err = nfsd_break_lease(rdentry->d_inode); if (host_err) - goto out_drop_write; + goto out_put; if (type != S_IFDIR) host_err = vfs_unlink(dirp, rdentry); else host_err = vfs_rmdir(dirp, rdentry); - if (!host_err) - host_err = commit_metadata(fhp); -out_drop_write: - mnt_drop_write(fhp->fh_export->ex_path.mnt); out_put: dput(rdentry); + if (!host_err) + host_err = commit_metadata(fhp); + + mnt_drop_write(fhp->fh_export->ex_path.mnt); out_nfserr: err = nfserrno(host_err); out: diff --git a/trunk/fs/proc/array.c b/trunk/fs/proc/array.c index 7c99c1cf7e5c..df2b703b9d0f 100644 --- a/trunk/fs/proc/array.c +++ b/trunk/fs/proc/array.c @@ -353,6 +353,9 @@ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, task_cap(m, task); task_cpus_allowed(m, task); cpuset_task_status_allowed(m, task); +#if defined(CONFIG_S390) + task_show_regs(m, task); +#endif task_context_switch_counts(m, task); return 0; } diff --git a/trunk/include/linux/huge_mm.h b/trunk/include/linux/huge_mm.h index df29c8fde36b..8e6c8c42bc3c 100644 --- a/trunk/include/linux/huge_mm.h +++ b/trunk/include/linux/huge_mm.h @@ -57,8 +57,7 @@ extern pmd_t *page_check_address_pmd(struct page *page, (transparent_hugepage_flags & \ (1<vm_flags & VM_HUGEPAGE))) && \ - !((__vma)->vm_flags & VM_NOHUGEPAGE) && \ - !is_vma_temporary_stack(__vma)) + !((__vma)->vm_flags & VM_NOHUGEPAGE)) #define transparent_hugepage_defrag(__vma) \ ((transparent_hugepage_flags & \ (1< #include -#define MATRIX_MAX_ROWS 32 -#define MATRIX_MAX_COLS 32 +#define MATRIX_MAX_ROWS 16 +#define MATRIX_MAX_COLS 16 #define KEY(row, col, val) ((((row) & (MATRIX_MAX_ROWS - 1)) << 24) |\ (((col) & (MATRIX_MAX_COLS - 1)) << 16) |\ diff --git a/trunk/include/linux/oprofile.h b/trunk/include/linux/oprofile.h index 1ca64113efe8..32fb81212fd1 100644 --- a/trunk/include/linux/oprofile.h +++ b/trunk/include/linux/oprofile.h @@ -16,8 +16,6 @@ #include #include #include -#include -#include #include /* Each escaped entry is prefixed by ESCAPE_CODE @@ -188,17 +186,10 @@ int oprofile_add_data(struct op_entry *entry, unsigned long val); int oprofile_add_data64(struct op_entry *entry, u64 val); int oprofile_write_commit(struct op_entry *entry); -#ifdef CONFIG_HW_PERF_EVENTS +#ifdef CONFIG_PERF_EVENTS int __init oprofile_perf_init(struct oprofile_operations *ops); void oprofile_perf_exit(void); char *op_name_from_perf_id(void); -#else -static inline int __init oprofile_perf_init(struct oprofile_operations *ops) -{ - pr_info("oprofile: hardware counters not available\n"); - return -ENODEV; -} -static inline void oprofile_perf_exit(void) { } -#endif /* CONFIG_HW_PERF_EVENTS */ +#endif /* CONFIG_PERF_EVENTS */ #endif /* OPROFILE_H */ diff --git a/trunk/kernel/time/timer_list.c b/trunk/kernel/time/timer_list.c index 3258455549f4..32a19f9397fc 100644 --- a/trunk/kernel/time/timer_list.c +++ b/trunk/kernel/time/timer_list.c @@ -41,7 +41,7 @@ static void print_name_offset(struct seq_file *m, void *sym) char symname[KSYM_NAME_LEN]; if (lookup_symbol_name((unsigned long)sym, symname) < 0) - SEQ_printf(m, "<%pK>", sym); + SEQ_printf(m, "<%p>", sym); else SEQ_printf(m, "%s", symname); } @@ -112,7 +112,7 @@ print_active_timers(struct seq_file *m, struct hrtimer_clock_base *base, static void print_base(struct seq_file *m, struct hrtimer_clock_base *base, u64 now) { - SEQ_printf(m, " .base: %pK\n", base); + SEQ_printf(m, " .base: %p\n", base); SEQ_printf(m, " .index: %d\n", base->index); SEQ_printf(m, " .resolution: %Lu nsecs\n", diff --git a/trunk/kernel/timer.c b/trunk/kernel/timer.c index d6459923d245..d53ce66daea0 100644 --- a/trunk/kernel/timer.c +++ b/trunk/kernel/timer.c @@ -959,7 +959,7 @@ EXPORT_SYMBOL(try_to_del_timer_sync); * * Synchronization rules: Callers must prevent restarting of the timer, * otherwise this function is meaningless. It must not be called from - * interrupt contexts. The caller must not hold locks which would prevent + * hardirq contexts. The caller must not hold locks which would prevent * completion of the timer's handler. The timer's handler must not call * add_timer_on(). Upon exit the timer is not queued and the handler is * not running on any CPU. @@ -971,10 +971,12 @@ int del_timer_sync(struct timer_list *timer) #ifdef CONFIG_LOCKDEP unsigned long flags; - local_irq_save(flags); + raw_local_irq_save(flags); + local_bh_disable(); lock_map_acquire(&timer->lockdep_map); lock_map_release(&timer->lockdep_map); - local_irq_restore(flags); + _local_bh_enable(); + raw_local_irq_restore(flags); #endif /* * don't use it in hardirq context, because it diff --git a/trunk/kernel/watchdog.c b/trunk/kernel/watchdog.c index 18bb15776c57..f37f974aa81b 100644 --- a/trunk/kernel/watchdog.c +++ b/trunk/kernel/watchdog.c @@ -363,14 +363,8 @@ static int watchdog_nmi_enable(int cpu) goto out_save; } - - /* vary the KERN level based on the returned errno */ - if (PTR_ERR(event) == -EOPNOTSUPP) - printk(KERN_INFO "NMI watchdog disabled (cpu%i): not supported (no LAPIC?)\n", cpu); - else if (PTR_ERR(event) == -ENOENT) - printk(KERN_WARNING "NMI watchdog disabled (cpu%i): hardware events not enabled\n", cpu); - else - printk(KERN_ERR "NMI watchdog disabled (cpu%i): unable to create perf event: %ld\n", cpu, PTR_ERR(event)); + printk(KERN_ERR "NMI watchdog disabled for cpu%i: unable to create perf event: %ld\n", + cpu, PTR_ERR(event)); return PTR_ERR(event); /* success path */ diff --git a/trunk/mm/huge_memory.c b/trunk/mm/huge_memory.c index 3e29781ee762..e62ddb8f24b6 100644 --- a/trunk/mm/huge_memory.c +++ b/trunk/mm/huge_memory.c @@ -1811,8 +1811,6 @@ static void collapse_huge_page(struct mm_struct *mm, /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ if (!vma->anon_vma || vma->vm_ops || vma->vm_file) goto out; - if (is_vma_temporary_stack(vma)) - goto out; VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma)); pgd = pgd_offset(mm, address); @@ -2034,27 +2032,32 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, if ((!(vma->vm_flags & VM_HUGEPAGE) && !khugepaged_always()) || (vma->vm_flags & VM_NOHUGEPAGE)) { - skip: progress++; continue; } - /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ - if (!vma->anon_vma || vma->vm_ops || vma->vm_file) - goto skip; - if (is_vma_temporary_stack(vma)) - goto skip; + /* VM_PFNMAP vmas may have vm_ops null but vm_file set */ + if (!vma->anon_vma || vma->vm_ops || vma->vm_file) { + khugepaged_scan.address = vma->vm_end; + progress++; + continue; + } VM_BUG_ON(is_linear_pfn_mapping(vma) || is_pfn_mapping(vma)); hstart = (vma->vm_start + ~HPAGE_PMD_MASK) & HPAGE_PMD_MASK; hend = vma->vm_end & HPAGE_PMD_MASK; - if (hstart >= hend) - goto skip; - if (khugepaged_scan.address > hend) - goto skip; + if (hstart >= hend) { + progress++; + continue; + } if (khugepaged_scan.address < hstart) khugepaged_scan.address = hstart; - VM_BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK); + if (khugepaged_scan.address > hend) { + khugepaged_scan.address = hend + HPAGE_PMD_SIZE; + progress++; + continue; + } + BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK); while (khugepaged_scan.address < hend) { int ret; @@ -2083,7 +2086,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, breakouterloop_mmap_sem: spin_lock(&khugepaged_mm_lock); - VM_BUG_ON(khugepaged_scan.mm_slot != mm_slot); + BUG_ON(khugepaged_scan.mm_slot != mm_slot); /* * Release the current mm_slot if this mm is about to die, or * if we scanned all vmas of this mm. @@ -2238,9 +2241,9 @@ static int khugepaged(void *none) for (;;) { mutex_unlock(&khugepaged_mutex); - VM_BUG_ON(khugepaged_thread != current); + BUG_ON(khugepaged_thread != current); khugepaged_loop(); - VM_BUG_ON(khugepaged_thread != current); + BUG_ON(khugepaged_thread != current); mutex_lock(&khugepaged_mutex); if (!khugepaged_enabled()) diff --git a/trunk/tools/perf/builtin-record.c b/trunk/tools/perf/builtin-record.c index 60cac6f92e8b..b2f729fdb317 100644 --- a/trunk/tools/perf/builtin-record.c +++ b/trunk/tools/perf/builtin-record.c @@ -759,8 +759,8 @@ static int __cmd_record(int argc, const char **argv) perf_session__process_machines(session, event__synthesize_guest_os); if (!system_wide) - event__synthesize_thread_map(threads, process_synthesized_event, - session); + event__synthesize_thread(target_tid, process_synthesized_event, + session); else event__synthesize_threads(process_synthesized_event, session); diff --git a/trunk/tools/perf/builtin-top.c b/trunk/tools/perf/builtin-top.c index 5a29d9cd9486..b6998e055767 100644 --- a/trunk/tools/perf/builtin-top.c +++ b/trunk/tools/perf/builtin-top.c @@ -1306,7 +1306,7 @@ static int __cmd_top(void) return -ENOMEM; if (target_tid != -1) - event__synthesize_thread_map(threads, event__process, session); + event__synthesize_thread(target_tid, event__process, session); else event__synthesize_threads(event__process, session); diff --git a/trunk/tools/perf/util/event.c b/trunk/tools/perf/util/event.c index 50d0a931497a..1478ab4ee222 100644 --- a/trunk/tools/perf/util/event.c +++ b/trunk/tools/perf/util/event.c @@ -263,12 +263,11 @@ static int __event__synthesize_thread(event_t *comm_event, event_t *mmap_event, process, session); } -int event__synthesize_thread_map(struct thread_map *threads, - event__handler_t process, - struct perf_session *session) +int event__synthesize_thread(pid_t pid, event__handler_t process, + struct perf_session *session) { event_t *comm_event, *mmap_event; - int err = -1, thread; + int err = -1; comm_event = malloc(sizeof(comm_event->comm) + session->id_hdr_size); if (comm_event == NULL) @@ -278,15 +277,8 @@ int event__synthesize_thread_map(struct thread_map *threads, if (mmap_event == NULL) goto out_free_comm; - err = 0; - for (thread = 0; thread < threads->nr; ++thread) { - if (__event__synthesize_thread(comm_event, mmap_event, - threads->map[thread], - process, session)) { - err = -1; - break; - } - } + err = __event__synthesize_thread(comm_event, mmap_event, pid, + process, session); free(mmap_event); out_free_comm: free(comm_event); diff --git a/trunk/tools/perf/util/event.h b/trunk/tools/perf/util/event.h index cc7b52f9b492..2b7e91902f10 100644 --- a/trunk/tools/perf/util/event.h +++ b/trunk/tools/perf/util/event.h @@ -135,16 +135,14 @@ typedef union event_union { void event__print_totals(void); struct perf_session; -struct thread_map; typedef int (*event__handler_synth_t)(event_t *event, struct perf_session *session); typedef int (*event__handler_t)(event_t *event, struct sample_data *sample, struct perf_session *session); -int event__synthesize_thread_map(struct thread_map *threads, - event__handler_t process, - struct perf_session *session); +int event__synthesize_thread(pid_t pid, event__handler_t process, + struct perf_session *session); int event__synthesize_threads(event__handler_t process, struct perf_session *session); int event__synthesize_kernel_mmap(event__handler_t process, diff --git a/trunk/tools/power/x86/turbostat/turbostat.c b/trunk/tools/power/x86/turbostat/turbostat.c index 362a0cb448db..4c6983de6fd9 100644 --- a/trunk/tools/power/x86/turbostat/turbostat.c +++ b/trunk/tools/power/x86/turbostat/turbostat.c @@ -72,7 +72,7 @@ int need_reinitialize; int num_cpus; -struct counters { +typedef struct per_cpu_counters { unsigned long long tsc; /* per thread */ unsigned long long aperf; /* per thread */ unsigned long long mperf; /* per thread */ @@ -88,13 +88,13 @@ struct counters { int pkg; int core; int cpu; - struct counters *next; -}; + struct per_cpu_counters *next; +} PCC; -struct counters *cnt_even; -struct counters *cnt_odd; -struct counters *cnt_delta; -struct counters *cnt_average; +PCC *pcc_even; +PCC *pcc_odd; +PCC *pcc_delta; +PCC *pcc_average; struct timeval tv_even; struct timeval tv_odd; struct timeval tv_delta; @@ -125,7 +125,7 @@ unsigned long long get_msr(int cpu, off_t offset) return msr; } -void print_header(void) +void print_header() { if (show_pkg) fprintf(stderr, "pkg "); @@ -160,39 +160,39 @@ void print_header(void) putc('\n', stderr); } -void dump_cnt(struct counters *cnt) +void dump_pcc(PCC *pcc) { - fprintf(stderr, "package: %d ", cnt->pkg); - fprintf(stderr, "core:: %d ", cnt->core); - fprintf(stderr, "CPU: %d ", cnt->cpu); - fprintf(stderr, "TSC: %016llX\n", cnt->tsc); - fprintf(stderr, "c3: %016llX\n", cnt->c3); - fprintf(stderr, "c6: %016llX\n", cnt->c6); - fprintf(stderr, "c7: %016llX\n", cnt->c7); - fprintf(stderr, "aperf: %016llX\n", cnt->aperf); - fprintf(stderr, "pc2: %016llX\n", cnt->pc2); - fprintf(stderr, "pc3: %016llX\n", cnt->pc3); - fprintf(stderr, "pc6: %016llX\n", cnt->pc6); - fprintf(stderr, "pc7: %016llX\n", cnt->pc7); - fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, cnt->extra_msr); + fprintf(stderr, "package: %d ", pcc->pkg); + fprintf(stderr, "core:: %d ", pcc->core); + fprintf(stderr, "CPU: %d ", pcc->cpu); + fprintf(stderr, "TSC: %016llX\n", pcc->tsc); + fprintf(stderr, "c3: %016llX\n", pcc->c3); + fprintf(stderr, "c6: %016llX\n", pcc->c6); + fprintf(stderr, "c7: %016llX\n", pcc->c7); + fprintf(stderr, "aperf: %016llX\n", pcc->aperf); + fprintf(stderr, "pc2: %016llX\n", pcc->pc2); + fprintf(stderr, "pc3: %016llX\n", pcc->pc3); + fprintf(stderr, "pc6: %016llX\n", pcc->pc6); + fprintf(stderr, "pc7: %016llX\n", pcc->pc7); + fprintf(stderr, "msr0x%x: %016llX\n", extra_msr_offset, pcc->extra_msr); } -void dump_list(struct counters *cnt) +void dump_list(PCC *pcc) { - printf("dump_list 0x%p\n", cnt); + printf("dump_list 0x%p\n", pcc); - for (; cnt; cnt = cnt->next) - dump_cnt(cnt); + for (; pcc; pcc = pcc->next) + dump_pcc(pcc); } -void print_cnt(struct counters *p) +void print_pcc(PCC *p) { double interval_float; interval_float = tv_delta.tv_sec + tv_delta.tv_usec/1000000.0; /* topology columns, print blanks on 1st (average) line */ - if (p == cnt_average) { + if (p == pcc_average) { if (show_pkg) fprintf(stderr, " "); if (show_core) @@ -262,24 +262,24 @@ void print_cnt(struct counters *p) putc('\n', stderr); } -void print_counters(struct counters *counters) +void print_counters(PCC *cnt) { - struct counters *cnt; + PCC *pcc; print_header(); if (num_cpus > 1) - print_cnt(cnt_average); + print_pcc(pcc_average); - for (cnt = counters; cnt != NULL; cnt = cnt->next) - print_cnt(cnt); + for (pcc = cnt; pcc != NULL; pcc = pcc->next) + print_pcc(pcc); } #define SUBTRACT_COUNTER(after, before, delta) (delta = (after - before), (before > after)) -int compute_delta(struct counters *after, - struct counters *before, struct counters *delta) + +int compute_delta(PCC *after, PCC *before, PCC *delta) { int errors = 0; int perf_err = 0; @@ -391,20 +391,20 @@ int compute_delta(struct counters *after, delta->extra_msr = after->extra_msr; if (errors) { fprintf(stderr, "ERROR cpu%d before:\n", before->cpu); - dump_cnt(before); + dump_pcc(before); fprintf(stderr, "ERROR cpu%d after:\n", before->cpu); - dump_cnt(after); + dump_pcc(after); errors = 0; } } return 0; } -void compute_average(struct counters *delta, struct counters *avg) +void compute_average(PCC *delta, PCC *avg) { - struct counters *sum; + PCC *sum; - sum = calloc(1, sizeof(struct counters)); + sum = calloc(1, sizeof(PCC)); if (sum == NULL) { perror("calloc sum"); exit(1); @@ -438,34 +438,35 @@ void compute_average(struct counters *delta, struct counters *avg) free(sum); } -void get_counters(struct counters *cnt) +void get_counters(PCC *pcc) { - for ( ; cnt; cnt = cnt->next) { - cnt->tsc = get_msr(cnt->cpu, MSR_TSC); + for ( ; pcc; pcc = pcc->next) { + pcc->tsc = get_msr(pcc->cpu, MSR_TSC); if (do_nhm_cstates) - cnt->c3 = get_msr(cnt->cpu, MSR_CORE_C3_RESIDENCY); + pcc->c3 = get_msr(pcc->cpu, MSR_CORE_C3_RESIDENCY); if (do_nhm_cstates) - cnt->c6 = get_msr(cnt->cpu, MSR_CORE_C6_RESIDENCY); + pcc->c6 = get_msr(pcc->cpu, MSR_CORE_C6_RESIDENCY); if (do_snb_cstates) - cnt->c7 = get_msr(cnt->cpu, MSR_CORE_C7_RESIDENCY); + pcc->c7 = get_msr(pcc->cpu, MSR_CORE_C7_RESIDENCY); if (has_aperf) - cnt->aperf = get_msr(cnt->cpu, MSR_APERF); + pcc->aperf = get_msr(pcc->cpu, MSR_APERF); if (has_aperf) - cnt->mperf = get_msr(cnt->cpu, MSR_MPERF); + pcc->mperf = get_msr(pcc->cpu, MSR_MPERF); if (do_snb_cstates) - cnt->pc2 = get_msr(cnt->cpu, MSR_PKG_C2_RESIDENCY); + pcc->pc2 = get_msr(pcc->cpu, MSR_PKG_C2_RESIDENCY); if (do_nhm_cstates) - cnt->pc3 = get_msr(cnt->cpu, MSR_PKG_C3_RESIDENCY); + pcc->pc3 = get_msr(pcc->cpu, MSR_PKG_C3_RESIDENCY); if (do_nhm_cstates) - cnt->pc6 = get_msr(cnt->cpu, MSR_PKG_C6_RESIDENCY); + pcc->pc6 = get_msr(pcc->cpu, MSR_PKG_C6_RESIDENCY); if (do_snb_cstates) - cnt->pc7 = get_msr(cnt->cpu, MSR_PKG_C7_RESIDENCY); + pcc->pc7 = get_msr(pcc->cpu, MSR_PKG_C7_RESIDENCY); if (extra_msr_offset) - cnt->extra_msr = get_msr(cnt->cpu, extra_msr_offset); + pcc->extra_msr = get_msr(pcc->cpu, extra_msr_offset); } } -void print_nehalem_info(void) + +void print_nehalem_info() { unsigned long long msr; unsigned int ratio; @@ -513,38 +514,38 @@ void print_nehalem_info(void) } -void free_counter_list(struct counters *list) +void free_counter_list(PCC *list) { - struct counters *p; + PCC *p; for (p = list; p; ) { - struct counters *free_me; + PCC *free_me; free_me = p; p = p->next; free(free_me); } + return; } void free_all_counters(void) { - free_counter_list(cnt_even); - cnt_even = NULL; + free_counter_list(pcc_even); + pcc_even = NULL; - free_counter_list(cnt_odd); - cnt_odd = NULL; + free_counter_list(pcc_odd); + pcc_odd = NULL; - free_counter_list(cnt_delta); - cnt_delta = NULL; + free_counter_list(pcc_delta); + pcc_delta = NULL; - free_counter_list(cnt_average); - cnt_average = NULL; + free_counter_list(pcc_average); + pcc_average = NULL; } -void insert_counters(struct counters **list, - struct counters *new) +void insert_cpu_counters(PCC **list, PCC *new) { - struct counters *prev; + PCC *prev; /* * list was empty @@ -593,16 +594,18 @@ void insert_counters(struct counters **list, */ new->next = prev->next; prev->next = new; + + return; } -void alloc_new_counters(int pkg, int core, int cpu) +void alloc_new_cpu_counters(int pkg, int core, int cpu) { - struct counters *new; + PCC *new; if (verbose > 1) printf("pkg%d core%d, cpu%d\n", pkg, core, cpu); - new = (struct counters *)calloc(1, sizeof(struct counters)); + new = (PCC *)calloc(1, sizeof(PCC)); if (new == NULL) { perror("calloc"); exit(1); @@ -610,10 +613,9 @@ void alloc_new_counters(int pkg, int core, int cpu) new->pkg = pkg; new->core = core; new->cpu = cpu; - insert_counters(&cnt_odd, new); + insert_cpu_counters(&pcc_odd, new); - new = (struct counters *)calloc(1, - sizeof(struct counters)); + new = (PCC *)calloc(1, sizeof(PCC)); if (new == NULL) { perror("calloc"); exit(1); @@ -621,9 +623,9 @@ void alloc_new_counters(int pkg, int core, int cpu) new->pkg = pkg; new->core = core; new->cpu = cpu; - insert_counters(&cnt_even, new); + insert_cpu_counters(&pcc_even, new); - new = (struct counters *)calloc(1, sizeof(struct counters)); + new = (PCC *)calloc(1, sizeof(PCC)); if (new == NULL) { perror("calloc"); exit(1); @@ -631,9 +633,9 @@ void alloc_new_counters(int pkg, int core, int cpu) new->pkg = pkg; new->core = core; new->cpu = cpu; - insert_counters(&cnt_delta, new); + insert_cpu_counters(&pcc_delta, new); - new = (struct counters *)calloc(1, sizeof(struct counters)); + new = (PCC *)calloc(1, sizeof(PCC)); if (new == NULL) { perror("calloc"); exit(1); @@ -641,7 +643,7 @@ void alloc_new_counters(int pkg, int core, int cpu) new->pkg = pkg; new->core = core; new->cpu = cpu; - cnt_average = new; + pcc_average = new; } int get_physical_package_id(int cpu) @@ -717,7 +719,7 @@ void re_initialize(void) { printf("turbostat: topology changed, re-initializing.\n"); free_all_counters(); - num_cpus = for_all_cpus(alloc_new_counters); + num_cpus = for_all_cpus(alloc_new_cpu_counters); need_reinitialize = 0; printf("num_cpus is now %d\n", num_cpus); } @@ -726,7 +728,7 @@ void dummy(int pkg, int core, int cpu) { return; } /* * check to see if a cpu came on-line */ -void verify_num_cpus(void) +void verify_num_cpus() { int new_num_cpus; @@ -738,12 +740,14 @@ void verify_num_cpus(void) num_cpus, new_num_cpus); need_reinitialize = 1; } + + return; } void turbostat_loop() { restart: - get_counters(cnt_even); + get_counters(pcc_even); gettimeofday(&tv_even, (struct timezone *)NULL); while (1) { @@ -753,24 +757,24 @@ void turbostat_loop() goto restart; } sleep(interval_sec); - get_counters(cnt_odd); + get_counters(pcc_odd); gettimeofday(&tv_odd, (struct timezone *)NULL); - compute_delta(cnt_odd, cnt_even, cnt_delta); + compute_delta(pcc_odd, pcc_even, pcc_delta); timersub(&tv_odd, &tv_even, &tv_delta); - compute_average(cnt_delta, cnt_average); - print_counters(cnt_delta); + compute_average(pcc_delta, pcc_average); + print_counters(pcc_delta); if (need_reinitialize) { re_initialize(); goto restart; } sleep(interval_sec); - get_counters(cnt_even); + get_counters(pcc_even); gettimeofday(&tv_even, (struct timezone *)NULL); - compute_delta(cnt_even, cnt_odd, cnt_delta); + compute_delta(pcc_even, pcc_odd, pcc_delta); timersub(&tv_even, &tv_odd, &tv_delta); - compute_average(cnt_delta, cnt_average); - print_counters(cnt_delta); + compute_average(pcc_delta, pcc_average); + print_counters(pcc_delta); } } @@ -888,7 +892,7 @@ void check_cpuid() * this check is valid for both Intel and AMD */ asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x80000007)); - has_invariant_tsc = edx & (1 << 8); + has_invariant_tsc = edx && (1 << 8); if (!has_invariant_tsc) { fprintf(stderr, "No invariant TSC\n"); @@ -901,7 +905,7 @@ void check_cpuid() */ asm("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (0x6)); - has_aperf = ecx & (1 << 0); + has_aperf = ecx && (1 << 0); if (!has_aperf) { fprintf(stderr, "No APERF MSR\n"); exit(1); @@ -948,7 +952,7 @@ void turbostat_init() check_dev_msr(); check_super_user(); - num_cpus = for_all_cpus(alloc_new_counters); + num_cpus = for_all_cpus(alloc_new_cpu_counters); if (verbose) print_nehalem_info(); @@ -958,7 +962,7 @@ int fork_it(char **argv) { int retval; pid_t child_pid; - get_counters(cnt_even); + get_counters(pcc_even); gettimeofday(&tv_even, (struct timezone *)NULL); child_pid = fork(); @@ -981,14 +985,14 @@ int fork_it(char **argv) exit(1); } } - get_counters(cnt_odd); + get_counters(pcc_odd); gettimeofday(&tv_odd, (struct timezone *)NULL); - retval = compute_delta(cnt_odd, cnt_even, cnt_delta); + retval = compute_delta(pcc_odd, pcc_even, pcc_delta); timersub(&tv_odd, &tv_even, &tv_delta); - compute_average(cnt_delta, cnt_average); + compute_average(pcc_delta, pcc_average); if (!retval) - print_counters(cnt_delta); + print_counters(pcc_delta); fprintf(stderr, "%.6f sec\n", tv_delta.tv_sec + tv_delta.tv_usec/1000000.0);;