diff --git a/[refs] b/[refs] index ad9ad92b60a2..588a5fadf330 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7bcd5b4671c3aa9185a7e6f76ee12e392070ddea +refs/heads/master: 40c8cefaaf12734327db7199a56e60058d98e7b6 diff --git a/trunk/arch/arm/kernel/traps.c b/trunk/arch/arm/kernel/traps.c index f84dfe67724f..99a572702509 100644 --- a/trunk/arch/arm/kernel/traps.c +++ b/trunk/arch/arm/kernel/traps.c @@ -266,7 +266,6 @@ void die(const char *str, struct pt_regs *regs, int err) { struct thread_info *thread = current_thread_info(); int ret; - enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE; oops_enter(); @@ -274,9 +273,7 @@ void die(const char *str, struct pt_regs *regs, int err) console_verbose(); bust_spinlocks(1); if (!user_mode(regs)) - bug_type = report_bug(regs->ARM_pc, regs); - if (bug_type != BUG_TRAP_TYPE_NONE) - str = "Oops - BUG"; + report_bug(regs->ARM_pc, regs); ret = __die(str, err, thread, regs); if (regs && kexec_should_crash(thread->task)) diff --git a/trunk/arch/arm/kernel/vmlinux.lds.S b/trunk/arch/arm/kernel/vmlinux.lds.S index 43a31fb06318..1e19691e0406 100644 --- a/trunk/arch/arm/kernel/vmlinux.lds.S +++ b/trunk/arch/arm/kernel/vmlinux.lds.S @@ -10,7 +10,6 @@ #include #define PROC_INFO \ - . = ALIGN(4); \ VMLINUX_SYMBOL(__proc_info_begin) = .; \ *(.proc.info.init) \ VMLINUX_SYMBOL(__proc_info_end) = .; diff --git a/trunk/arch/arm/mach-omap2/board-4430sdp.c b/trunk/arch/arm/mach-omap2/board-4430sdp.c index 4e9071589bfb..21fc87648660 100644 --- a/trunk/arch/arm/mach-omap2/board-4430sdp.c +++ b/trunk/arch/arm/mach-omap2/board-4430sdp.c @@ -814,7 +814,7 @@ static struct omap_dss_board_info sdp4430_dss_data = { .default_device = &sdp4430_lcd_device, }; -static void __init omap_4430sdp_display_init(void) +static void omap_4430sdp_display_init(void) { int r; @@ -851,7 +851,7 @@ static struct omap_board_mux board_mux[] __initdata = { #define board_mux NULL #endif -static void __init omap4_sdp4430_wifi_mux_init(void) +static void omap4_sdp4430_wifi_mux_init(void) { omap_mux_init_gpio(GPIO_WIFI_IRQ, OMAP_PIN_INPUT | OMAP_PIN_OFF_WAKEUPENABLE); @@ -878,17 +878,12 @@ static struct wl12xx_platform_data omap4_sdp4430_wlan_data __initdata = { .board_tcxo_clock = WL12XX_TCXOCLOCK_26, }; -static void __init omap4_sdp4430_wifi_init(void) +static void omap4_sdp4430_wifi_init(void) { - int ret; - omap4_sdp4430_wifi_mux_init(); - ret = wl12xx_set_platform_data(&omap4_sdp4430_wlan_data); - if (ret) - pr_err("Error setting wl12xx data: %d\n", ret); - ret = platform_device_register(&omap_vwlan_device); - if (ret) - pr_err("Error registering wl12xx device: %d\n", ret); + if (wl12xx_set_platform_data(&omap4_sdp4430_wlan_data)) + pr_err("Error setting wl12xx data\n"); + platform_device_register(&omap_vwlan_device); } static void __init omap_4430sdp_init(void) diff --git a/trunk/arch/arm/mach-omap2/board-omap3evm.c b/trunk/arch/arm/mach-omap2/board-omap3evm.c index c775bead1497..003fe34c9343 100644 --- a/trunk/arch/arm/mach-omap2/board-omap3evm.c +++ b/trunk/arch/arm/mach-omap2/board-omap3evm.c @@ -617,21 +617,6 @@ static struct gpio omap3_evm_ehci_gpios[] __initdata = { { OMAP3_EVM_EHCI_SELECT, GPIOF_OUT_INIT_LOW, "select EHCI port" }, }; -static void __init omap3_evm_wl12xx_init(void) -{ -#ifdef CONFIG_WL12XX_PLATFORM_DATA - int ret; - - /* WL12xx WLAN Init */ - ret = wl12xx_set_platform_data(&omap3evm_wlan_data); - if (ret) - pr_err("error setting wl12xx data: %d\n", ret); - ret = platform_device_register(&omap3evm_wlan_regulator); - if (ret) - pr_err("error registering wl12xx device: %d\n", ret); -#endif -} - static void __init omap3_evm_init(void) { omap3_evm_get_revision(); @@ -680,7 +665,13 @@ static void __init omap3_evm_init(void) omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL); omap3evm_init_smsc911x(); omap3_evm_display_init(); - omap3_evm_wl12xx_init(); + +#ifdef CONFIG_WL12XX_PLATFORM_DATA + /* WL12xx WLAN Init */ + if (wl12xx_set_platform_data(&omap3evm_wlan_data)) + pr_err("error setting wl12xx data\n"); + platform_device_register(&omap3evm_wlan_regulator); +#endif } MACHINE_START(OMAP3EVM, "OMAP3 EVM") diff --git a/trunk/arch/arm/mach-omap2/board-omap4panda.c b/trunk/arch/arm/mach-omap2/board-omap4panda.c index 28fc271f7031..b7779c206a90 100644 --- a/trunk/arch/arm/mach-omap2/board-omap4panda.c +++ b/trunk/arch/arm/mach-omap2/board-omap4panda.c @@ -488,15 +488,13 @@ void omap4_panda_display_init(void) static void __init omap4_panda_init(void) { int package = OMAP_PACKAGE_CBS; - int ret; if (omap_rev() == OMAP4430_REV_ES1_0) package = OMAP_PACKAGE_CBL; omap4_mux_init(board_mux, NULL, package); - ret = wl12xx_set_platform_data(&omap_panda_wlan_data); - if (ret) - pr_err("error setting wl12xx data: %d\n", ret); + if (wl12xx_set_platform_data(&omap_panda_wlan_data)) + pr_err("error setting wl12xx data\n"); omap4_panda_i2c_init(); platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices)); diff --git a/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c b/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c index c126461836ac..8d7ce11cfeaf 100644 --- a/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c +++ b/trunk/arch/arm/mach-omap2/board-zoom-peripherals.c @@ -296,10 +296,8 @@ static void enable_board_wakeup_source(void) void __init zoom_peripherals_init(void) { - int ret = wl12xx_set_platform_data(&omap_zoom_wlan_data); - - if (ret) - pr_err("error setting wl12xx data: %d\n", ret); + if (wl12xx_set_platform_data(&omap_zoom_wlan_data)) + pr_err("error setting wl12xx data\n"); omap_i2c_init(); platform_device_register(&omap_vwlan_device); diff --git a/trunk/arch/arm/mach-omap2/hsmmc.c b/trunk/arch/arm/mach-omap2/hsmmc.c index b40c28895298..ad0adb5a1e0e 100644 --- a/trunk/arch/arm/mach-omap2/hsmmc.c +++ b/trunk/arch/arm/mach-omap2/hsmmc.c @@ -293,8 +293,8 @@ static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller, } } -static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, - struct omap_mmc_platform_data *mmc) +static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, + struct omap_mmc_platform_data *mmc) { char *hc_name; @@ -430,7 +430,7 @@ static int omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, #define MAX_OMAP_MMC_HWMOD_NAME_LEN 16 -void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) +void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) { struct omap_hwmod *oh; struct platform_device *pdev; @@ -487,7 +487,7 @@ void omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr) kfree(mmc_data); } -void omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) +void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers) { u32 reg; diff --git a/trunk/arch/arm/mach-omap2/mux.c b/trunk/arch/arm/mach-omap2/mux.c index fb8bc9fa43b1..e1cc75d1a57a 100644 --- a/trunk/arch/arm/mach-omap2/mux.c +++ b/trunk/arch/arm/mach-omap2/mux.c @@ -100,8 +100,8 @@ void omap_mux_write_array(struct omap_mux_partition *partition, static char *omap_mux_options; -static int _omap_mux_init_gpio(struct omap_mux_partition *partition, - int gpio, int val) +static int __init _omap_mux_init_gpio(struct omap_mux_partition *partition, + int gpio, int val) { struct omap_mux_entry *e; struct omap_mux *gpio_mux = NULL; @@ -145,7 +145,7 @@ static int _omap_mux_init_gpio(struct omap_mux_partition *partition, return 0; } -int omap_mux_init_gpio(int gpio, int val) +int __init omap_mux_init_gpio(int gpio, int val) { struct omap_mux_partition *partition; int ret; @@ -159,9 +159,9 @@ int omap_mux_init_gpio(int gpio, int val) return -ENODEV; } -static int _omap_mux_get_by_name(struct omap_mux_partition *partition, - const char *muxname, - struct omap_mux **found_mux) +static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition, + const char *muxname, + struct omap_mux **found_mux) { struct omap_mux *mux = NULL; struct omap_mux_entry *e; @@ -240,7 +240,7 @@ omap_mux_get_by_name(const char *muxname, return -ENODEV; } -int omap_mux_init_signal(const char *muxname, int val) +int __init omap_mux_init_signal(const char *muxname, int val) { struct omap_mux_partition *partition = NULL; struct omap_mux *mux = NULL; @@ -1094,8 +1094,8 @@ static void omap_mux_init_package(struct omap_mux *superset, omap_mux_package_init_balls(package_balls, superset); } -static void __init omap_mux_init_signals(struct omap_mux_partition *partition, - struct omap_board_mux *board_mux) +static void omap_mux_init_signals(struct omap_mux_partition *partition, + struct omap_board_mux *board_mux) { omap_mux_set_cmdline_signals(); omap_mux_write_array(partition, board_mux); @@ -1109,8 +1109,8 @@ static void omap_mux_init_package(struct omap_mux *superset, { } -static void __init omap_mux_init_signals(struct omap_mux_partition *partition, - struct omap_board_mux *board_mux) +static void omap_mux_init_signals(struct omap_mux_partition *partition, + struct omap_board_mux *board_mux) { } diff --git a/trunk/arch/arm/mach-omap2/omap-headsmp.S b/trunk/arch/arm/mach-omap2/omap-headsmp.S index 503ac777a2ba..b13ef7ef5ef4 100644 --- a/trunk/arch/arm/mach-omap2/omap-headsmp.S +++ b/trunk/arch/arm/mach-omap2/omap-headsmp.S @@ -18,7 +18,6 @@ #include #include - __CPUINIT /* * OMAP4 specific entry point for secondary CPU to jump from ROM * code. This routine also provides a holding flag into which diff --git a/trunk/arch/arm/mach-omap2/omap_hwmod.c b/trunk/arch/arm/mach-omap2/omap_hwmod.c index eba6cd3816f5..5192cabb40ed 100644 --- a/trunk/arch/arm/mach-omap2/omap_hwmod.c +++ b/trunk/arch/arm/mach-omap2/omap_hwmod.c @@ -1517,8 +1517,8 @@ static int _enable(struct omap_hwmod *oh) if (oh->_state != _HWMOD_STATE_INITIALIZED && oh->_state != _HWMOD_STATE_IDLE && oh->_state != _HWMOD_STATE_DISABLED) { - WARN(1, "omap_hwmod: %s: enabled state can only be entered from initialized, idle, or disabled state\n", - oh->name); + WARN(1, "omap_hwmod: %s: enabled state can only be entered " + "from initialized, idle, or disabled state\n", oh->name); return -EINVAL; } @@ -1600,8 +1600,8 @@ static int _idle(struct omap_hwmod *oh) pr_debug("omap_hwmod: %s: idling\n", oh->name); if (oh->_state != _HWMOD_STATE_ENABLED) { - WARN(1, "omap_hwmod: %s: idle state can only be entered from enabled state\n", - oh->name); + WARN(1, "omap_hwmod: %s: idle state can only be entered from " + "enabled state\n", oh->name); return -EINVAL; } @@ -1682,8 +1682,8 @@ static int _shutdown(struct omap_hwmod *oh) if (oh->_state != _HWMOD_STATE_IDLE && oh->_state != _HWMOD_STATE_ENABLED) { - WARN(1, "omap_hwmod: %s: disabled state can only be entered from idle, or enabled state\n", - oh->name); + WARN(1, "omap_hwmod: %s: disabled state can only be entered " + "from idle, or enabled state\n", oh->name); return -EINVAL; } @@ -2240,8 +2240,8 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh) BUG_ON(!oh); if (!oh->class->sysc || !oh->class->sysc->sysc_flags) { - WARN(1, "omap_device: %s: OCP barrier impossible due to device configuration\n", - oh->name); + WARN(1, "omap_device: %s: OCP barrier impossible due to " + "device configuration\n", oh->name); return; } diff --git a/trunk/arch/arm/mach-omap2/prm44xx.c b/trunk/arch/arm/mach-omap2/prm44xx.c index a1d6154dc120..33dd655e6aab 100644 --- a/trunk/arch/arm/mach-omap2/prm44xx.c +++ b/trunk/arch/arm/mach-omap2/prm44xx.c @@ -19,7 +19,6 @@ #include "common.h" #include -#include #include #include "vp.h" diff --git a/trunk/arch/arm/mach-omap2/vc.c b/trunk/arch/arm/mach-omap2/vc.c index 175b7d86d86a..031d116fbf10 100644 --- a/trunk/arch/arm/mach-omap2/vc.c +++ b/trunk/arch/arm/mach-omap2/vc.c @@ -247,7 +247,7 @@ static void __init omap4_vc_init_channel(struct voltagedomain *voltdm) * omap_vc_i2c_init - initialize I2C interface to PMIC * @voltdm: voltage domain containing VC data * - * Use PMIC supplied settings for I2C high-speed mode and + * Use PMIC supplied seetings for I2C high-speed mode and * master code (if set) and program the VC I2C configuration * register. * @@ -265,8 +265,8 @@ static void __init omap_vc_i2c_init(struct voltagedomain *voltdm) if (initialized) { if (voltdm->pmic->i2c_high_speed != i2c_high_speed) - pr_warn("%s: I2C config for vdd_%s does not match other channels (%u).", - __func__, voltdm->name, i2c_high_speed); + pr_warn("%s: I2C config for all channels must match.", + __func__); return; } @@ -292,7 +292,9 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm) u32 val; if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { - pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name); + pr_err("%s: PMIC info requried to configure vc for" + "vdd_%s not populated.Hence cannot initialize vc\n", + __func__, voltdm->name); return; } diff --git a/trunk/arch/arm/mach-omap2/vp.c b/trunk/arch/arm/mach-omap2/vp.c index 0df88820978d..807391d84a9d 100644 --- a/trunk/arch/arm/mach-omap2/vp.c +++ b/trunk/arch/arm/mach-omap2/vp.c @@ -41,11 +41,6 @@ void __init omap_vp_init(struct voltagedomain *voltdm) u32 val, sys_clk_rate, timeout, waittime; u32 vddmin, vddmax, vstepmin, vstepmax; - if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) { - pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name); - return; - } - if (!voltdm->read || !voltdm->write) { pr_err("%s: No read/write API for accessing vdd_%s regs\n", __func__, voltdm->name); diff --git a/trunk/arch/arm/mm/cache-v7.S b/trunk/arch/arm/mm/cache-v7.S index 7a24d39661f0..07c4bc8ea0a4 100644 --- a/trunk/arch/arm/mm/cache-v7.S +++ b/trunk/arch/arm/mm/cache-v7.S @@ -54,15 +54,9 @@ loop1: and r1, r1, #7 @ mask of the bits for current cache only cmp r1, #2 @ see what cache we have at this level blt skip @ skip if no cache, or just i-cache -#ifdef CONFIG_PREEMPT - save_and_disable_irqs r9 @ make cssr&csidr read atomic -#endif mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr isb @ isb to sych the new cssr&csidr mrc p15, 1, r1, c0, c0, 0 @ read the new csidr -#ifdef CONFIG_PREEMPT - restore_irqs_notrace r9 -#endif and r2, r1, #7 @ extract the length of the cache lines add r2, r2, #4 @ add 4 (line length offset) ldr r4, =0x3ff diff --git a/trunk/arch/powerpc/kernel/process.c b/trunk/arch/powerpc/kernel/process.c index ebe5766781aa..d817ab018486 100644 --- a/trunk/arch/powerpc/kernel/process.c +++ b/trunk/arch/powerpc/kernel/process.c @@ -566,12 +566,12 @@ static void show_instructions(struct pt_regs *regs) */ if (!__kernel_text_address(pc) || __get_user(instr, (unsigned int __user *)pc)) { - printk("XXXXXXXX "); + printk(KERN_CONT "XXXXXXXX "); } else { if (regs->nip == pc) - printk("<%08x> ", instr); + printk(KERN_CONT "<%08x> ", instr); else - printk("%08x ", instr); + printk(KERN_CONT "%08x ", instr); } pc += sizeof(int); diff --git a/trunk/arch/x86/include/asm/i387.h b/trunk/arch/x86/include/asm/i387.h index a850b4d8d14d..6919e936345b 100644 --- a/trunk/arch/x86/include/asm/i387.h +++ b/trunk/arch/x86/include/asm/i387.h @@ -29,8 +29,8 @@ extern unsigned int sig_xstate_size; extern void fpu_init(void); extern void mxcsr_feature_mask_init(void); extern int init_fpu(struct task_struct *child); -extern void __math_state_restore(struct task_struct *); -extern void math_state_restore(void); +extern asmlinkage void math_state_restore(void); +extern void __math_state_restore(void); extern int dump_fpu(struct pt_regs *, struct user_i387_struct *); extern user_regset_active_fn fpregs_active, xfpregs_active; @@ -212,11 +212,19 @@ static inline void fpu_fxsave(struct fpu *fpu) #endif /* CONFIG_X86_64 */ +/* We need a safe address that is cheap to find and that is already + in L1 during context switch. The best choices are unfortunately + different for UP and SMP */ +#ifdef CONFIG_SMP +#define safe_address (__per_cpu_offset[0]) +#else +#define safe_address (__get_cpu_var(kernel_cpustat).cpustat[CPUTIME_USER]) +#endif + /* - * These must be called with preempt disabled. Returns - * 'true' if the FPU state is still intact. + * These must be called with preempt disabled */ -static inline int fpu_save_init(struct fpu *fpu) +static inline void fpu_save_init(struct fpu *fpu) { if (use_xsave()) { fpu_xsave(fpu); @@ -225,33 +233,33 @@ static inline int fpu_save_init(struct fpu *fpu) * xsave header may indicate the init state of the FP. */ if (!(fpu->state->xsave.xsave_hdr.xstate_bv & XSTATE_FP)) - return 1; + return; } else if (use_fxsr()) { fpu_fxsave(fpu); } else { asm volatile("fnsave %[fx]; fwait" : [fx] "=m" (fpu->state->fsave)); - return 0; + return; } - /* - * If exceptions are pending, we need to clear them so - * that we don't randomly get exceptions later. - * - * FIXME! Is this perhaps only true for the old-style - * irq13 case? Maybe we could leave the x87 state - * intact otherwise? - */ - if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) { + if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) asm volatile("fnclex"); - return 0; - } - return 1; + + /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception + is pending. Clear the x87 state here by setting it to fixed + values. safe_address is a random variable that should be in L1 */ + alternative_input( + ASM_NOP8 ASM_NOP2, + "emms\n\t" /* clear stack tags */ + "fildl %P[addr]", /* set F?P to defined value */ + X86_FEATURE_FXSAVE_LEAK, + [addr] "m" (safe_address)); } -static inline int __save_init_fpu(struct task_struct *tsk) +static inline void __save_init_fpu(struct task_struct *tsk) { - return fpu_save_init(&tsk->thread.fpu); + fpu_save_init(&tsk->thread.fpu); + task_thread_info(tsk)->status &= ~TS_USEDFPU; } static inline int fpu_fxrstor_checking(struct fpu *fpu) @@ -272,186 +280,40 @@ static inline int restore_fpu_checking(struct task_struct *tsk) return fpu_restore_checking(&tsk->thread.fpu); } -/* - * Software FPU state helpers. Careful: these need to - * be preemption protection *and* they need to be - * properly paired with the CR0.TS changes! - */ -static inline int __thread_has_fpu(struct task_struct *tsk) -{ - return tsk->thread.has_fpu; -} - -/* Must be paired with an 'stts' after! */ -static inline void __thread_clear_has_fpu(struct task_struct *tsk) -{ - tsk->thread.has_fpu = 0; -} - -/* Must be paired with a 'clts' before! */ -static inline void __thread_set_has_fpu(struct task_struct *tsk) -{ - tsk->thread.has_fpu = 1; -} - -/* - * Encapsulate the CR0.TS handling together with the - * software flag. - * - * These generally need preemption protection to work, - * do try to avoid using these on their own. - */ -static inline void __thread_fpu_end(struct task_struct *tsk) -{ - __thread_clear_has_fpu(tsk); - stts(); -} - -static inline void __thread_fpu_begin(struct task_struct *tsk) -{ - clts(); - __thread_set_has_fpu(tsk); -} - -/* - * FPU state switching for scheduling. - * - * This is a two-stage process: - * - * - switch_fpu_prepare() saves the old state and - * sets the new state of the CR0.TS bit. This is - * done within the context of the old process. - * - * - switch_fpu_finish() restores the new state as - * necessary. - */ -typedef struct { int preload; } fpu_switch_t; - -/* - * FIXME! We could do a totally lazy restore, but we need to - * add a per-cpu "this was the task that last touched the FPU - * on this CPU" variable, and the task needs to have a "I last - * touched the FPU on this CPU" and check them. - * - * We don't do that yet, so "fpu_lazy_restore()" always returns - * false, but some day.. - */ -#define fpu_lazy_restore(tsk) (0) -#define fpu_lazy_state_intact(tsk) do { } while (0) - -static inline fpu_switch_t switch_fpu_prepare(struct task_struct *old, struct task_struct *new) -{ - fpu_switch_t fpu; - - fpu.preload = tsk_used_math(new) && new->fpu_counter > 5; - if (__thread_has_fpu(old)) { - if (__save_init_fpu(old)) - fpu_lazy_state_intact(old); - __thread_clear_has_fpu(old); - old->fpu_counter++; - - /* Don't change CR0.TS if we just switch! */ - if (fpu.preload) { - __thread_set_has_fpu(new); - prefetch(new->thread.fpu.state); - } else - stts(); - } else { - old->fpu_counter = 0; - if (fpu.preload) { - if (fpu_lazy_restore(new)) - fpu.preload = 0; - else - prefetch(new->thread.fpu.state); - __thread_fpu_begin(new); - } - } - return fpu; -} - -/* - * By the time this gets called, we've already cleared CR0.TS and - * given the process the FPU if we are going to preload the FPU - * state - all we need to do is to conditionally restore the register - * state itself. - */ -static inline void switch_fpu_finish(struct task_struct *new, fpu_switch_t fpu) -{ - if (fpu.preload) - __math_state_restore(new); -} - /* * Signal frame handlers... */ extern int save_i387_xstate(void __user *buf); extern int restore_i387_xstate(void __user *buf); +static inline void __unlazy_fpu(struct task_struct *tsk) +{ + if (task_thread_info(tsk)->status & TS_USEDFPU) { + __save_init_fpu(tsk); + stts(); + } else + tsk->fpu_counter = 0; +} + static inline void __clear_fpu(struct task_struct *tsk) { - if (__thread_has_fpu(tsk)) { + if (task_thread_info(tsk)->status & TS_USEDFPU) { /* Ignore delayed exceptions from user space */ asm volatile("1: fwait\n" "2:\n" _ASM_EXTABLE(1b, 2b)); - __thread_fpu_end(tsk); + task_thread_info(tsk)->status &= ~TS_USEDFPU; + stts(); } } -/* - * Were we in an interrupt that interrupted kernel mode? - * - * We can do a kernel_fpu_begin/end() pair *ONLY* if that - * pair does nothing at all: the thread must not have fpu (so - * that we don't try to save the FPU state), and TS must - * be set (so that the clts/stts pair does nothing that is - * visible in the interrupted kernel thread). - */ -static inline bool interrupted_kernel_fpu_idle(void) -{ - return !__thread_has_fpu(current) && - (read_cr0() & X86_CR0_TS); -} - -/* - * Were we in user mode (or vm86 mode) when we were - * interrupted? - * - * Doing kernel_fpu_begin/end() is ok if we are running - * in an interrupt context from user mode - we'll just - * save the FPU state as required. - */ -static inline bool interrupted_user_mode(void) -{ - struct pt_regs *regs = get_irq_regs(); - return regs && user_mode_vm(regs); -} - -/* - * Can we use the FPU in kernel mode with the - * whole "kernel_fpu_begin/end()" sequence? - * - * It's always ok in process context (ie "not interrupt") - * but it is sometimes ok even from an irq. - */ -static inline bool irq_fpu_usable(void) -{ - return !in_interrupt() || - interrupted_user_mode() || - interrupted_kernel_fpu_idle(); -} - static inline void kernel_fpu_begin(void) { - struct task_struct *me = current; - - WARN_ON_ONCE(!irq_fpu_usable()); + struct thread_info *me = current_thread_info(); preempt_disable(); - if (__thread_has_fpu(me)) { - __save_init_fpu(me); - __thread_clear_has_fpu(me); - /* We do 'stts()' in kernel_fpu_end() */ - } else + if (me->status & TS_USEDFPU) + __save_init_fpu(me->task); + else clts(); } @@ -461,6 +323,14 @@ static inline void kernel_fpu_end(void) preempt_enable(); } +static inline bool irq_fpu_usable(void) +{ + struct pt_regs *regs; + + return !in_interrupt() || !(regs = get_irq_regs()) || \ + user_mode(regs) || (read_cr0() & X86_CR0_TS); +} + /* * Some instructions like VIA's padlock instructions generate a spurious * DNA fault but don't modify SSE registers. And these instructions @@ -492,65 +362,21 @@ static inline void irq_ts_restore(int TS_state) stts(); } -/* - * The question "does this thread have fpu access?" - * is slightly racy, since preemption could come in - * and revoke it immediately after the test. - * - * However, even in that very unlikely scenario, - * we can just assume we have FPU access - typically - * to save the FP state - we'll just take a #NM - * fault and get the FPU access back. - * - * The actual user_fpu_begin/end() functions - * need to be preemption-safe, though. - * - * NOTE! user_fpu_end() must be used only after you - * have saved the FP state, and user_fpu_begin() must - * be used only immediately before restoring it. - * These functions do not do any save/restore on - * their own. - */ -static inline int user_has_fpu(void) -{ - return __thread_has_fpu(current); -} - -static inline void user_fpu_end(void) -{ - preempt_disable(); - __thread_fpu_end(current); - preempt_enable(); -} - -static inline void user_fpu_begin(void) -{ - preempt_disable(); - if (!user_has_fpu()) - __thread_fpu_begin(current); - preempt_enable(); -} - /* * These disable preemption on their own and are safe */ static inline void save_init_fpu(struct task_struct *tsk) { - WARN_ON_ONCE(!__thread_has_fpu(tsk)); preempt_disable(); __save_init_fpu(tsk); - __thread_fpu_end(tsk); + stts(); preempt_enable(); } static inline void unlazy_fpu(struct task_struct *tsk) { preempt_disable(); - if (__thread_has_fpu(tsk)) { - __save_init_fpu(tsk); - __thread_fpu_end(tsk); - } else - tsk->fpu_counter = 0; + __unlazy_fpu(tsk); preempt_enable(); } diff --git a/trunk/arch/x86/include/asm/processor.h b/trunk/arch/x86/include/asm/processor.h index f7c89e231c6c..aa9088c26931 100644 --- a/trunk/arch/x86/include/asm/processor.h +++ b/trunk/arch/x86/include/asm/processor.h @@ -454,7 +454,6 @@ struct thread_struct { unsigned long trap_no; unsigned long error_code; /* floating point and extended processor state */ - unsigned long has_fpu; struct fpu fpu; #ifdef CONFIG_X86_32 /* Virtual 86 mode info */ diff --git a/trunk/arch/x86/include/asm/thread_info.h b/trunk/arch/x86/include/asm/thread_info.h index cfd8144d5527..bc817cd8b443 100644 --- a/trunk/arch/x86/include/asm/thread_info.h +++ b/trunk/arch/x86/include/asm/thread_info.h @@ -247,6 +247,8 @@ static inline struct thread_info *current_thread_info(void) * ever touches our thread-synchronous status, so we don't * have to worry about atomic accesses. */ +#define TS_USEDFPU 0x0001 /* FPU was used by this task + this quantum (SMP) */ #define TS_COMPAT 0x0002 /* 32bit syscall active (64BIT)*/ #define TS_POLLING 0x0004 /* idle task polling need_resched, skip sending interrupt */ diff --git a/trunk/arch/x86/kernel/process_32.c b/trunk/arch/x86/kernel/process_32.c index 80bfe1ab0031..485204f58cda 100644 --- a/trunk/arch/x86/kernel/process_32.c +++ b/trunk/arch/x86/kernel/process_32.c @@ -299,11 +299,22 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) *next = &next_p->thread; int cpu = smp_processor_id(); struct tss_struct *tss = &per_cpu(init_tss, cpu); - fpu_switch_t fpu; + bool preload_fpu; /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ - fpu = switch_fpu_prepare(prev_p, next_p); + /* + * If the task has used fpu the last 5 timeslices, just do a full + * restore of the math state immediately to avoid the trap; the + * chances of needing FPU soon are obviously high now + */ + preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5; + + __unlazy_fpu(prev_p); + + /* we're going to use this soon, after a few expensive things */ + if (preload_fpu) + prefetch(next->fpu.state); /* * Reload esp0. @@ -343,6 +354,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) task_thread_info(next_p)->flags & _TIF_WORK_CTXSW_NEXT)) __switch_to_xtra(prev_p, next_p, tss); + /* If we're going to preload the fpu context, make sure clts + is run while we're batching the cpu state updates. */ + if (preload_fpu) + clts(); + /* * Leave lazy mode, flushing any hypercalls made here. * This must be done before restoring TLS segments so @@ -352,14 +368,15 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) */ arch_end_context_switch(next_p); + if (preload_fpu) + __math_state_restore(); + /* * Restore %gs if needed (which is common) */ if (prev->gs | next->gs) lazy_load_gs(next->gs); - switch_fpu_finish(next_p, fpu); - percpu_write(current_task, next_p); return prev_p; diff --git a/trunk/arch/x86/kernel/process_64.c b/trunk/arch/x86/kernel/process_64.c index 1fd94bc4279d..9b9fe4a85c87 100644 --- a/trunk/arch/x86/kernel/process_64.c +++ b/trunk/arch/x86/kernel/process_64.c @@ -386,9 +386,18 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) int cpu = smp_processor_id(); struct tss_struct *tss = &per_cpu(init_tss, cpu); unsigned fsindex, gsindex; - fpu_switch_t fpu; + bool preload_fpu; - fpu = switch_fpu_prepare(prev_p, next_p); + /* + * If the task has used fpu the last 5 timeslices, just do a full + * restore of the math state immediately to avoid the trap; the + * chances of needing FPU soon are obviously high now + */ + preload_fpu = tsk_used_math(next_p) && next_p->fpu_counter > 5; + + /* we're going to use this soon, after a few expensive things */ + if (preload_fpu) + prefetch(next->fpu.state); /* * Reload esp0, LDT and the page table pointer: @@ -418,6 +427,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) load_TLS(next, cpu); + /* Must be after DS reload */ + __unlazy_fpu(prev_p); + + /* Make sure cpu is ready for new context */ + if (preload_fpu) + clts(); + /* * Leave lazy mode, flushing any hypercalls made here. * This must be done before restoring TLS segments so @@ -458,8 +474,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) wrmsrl(MSR_KERNEL_GS_BASE, next->gs); prev->gsindex = gsindex; - switch_fpu_finish(next_p, fpu); - /* * Switch the PDA and FPU contexts. */ @@ -478,6 +492,13 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) task_thread_info(prev_p)->flags & _TIF_WORK_CTXSW_PREV)) __switch_to_xtra(prev_p, next_p, tss); + /* + * Preload the FPU context, now that we've determined that the + * task is likely to be using it. + */ + if (preload_fpu) + __math_state_restore(); + return prev_p; } diff --git a/trunk/arch/x86/kernel/traps.c b/trunk/arch/x86/kernel/traps.c index 77da5b475ad2..482ec3af2067 100644 --- a/trunk/arch/x86/kernel/traps.c +++ b/trunk/arch/x86/kernel/traps.c @@ -571,34 +571,25 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void) } /* - * This gets called with the process already owning the - * FPU state, and with CR0.TS cleared. It just needs to - * restore the FPU register state. + * __math_state_restore assumes that cr0.TS is already clear and the + * fpu state is all ready for use. Used during context switch. */ -void __math_state_restore(struct task_struct *tsk) +void __math_state_restore(void) { - /* We need a safe address that is cheap to find and that is already - in L1. We've just brought in "tsk->thread.has_fpu", so use that */ -#define safe_address (tsk->thread.has_fpu) - - /* AMD K7/K8 CPUs don't save/restore FDP/FIP/FOP unless an exception - is pending. Clear the x87 state here by setting it to fixed - values. safe_address is a random variable that should be in L1 */ - alternative_input( - ASM_NOP8 ASM_NOP2, - "emms\n\t" /* clear stack tags */ - "fildl %P[addr]", /* set F?P to defined value */ - X86_FEATURE_FXSAVE_LEAK, - [addr] "m" (safe_address)); + struct thread_info *thread = current_thread_info(); + struct task_struct *tsk = thread->task; /* * Paranoid restore. send a SIGSEGV if we fail to restore the state. */ if (unlikely(restore_fpu_checking(tsk))) { - __thread_fpu_end(tsk); + stts(); force_sig(SIGSEGV, tsk); return; } + + thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ + tsk->fpu_counter++; } /* @@ -608,12 +599,13 @@ void __math_state_restore(struct task_struct *tsk) * Careful.. There are problems with IBM-designed IRQ13 behaviour. * Don't touch unless you *really* know how it works. * - * Must be called with kernel preemption disabled (eg with local - * local interrupts as in the case of do_device_not_available). + * Must be called with kernel preemption disabled (in this case, + * local interrupts are disabled at the call-site in entry.S). */ -void math_state_restore(void) +asmlinkage void math_state_restore(void) { - struct task_struct *tsk = current; + struct thread_info *thread = current_thread_info(); + struct task_struct *tsk = thread->task; if (!tsk_used_math(tsk)) { local_irq_enable(); @@ -630,10 +622,9 @@ void math_state_restore(void) local_irq_disable(); } - __thread_fpu_begin(tsk); - __math_state_restore(tsk); + clts(); /* Allow maths ops (or we recurse) */ - tsk->fpu_counter++; + __math_state_restore(); } EXPORT_SYMBOL_GPL(math_state_restore); diff --git a/trunk/arch/x86/kernel/xsave.c b/trunk/arch/x86/kernel/xsave.c index 711091114119..a3911343976b 100644 --- a/trunk/arch/x86/kernel/xsave.c +++ b/trunk/arch/x86/kernel/xsave.c @@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_struct *tsk) if (!fx) return; - BUG_ON(__thread_has_fpu(tsk)); + BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU); xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv; @@ -168,7 +168,7 @@ int save_i387_xstate(void __user *buf) if (!used_math()) return 0; - if (user_has_fpu()) { + if (task_thread_info(tsk)->status & TS_USEDFPU) { if (use_xsave()) err = xsave_user(buf); else @@ -176,7 +176,8 @@ int save_i387_xstate(void __user *buf) if (err) return err; - user_fpu_end(); + task_thread_info(tsk)->status &= ~TS_USEDFPU; + stts(); } else { sanitize_i387_state(tsk); if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, @@ -291,7 +292,10 @@ int restore_i387_xstate(void __user *buf) return err; } - user_fpu_begin(); + if (!(task_thread_info(current)->status & TS_USEDFPU)) { + clts(); + task_thread_info(current)->status |= TS_USEDFPU; + } if (use_xsave()) err = restore_user_xstate(buf); else diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index 3b4c8d8ad906..d29216c462b3 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -1457,7 +1457,7 @@ static void __vmx_load_host_state(struct vcpu_vmx *vmx) #ifdef CONFIG_X86_64 wrmsrl(MSR_KERNEL_GS_BASE, vmx->msr_host_kernel_gs_base); #endif - if (__thread_has_fpu(current)) + if (current_thread_info()->status & TS_USEDFPU) clts(); load_gdt(&__get_cpu_var(host_gdt)); } diff --git a/trunk/arch/x86/pci/xen.c b/trunk/arch/x86/pci/xen.c index d99346ea8fdb..492ade8c978e 100644 --- a/trunk/arch/x86/pci/xen.c +++ b/trunk/arch/x86/pci/xen.c @@ -374,7 +374,7 @@ int __init pci_xen_init(void) int __init pci_xen_hvm_init(void) { - if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) + if (!xen_feature(XENFEAT_hvm_pirqs)) return 0; #ifdef CONFIG_ACPI diff --git a/trunk/arch/x86/xen/smp.c b/trunk/arch/x86/xen/smp.c index 501d4e0244ba..041d4fe9dfe4 100644 --- a/trunk/arch/x86/xen/smp.c +++ b/trunk/arch/x86/xen/smp.c @@ -409,13 +409,6 @@ static void __cpuinit xen_play_dead(void) /* used only with HOTPLUG_CPU */ play_dead_common(); HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL); cpu_bringup(); - /* - * Balance out the preempt calls - as we are running in cpu_idle - * loop which has been called at bootup from cpu_bringup_and_idle. - * The cpucpu_bringup_and_idle called cpu_bringup which made a - * preempt_disable() So this preempt_enable will balance it out. - */ - preempt_enable(); } #else /* !CONFIG_HOTPLUG_CPU */ diff --git a/trunk/crypto/sha512_generic.c b/trunk/crypto/sha512_generic.c index 107f6f7be5e1..88f160b77b1f 100644 --- a/trunk/crypto/sha512_generic.c +++ b/trunk/crypto/sha512_generic.c @@ -31,6 +31,11 @@ static inline u64 Maj(u64 x, u64 y, u64 z) return (x & y) | (z & (x | y)); } +static inline u64 RORu64(u64 x, u64 y) +{ + return (x >> y) | (x << (64 - y)); +} + static const u64 sha512_K[80] = { 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL, 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, @@ -61,10 +66,10 @@ static const u64 sha512_K[80] = { 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, }; -#define e0(x) (ror64(x,28) ^ ror64(x,34) ^ ror64(x,39)) -#define e1(x) (ror64(x,14) ^ ror64(x,18) ^ ror64(x,41)) -#define s0(x) (ror64(x, 1) ^ ror64(x, 8) ^ (x >> 7)) -#define s1(x) (ror64(x,19) ^ ror64(x,61) ^ (x >> 6)) +#define e0(x) (RORu64(x,28) ^ RORu64(x,34) ^ RORu64(x,39)) +#define e1(x) (RORu64(x,14) ^ RORu64(x,18) ^ RORu64(x,41)) +#define s0(x) (RORu64(x, 1) ^ RORu64(x, 8) ^ (x >> 7)) +#define s1(x) (RORu64(x,19) ^ RORu64(x,61) ^ (x >> 6)) static inline void LOAD_OP(int I, u64 *W, const u8 *input) { @@ -73,7 +78,7 @@ static inline void LOAD_OP(int I, u64 *W, const u8 *input) static inline void BLEND_OP(int I, u64 *W) { - W[I & 15] += s1(W[(I-2) & 15]) + W[(I-7) & 15] + s0(W[(I-15) & 15]); + W[I % 16] += s1(W[(I-2) % 16]) + W[(I-7) % 16] + s0(W[(I-15) % 16]); } static void @@ -84,42 +89,46 @@ sha512_transform(u64 *state, const u8 *input) int i; u64 W[16]; + /* load the input */ + for (i = 0; i < 16; i++) + LOAD_OP(i, W, input); + /* load the state into our registers */ a=state[0]; b=state[1]; c=state[2]; d=state[3]; e=state[4]; f=state[5]; g=state[6]; h=state[7]; - /* now iterate */ - for (i=0; i<80; i+=8) { - if (!(i & 8)) { - int j; - - if (i < 16) { - /* load the input */ - for (j = 0; j < 16; j++) - LOAD_OP(i + j, W, input); - } else { - for (j = 0; j < 16; j++) { - BLEND_OP(i + j, W); - } - } - } - - t1 = h + e1(e) + Ch(e,f,g) + sha512_K[i ] + W[(i & 15)]; - t2 = e0(a) + Maj(a,b,c); d+=t1; h=t1+t2; - t1 = g + e1(d) + Ch(d,e,f) + sha512_K[i+1] + W[(i & 15) + 1]; - t2 = e0(h) + Maj(h,a,b); c+=t1; g=t1+t2; - t1 = f + e1(c) + Ch(c,d,e) + sha512_K[i+2] + W[(i & 15) + 2]; - t2 = e0(g) + Maj(g,h,a); b+=t1; f=t1+t2; - t1 = e + e1(b) + Ch(b,c,d) + sha512_K[i+3] + W[(i & 15) + 3]; - t2 = e0(f) + Maj(f,g,h); a+=t1; e=t1+t2; - t1 = d + e1(a) + Ch(a,b,c) + sha512_K[i+4] + W[(i & 15) + 4]; - t2 = e0(e) + Maj(e,f,g); h+=t1; d=t1+t2; - t1 = c + e1(h) + Ch(h,a,b) + sha512_K[i+5] + W[(i & 15) + 5]; - t2 = e0(d) + Maj(d,e,f); g+=t1; c=t1+t2; - t1 = b + e1(g) + Ch(g,h,a) + sha512_K[i+6] + W[(i & 15) + 6]; - t2 = e0(c) + Maj(c,d,e); f+=t1; b=t1+t2; - t1 = a + e1(f) + Ch(f,g,h) + sha512_K[i+7] + W[(i & 15) + 7]; - t2 = e0(b) + Maj(b,c,d); e+=t1; a=t1+t2; +#define SHA512_0_15(i, a, b, c, d, e, f, g, h) \ + t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[i]; \ + t2 = e0(a) + Maj(a, b, c); \ + d += t1; \ + h = t1 + t2 + +#define SHA512_16_79(i, a, b, c, d, e, f, g, h) \ + BLEND_OP(i, W); \ + t1 = h + e1(e) + Ch(e, f, g) + sha512_K[i] + W[(i)%16]; \ + t2 = e0(a) + Maj(a, b, c); \ + d += t1; \ + h = t1 + t2 + + for (i = 0; i < 16; i += 8) { + SHA512_0_15(i, a, b, c, d, e, f, g, h); + SHA512_0_15(i + 1, h, a, b, c, d, e, f, g); + SHA512_0_15(i + 2, g, h, a, b, c, d, e, f); + SHA512_0_15(i + 3, f, g, h, a, b, c, d, e); + SHA512_0_15(i + 4, e, f, g, h, a, b, c, d); + SHA512_0_15(i + 5, d, e, f, g, h, a, b, c); + SHA512_0_15(i + 6, c, d, e, f, g, h, a, b); + SHA512_0_15(i + 7, b, c, d, e, f, g, h, a); + } + for (i = 16; i < 80; i += 8) { + SHA512_16_79(i, a, b, c, d, e, f, g, h); + SHA512_16_79(i + 1, h, a, b, c, d, e, f, g); + SHA512_16_79(i + 2, g, h, a, b, c, d, e, f); + SHA512_16_79(i + 3, f, g, h, a, b, c, d, e); + SHA512_16_79(i + 4, e, f, g, h, a, b, c, d); + SHA512_16_79(i + 5, d, e, f, g, h, a, b, c); + SHA512_16_79(i + 6, c, d, e, f, g, h, a, b); + SHA512_16_79(i + 7, b, c, d, e, f, g, h, a); } state[0] += a; state[1] += b; state[2] += c; state[3] += d; diff --git a/trunk/drivers/gpu/drm/radeon/r100.c b/trunk/drivers/gpu/drm/radeon/r100.c index 18cd84fae99c..bfd36ab643a6 100644 --- a/trunk/drivers/gpu/drm/radeon/r100.c +++ b/trunk/drivers/gpu/drm/radeon/r100.c @@ -789,7 +789,9 @@ int r100_irq_process(struct radeon_device *rdev) WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM); break; default: - WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); + msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN; + WREG32(RADEON_MSI_REARM_EN, msi_rearm); + WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN); break; } } diff --git a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c index 9e72daeeddc6..5082d17d14dc 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2931,20 +2931,6 @@ radeon_atombios_connected_scratch_regs(struct drm_connector *connector, bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP5; } } - if ((radeon_encoder->devices & ATOM_DEVICE_DFP6_SUPPORT) && - (radeon_connector->devices & ATOM_DEVICE_DFP6_SUPPORT)) { - if (connected) { - DRM_DEBUG_KMS("DFP6 connected\n"); - bios_0_scratch |= ATOM_S0_DFP6; - bios_3_scratch |= ATOM_S3_DFP6_ACTIVE; - bios_6_scratch |= ATOM_S6_ACC_REQ_DFP6; - } else { - DRM_DEBUG_KMS("DFP6 disconnected\n"); - bios_0_scratch &= ~ATOM_S0_DFP6; - bios_3_scratch &= ~ATOM_S3_DFP6_ACTIVE; - bios_6_scratch &= ~ATOM_S6_ACC_REQ_DFP6; - } - } if (rdev->family >= CHIP_R600) { WREG32(R600_BIOS_0_SCRATCH, bios_0_scratch); @@ -2965,9 +2951,6 @@ radeon_atombios_encoder_crtc_scratch_regs(struct drm_encoder *encoder, int crtc) struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); uint32_t bios_3_scratch; - if (ASIC_IS_DCE4(rdev)) - return; - if (rdev->family >= CHIP_R600) bios_3_scratch = RREG32(R600_BIOS_3_SCRATCH); else diff --git a/trunk/drivers/gpu/drm/radeon/radeon_fence.c b/trunk/drivers/gpu/drm/radeon/radeon_fence.c index 4bd36a354fbe..64ea3dd9e6ff 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_fence.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_fence.c @@ -364,10 +364,8 @@ int radeon_fence_count_emitted(struct radeon_device *rdev, int ring) int not_processed = 0; read_lock_irqsave(&rdev->fence_lock, irq_flags); - if (!rdev->fence_drv[ring].initialized) { - read_unlock_irqrestore(&rdev->fence_lock, irq_flags); + if (!rdev->fence_drv[ring].initialized) return 0; - } if (!list_empty(&rdev->fence_drv[ring].emitted)) { struct list_head *ptr; diff --git a/trunk/drivers/gpu/drm/radeon/rs600.c b/trunk/drivers/gpu/drm/radeon/rs600.c index c05865e5521f..ec46eb45e34c 100644 --- a/trunk/drivers/gpu/drm/radeon/rs600.c +++ b/trunk/drivers/gpu/drm/radeon/rs600.c @@ -684,7 +684,9 @@ int rs600_irq_process(struct radeon_device *rdev) WREG32(RADEON_BUS_CNTL, msi_rearm | RS600_MSI_REARM); break; default: - WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); + msi_rearm = RREG32(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN; + WREG32(RADEON_MSI_REARM_EN, msi_rearm); + WREG32(RADEON_MSI_REARM_EN, msi_rearm | RV370_MSI_REARM_EN); break; } } diff --git a/trunk/drivers/mfd/Kconfig b/trunk/drivers/mfd/Kconfig index f147395bac9a..cd13e9f2f5e6 100644 --- a/trunk/drivers/mfd/Kconfig +++ b/trunk/drivers/mfd/Kconfig @@ -200,7 +200,7 @@ config MENELAUS config TWL4030_CORE bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" - depends on I2C=y && GENERIC_HARDIRQS + depends on I2C=y && GENERIC_HARDIRQS && IRQ_DOMAIN help Say yes here if you have TWL4030 / TWL6030 family chip on your board. This core driver provides register access and IRQ handling diff --git a/trunk/drivers/mfd/twl-core.c b/trunk/drivers/mfd/twl-core.c index 8ce3959c6919..e04e04ddc15e 100644 --- a/trunk/drivers/mfd/twl-core.c +++ b/trunk/drivers/mfd/twl-core.c @@ -263,9 +263,7 @@ struct twl_client { static struct twl_client twl_modules[TWL_NUM_SLAVES]; -#ifdef CONFIG_IRQ_DOMAIN static struct irq_domain domain; -#endif /* mapping the module id to slave id and base address */ struct twl_mapping { @@ -1228,13 +1226,13 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id) pdata->irq_base = status; pdata->irq_end = pdata->irq_base + nr_irqs; -#ifdef CONFIG_IRQ_DOMAIN domain.irq_base = pdata->irq_base; domain.nr_irq = nr_irqs; +#ifdef CONFIG_OF_IRQ domain.of_node = of_node_get(node); domain.ops = &irq_domain_simple_ops; - irq_domain_add(&domain); #endif + irq_domain_add(&domain); if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { dev_dbg(&client->dev, "can't talk I2C?\n"); diff --git a/trunk/drivers/mfd/twl4030-power.c b/trunk/drivers/mfd/twl4030-power.c index 79ca33dfacca..d905f5171153 100644 --- a/trunk/drivers/mfd/twl4030-power.c +++ b/trunk/drivers/mfd/twl4030-power.c @@ -124,7 +124,7 @@ static u8 res_config_addrs[] = { [RES_MAIN_REF] = 0x94, }; -static int __devinit twl4030_write_script_byte(u8 address, u8 byte) +static int __init twl4030_write_script_byte(u8 address, u8 byte) { int err; @@ -138,7 +138,7 @@ static int __devinit twl4030_write_script_byte(u8 address, u8 byte) return err; } -static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message, +static int __init twl4030_write_script_ins(u8 address, u16 pmb_message, u8 delay, u8 next) { int err; @@ -158,7 +158,7 @@ static int __devinit twl4030_write_script_ins(u8 address, u16 pmb_message, return err; } -static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script, +static int __init twl4030_write_script(u8 address, struct twl4030_ins *script, int len) { int err; @@ -183,7 +183,7 @@ static int __devinit twl4030_write_script(u8 address, struct twl4030_ins *script return err; } -static int __devinit twl4030_config_wakeup3_sequence(u8 address) +static int __init twl4030_config_wakeup3_sequence(u8 address) { int err; u8 data; @@ -208,7 +208,7 @@ static int __devinit twl4030_config_wakeup3_sequence(u8 address) return err; } -static int __devinit twl4030_config_wakeup12_sequence(u8 address) +static int __init twl4030_config_wakeup12_sequence(u8 address) { int err = 0; u8 data; @@ -262,7 +262,7 @@ static int __devinit twl4030_config_wakeup12_sequence(u8 address) return err; } -static int __devinit twl4030_config_sleep_sequence(u8 address) +static int __init twl4030_config_sleep_sequence(u8 address) { int err; @@ -276,7 +276,7 @@ static int __devinit twl4030_config_sleep_sequence(u8 address) return err; } -static int __devinit twl4030_config_warmreset_sequence(u8 address) +static int __init twl4030_config_warmreset_sequence(u8 address) { int err; u8 rd_data; @@ -324,7 +324,7 @@ static int __devinit twl4030_config_warmreset_sequence(u8 address) return err; } -static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfig) +static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig) { int rconfig_addr; int err; @@ -416,7 +416,7 @@ static int __devinit twl4030_configure_resource(struct twl4030_resconfig *rconfi return 0; } -static int __devinit load_twl4030_script(struct twl4030_script *tscript, +static int __init load_twl4030_script(struct twl4030_script *tscript, u8 address) { int err; @@ -527,7 +527,7 @@ void twl4030_power_off(void) pr_err("TWL4030 Unable to power off\n"); } -void __devinit twl4030_power_init(struct twl4030_power_data *twl4030_scripts) +void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts) { int err = 0; int i; diff --git a/trunk/drivers/mmc/card/block.c b/trunk/drivers/mmc/card/block.c index c6a383d0244d..0cad48a284a8 100644 --- a/trunk/drivers/mmc/card/block.c +++ b/trunk/drivers/mmc/card/block.c @@ -1694,7 +1694,6 @@ static int mmc_add_disk(struct mmc_blk_data *md) md->power_ro_lock.show = power_ro_lock_show; md->power_ro_lock.store = power_ro_lock_store; - sysfs_attr_init(&md->power_ro_lock.attr); md->power_ro_lock.attr.mode = mode; md->power_ro_lock.attr.name = "ro_lock_until_next_power_on"; diff --git a/trunk/drivers/mmc/core/core.c b/trunk/drivers/mmc/core/core.c index 690255c7d4dc..f545a3e6eb80 100644 --- a/trunk/drivers/mmc/core/core.c +++ b/trunk/drivers/mmc/core/core.c @@ -290,11 +290,8 @@ static void mmc_wait_for_req_done(struct mmc_host *host, static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, bool is_first_req) { - if (host->ops->pre_req) { - mmc_host_clk_hold(host); + if (host->ops->pre_req) host->ops->pre_req(host, mrq, is_first_req); - mmc_host_clk_release(host); - } } /** @@ -309,11 +306,8 @@ static void mmc_pre_req(struct mmc_host *host, struct mmc_request *mrq, static void mmc_post_req(struct mmc_host *host, struct mmc_request *mrq, int err) { - if (host->ops->post_req) { - mmc_host_clk_hold(host); + if (host->ops->post_req) host->ops->post_req(host, mrq, err); - mmc_host_clk_release(host); - } } /** @@ -626,9 +620,7 @@ int mmc_host_enable(struct mmc_host *host) int err; host->en_dis_recurs = 1; - mmc_host_clk_hold(host); err = host->ops->enable(host); - mmc_host_clk_release(host); host->en_dis_recurs = 0; if (err) { @@ -648,9 +640,7 @@ static int mmc_host_do_disable(struct mmc_host *host, int lazy) int err; host->en_dis_recurs = 1; - mmc_host_clk_hold(host); err = host->ops->disable(host, lazy); - mmc_host_clk_release(host); host->en_dis_recurs = 0; if (err < 0) { @@ -1131,10 +1121,6 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc, * might not allow this operation */ voltage = regulator_get_voltage(supply); - - if (mmc->caps2 & MMC_CAP2_BROKEN_VOLTAGE) - min_uV = max_uV = voltage; - if (voltage < 0) result = voltage; else if (voltage < min_uV || voltage > max_uV) @@ -1217,11 +1203,8 @@ int mmc_set_signal_voltage(struct mmc_host *host, int signal_voltage, bool cmd11 host->ios.signal_voltage = signal_voltage; - if (host->ops->start_signal_voltage_switch) { - mmc_host_clk_hold(host); + if (host->ops->start_signal_voltage_switch) err = host->ops->start_signal_voltage_switch(host, &host->ios); - mmc_host_clk_release(host); - } return err; } @@ -1256,7 +1239,6 @@ static void mmc_poweroff_notify(struct mmc_host *host) int err = 0; card = host->card; - mmc_claim_host(host); /* * Send power notify command only if card @@ -1287,7 +1269,6 @@ static void mmc_poweroff_notify(struct mmc_host *host) /* Set the card state to no notification after the poweroff */ card->poweroff_notify_state = MMC_NO_POWER_NOTIFICATION; } - mmc_release_host(host); } /* @@ -1346,28 +1327,12 @@ static void mmc_power_up(struct mmc_host *host) void mmc_power_off(struct mmc_host *host) { - int err = 0; mmc_host_clk_hold(host); host->ios.clock = 0; host->ios.vdd = 0; - /* - * For eMMC 4.5 device send AWAKE command before - * POWER_OFF_NOTIFY command, because in sleep state - * eMMC 4.5 devices respond to only RESET and AWAKE cmd - */ - if (host->card && mmc_card_is_sleep(host->card) && - host->bus_ops->resume) { - err = host->bus_ops->resume(host); - - if (!err) - mmc_poweroff_notify(host); - else - pr_warning("%s: error %d during resume " - "(continue with poweroff sequence)\n", - mmc_hostname(host), err); - } + mmc_poweroff_notify(host); /* * Reset ocr mask to be the highest possible voltage supported for @@ -2421,6 +2386,12 @@ int mmc_suspend_host(struct mmc_host *host) */ if (mmc_try_claim_host(host)) { if (host->bus_ops->suspend) { + /* + * For eMMC 4.5 device send notify command + * before sleep, because in sleep state eMMC 4.5 + * devices respond to only RESET and AWAKE cmd + */ + mmc_poweroff_notify(host); err = host->bus_ops->suspend(host); } mmc_do_release_host(host); diff --git a/trunk/drivers/mmc/core/host.h b/trunk/drivers/mmc/core/host.h index 08a7852ade44..fb8a5cd2e4a1 100644 --- a/trunk/drivers/mmc/core/host.h +++ b/trunk/drivers/mmc/core/host.h @@ -14,6 +14,27 @@ int mmc_register_host_class(void); void mmc_unregister_host_class(void); + +#ifdef CONFIG_MMC_CLKGATE +void mmc_host_clk_hold(struct mmc_host *host); +void mmc_host_clk_release(struct mmc_host *host); +unsigned int mmc_host_clk_rate(struct mmc_host *host); + +#else +static inline void mmc_host_clk_hold(struct mmc_host *host) +{ +} + +static inline void mmc_host_clk_release(struct mmc_host *host) +{ +} + +static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) +{ + return host->ios.clock; +} +#endif + void mmc_host_deeper_disable(struct work_struct *work); #endif diff --git a/trunk/drivers/mmc/core/mmc.c b/trunk/drivers/mmc/core/mmc.c index a48066344fa8..59b9ba52e66a 100644 --- a/trunk/drivers/mmc/core/mmc.c +++ b/trunk/drivers/mmc/core/mmc.c @@ -376,7 +376,7 @@ static int mmc_read_ext_csd(struct mmc_card *card, u8 *ext_csd) } card->ext_csd.raw_hc_erase_gap_size = - ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; + ext_csd[EXT_CSD_PARTITION_ATTRIBUTE]; card->ext_csd.raw_sec_trim_mult = ext_csd[EXT_CSD_SEC_TRIM_MULT]; card->ext_csd.raw_sec_erase_mult = @@ -551,7 +551,7 @@ static int mmc_compare_ext_csds(struct mmc_card *card, unsigned bus_width) goto out; /* only compare read only fields */ - err = !((card->ext_csd.raw_partition_support == + err = (!(card->ext_csd.raw_partition_support == bw_ext_csd[EXT_CSD_PARTITION_SUPPORT]) && (card->ext_csd.raw_erased_mem_count == bw_ext_csd[EXT_CSD_ERASED_MEM_CONT]) && @@ -1006,8 +1006,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_select_hs200(card); else if (host->caps & MMC_CAP_MMC_HIGHSPEED) err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, - EXT_CSD_HS_TIMING, 1, - card->ext_csd.generic_cmd6_time); + EXT_CSD_HS_TIMING, 1, 0); if (err && err != -EBADMSG) goto free_card; @@ -1117,7 +1116,7 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, * Activate wide bus and DDR (if supported). */ if (!mmc_card_hs200(card) && - (card->csd.mmca_vsn >= CSD_SPEC_VER_4) && + (card->csd.mmca_vsn >= CSD_SPEC_VER_3) && (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { static unsigned ext_csd_bits[][2] = { { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, @@ -1316,13 +1315,11 @@ static int mmc_suspend(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); - if (mmc_card_can_sleep(host)) { + if (mmc_card_can_sleep(host)) err = mmc_card_sleep(host); - if (!err) - mmc_card_set_sleep(host->card); - } else if (!mmc_host_is_spi(host)) + else if (!mmc_host_is_spi(host)) mmc_deselect_cards(host); - host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); + host->card->state &= ~MMC_STATE_HIGHSPEED; mmc_release_host(host); return err; @@ -1342,11 +1339,7 @@ static int mmc_resume(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); - if (mmc_card_is_sleep(host->card)) { - err = mmc_card_awake(host); - mmc_card_clr_sleep(host->card); - } else - err = mmc_init_card(host, host->ocr, host->card); + err = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); return err; @@ -1356,8 +1349,7 @@ static int mmc_power_restore(struct mmc_host *host) { int ret; - host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); - mmc_card_clr_sleep(host->card); + host->card->state &= ~MMC_STATE_HIGHSPEED; mmc_claim_host(host); ret = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); diff --git a/trunk/drivers/mmc/core/sd.c b/trunk/drivers/mmc/core/sd.c index 5017f9354ce2..c63ad03c29c7 100644 --- a/trunk/drivers/mmc/core/sd.c +++ b/trunk/drivers/mmc/core/sd.c @@ -451,11 +451,9 @@ static int sd_select_driver_type(struct mmc_card *card, u8 *status) * information and let the hardware specific code * return what is possible given the options */ - mmc_host_clk_hold(card->host); drive_strength = card->host->ops->select_drive_strength( card->sw_caps.uhs_max_dtr, host_drv_type, card_drv_type); - mmc_host_clk_release(card->host); err = mmc_sd_switch(card, 1, 2, drive_strength, status); if (err) @@ -662,12 +660,9 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) goto out; /* SPI mode doesn't define CMD19 */ - if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) { - mmc_host_clk_hold(card->host); + if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK); - mmc_host_clk_release(card->host); - } out: kfree(status); @@ -855,11 +850,8 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, if (!reinit) { int ro = -1; - if (host->ops->get_ro) { - mmc_host_clk_hold(card->host); + if (host->ops->get_ro) ro = host->ops->get_ro(host); - mmc_host_clk_release(card->host); - } if (ro < 0) { pr_warning("%s: host does not " @@ -975,11 +967,8 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, * Since initialization is now complete, enable preset * value registers for UHS-I cards. */ - if (host->ops->enable_preset_value) { - mmc_host_clk_hold(card->host); + if (host->ops->enable_preset_value) host->ops->enable_preset_value(host, true); - mmc_host_clk_release(card->host); - } } else { /* * Attempt to change to high-speed (if supported) @@ -1162,11 +1151,8 @@ int mmc_attach_sd(struct mmc_host *host) return err; /* Disable preset value enable if already set since last time */ - if (host->ops->enable_preset_value) { - mmc_host_clk_hold(host); + if (host->ops->enable_preset_value) host->ops->enable_preset_value(host, false); - mmc_host_clk_release(host); - } err = mmc_send_app_op_cond(host, 0, &ocr); if (err) diff --git a/trunk/drivers/mmc/core/sdio.c b/trunk/drivers/mmc/core/sdio.c index 12cde6ee17f5..bd7bacc950dc 100644 --- a/trunk/drivers/mmc/core/sdio.c +++ b/trunk/drivers/mmc/core/sdio.c @@ -98,11 +98,10 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn) return ret; } -static int sdio_read_cccr(struct mmc_card *card, u32 ocr) +static int sdio_read_cccr(struct mmc_card *card) { int ret; int cccr_vsn; - int uhs = ocr & R4_18V_PRESENT; unsigned char data; unsigned char speed; @@ -150,7 +149,7 @@ static int sdio_read_cccr(struct mmc_card *card, u32 ocr) card->scr.sda_spec3 = 0; card->sw_caps.sd3_bus_mode = 0; card->sw_caps.sd3_drv_type = 0; - if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) { + if (cccr_vsn >= SDIO_CCCR_REV_3_00) { card->scr.sda_spec3 = 1; ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_UHS, 0, &data); @@ -713,7 +712,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, /* * Read the common registers. */ - err = sdio_read_cccr(card, ocr); + err = sdio_read_cccr(card); if (err) goto remove; diff --git a/trunk/drivers/mmc/core/sdio_irq.c b/trunk/drivers/mmc/core/sdio_irq.c index f573e7f9f740..68f81b9ee0fb 100644 --- a/trunk/drivers/mmc/core/sdio_irq.c +++ b/trunk/drivers/mmc/core/sdio_irq.c @@ -146,21 +146,15 @@ static int sdio_irq_thread(void *_host) } set_current_state(TASK_INTERRUPTIBLE); - if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 1); - mmc_host_clk_release(host); - } if (!kthread_should_stop()) schedule_timeout(period); set_current_state(TASK_RUNNING); } while (!kthread_should_stop()); - if (host->caps & MMC_CAP_SDIO_IRQ) { - mmc_host_clk_hold(host); + if (host->caps & MMC_CAP_SDIO_IRQ) host->ops->enable_sdio_irq(host, 0); - mmc_host_clk_release(host); - } pr_debug("%s: IRQ thread exiting with code %d\n", mmc_hostname(host), ret); diff --git a/trunk/drivers/mmc/host/atmel-mci.c b/trunk/drivers/mmc/host/atmel-mci.c index 6985cdb0bb26..fcfe1eb5acc8 100644 --- a/trunk/drivers/mmc/host/atmel-mci.c +++ b/trunk/drivers/mmc/host/atmel-mci.c @@ -969,14 +969,11 @@ static void atmci_start_request(struct atmel_mci *host, host->data_status = 0; if (host->need_reset) { - iflags = atmci_readl(host, ATMCI_IMR); - iflags &= (ATMCI_SDIOIRQA | ATMCI_SDIOIRQB); atmci_writel(host, ATMCI_CR, ATMCI_CR_SWRST); atmci_writel(host, ATMCI_CR, ATMCI_CR_MCIEN); atmci_writel(host, ATMCI_MR, host->mode_reg); if (host->caps.has_cfg_reg) atmci_writel(host, ATMCI_CFG, host->cfg_reg); - atmci_writel(host, ATMCI_IER, iflags); host->need_reset = false; } atmci_writel(host, ATMCI_SDCR, slot->sdc_reg); diff --git a/trunk/drivers/mmc/host/dw_mmc.c b/trunk/drivers/mmc/host/dw_mmc.c index 8bec1c36b159..0e342793ff14 100644 --- a/trunk/drivers/mmc/host/dw_mmc.c +++ b/trunk/drivers/mmc/host/dw_mmc.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -501,14 +502,8 @@ static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) host->dir_status = DW_MCI_SEND_STATUS; if (dw_mci_submit_data_dma(host, data)) { - int flags = SG_MITER_ATOMIC; - if (host->data->flags & MMC_DATA_READ) - flags |= SG_MITER_TO_SG; - else - flags |= SG_MITER_FROM_SG; - - sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags); host->sg = data->sg; + host->pio_offset = 0; host->part_buf_start = 0; host->part_buf_count = 0; @@ -977,7 +972,6 @@ static void dw_mci_tasklet_func(unsigned long priv) * generates a block interrupt, hence setting * the scatter-gather pointer to NULL. */ - sg_miter_stop(&host->sg_miter); host->sg = NULL; ctrl = mci_readl(host, CTRL); ctrl |= SDMMC_CTRL_FIFO_RESET; @@ -1317,44 +1311,54 @@ static void dw_mci_pull_data(struct dw_mci *host, void *buf, int cnt) static void dw_mci_read_data_pio(struct dw_mci *host) { - struct sg_mapping_iter *sg_miter = &host->sg_miter; - void *buf; - unsigned int offset; + struct scatterlist *sg = host->sg; + void *buf = sg_virt(sg); + unsigned int offset = host->pio_offset; struct mmc_data *data = host->data; int shift = host->data_shift; u32 status; unsigned int nbytes = 0, len; - unsigned int remain, fcnt; do { - if (!sg_miter_next(sg_miter)) - goto done; - - host->sg = sg_miter->__sg; - buf = sg_miter->addr; - remain = sg_miter->length; - offset = 0; - - do { - fcnt = (SDMMC_GET_FCNT(mci_readl(host, STATUS)) - << shift) + host->part_buf_count; - len = min(remain, fcnt); - if (!len) - break; + len = host->part_buf_count + + (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); + if (offset + len <= sg->length) { dw_mci_pull_data(host, (void *)(buf + offset), len); + offset += len; nbytes += len; - remain -= len; - } while (remain); - sg_miter->consumed = offset; + + if (offset == sg->length) { + flush_dcache_page(sg_page(sg)); + host->sg = sg = sg_next(sg); + if (!sg) + goto done; + + offset = 0; + buf = sg_virt(sg); + } + } else { + unsigned int remaining = sg->length - offset; + dw_mci_pull_data(host, (void *)(buf + offset), + remaining); + nbytes += remaining; + + flush_dcache_page(sg_page(sg)); + host->sg = sg = sg_next(sg); + if (!sg) + goto done; + + offset = len - remaining; + buf = sg_virt(sg); + dw_mci_pull_data(host, buf, offset); + nbytes += offset; + } status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_RXDR); if (status & DW_MCI_DATA_ERROR_FLAGS) { host->data_status = status; data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; smp_wmb(); set_bit(EVENT_DATA_ERROR, &host->pending_events); @@ -1363,66 +1367,65 @@ static void dw_mci_read_data_pio(struct dw_mci *host) return; } } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ + host->pio_offset = offset; data->bytes_xfered += nbytes; - - if (!remain) { - if (!sg_miter_next(sg_miter)) - goto done; - sg_miter->consumed = 0; - } - sg_miter_stop(sg_miter); return; done: data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; smp_wmb(); set_bit(EVENT_XFER_COMPLETE, &host->pending_events); } static void dw_mci_write_data_pio(struct dw_mci *host) { - struct sg_mapping_iter *sg_miter = &host->sg_miter; - void *buf; - unsigned int offset; + struct scatterlist *sg = host->sg; + void *buf = sg_virt(sg); + unsigned int offset = host->pio_offset; struct mmc_data *data = host->data; int shift = host->data_shift; u32 status; unsigned int nbytes = 0, len; - unsigned int fifo_depth = host->fifo_depth; - unsigned int remain, fcnt; do { - if (!sg_miter_next(sg_miter)) - goto done; - - host->sg = sg_miter->__sg; - buf = sg_miter->addr; - remain = sg_miter->length; - offset = 0; - - do { - fcnt = ((fifo_depth - - SDMMC_GET_FCNT(mci_readl(host, STATUS))) - << shift) - host->part_buf_count; - len = min(remain, fcnt); - if (!len) - break; + len = ((host->fifo_depth - + SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift) + - host->part_buf_count; + if (offset + len <= sg->length) { host->push_data(host, (void *)(buf + offset), len); + offset += len; nbytes += len; - remain -= len; - } while (remain); - sg_miter->consumed = offset; + if (offset == sg->length) { + host->sg = sg = sg_next(sg); + if (!sg) + goto done; + + offset = 0; + buf = sg_virt(sg); + } + } else { + unsigned int remaining = sg->length - offset; + + host->push_data(host, (void *)(buf + offset), + remaining); + nbytes += remaining; + + host->sg = sg = sg_next(sg); + if (!sg) + goto done; + + offset = len - remaining; + buf = sg_virt(sg); + host->push_data(host, (void *)buf, offset); + nbytes += offset; + } status = mci_readl(host, MINTSTS); mci_writel(host, RINTSTS, SDMMC_INT_TXDR); if (status & DW_MCI_DATA_ERROR_FLAGS) { host->data_status = status; data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; smp_wmb(); @@ -1432,20 +1435,12 @@ static void dw_mci_write_data_pio(struct dw_mci *host) return; } } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ + host->pio_offset = offset; data->bytes_xfered += nbytes; - - if (!remain) { - if (!sg_miter_next(sg_miter)) - goto done; - sg_miter->consumed = 0; - } - sg_miter_stop(sg_miter); return; done: data->bytes_xfered += nbytes; - sg_miter_stop(sg_miter); - host->sg = NULL; smp_wmb(); set_bit(EVENT_XFER_COMPLETE, &host->pending_events); } @@ -1648,7 +1643,6 @@ static void dw_mci_work_routine_card(struct work_struct *work) * block interrupt, hence setting the * scatter-gather pointer to NULL. */ - sg_miter_stop(&host->sg_miter); host->sg = NULL; ctrl = mci_readl(host, CTRL); diff --git a/trunk/drivers/mmc/host/of_mmc_spi.c b/trunk/drivers/mmc/host/of_mmc_spi.c index 1534b582c419..ab66f2454dc4 100644 --- a/trunk/drivers/mmc/host/of_mmc_spi.c +++ b/trunk/drivers/mmc/host/of_mmc_spi.c @@ -113,8 +113,8 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) const int j = i * 2; u32 mask; - mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), - be32_to_cpu(voltage_ranges[j + 1])); + mask = mmc_vddrange_to_ocrmask(voltage_ranges[j], + voltage_ranges[j + 1]); if (!mask) { ret = -EINVAL; dev_err(dev, "OF: voltage-range #%d is invalid\n", i); diff --git a/trunk/drivers/mmc/host/sdhci-of-esdhc.c b/trunk/drivers/mmc/host/sdhci-of-esdhc.c index 5d876ff86f37..ff4adc018041 100644 --- a/trunk/drivers/mmc/host/sdhci-of-esdhc.c +++ b/trunk/drivers/mmc/host/sdhci-of-esdhc.c @@ -38,23 +38,6 @@ static u8 esdhc_readb(struct sdhci_host *host, int reg) int base = reg & ~0x3; int shift = (reg & 0x3) * 8; u8 ret = (in_be32(host->ioaddr + base) >> shift) & 0xff; - - /* - * "DMA select" locates at offset 0x28 in SD specification, but on - * P5020 or P3041, it locates at 0x29. - */ - if (reg == SDHCI_HOST_CONTROL) { - u32 dma_bits; - - dma_bits = in_be32(host->ioaddr + reg); - /* DMA select is 22,23 bits in Protocol Control Register */ - dma_bits = (dma_bits >> 5) & SDHCI_CTRL_DMA_MASK; - - /* fixup the result */ - ret &= ~SDHCI_CTRL_DMA_MASK; - ret |= dma_bits; - } - return ret; } @@ -73,21 +56,6 @@ static void esdhc_writew(struct sdhci_host *host, u16 val, int reg) static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) { - /* - * "DMA select" location is offset 0x28 in SD specification, but on - * P5020 or P3041, it's located at 0x29. - */ - if (reg == SDHCI_HOST_CONTROL) { - u32 dma_bits; - - /* DMA select is 22,23 bits in Protocol Control Register */ - dma_bits = (val & SDHCI_CTRL_DMA_MASK) << 5; - clrsetbits_be32(host->ioaddr + reg , SDHCI_CTRL_DMA_MASK << 5, - dma_bits); - val &= ~SDHCI_CTRL_DMA_MASK; - val |= in_be32(host->ioaddr + reg) & SDHCI_CTRL_DMA_MASK; - } - /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ if (reg == SDHCI_HOST_CONTROL) val &= ~ESDHC_HOST_CONTROL_RES; diff --git a/trunk/drivers/mmc/host/sdhci-pci.c b/trunk/drivers/mmc/host/sdhci-pci.c index 6ebdc4010e7c..7165e6a09274 100644 --- a/trunk/drivers/mmc/host/sdhci-pci.c +++ b/trunk/drivers/mmc/host/sdhci-pci.c @@ -250,7 +250,7 @@ static int mfd_emmc_probe_slot(struct sdhci_pci_slot *slot) static int mfd_sdio_probe_slot(struct sdhci_pci_slot *slot) { - slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; + slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD; return 0; } diff --git a/trunk/drivers/mmc/host/sdhci-pltfm.c b/trunk/drivers/mmc/host/sdhci-pltfm.c index c5c2a48bdd94..03970bcb3495 100644 --- a/trunk/drivers/mmc/host/sdhci-pltfm.c +++ b/trunk/drivers/mmc/host/sdhci-pltfm.c @@ -2,7 +2,7 @@ * sdhci-pltfm.c Support for SDHCI platform devices * Copyright (c) 2009 Intel Corporation * - * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc. + * Copyright (c) 2007 Freescale Semiconductor, Inc. * Copyright (c) 2009 MontaVista Software, Inc. * * Authors: Xiaobo Xie @@ -71,14 +71,6 @@ void sdhci_get_of_property(struct platform_device *pdev) if (sdhci_of_wp_inverted(np)) host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; - if (of_device_is_compatible(np, "fsl,p2020-rev1-esdhc")) - host->quirks |= SDHCI_QUIRK_BROKEN_DMA; - - if (of_device_is_compatible(np, "fsl,p2020-esdhc") || - of_device_is_compatible(np, "fsl,p1010-esdhc") || - of_device_is_compatible(np, "fsl,mpc8536-esdhc")) - host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; - clk = of_get_property(np, "clock-frequency", &size); if (clk && size == sizeof(*clk) && *clk) pltfm_host->clock = be32_to_cpup(clk); diff --git a/trunk/drivers/mmc/host/sh_mmcif.c b/trunk/drivers/mmc/host/sh_mmcif.c index 352d4797865b..f5d8b53be333 100644 --- a/trunk/drivers/mmc/host/sh_mmcif.c +++ b/trunk/drivers/mmc/host/sh_mmcif.c @@ -1327,7 +1327,7 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) if (ret < 0) goto clean_up2; - INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); + mmc_add_host(mmc); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); @@ -1338,24 +1338,22 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev) } ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host); if (ret) { + free_irq(irq[0], host); dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n"); - goto clean_up4; + goto clean_up3; } - ret = mmc_add_host(mmc); - if (ret < 0) - goto clean_up5; + INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); + + mmc_detect_change(host->mmc, 0); dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION); dev_dbg(&pdev->dev, "chip ver H'%04x\n", sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff); return ret; -clean_up5: - free_irq(irq[1], host); -clean_up4: - free_irq(irq[0], host); clean_up3: + mmc_remove_host(mmc); pm_runtime_suspend(&pdev->dev); clean_up2: pm_runtime_disable(&pdev->dev); diff --git a/trunk/drivers/mmc/host/tmio_mmc.h b/trunk/drivers/mmc/host/tmio_mmc.h index f96c536d130a..a95e6d901726 100644 --- a/trunk/drivers/mmc/host/tmio_mmc.h +++ b/trunk/drivers/mmc/host/tmio_mmc.h @@ -20,8 +20,8 @@ #include #include #include -#include #include +#include /* Definitions for values the CTRL_SDIO_STATUS register can take. */ #define TMIO_SDIO_STAT_IOIRQ 0x0001 @@ -120,7 +120,6 @@ void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data); void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable); void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata); void tmio_mmc_release_dma(struct tmio_mmc_host *host); -void tmio_mmc_abort_dma(struct tmio_mmc_host *host); #else static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data) @@ -141,10 +140,6 @@ static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host, static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host) { } - -static inline void tmio_mmc_abort_dma(struct tmio_mmc_host *host) -{ -} #endif #ifdef CONFIG_PM diff --git a/trunk/drivers/mmc/host/tmio_mmc_dma.c b/trunk/drivers/mmc/host/tmio_mmc_dma.c index 8253ec12003e..7a6e6cc8f8b8 100644 --- a/trunk/drivers/mmc/host/tmio_mmc_dma.c +++ b/trunk/drivers/mmc/host/tmio_mmc_dma.c @@ -34,18 +34,6 @@ void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) #endif } -void tmio_mmc_abort_dma(struct tmio_mmc_host *host) -{ - tmio_mmc_enable_dma(host, false); - - if (host->chan_rx) - dmaengine_terminate_all(host->chan_rx); - if (host->chan_tx) - dmaengine_terminate_all(host->chan_tx); - - tmio_mmc_enable_dma(host, true); -} - static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) { struct scatterlist *sg = host->sg_ptr, *sg_tmp; diff --git a/trunk/drivers/mmc/host/tmio_mmc_pio.c b/trunk/drivers/mmc/host/tmio_mmc_pio.c index 5f9ad74fbf80..abad01b37cfb 100644 --- a/trunk/drivers/mmc/host/tmio_mmc_pio.c +++ b/trunk/drivers/mmc/host/tmio_mmc_pio.c @@ -41,8 +41,8 @@ #include #include #include -#include #include +#include #include "tmio_mmc.h" @@ -246,7 +246,6 @@ static void tmio_mmc_reset_work(struct work_struct *work) /* Ready for new calls */ host->mrq = NULL; - tmio_mmc_abort_dma(host); mmc_request_done(host->mmc, mrq); } @@ -273,9 +272,6 @@ static void tmio_mmc_finish_request(struct tmio_mmc_host *host) host->mrq = NULL; spin_unlock_irqrestore(&host->lock, flags); - if (mrq->cmd->error || (mrq->data && mrq->data->error)) - tmio_mmc_abort_dma(host); - mmc_request_done(host->mmc, mrq); } diff --git a/trunk/drivers/pci/iov.c b/trunk/drivers/pci/iov.c index 0dab5ecf61bb..0321fa3b4226 100644 --- a/trunk/drivers/pci/iov.c +++ b/trunk/drivers/pci/iov.c @@ -347,6 +347,8 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn) return rc; } + pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz); + iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE; pci_cfg_access_lock(dev); pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl); @@ -464,7 +466,6 @@ static int sriov_init(struct pci_dev *dev, int pos) return -EIO; pgsz &= ~(pgsz - 1); - pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz); nres = 0; for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) { diff --git a/trunk/drivers/pci/probe.c b/trunk/drivers/pci/probe.c index 71eac9cd724d..7cc9e2f0f47c 100644 --- a/trunk/drivers/pci/probe.c +++ b/trunk/drivers/pci/probe.c @@ -651,11 +651,6 @@ int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev *dev, int max, dev_dbg(&dev->dev, "scanning [bus %02x-%02x] behind bridge, pass %d\n", secondary, subordinate, pass); - if (!primary && (primary != bus->number) && secondary && subordinate) { - dev_warn(&dev->dev, "Primary bus is hard wired to 0\n"); - primary = bus->number; - } - /* Check if setup is sensible at all */ if (!pass && (primary != bus->number || secondary <= bus->number)) { diff --git a/trunk/drivers/pci/remove.c b/trunk/drivers/pci/remove.c index ef8b18c48f26..6def3624c688 100644 --- a/trunk/drivers/pci/remove.c +++ b/trunk/drivers/pci/remove.c @@ -77,7 +77,6 @@ void pci_remove_bus(struct pci_bus *pci_bus) } EXPORT_SYMBOL(pci_remove_bus); -static void __pci_remove_behind_bridge(struct pci_dev *dev); /** * pci_remove_bus_device - remove a PCI device and any children * @dev: the device to remove @@ -95,7 +94,7 @@ static void __pci_remove_bus_device(struct pci_dev *dev) if (dev->subordinate) { struct pci_bus *b = dev->subordinate; - __pci_remove_behind_bridge(dev); + pci_remove_behind_bridge(dev); pci_remove_bus(b); dev->subordinate = NULL; } @@ -108,24 +107,6 @@ void pci_remove_bus_device(struct pci_dev *dev) __pci_remove_bus_device(dev); } -static void __pci_remove_behind_bridge(struct pci_dev *dev) -{ - struct list_head *l, *n; - - if (dev->subordinate) - list_for_each_safe(l, n, &dev->subordinate->devices) - __pci_remove_bus_device(pci_dev_b(l)); -} - -static void pci_stop_behind_bridge(struct pci_dev *dev) -{ - struct list_head *l, *n; - - if (dev->subordinate) - list_for_each_safe(l, n, &dev->subordinate->devices) - pci_stop_bus_device(pci_dev_b(l)); -} - /** * pci_remove_behind_bridge - remove all devices behind a PCI bridge * @dev: PCI bridge device @@ -136,8 +117,11 @@ static void pci_stop_behind_bridge(struct pci_dev *dev) */ void pci_remove_behind_bridge(struct pci_dev *dev) { - pci_stop_behind_bridge(dev); - __pci_remove_behind_bridge(dev); + struct list_head *l, *n; + + if (dev->subordinate) + list_for_each_safe(l, n, &dev->subordinate->devices) + __pci_remove_bus_device(pci_dev_b(l)); } static void pci_stop_bus_devices(struct pci_bus *bus) diff --git a/trunk/drivers/pci/xen-pcifront.c b/trunk/drivers/pci/xen-pcifront.c index 1620088a0e7e..7cf3d2fcf56a 100644 --- a/trunk/drivers/pci/xen-pcifront.c +++ b/trunk/drivers/pci/xen-pcifront.c @@ -189,7 +189,7 @@ static int pcifront_bus_read(struct pci_bus *bus, unsigned int devfn, if (verbose_request) dev_info(&pdev->xdev->dev, - "read dev=%04x:%02x:%02x.%d - offset %x size %d\n", + "read dev=%04x:%02x:%02x.%01x - offset %x size %d\n", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size); @@ -228,7 +228,7 @@ static int pcifront_bus_write(struct pci_bus *bus, unsigned int devfn, if (verbose_request) dev_info(&pdev->xdev->dev, - "write dev=%04x:%02x:%02x.%d - " + "write dev=%04x:%02x:%02x.%01x - " "offset %x size %d val %x\n", pci_domain_nr(bus), bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, val); @@ -432,7 +432,7 @@ static int __devinit pcifront_scan_bus(struct pcifront_device *pdev, d = pci_scan_single_device(b, devfn); if (d) dev_info(&pdev->xdev->dev, "New device on " - "%04x:%02x:%02x.%d found.\n", domain, bus, + "%04x:%02x:%02x.%02x found.\n", domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); } @@ -1041,7 +1041,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev) pci_dev = pci_get_slot(pci_bus, PCI_DEVFN(slot, func)); if (!pci_dev) { dev_dbg(&pdev->xdev->dev, - "Cannot get PCI device %04x:%02x:%02x.%d\n", + "Cannot get PCI device %04x:%02x:%02x.%02x\n", domain, bus, slot, func); continue; } @@ -1049,7 +1049,7 @@ static int pcifront_detach_devices(struct pcifront_device *pdev) pci_dev_put(pci_dev); dev_dbg(&pdev->xdev->dev, - "PCI device %04x:%02x:%02x.%d removed.\n", + "PCI device %04x:%02x:%02x.%02x removed.\n", domain, bus, slot, func); } diff --git a/trunk/drivers/power/bq27x00_battery.c b/trunk/drivers/power/bq27x00_battery.c index 1ed6ea0bad6e..98bf5676318d 100644 --- a/trunk/drivers/power/bq27x00_battery.c +++ b/trunk/drivers/power/bq27x00_battery.c @@ -62,10 +62,11 @@ #define BQ27500_REG_SOC 0x2C #define BQ27500_REG_DCAP 0x3C /* Design capacity */ -#define BQ27500_FLAG_DSC BIT(0) +#define BQ27500_FLAG_DSG BIT(0) /* Discharging */ #define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */ #define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */ -#define BQ27500_FLAG_FC BIT(9) +#define BQ27500_FLAG_CHG BIT(8) /* Charging */ +#define BQ27500_FLAG_FC BIT(9) /* Fully charged */ #define BQ27000_RS 20 /* Resistor sense */ @@ -311,7 +312,7 @@ static void bq27x00_update(struct bq27x00_device_info *di) struct bq27x00_reg_cache cache = {0, }; bool is_bq27500 = di->chip == BQ27500; - cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, !is_bq27500); + cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500); if (cache.flags >= 0) { if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) { dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n"); @@ -400,10 +401,14 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di, if (di->chip == BQ27500) { if (di->cache.flags & BQ27500_FLAG_FC) status = POWER_SUPPLY_STATUS_FULL; - else if (di->cache.flags & BQ27500_FLAG_DSC) + else if (di->cache.flags & BQ27500_FLAG_DSG) status = POWER_SUPPLY_STATUS_DISCHARGING; - else + else if (di->cache.flags & BQ27500_FLAG_CHG) status = POWER_SUPPLY_STATUS_CHARGING; + else if (power_supply_am_i_supplied(&di->bat)) + status = POWER_SUPPLY_STATUS_NOT_CHARGING; + else + status = POWER_SUPPLY_STATUS_UNKNOWN; } else { if (di->cache.flags & BQ27000_FLAG_FC) status = POWER_SUPPLY_STATUS_FULL; diff --git a/trunk/drivers/power/charger-manager.c b/trunk/drivers/power/charger-manager.c index 88fd9710bda2..0378d019efae 100644 --- a/trunk/drivers/power/charger-manager.c +++ b/trunk/drivers/power/charger-manager.c @@ -974,11 +974,10 @@ static int __devexit charger_manager_remove(struct platform_device *pdev) return 0; } -static const struct platform_device_id charger_manager_id[] = { +const struct platform_device_id charger_manager_id[] = { { "charger-manager", 0 }, { }, }; -MODULE_DEVICE_TABLE(platform, charger_manager_id); static int cm_suspend_prepare(struct device *dev) { @@ -1070,3 +1069,4 @@ module_exit(charger_manager_cleanup); MODULE_AUTHOR("MyungJoo Ham "); MODULE_DESCRIPTION("Charger Manager"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("charger-manager"); diff --git a/trunk/drivers/power/lp8727_charger.c b/trunk/drivers/power/lp8727_charger.c index c53dd1292f81..b15b575c070c 100644 --- a/trunk/drivers/power/lp8727_charger.c +++ b/trunk/drivers/power/lp8727_charger.c @@ -464,7 +464,6 @@ static int __devexit lp8727_remove(struct i2c_client *cl) static const struct i2c_device_id lp8727_ids[] = { {"lp8727", 0}, - { } }; static struct i2c_driver lp8727_driver = { diff --git a/trunk/drivers/regulator/max8649.c b/trunk/drivers/regulator/max8649.c index d0e1180ad961..b06a2399587c 100644 --- a/trunk/drivers/regulator/max8649.c +++ b/trunk/drivers/regulator/max8649.c @@ -150,7 +150,7 @@ static int max8649_enable_time(struct regulator_dev *rdev) if (ret != 0) return ret; val &= MAX8649_VOL_MASK; - voltage = max8649_list_voltage(rdev, (unsigned char)val); /* uV */ + voltage = max8649_list_voltage(rdev, (unsigned char)ret); /* uV */ /* get rate */ ret = regmap_read(info->regmap, MAX8649_RAMP, &val); diff --git a/trunk/drivers/regulator/mc13xxx-regulator-core.c b/trunk/drivers/regulator/mc13xxx-regulator-core.c index 62dcd0a432bb..80ecafef1bc3 100644 --- a/trunk/drivers/regulator/mc13xxx-regulator-core.c +++ b/trunk/drivers/regulator/mc13xxx-regulator-core.c @@ -254,7 +254,6 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev) return num; } -EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt); struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt( struct platform_device *pdev, struct mc13xxx_regulator *regulators, @@ -292,7 +291,6 @@ struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt( return data; } -EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt); #endif MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/video/omap2/dss/dpi.c b/trunk/drivers/video/omap2/dss/dpi.c index faaf305fda27..395d658a94fc 100644 --- a/trunk/drivers/video/omap2/dss/dpi.c +++ b/trunk/drivers/video/omap2/dss/dpi.c @@ -180,11 +180,6 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) { int r; - if (cpu_is_omap34xx() && !dpi.vdds_dsi_reg) { - DSSERR("no VDSS_DSI regulator\n"); - return -ENODEV; - } - if (dssdev->manager == NULL) { DSSERR("failed to enable display: no manager\n"); return -ENODEV; diff --git a/trunk/drivers/xen/cpu_hotplug.c b/trunk/drivers/xen/cpu_hotplug.c index 4dcfced107f5..14e2d995e958 100644 --- a/trunk/drivers/xen/cpu_hotplug.c +++ b/trunk/drivers/xen/cpu_hotplug.c @@ -30,8 +30,7 @@ static int vcpu_online(unsigned int cpu) sprintf(dir, "cpu/%u", cpu); err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); if (err != 1) { - if (!xen_initial_domain()) - printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); + printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); return err; } diff --git a/trunk/drivers/xen/xen-pciback/pci_stub.c b/trunk/drivers/xen/xen-pciback/pci_stub.c index 19834d1c7c36..7944a17f5cbf 100644 --- a/trunk/drivers/xen/xen-pciback/pci_stub.c +++ b/trunk/drivers/xen/xen-pciback/pci_stub.c @@ -884,7 +884,7 @@ static inline int str_to_quirk(const char *buf, int *domain, int *bus, int int err; err = - sscanf(buf, " %04x:%02x:%02x.%d-%08x:%1x:%08x", domain, bus, slot, + sscanf(buf, " %04x:%02x:%02x.%1x-%08x:%1x:%08x", domain, bus, slot, func, reg, size, mask); if (err == 7) return 0; @@ -904,7 +904,7 @@ static int pcistub_device_id_add(int domain, int bus, int slot, int func) pci_dev_id->bus = bus; pci_dev_id->devfn = PCI_DEVFN(slot, func); - pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\n", + pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%01x\n", domain, bus, slot, func); spin_lock_irqsave(&device_ids_lock, flags); @@ -934,7 +934,7 @@ static int pcistub_device_id_remove(int domain, int bus, int slot, int func) err = 0; - pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%d from " + pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%01x from " "seize list\n", domain, bus, slot, func); } } @@ -1029,7 +1029,7 @@ static ssize_t pcistub_slot_show(struct device_driver *drv, char *buf) break; count += scnprintf(buf + count, PAGE_SIZE - count, - "%04x:%02x:%02x.%d\n", + "%04x:%02x:%02x.%01x\n", pci_dev_id->domain, pci_dev_id->bus, PCI_SLOT(pci_dev_id->devfn), PCI_FUNC(pci_dev_id->devfn)); diff --git a/trunk/drivers/xen/xen-pciback/xenbus.c b/trunk/drivers/xen/xen-pciback/xenbus.c index 64b11f99eacc..d5dcf8d5d3d9 100644 --- a/trunk/drivers/xen/xen-pciback/xenbus.c +++ b/trunk/drivers/xen/xen-pciback/xenbus.c @@ -206,7 +206,6 @@ static int xen_pcibk_publish_pci_dev(struct xen_pcibk_device *pdev, goto out; } - /* Note: The PV protocol uses %02x, don't change it */ err = xenbus_printf(XBT_NIL, pdev->xdev->nodename, str, "%04x:%02x:%02x.%02x", domain, bus, PCI_SLOT(devfn), PCI_FUNC(devfn)); @@ -230,7 +229,7 @@ static int xen_pcibk_export_device(struct xen_pcibk_device *pdev, err = -EINVAL; xenbus_dev_fatal(pdev->xdev, err, "Couldn't locate PCI device " - "(%04x:%02x:%02x.%d)! " + "(%04x:%02x:%02x.%01x)! " "perhaps already in-use?", domain, bus, slot, func); goto out; @@ -275,7 +274,7 @@ static int xen_pcibk_remove_device(struct xen_pcibk_device *pdev, if (!dev) { err = -EINVAL; dev_dbg(&pdev->xdev->dev, "Couldn't locate PCI device " - "(%04x:%02x:%02x.%d)! not owned by this domain\n", + "(%04x:%02x:%02x.%01x)! not owned by this domain\n", domain, bus, slot, func); goto out; } diff --git a/trunk/drivers/xen/xenbus/xenbus_dev_frontend.c b/trunk/drivers/xen/xenbus/xenbus_dev_frontend.c index 89f76252a16f..527dc2a3b89f 100644 --- a/trunk/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/trunk/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -369,10 +369,6 @@ static int xenbus_write_watch(unsigned msg_type, struct xenbus_file_priv *u) goto out; } token++; - if (memchr(token, 0, u->u.msg.len - (token - path)) == NULL) { - rc = -EILSEQ; - goto out; - } if (msg_type == XS_WATCH) { watch = alloc_watch_adapter(path, token); diff --git a/trunk/fs/cifs/connect.c b/trunk/fs/cifs/connect.c index 602f77c304c9..9c288653e6d6 100644 --- a/trunk/fs/cifs/connect.c +++ b/trunk/fs/cifs/connect.c @@ -773,11 +773,10 @@ standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) cifs_dump_mem("Bad SMB: ", buf, min_t(unsigned int, server->total_read, 48)); - if (!mid) - return length; + if (mid) + handle_mid(mid, server, smb_buffer, length); - handle_mid(mid, server, smb_buffer, length); - return 0; + return length; } static int @@ -2126,7 +2125,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) down_read(&key->sem); upayload = key->payload.data; if (IS_ERR_OR_NULL(upayload)) { - rc = upayload ? PTR_ERR(upayload) : -EINVAL; + rc = PTR_ERR(key); goto out_key_put; } diff --git a/trunk/fs/cifs/dir.c b/trunk/fs/cifs/dir.c index 63a196b97d50..df8fecb5b993 100644 --- a/trunk/fs/cifs/dir.c +++ b/trunk/fs/cifs/dir.c @@ -492,7 +492,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, { int xid; int rc = 0; /* to get around spurious gcc warning, set to zero here */ - __u32 oplock = enable_oplocks ? REQ_OPLOCK : 0; + __u32 oplock = 0; __u16 fileHandle = 0; bool posix_open = false; struct cifs_sb_info *cifs_sb; diff --git a/trunk/fs/xfs/kmem.h b/trunk/fs/xfs/kmem.h index ab7c53fe346e..292eff198030 100644 --- a/trunk/fs/xfs/kmem.h +++ b/trunk/fs/xfs/kmem.h @@ -110,4 +110,10 @@ kmem_zone_destroy(kmem_zone_t *zone) extern void *kmem_zone_alloc(kmem_zone_t *, unsigned int __nocast); extern void *kmem_zone_zalloc(kmem_zone_t *, unsigned int __nocast); +static inline int +kmem_shake_allow(gfp_t gfp_mask) +{ + return ((gfp_mask & __GFP_WAIT) && (gfp_mask & __GFP_FS)); +} + #endif /* __XFS_SUPPORT_KMEM_H__ */ diff --git a/trunk/fs/xfs/xfs_dquot.c b/trunk/fs/xfs/xfs_dquot.c index cbcb7bea38e2..b4ff40b5f918 100644 --- a/trunk/fs/xfs/xfs_dquot.c +++ b/trunk/fs/xfs/xfs_dquot.c @@ -62,6 +62,82 @@ int xfs_dqerror_mod = 33; static struct lock_class_key xfs_dquot_other_class; +/* + * Allocate and initialize a dquot. We don't always allocate fresh memory; + * we try to reclaim a free dquot if the number of incore dquots are above + * a threshold. + * The only field inside the core that gets initialized at this point + * is the d_id field. The idea is to fill in the entire q_core + * when we read in the on disk dquot. + */ +STATIC xfs_dquot_t * +xfs_qm_dqinit( + xfs_mount_t *mp, + xfs_dqid_t id, + uint type) +{ + xfs_dquot_t *dqp; + boolean_t brandnewdquot; + + brandnewdquot = xfs_qm_dqalloc_incore(&dqp); + dqp->dq_flags = type; + dqp->q_core.d_id = cpu_to_be32(id); + dqp->q_mount = mp; + + /* + * No need to re-initialize these if this is a reclaimed dquot. + */ + if (brandnewdquot) { + INIT_LIST_HEAD(&dqp->q_freelist); + mutex_init(&dqp->q_qlock); + init_waitqueue_head(&dqp->q_pinwait); + + /* + * Because we want to use a counting completion, complete + * the flush completion once to allow a single access to + * the flush completion without blocking. + */ + init_completion(&dqp->q_flush); + complete(&dqp->q_flush); + + trace_xfs_dqinit(dqp); + } else { + /* + * Only the q_core portion was zeroed in dqreclaim_one(). + * So, we need to reset others. + */ + dqp->q_nrefs = 0; + dqp->q_blkno = 0; + INIT_LIST_HEAD(&dqp->q_mplist); + INIT_LIST_HEAD(&dqp->q_hashlist); + dqp->q_bufoffset = 0; + dqp->q_fileoffset = 0; + dqp->q_transp = NULL; + dqp->q_gdquot = NULL; + dqp->q_res_bcount = 0; + dqp->q_res_icount = 0; + dqp->q_res_rtbcount = 0; + atomic_set(&dqp->q_pincount, 0); + dqp->q_hash = NULL; + ASSERT(list_empty(&dqp->q_freelist)); + + trace_xfs_dqreuse(dqp); + } + + /* + * In either case we need to make sure group quotas have a different + * lock class than user quotas, to make sure lockdep knows we can + * locks of one of each at the same time. + */ + if (!(type & XFS_DQ_USER)) + lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); + + /* + * log item gets initialized later + */ + return (dqp); +} + /* * This is called to free all the memory associated with a dquot */ @@ -491,32 +567,7 @@ xfs_qm_dqread( int error; int cancelflags = 0; - - dqp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); - - dqp->dq_flags = type; - dqp->q_core.d_id = cpu_to_be32(id); - dqp->q_mount = mp; - INIT_LIST_HEAD(&dqp->q_freelist); - mutex_init(&dqp->q_qlock); - init_waitqueue_head(&dqp->q_pinwait); - - /* - * Because we want to use a counting completion, complete - * the flush completion once to allow a single access to - * the flush completion without blocking. - */ - init_completion(&dqp->q_flush); - complete(&dqp->q_flush); - - /* - * Make sure group quotas have a different lock class than user - * quotas. - */ - if (!(type & XFS_DQ_USER)) - lockdep_set_class(&dqp->q_qlock, &xfs_dquot_other_class); - - atomic_inc(&xfs_Gqm->qm_totaldquots); + dqp = xfs_qm_dqinit(mp, id, type); trace_xfs_dqread(dqp); diff --git a/trunk/fs/xfs/xfs_log_recover.c b/trunk/fs/xfs/xfs_log_recover.c index 15ff5392fb65..541a508adea1 100644 --- a/trunk/fs/xfs/xfs_log_recover.c +++ b/trunk/fs/xfs/xfs_log_recover.c @@ -1489,7 +1489,7 @@ xlog_recover_add_to_cont_trans( old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; old_len = item->ri_buf[item->ri_cnt-1].i_len; - ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP); + ptr = kmem_realloc(old_ptr, len+old_len, old_len, 0u); memcpy(&ptr[old_len], dp, len); /* d, s, l */ item->ri_buf[item->ri_cnt-1].i_len += len; item->ri_buf[item->ri_cnt-1].i_addr = ptr; diff --git a/trunk/fs/xfs/xfs_qm.c b/trunk/fs/xfs/xfs_qm.c index c436def733bf..671f37eae1c7 100644 --- a/trunk/fs/xfs/xfs_qm.c +++ b/trunk/fs/xfs/xfs_qm.c @@ -50,6 +50,7 @@ */ struct mutex xfs_Gqm_lock; struct xfs_qm *xfs_Gqm; +uint ndquot; kmem_zone_t *qm_dqzone; kmem_zone_t *qm_dqtrxzone; @@ -92,6 +93,7 @@ xfs_Gqm_init(void) goto out_free_udqhash; hsize /= sizeof(xfs_dqhash_t); + ndquot = hsize << 8; xqm = kmem_zalloc(sizeof(xfs_qm_t), KM_SLEEP); xqm->qm_dqhashmask = hsize - 1; @@ -135,6 +137,7 @@ xfs_Gqm_init(void) xqm->qm_dqtrxzone = qm_dqtrxzone; atomic_set(&xqm->qm_totaldquots, 0); + xqm->qm_dqfree_ratio = XFS_QM_DQFREE_RATIO; xqm->qm_nrefs = 0; return xqm; @@ -1597,150 +1600,216 @@ xfs_qm_init_quotainos( return 0; } -STATIC void -xfs_qm_dqfree_one( - struct xfs_dquot *dqp) -{ - struct xfs_mount *mp = dqp->q_mount; - struct xfs_quotainfo *qi = mp->m_quotainfo; - mutex_lock(&dqp->q_hash->qh_lock); - list_del_init(&dqp->q_hashlist); - dqp->q_hash->qh_version++; - mutex_unlock(&dqp->q_hash->qh_lock); - mutex_lock(&qi->qi_dqlist_lock); - list_del_init(&dqp->q_mplist); - qi->qi_dquots--; - qi->qi_dqreclaims++; - mutex_unlock(&qi->qi_dqlist_lock); - - xfs_qm_dqdestroy(dqp); -} - -STATIC void -xfs_qm_dqreclaim_one( - struct xfs_dquot *dqp, - struct list_head *dispose_list) +/* + * Pop the least recently used dquot off the freelist and recycle it. + */ +STATIC struct xfs_dquot * +xfs_qm_dqreclaim_one(void) { - struct xfs_mount *mp = dqp->q_mount; - int error; - - if (!xfs_dqlock_nowait(dqp)) - goto out_busy; - - /* - * This dquot has acquired a reference in the meantime remove it from - * the freelist and try again. - */ - if (dqp->q_nrefs) { - xfs_dqunlock(dqp); + struct xfs_dquot *dqp; + int restarts = 0; - trace_xfs_dqreclaim_want(dqp); - XQM_STATS_INC(xqmstats.xs_qm_dqwants); + mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); +restart: + list_for_each_entry(dqp, &xfs_Gqm->qm_dqfrlist, q_freelist) { + struct xfs_mount *mp = dqp->q_mount; - list_del_init(&dqp->q_freelist); - xfs_Gqm->qm_dqfrlist_cnt--; - return; - } + if (!xfs_dqlock_nowait(dqp)) + continue; - ASSERT(dqp->q_hash); - ASSERT(!list_empty(&dqp->q_mplist)); + /* + * This dquot has already been grabbed by dqlookup. + * Remove it from the freelist and try again. + */ + if (dqp->q_nrefs) { + trace_xfs_dqreclaim_want(dqp); + XQM_STATS_INC(xqmstats.xs_qm_dqwants); + + list_del_init(&dqp->q_freelist); + xfs_Gqm->qm_dqfrlist_cnt--; + restarts++; + goto dqunlock; + } - /* - * Try to grab the flush lock. If this dquot is in the process of - * getting flushed to disk, we don't want to reclaim it. - */ - if (!xfs_dqflock_nowait(dqp)) - goto out_busy; + ASSERT(dqp->q_hash); + ASSERT(!list_empty(&dqp->q_mplist)); - /* - * We have the flush lock so we know that this is not in the - * process of being flushed. So, if this is dirty, flush it - * DELWRI so that we don't get a freelist infested with - * dirty dquots. - */ - if (XFS_DQ_IS_DIRTY(dqp)) { - trace_xfs_dqreclaim_dirty(dqp); + /* + * Try to grab the flush lock. If this dquot is in the process + * of getting flushed to disk, we don't want to reclaim it. + */ + if (!xfs_dqflock_nowait(dqp)) + goto dqunlock; /* - * We flush it delayed write, so don't bother releasing the - * freelist lock. + * We have the flush lock so we know that this is not in the + * process of being flushed. So, if this is dirty, flush it + * DELWRI so that we don't get a freelist infested with + * dirty dquots. */ - error = xfs_qm_dqflush(dqp, 0); - if (error) { - xfs_warn(mp, "%s: dquot %p flush failed", - __func__, dqp); + if (XFS_DQ_IS_DIRTY(dqp)) { + int error; + + trace_xfs_dqreclaim_dirty(dqp); + + /* + * We flush it delayed write, so don't bother + * releasing the freelist lock. + */ + error = xfs_qm_dqflush(dqp, SYNC_TRYLOCK); + if (error) { + xfs_warn(mp, "%s: dquot %p flush failed", + __func__, dqp); + } + goto dqunlock; } + xfs_dqfunlock(dqp); /* - * Give the dquot another try on the freelist, as the - * flushing will take some time. + * Prevent lookup now that we are going to reclaim the dquot. + * Once XFS_DQ_FREEING is set lookup won't touch the dquot, + * thus we can drop the lock now. */ - goto out_busy; - } - xfs_dqfunlock(dqp); + dqp->dq_flags |= XFS_DQ_FREEING; + xfs_dqunlock(dqp); - /* - * Prevent lookups now that we are past the point of no return. - */ - dqp->dq_flags |= XFS_DQ_FREEING; - xfs_dqunlock(dqp); + mutex_lock(&dqp->q_hash->qh_lock); + list_del_init(&dqp->q_hashlist); + dqp->q_hash->qh_version++; + mutex_unlock(&dqp->q_hash->qh_lock); - ASSERT(dqp->q_nrefs == 0); - list_move_tail(&dqp->q_freelist, dispose_list); - xfs_Gqm->qm_dqfrlist_cnt--; + mutex_lock(&mp->m_quotainfo->qi_dqlist_lock); + list_del_init(&dqp->q_mplist); + mp->m_quotainfo->qi_dquots--; + mp->m_quotainfo->qi_dqreclaims++; + mutex_unlock(&mp->m_quotainfo->qi_dqlist_lock); - trace_xfs_dqreclaim_done(dqp); - XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); - return; + ASSERT(dqp->q_nrefs == 0); + list_del_init(&dqp->q_freelist); + xfs_Gqm->qm_dqfrlist_cnt--; -out_busy: - xfs_dqunlock(dqp); + mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); + return dqp; +dqunlock: + xfs_dqunlock(dqp); + if (restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) + break; + goto restart; + } - /* - * Move the dquot to the tail of the list so that we don't spin on it. - */ - list_move_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist); + mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); + return NULL; +} - trace_xfs_dqreclaim_busy(dqp); - XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); +/* + * Traverse the freelist of dquots and attempt to reclaim a maximum of + * 'howmany' dquots. This operation races with dqlookup(), and attempts to + * favor the lookup function ... + */ +STATIC int +xfs_qm_shake_freelist( + int howmany) +{ + int nreclaimed = 0; + xfs_dquot_t *dqp; + + if (howmany <= 0) + return 0; + + while (nreclaimed < howmany) { + dqp = xfs_qm_dqreclaim_one(); + if (!dqp) + return nreclaimed; + xfs_qm_dqdestroy(dqp); + nreclaimed++; + } + return nreclaimed; } +/* + * The kmem_shake interface is invoked when memory is running low. + */ +/* ARGSUSED */ STATIC int xfs_qm_shake( - struct shrinker *shrink, - struct shrink_control *sc) + struct shrinker *shrink, + struct shrink_control *sc) { - int nr_to_scan = sc->nr_to_scan; - LIST_HEAD (dispose_list); - struct xfs_dquot *dqp; + int ndqused, nfree, n; + gfp_t gfp_mask = sc->gfp_mask; - if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT)) + if (!kmem_shake_allow(gfp_mask)) + return 0; + if (!xfs_Gqm) return 0; - if (!nr_to_scan) - goto out; - mutex_lock(&xfs_Gqm->qm_dqfrlist_lock); - while (!list_empty(&xfs_Gqm->qm_dqfrlist)) { - if (nr_to_scan-- <= 0) - break; - dqp = list_first_entry(&xfs_Gqm->qm_dqfrlist, struct xfs_dquot, - q_freelist); - xfs_qm_dqreclaim_one(dqp, &dispose_list); - } - mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock); + nfree = xfs_Gqm->qm_dqfrlist_cnt; /* free dquots */ + /* incore dquots in all f/s's */ + ndqused = atomic_read(&xfs_Gqm->qm_totaldquots) - nfree; - while (!list_empty(&dispose_list)) { - dqp = list_first_entry(&dispose_list, struct xfs_dquot, - q_freelist); - list_del_init(&dqp->q_freelist); - xfs_qm_dqfree_one(dqp); + ASSERT(ndqused >= 0); + + if (nfree <= ndqused && nfree < ndquot) + return 0; + + ndqused *= xfs_Gqm->qm_dqfree_ratio; /* target # of free dquots */ + n = nfree - ndqused - ndquot; /* # over target */ + + return xfs_qm_shake_freelist(MAX(nfree, n)); +} + + +/*------------------------------------------------------------------*/ + +/* + * Return a new incore dquot. Depending on the number of + * dquots in the system, we either allocate a new one on the kernel heap, + * or reclaim a free one. + * Return value is B_TRUE if we allocated a new dquot, B_FALSE if we managed + * to reclaim an existing one from the freelist. + */ +boolean_t +xfs_qm_dqalloc_incore( + xfs_dquot_t **O_dqpp) +{ + xfs_dquot_t *dqp; + + /* + * Check against high water mark to see if we want to pop + * a nincompoop dquot off the freelist. + */ + if (atomic_read(&xfs_Gqm->qm_totaldquots) >= ndquot) { + /* + * Try to recycle a dquot from the freelist. + */ + if ((dqp = xfs_qm_dqreclaim_one())) { + XQM_STATS_INC(xqmstats.xs_qm_dqreclaims); + /* + * Just zero the core here. The rest will get + * reinitialized by caller. XXX we shouldn't even + * do this zero ... + */ + memset(&dqp->q_core, 0, sizeof(dqp->q_core)); + *O_dqpp = dqp; + return B_FALSE; + } + XQM_STATS_INC(xqmstats.xs_qm_dqreclaim_misses); } -out: - return (xfs_Gqm->qm_dqfrlist_cnt / 100) * sysctl_vfs_cache_pressure; + + /* + * Allocate a brand new dquot on the kernel heap and return it + * to the caller to initialize. + */ + ASSERT(xfs_Gqm->qm_dqzone != NULL); + *O_dqpp = kmem_zone_zalloc(xfs_Gqm->qm_dqzone, KM_SLEEP); + atomic_inc(&xfs_Gqm->qm_totaldquots); + + return B_TRUE; } + /* * Start a transaction and write the incore superblock changes to * disk. flags parameter indicates which fields have changed. diff --git a/trunk/fs/xfs/xfs_qm.h b/trunk/fs/xfs/xfs_qm.h index 9a9b997e1a0a..9b4f3adefbc5 100644 --- a/trunk/fs/xfs/xfs_qm.h +++ b/trunk/fs/xfs/xfs_qm.h @@ -26,11 +26,23 @@ struct xfs_qm; struct xfs_inode; +extern uint ndquot; extern struct mutex xfs_Gqm_lock; extern struct xfs_qm *xfs_Gqm; extern kmem_zone_t *qm_dqzone; extern kmem_zone_t *qm_dqtrxzone; +/* + * Ditto, for xfs_qm_dqreclaim_one. + */ +#define XFS_QM_RECLAIM_MAX_RESTARTS 4 + +/* + * Ideal ratio of free to in use dquots. Quota manager makes an attempt + * to keep this balance. + */ +#define XFS_QM_DQFREE_RATIO 2 + /* * Dquot hashtable constants/threshold values. */ @@ -62,6 +74,7 @@ typedef struct xfs_qm { int qm_dqfrlist_cnt; atomic_t qm_totaldquots; /* total incore dquots */ uint qm_nrefs; /* file systems with quota on */ + int qm_dqfree_ratio;/* ratio of free to inuse dquots */ kmem_zone_t *qm_dqzone; /* dquot mem-alloc zone */ kmem_zone_t *qm_dqtrxzone; /* t_dqinfo of transactions */ } xfs_qm_t; @@ -130,6 +143,7 @@ extern int xfs_qm_quotacheck(xfs_mount_t *); extern int xfs_qm_write_sb_changes(xfs_mount_t *, __int64_t); /* dquot stuff */ +extern boolean_t xfs_qm_dqalloc_incore(xfs_dquot_t **); extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); diff --git a/trunk/fs/xfs/xfs_qm_stats.c b/trunk/fs/xfs/xfs_qm_stats.c index 5729ba570877..8671a0b32644 100644 --- a/trunk/fs/xfs/xfs_qm_stats.c +++ b/trunk/fs/xfs/xfs_qm_stats.c @@ -42,9 +42,9 @@ static int xqm_proc_show(struct seq_file *m, void *v) { /* maximum; incore; ratio free to inuse; freelist */ seq_printf(m, "%d\t%d\t%d\t%u\n", - 0, + ndquot, xfs_Gqm? atomic_read(&xfs_Gqm->qm_totaldquots) : 0, - 0, + xfs_Gqm? xfs_Gqm->qm_dqfree_ratio : 0, xfs_Gqm? xfs_Gqm->qm_dqfrlist_cnt : 0); return 0; } diff --git a/trunk/fs/xfs/xfs_trace.h b/trunk/fs/xfs/xfs_trace.h index bb134a819930..6b6df5802e95 100644 --- a/trunk/fs/xfs/xfs_trace.h +++ b/trunk/fs/xfs/xfs_trace.h @@ -733,10 +733,11 @@ DEFINE_EVENT(xfs_dquot_class, name, \ DEFINE_DQUOT_EVENT(xfs_dqadjust); DEFINE_DQUOT_EVENT(xfs_dqreclaim_want); DEFINE_DQUOT_EVENT(xfs_dqreclaim_dirty); -DEFINE_DQUOT_EVENT(xfs_dqreclaim_busy); -DEFINE_DQUOT_EVENT(xfs_dqreclaim_done); +DEFINE_DQUOT_EVENT(xfs_dqreclaim_unlink); DEFINE_DQUOT_EVENT(xfs_dqattach_found); DEFINE_DQUOT_EVENT(xfs_dqattach_get); +DEFINE_DQUOT_EVENT(xfs_dqinit); +DEFINE_DQUOT_EVENT(xfs_dqreuse); DEFINE_DQUOT_EVENT(xfs_dqalloc); DEFINE_DQUOT_EVENT(xfs_dqtobp_read); DEFINE_DQUOT_EVENT(xfs_dqread); diff --git a/trunk/include/linux/bitops.h b/trunk/include/linux/bitops.h index 94300fe46cce..3c1063acb2ab 100644 --- a/trunk/include/linux/bitops.h +++ b/trunk/include/linux/bitops.h @@ -55,26 +55,6 @@ static inline unsigned long hweight_long(unsigned long w) return sizeof(w) == 4 ? hweight32(w) : hweight64(w); } -/** - * rol64 - rotate a 64-bit value left - * @word: value to rotate - * @shift: bits to roll - */ -static inline __u64 rol64(__u64 word, unsigned int shift) -{ - return (word << shift) | (word >> (64 - shift)); -} - -/** - * ror64 - rotate a 64-bit value right - * @word: value to rotate - * @shift: bits to roll - */ -static inline __u64 ror64(__u64 word, unsigned int shift) -{ - return (word >> shift) | (word << (64 - shift)); -} - /** * rol32 - rotate a 32-bit value left * @word: value to rotate diff --git a/trunk/include/linux/mmc/card.h b/trunk/include/linux/mmc/card.h index 19a41d1737af..9f22ba572de0 100644 --- a/trunk/include/linux/mmc/card.h +++ b/trunk/include/linux/mmc/card.h @@ -217,7 +217,6 @@ struct mmc_card { #define MMC_CARD_SDXC (1<<6) /* card is SDXC */ #define MMC_CARD_REMOVED (1<<7) /* card has been removed */ #define MMC_STATE_HIGHSPEED_200 (1<<8) /* card is in HS200 mode */ -#define MMC_STATE_SLEEP (1<<9) /* card is in sleep state */ unsigned int quirks; /* card quirks */ #define MMC_QUIRK_LENIENT_FN0 (1<<0) /* allow SDIO FN0 writes outside of the VS CCCR range */ #define MMC_QUIRK_BLKSZ_FOR_BYTE_MODE (1<<1) /* use func->cur_blksize */ @@ -383,7 +382,6 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_sd_card_uhs(c) ((c)->state & MMC_STATE_ULTRAHIGHSPEED) #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC) #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED)) -#define mmc_card_is_sleep(c) ((c)->state & MMC_STATE_SLEEP) #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT) #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY) @@ -395,9 +393,7 @@ static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) #define mmc_sd_card_set_uhs(c) ((c)->state |= MMC_STATE_ULTRAHIGHSPEED) #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC) #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED) -#define mmc_card_set_sleep(c) ((c)->state |= MMC_STATE_SLEEP) -#define mmc_card_clr_sleep(c) ((c)->state &= ~MMC_STATE_SLEEP) /* * Quirk add/remove for MMC products. */ diff --git a/trunk/include/linux/mmc/dw_mmc.h b/trunk/include/linux/mmc/dw_mmc.h index aae5d1f1bb39..e8779c6d1759 100644 --- a/trunk/include/linux/mmc/dw_mmc.h +++ b/trunk/include/linux/mmc/dw_mmc.h @@ -14,8 +14,6 @@ #ifndef LINUX_MMC_DW_MMC_H #define LINUX_MMC_DW_MMC_H -#include - #define MAX_MCI_SLOTS 2 enum dw_mci_state { @@ -42,7 +40,7 @@ struct mmc_data; * @lock: Spinlock protecting the queue and associated data. * @regs: Pointer to MMIO registers. * @sg: Scatterlist entry currently being processed by PIO code, if any. - * @sg_miter: PIO mapping scatterlist iterator. + * @pio_offset: Offset into the current scatterlist entry. * @cur_slot: The slot which is currently using the controller. * @mrq: The request currently being processed on @cur_slot, * or NULL if the controller is idle. @@ -117,7 +115,7 @@ struct dw_mci { void __iomem *regs; struct scatterlist *sg; - struct sg_mapping_iter sg_miter; + unsigned int pio_offset; struct dw_mci_slot *cur_slot; struct mmc_request *mrq; diff --git a/trunk/include/linux/mmc/host.h b/trunk/include/linux/mmc/host.h index ee2b0363c040..0beba1e5e1ed 100644 --- a/trunk/include/linux/mmc/host.h +++ b/trunk/include/linux/mmc/host.h @@ -257,7 +257,6 @@ struct mmc_host { #define MMC_CAP2_HS200_1_2V_SDR (1 << 6) /* can support */ #define MMC_CAP2_HS200 (MMC_CAP2_HS200_1_8V_SDR | \ MMC_CAP2_HS200_1_2V_SDR) -#define MMC_CAP2_BROKEN_VOLTAGE (1 << 7) /* Use the broken voltage */ mmc_pm_flag_t pm_caps; /* supported pm features */ unsigned int power_notify_type; @@ -445,23 +444,4 @@ static inline int mmc_boot_partition_access(struct mmc_host *host) return !(host->caps2 & MMC_CAP2_BOOTPART_NOACC); } -#ifdef CONFIG_MMC_CLKGATE -void mmc_host_clk_hold(struct mmc_host *host); -void mmc_host_clk_release(struct mmc_host *host); -unsigned int mmc_host_clk_rate(struct mmc_host *host); - -#else -static inline void mmc_host_clk_hold(struct mmc_host *host) -{ -} - -static inline void mmc_host_clk_release(struct mmc_host *host) -{ -} - -static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) -{ - return host->ios.clock; -} -#endif #endif /* LINUX_MMC_HOST_H */ diff --git a/trunk/kernel/params.c b/trunk/kernel/params.c index 4bc965d8a1fe..32ee04308285 100644 --- a/trunk/kernel/params.c +++ b/trunk/kernel/params.c @@ -97,8 +97,7 @@ static int parse_one(char *param, for (i = 0; i < num_params; i++) { if (parameq(param, params[i].name)) { /* No one handled NULL, so do it here. */ - if (!val && params[i].ops->set != param_set_bool - && params[i].ops->set != param_set_bint) + if (!val && params[i].ops->set != param_set_bool) return -EINVAL; pr_debug("They are equal! Calling %p\n", params[i].ops->set); diff --git a/trunk/scripts/mod/file2alias.c b/trunk/scripts/mod/file2alias.c index d0de2a2c3a2d..e8c969577768 100644 --- a/trunk/scripts/mod/file2alias.c +++ b/trunk/scripts/mod/file2alias.c @@ -932,7 +932,7 @@ static int do_isapnp_entry(const char *filename, (id->function >> 12) & 0x0f, (id->function >> 8) & 0x0f); return 1; } -ADD_TO_DEVTABLE("isapnp", struct isapnp_device_id, do_isapnp_entry); +ADD_TO_DEVTABLE("isa", struct isapnp_device_id, do_isapnp_entry); /* * Append a match expression for a single masked hex digit. diff --git a/trunk/sound/pci/hda/patch_realtek.c b/trunk/sound/pci/hda/patch_realtek.c index 1358987c49d8..9350f3c3bdf8 100644 --- a/trunk/sound/pci/hda/patch_realtek.c +++ b/trunk/sound/pci/hda/patch_realtek.c @@ -4374,7 +4374,6 @@ enum { ALC882_FIXUP_ACER_ASPIRE_8930G, ALC882_FIXUP_ASPIRE_8930G_VERBS, ALC885_FIXUP_MACPRO_GPIO, - ALC889_FIXUP_DAC_ROUTE, }; static void alc889_fixup_coef(struct hda_codec *codec, @@ -4428,23 +4427,6 @@ static void alc885_fixup_macpro_gpio(struct hda_codec *codec, alc882_gpio_mute(codec, 1, 0); } -/* Fix the connection of some pins for ALC889: - * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't - * work correctly (bko#42740) - */ -static void alc889_fixup_dac_route(struct hda_codec *codec, - const struct alc_fixup *fix, int action) -{ - if (action == ALC_FIXUP_ACT_PRE_PROBE) { - hda_nid_t conn1[2] = { 0x0c, 0x0d }; - hda_nid_t conn2[2] = { 0x0e, 0x0f }; - snd_hda_override_conn_list(codec, 0x14, 2, conn1); - snd_hda_override_conn_list(codec, 0x15, 2, conn1); - snd_hda_override_conn_list(codec, 0x18, 2, conn2); - snd_hda_override_conn_list(codec, 0x1a, 2, conn2); - } -} - static const struct alc_fixup alc882_fixups[] = { [ALC882_FIXUP_ABIT_AW9D_MAX] = { .type = ALC_FIXUP_PINS, @@ -4592,10 +4574,6 @@ static const struct alc_fixup alc882_fixups[] = { .type = ALC_FIXUP_FUNC, .v.func = alc885_fixup_macpro_gpio, }, - [ALC889_FIXUP_DAC_ROUTE] = { - .type = ALC_FIXUP_FUNC, - .v.func = alc889_fixup_dac_route, - }, }; static const struct snd_pci_quirk alc882_fixup_tbl[] = { @@ -4620,7 +4598,6 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = { SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G", ALC882_FIXUP_ACER_ASPIRE_4930G), SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210), - SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE), SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736), SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD), SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V), diff --git a/trunk/sound/pci/hda/patch_sigmatel.c b/trunk/sound/pci/hda/patch_sigmatel.c index 6345df131a00..948f0be2f4f3 100644 --- a/trunk/sound/pci/hda/patch_sigmatel.c +++ b/trunk/sound/pci/hda/patch_sigmatel.c @@ -5078,9 +5078,9 @@ static int stac92xx_update_led_status(struct hda_codec *codec) spec->gpio_dir, spec->gpio_data); } else { notmtd_lvl = spec->gpio_led_polarity ? - AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; + AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD; muted_lvl = spec->gpio_led_polarity ? - AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50; + AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; spec->vref_led = muted ? muted_lvl : notmtd_lvl; stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); diff --git a/trunk/sound/pci/hda/patch_via.c b/trunk/sound/pci/hda/patch_via.c index dff9a00ee8fb..284e311040fe 100644 --- a/trunk/sound/pci/hda/patch_via.c +++ b/trunk/sound/pci/hda/patch_via.c @@ -666,9 +666,6 @@ static void via_auto_init_analog_input(struct hda_codec *codec) /* init input-src */ for (i = 0; i < spec->num_adc_nids; i++) { int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx; - /* secondary ADCs must have the unique MUX */ - if (i > 0 && !spec->mux_nids[i]) - break; if (spec->mux_nids[adc_idx]) { int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx; snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0, diff --git a/trunk/sound/pci/intel8x0.c b/trunk/sound/pci/intel8x0.c index e0a4263baa20..9f3b01bb72c8 100644 --- a/trunk/sound/pci/intel8x0.c +++ b/trunk/sound/pci/intel8x0.c @@ -2100,12 +2100,6 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { .name = "MSI P4 ATX 645 Ultra", .type = AC97_TUNE_HP_ONLY }, - { - .subvendor = 0x161f, - .subdevice = 0x202f, - .name = "Gateway M520", - .type = AC97_TUNE_INV_EAPD - }, { .subvendor = 0x161f, .subdevice = 0x203a, diff --git a/trunk/sound/soc/sh/fsi.c b/trunk/sound/soc/sh/fsi.c index ea4a82d01160..db6c89a28bda 100644 --- a/trunk/sound/soc/sh/fsi.c +++ b/trunk/sound/soc/sh/fsi.c @@ -1152,8 +1152,12 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream) { struct fsi_priv *fsi = fsi_get_priv(substream); struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream)); + int samples_pos = io->buff_sample_pos - 1; - return fsi_sample2frame(fsi, io->buff_sample_pos); + if (samples_pos < 0) + samples_pos = 0; + + return fsi_sample2frame(fsi, samples_pos); } static struct snd_pcm_ops fsi_pcm_ops = {