diff --git a/[refs] b/[refs] index 328ce54c99dd..a91acacd454b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: bff98bfcdb2124e4e640fa6d7c9c7c3d21362760 +refs/heads/master: cc9a672ee522d4805495b98680f4a3db5d0a0af9 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/configs/ppc64_defconfig b/trunk/arch/powerpc/configs/ppc64_defconfig index 1acf65026773..2156e077859b 100644 --- a/trunk/arch/powerpc/configs/ppc64_defconfig +++ b/trunk/arch/powerpc/configs/ppc64_defconfig @@ -24,6 +24,10 @@ CONFIG_PPC_SPLPAR=y CONFIG_SCANLOG=m CONFIG_PPC_SMLPAR=y CONFIG_DTL=y +CONFIG_PPC_ISERIES=y +CONFIG_VIODASD=y +CONFIG_VIOCD=m +CONFIG_VIOTAPE=m CONFIG_PPC_MAPLE=y CONFIG_PPC_PASEMI=y CONFIG_PPC_PASEMI_IOMMU=y @@ -255,6 +259,7 @@ CONFIG_PASEMI_MAC=y CONFIG_MLX4_EN=m CONFIG_QLGE=m CONFIG_BE2NET=m +CONFIG_ISERIES_VETH=m CONFIG_PPP=m CONFIG_PPP_ASYNC=m CONFIG_PPP_SYNC_TTY=m diff --git a/trunk/arch/powerpc/include/asm/ppc-pci.h b/trunk/arch/powerpc/include/asm/ppc-pci.h index 6d422979ebaf..43268f15004e 100644 --- a/trunk/arch/powerpc/include/asm/ppc-pci.h +++ b/trunk/arch/powerpc/include/asm/ppc-pci.h @@ -142,11 +142,6 @@ static inline const char *eeh_pci_name(struct pci_dev *pdev) return pdev ? pci_name(pdev) : ""; } -static inline const char *eeh_driver_name(struct pci_dev *pdev) -{ - return (pdev && pdev->driver) ? pdev->driver->name : ""; -} - #endif /* CONFIG_EEH */ #else /* CONFIG_PCI */ diff --git a/trunk/arch/powerpc/include/asm/ptrace.h b/trunk/arch/powerpc/include/asm/ptrace.h index 84cc7840cd18..78a205162fd7 100644 --- a/trunk/arch/powerpc/include/asm/ptrace.h +++ b/trunk/arch/powerpc/include/asm/ptrace.h @@ -83,18 +83,8 @@ struct pt_regs { #ifndef __ASSEMBLY__ -#define GET_IP(regs) ((regs)->nip) -#define GET_USP(regs) ((regs)->gpr[1]) -#define GET_FP(regs) (0) -#define SET_FP(regs, val) - -#ifdef CONFIG_SMP -extern unsigned long profile_pc(struct pt_regs *regs); -#define profile_pc profile_pc -#endif - -#include - +#define instruction_pointer(regs) ((regs)->nip) +#define user_stack_pointer(regs) ((regs)->gpr[1]) #define kernel_stack_pointer(regs) ((regs)->gpr[1]) static inline int is_syscall_success(struct pt_regs *regs) { @@ -109,6 +99,12 @@ static inline long regs_return_value(struct pt_regs *regs) return -regs->gpr[3]; } +#ifdef CONFIG_SMP +extern unsigned long profile_pc(struct pt_regs *regs); +#else +#define profile_pc(regs) instruction_pointer(regs) +#endif + #ifdef __powerpc64__ #define user_mode(regs) ((((regs)->msr) >> MSR_PR_LG) & 0x1) #else diff --git a/trunk/arch/powerpc/kernel/exceptions-64s.S b/trunk/arch/powerpc/kernel/exceptions-64s.S index 3844ca7c5099..d4be7bb3dbdf 100644 --- a/trunk/arch/powerpc/kernel/exceptions-64s.S +++ b/trunk/arch/powerpc/kernel/exceptions-64s.S @@ -775,7 +775,7 @@ program_check_common: EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD - DISABLE_INTS + ENABLE_INTS bl .program_check_exception b .ret_from_except diff --git a/trunk/arch/powerpc/kernel/irq.c b/trunk/arch/powerpc/kernel/irq.c index 01e2877e8e04..701d4aceb4f4 100644 --- a/trunk/arch/powerpc/kernel/irq.c +++ b/trunk/arch/powerpc/kernel/irq.c @@ -118,14 +118,10 @@ static inline notrace void set_soft_enabled(unsigned long enable) static inline notrace void decrementer_check_overflow(void) { u64 now = get_tb_or_rtc(); - u64 *next_tb; - - preempt_disable(); - next_tb = &__get_cpu_var(decrementers_next_tb); + u64 *next_tb = &__get_cpu_var(decrementers_next_tb); if (now >= *next_tb) set_dec(1); - preempt_enable(); } notrace void arch_local_irq_restore(unsigned long en) diff --git a/trunk/arch/powerpc/kernel/perf_event.c b/trunk/arch/powerpc/kernel/perf_event.c index 64483fde95c6..10a140f82cb8 100644 --- a/trunk/arch/powerpc/kernel/perf_event.c +++ b/trunk/arch/powerpc/kernel/perf_event.c @@ -865,7 +865,6 @@ static void power_pmu_start(struct perf_event *event, int ef_flags) { unsigned long flags; s64 left; - unsigned long val; if (!event->hw.idx || !event->hw.sample_period) return; @@ -881,12 +880,7 @@ static void power_pmu_start(struct perf_event *event, int ef_flags) event->hw.state = 0; left = local64_read(&event->hw.period_left); - - val = 0; - if (left < 0x80000000L) - val = 0x80000000L - left; - - write_pmc(event->hw.idx, val); + write_pmc(event->hw.idx, left); perf_event_update_userpage(event); perf_pmu_enable(event->pmu); diff --git a/trunk/arch/powerpc/kernel/process.c b/trunk/arch/powerpc/kernel/process.c index d817ab018486..ebe5766781aa 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(KERN_CONT "XXXXXXXX "); + printk("XXXXXXXX "); } else { if (regs->nip == pc) - printk(KERN_CONT "<%08x> ", instr); + printk("<%08x> ", instr); else - printk(KERN_CONT "%08x ", instr); + printk("%08x ", instr); } pc += sizeof(int); diff --git a/trunk/arch/powerpc/kernel/rtas.c b/trunk/arch/powerpc/kernel/rtas.c index 9f843cdfee9e..517b1d8f455b 100644 --- a/trunk/arch/powerpc/kernel/rtas.c +++ b/trunk/arch/powerpc/kernel/rtas.c @@ -716,6 +716,7 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w int cpu; slb_set_size(SLB_MIN_SIZE); + stop_topology_update(); printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", smp_processor_id()); while (rc == H_MULTI_THREADS_ACTIVE && !atomic_read(&data->done) && @@ -731,6 +732,7 @@ static int __rtas_suspend_last_cpu(struct rtas_suspend_me_data *data, int wake_w rc = atomic_read(&data->error); atomic_set(&data->error, rc); + start_topology_update(); pSeries_coalesce_init(); if (wake_when_done) { @@ -844,7 +846,6 @@ int rtas_ibm_suspend_me(struct rtas_args *args) atomic_set(&data.error, 0); data.token = rtas_token("ibm,suspend-me"); data.complete = &done; - stop_topology_update(); /* Call function on all CPUs. One of us will make the * rtas call @@ -857,8 +858,6 @@ int rtas_ibm_suspend_me(struct rtas_args *args) if (atomic_read(&data.error) != 0) printk(KERN_ERR "Error doing global join\n"); - start_topology_update(); - return atomic_read(&data.error); } #else /* CONFIG_PPC_PSERIES */ diff --git a/trunk/arch/powerpc/platforms/powernv/pci.c b/trunk/arch/powerpc/platforms/powernv/pci.c index f92b9ef7340e..a70bc1e385eb 100644 --- a/trunk/arch/powerpc/platforms/powernv/pci.c +++ b/trunk/arch/powerpc/platforms/powernv/pci.c @@ -52,38 +52,32 @@ static int pnv_msi_check_device(struct pci_dev* pdev, int nvec, int type) static unsigned int pnv_get_one_msi(struct pnv_phb *phb) { - unsigned long flags; - unsigned int id, rc; - - spin_lock_irqsave(&phb->lock, flags); + unsigned int id; + spin_lock(&phb->lock); id = find_next_zero_bit(phb->msi_map, phb->msi_count, phb->msi_next); if (id >= phb->msi_count && phb->msi_next) id = find_next_zero_bit(phb->msi_map, phb->msi_count, 0); if (id >= phb->msi_count) { - rc = 0; - goto out; + spin_unlock(&phb->lock); + return 0; } __set_bit(id, phb->msi_map); - rc = id + phb->msi_base; -out: - spin_unlock_irqrestore(&phb->lock, flags); - return rc; + spin_unlock(&phb->lock); + return id + phb->msi_base; } static void pnv_put_msi(struct pnv_phb *phb, unsigned int hwirq) { - unsigned long flags; unsigned int id; if (WARN_ON(hwirq < phb->msi_base || hwirq >= (phb->msi_base + phb->msi_count))) return; id = hwirq - phb->msi_base; - - spin_lock_irqsave(&phb->lock, flags); + spin_lock(&phb->lock); __clear_bit(id, phb->msi_map); - spin_unlock_irqrestore(&phb->lock, flags); + spin_unlock(&phb->lock); } static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) diff --git a/trunk/arch/powerpc/platforms/pseries/eeh.c b/trunk/arch/powerpc/platforms/pseries/eeh.c index c0b40af4ce4f..565869022e3d 100644 --- a/trunk/arch/powerpc/platforms/pseries/eeh.c +++ b/trunk/arch/powerpc/platforms/pseries/eeh.c @@ -551,9 +551,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev) printk (KERN_ERR "EEH: %d reads ignored for recovering device at " "location=%s driver=%s pci addr=%s\n", pdn->eeh_check_count, location, - eeh_driver_name(dev), eeh_pci_name(dev)); + dev->driver->name, eeh_pci_name(dev)); printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n", - eeh_driver_name(dev)); + dev->driver->name); dump_stack(); } goto dn_unlock; diff --git a/trunk/arch/powerpc/platforms/pseries/suspend.c b/trunk/arch/powerpc/platforms/pseries/suspend.c index 47226e04126d..b84a8b2238dd 100644 --- a/trunk/arch/powerpc/platforms/pseries/suspend.c +++ b/trunk/arch/powerpc/platforms/pseries/suspend.c @@ -24,7 +24,6 @@ #include #include #include -#include static u64 stream_id; static struct device suspend_dev; @@ -139,11 +138,8 @@ static ssize_t store_hibernate(struct device *dev, ssleep(1); } while (rc == -EAGAIN); - if (!rc) { - stop_topology_update(); + if (!rc) rc = pm_suspend(PM_SUSPEND_MEM); - start_topology_update(); - } stream_id = 0; diff --git a/trunk/arch/powerpc/platforms/wsp/ics.c b/trunk/arch/powerpc/platforms/wsp/ics.c index 97fe82ee8633..576874392543 100644 --- a/trunk/arch/powerpc/platforms/wsp/ics.c +++ b/trunk/arch/powerpc/platforms/wsp/ics.c @@ -346,7 +346,7 @@ static int wsp_chip_set_affinity(struct irq_data *d, * For the moment only implement delivery to all cpus or one cpu. * Get current irq_server for the given irq */ - ret = cache_hwirq_map(ics, hw_irq, cpumask); + ret = cache_hwirq_map(ics, d->irq, cpumask); if (ret == -1) { char cpulist[128]; cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); diff --git a/trunk/arch/powerpc/platforms/wsp/wsp_pci.c b/trunk/arch/powerpc/platforms/wsp/wsp_pci.c index d24b3acf858e..e0262cd0e2d3 100644 --- a/trunk/arch/powerpc/platforms/wsp/wsp_pci.c +++ b/trunk/arch/powerpc/platforms/wsp/wsp_pci.c @@ -468,15 +468,15 @@ static void __init wsp_pcie_configure_hw(struct pci_controller *hose) #define DUMP_REG(x) \ pr_debug("%-30s : 0x%016llx\n", #x, in_be64(hose->cfg_data + x)) - /* - * Some WSP variants has a bogus class code by default in the PCI-E - * root complex's built-in P2P bridge - */ +#ifdef CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS + /* WSP DD1 has a bogus class code by default in the PCI-E + * root complex's built-in P2P bridge */ val = in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1); pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", val); out_be64(hose->cfg_data + PCIE_REG_SYS_CFG1, (val & ~PCIE_REG_SYS_CFG1_CLASS_CODE) | (PCI_CLASS_BRIDGE_PCI << 8)); pr_debug("PCI-E SYS_CFG1 : 0x%llx\n", in_be64(hose->cfg_data + PCIE_REG_SYS_CFG1)); +#endif /* CONFIG_WSP_DD1_WORKAROUND_BAD_PCIE_CLASS */ #ifdef CONFIG_WSP_DD1_WORKAROUND_DD1_TCE_BUGS /* XXX Disable TCE caching, it doesn't work on DD1 */ diff --git a/trunk/arch/powerpc/sysdev/fsl_pci.c b/trunk/arch/powerpc/sysdev/fsl_pci.c index 6073288fed29..30eb17ecad49 100644 --- a/trunk/arch/powerpc/sysdev/fsl_pci.c +++ b/trunk/arch/powerpc/sysdev/fsl_pci.c @@ -385,36 +385,26 @@ static void __init setup_pci_cmd(struct pci_controller *hose) void fsl_pcibios_fixup_bus(struct pci_bus *bus) { struct pci_controller *hose = pci_bus_to_host(bus); - int i, is_pcie = 0, no_link; - - /* The root complex bridge comes up with bogus resources, - * we copy the PHB ones in. - * - * With the current generic PCI code, the PHB bus no longer - * has bus->resource[0..4] set, so things are a bit more - * tricky. - */ - - if (fsl_pcie_bus_fixup) - is_pcie = early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP); - no_link = !!(hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK); - - if (bus->parent == hose->bus && (is_pcie || no_link)) { - for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; ++i) { + int i; + + if ((bus->parent == hose->bus) && + ((fsl_pcie_bus_fixup && + early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) || + (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK))) + { + for (i = 0; i < 4; ++i) { struct resource *res = bus->resource[i]; - struct resource *par; - - if (!res) - continue; - if (i == 0) - par = &hose->io_resource; - else if (i < 4) - par = &hose->mem_resources[i-1]; - else par = NULL; - - res->start = par ? par->start : 0; - res->end = par ? par->end : 0; - res->flags = par ? par->flags : 0; + struct resource *par = bus->parent->resource[i]; + if (res) { + res->start = 0; + res->end = 0; + res->flags = 0; + } + if (res && par) { + res->start = par->start; + res->end = par->end; + res->flags = par->flags; + } } } } 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/block/blk-cgroup.c b/trunk/block/blk-cgroup.c index 75642a352a8f..fa8f26309444 100644 --- a/trunk/block/blk-cgroup.c +++ b/trunk/block/blk-cgroup.c @@ -1659,7 +1659,7 @@ static void blkiocg_attach(struct cgroup_subsys *ss, struct cgroup *cgrp, ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); if (ioc) { ioc_cgroup_changed(ioc); - put_io_context(ioc); + put_io_context(ioc, NULL); } } } diff --git a/trunk/block/blk-core.c b/trunk/block/blk-core.c index 3a78b00edd71..e6c05a97ee2b 100644 --- a/trunk/block/blk-core.c +++ b/trunk/block/blk-core.c @@ -642,7 +642,7 @@ static inline void blk_free_request(struct request_queue *q, struct request *rq) if (rq->cmd_flags & REQ_ELVPRIV) { elv_put_request(q, rq); if (rq->elv.icq) - put_io_context(rq->elv.icq->ioc); + put_io_context(rq->elv.icq->ioc, q); } mempool_free(rq, q->rq.rq_pool); @@ -872,15 +872,13 @@ static struct request *get_request(struct request_queue *q, int rw_flags, spin_unlock_irq(q->queue_lock); /* create icq if missing */ - if ((rw_flags & REQ_ELVPRIV) && unlikely(et->icq_cache && !icq)) { + if (unlikely(et->icq_cache && !icq)) icq = ioc_create_icq(q, gfp_mask); - if (!icq) - goto fail_icq; - } - rq = blk_alloc_request(q, icq, rw_flags, gfp_mask); + /* rqs are guaranteed to have icq on elv_set_request() if requested */ + if (likely(!et->icq_cache || icq)) + rq = blk_alloc_request(q, icq, rw_flags, gfp_mask); -fail_icq: if (unlikely(!rq)) { /* * Allocation failed presumably due to memory. Undo anything @@ -1212,6 +1210,7 @@ static bool bio_attempt_back_merge(struct request_queue *q, struct request *req, req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); drive_stat_acct(req, 0); + elv_bio_merged(q, req, bio); return true; } @@ -1242,6 +1241,7 @@ static bool bio_attempt_front_merge(struct request_queue *q, req->ioprio = ioprio_best(req->ioprio, bio_prio(bio)); drive_stat_acct(req, 0); + elv_bio_merged(q, req, bio); return true; } @@ -1255,12 +1255,13 @@ static bool bio_attempt_front_merge(struct request_queue *q, * on %current's plugged list. Returns %true if merge was successful, * otherwise %false. * - * Plugging coalesces IOs from the same issuer for the same purpose without - * going through @q->queue_lock. As such it's more of an issuing mechanism - * than scheduling, and the request, while may have elvpriv data, is not - * added on the elevator at this point. In addition, we don't have - * reliable access to the elevator outside queue lock. Only check basic - * merging parameters without querying the elevator. + * This function is called without @q->queue_lock; however, elevator is + * accessed iff there already are requests on the plugged list which in + * turn guarantees validity of the elevator. + * + * Note that, on successful merge, elevator operation + * elevator_bio_merged_fn() will be called without queue lock. Elevator + * must be ready for this. */ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio, unsigned int *request_count) @@ -1279,10 +1280,10 @@ static bool attempt_plug_merge(struct request_queue *q, struct bio *bio, (*request_count)++; - if (rq->q != q || !blk_rq_merge_ok(rq, bio)) + if (rq->q != q) continue; - el_ret = blk_try_merge(rq, bio); + el_ret = elv_try_merge(rq, bio); if (el_ret == ELEVATOR_BACK_MERGE) { ret = bio_attempt_back_merge(q, rq, bio); if (ret) @@ -1344,14 +1345,12 @@ void blk_queue_bio(struct request_queue *q, struct bio *bio) el_ret = elv_merge(q, &req, bio); if (el_ret == ELEVATOR_BACK_MERGE) { if (bio_attempt_back_merge(q, req, bio)) { - elv_bio_merged(q, req, bio); if (!attempt_back_merge(q, req)) elv_merged_request(q, req, el_ret); goto out_unlock; } } else if (el_ret == ELEVATOR_FRONT_MERGE) { if (bio_attempt_front_merge(q, req, bio)) { - elv_bio_merged(q, req, bio); if (!attempt_front_merge(q, req)) elv_merged_request(q, req, el_ret); goto out_unlock; diff --git a/trunk/block/blk-ioc.c b/trunk/block/blk-ioc.c index 8b782a63c297..27a06e00eaec 100644 --- a/trunk/block/blk-ioc.c +++ b/trunk/block/blk-ioc.c @@ -29,6 +29,21 @@ void get_io_context(struct io_context *ioc) } EXPORT_SYMBOL(get_io_context); +/* + * Releasing ioc may nest into another put_io_context() leading to nested + * fast path release. As the ioc's can't be the same, this is okay but + * makes lockdep whine. Keep track of nesting and use it as subclass. + */ +#ifdef CONFIG_LOCKDEP +#define ioc_release_depth(q) ((q) ? (q)->ioc_release_depth : 0) +#define ioc_release_depth_inc(q) (q)->ioc_release_depth++ +#define ioc_release_depth_dec(q) (q)->ioc_release_depth-- +#else +#define ioc_release_depth(q) 0 +#define ioc_release_depth_inc(q) do { } while (0) +#define ioc_release_depth_dec(q) do { } while (0) +#endif + static void icq_free_icq_rcu(struct rcu_head *head) { struct io_cq *icq = container_of(head, struct io_cq, __rcu_head); @@ -60,8 +75,11 @@ static void ioc_exit_icq(struct io_cq *icq) if (rcu_dereference_raw(ioc->icq_hint) == icq) rcu_assign_pointer(ioc->icq_hint, NULL); - if (et->ops.elevator_exit_icq_fn) + if (et->ops.elevator_exit_icq_fn) { + ioc_release_depth_inc(q); et->ops.elevator_exit_icq_fn(icq); + ioc_release_depth_dec(q); + } /* * @icq->q might have gone away by the time RCU callback runs @@ -80,15 +98,8 @@ static void ioc_release_fn(struct work_struct *work) struct io_context *ioc = container_of(work, struct io_context, release_work); struct request_queue *last_q = NULL; - unsigned long flags; - /* - * Exiting icq may call into put_io_context() through elevator - * which will trigger lockdep warning. The ioc's are guaranteed to - * be different, use a different locking subclass here. Use - * irqsave variant as there's no spin_lock_irq_nested(). - */ - spin_lock_irqsave_nested(&ioc->lock, flags, 1); + spin_lock_irq(&ioc->lock); while (!hlist_empty(&ioc->icq_list)) { struct io_cq *icq = hlist_entry(ioc->icq_list.first, @@ -110,15 +121,15 @@ static void ioc_release_fn(struct work_struct *work) */ if (last_q) { spin_unlock(last_q->queue_lock); - spin_unlock_irqrestore(&ioc->lock, flags); + spin_unlock_irq(&ioc->lock); blk_put_queue(last_q); } else { - spin_unlock_irqrestore(&ioc->lock, flags); + spin_unlock_irq(&ioc->lock); } last_q = this_q; - spin_lock_irqsave(this_q->queue_lock, flags); - spin_lock_nested(&ioc->lock, 1); + spin_lock_irq(this_q->queue_lock); + spin_lock(&ioc->lock); continue; } ioc_exit_icq(icq); @@ -126,10 +137,10 @@ static void ioc_release_fn(struct work_struct *work) if (last_q) { spin_unlock(last_q->queue_lock); - spin_unlock_irqrestore(&ioc->lock, flags); + spin_unlock_irq(&ioc->lock); blk_put_queue(last_q); } else { - spin_unlock_irqrestore(&ioc->lock, flags); + spin_unlock_irq(&ioc->lock); } kmem_cache_free(iocontext_cachep, ioc); @@ -138,29 +149,79 @@ static void ioc_release_fn(struct work_struct *work) /** * put_io_context - put a reference of io_context * @ioc: io_context to put + * @locked_q: request_queue the caller is holding queue_lock of (hint) * * Decrement reference count of @ioc and release it if the count reaches - * zero. + * zero. If the caller is holding queue_lock of a queue, it can indicate + * that with @locked_q. This is an optimization hint and the caller is + * allowed to pass in %NULL even when it's holding a queue_lock. */ -void put_io_context(struct io_context *ioc) +void put_io_context(struct io_context *ioc, struct request_queue *locked_q) { + struct request_queue *last_q = locked_q; unsigned long flags; if (ioc == NULL) return; BUG_ON(atomic_long_read(&ioc->refcount) <= 0); + if (locked_q) + lockdep_assert_held(locked_q->queue_lock); + + if (!atomic_long_dec_and_test(&ioc->refcount)) + return; /* - * Releasing ioc requires reverse order double locking and we may - * already be holding a queue_lock. Do it asynchronously from wq. + * Destroy @ioc. This is a bit messy because icq's are chained + * from both ioc and queue, and ioc->lock nests inside queue_lock. + * The inner ioc->lock should be held to walk our icq_list and then + * for each icq the outer matching queue_lock should be grabbed. + * ie. We need to do reverse-order double lock dancing. + * + * Another twist is that we are often called with one of the + * matching queue_locks held as indicated by @locked_q, which + * prevents performing double-lock dance for other queues. + * + * So, we do it in two stages. The fast path uses the queue_lock + * the caller is holding and, if other queues need to be accessed, + * uses trylock to avoid introducing locking dependency. This can + * handle most cases, especially if @ioc was performing IO on only + * single device. + * + * If trylock doesn't cut it, we defer to @ioc->release_work which + * can do all the double-locking dancing. */ - if (atomic_long_dec_and_test(&ioc->refcount)) { - spin_lock_irqsave(&ioc->lock, flags); - if (!hlist_empty(&ioc->icq_list)) - schedule_work(&ioc->release_work); - spin_unlock_irqrestore(&ioc->lock, flags); + spin_lock_irqsave_nested(&ioc->lock, flags, + ioc_release_depth(locked_q)); + + while (!hlist_empty(&ioc->icq_list)) { + struct io_cq *icq = hlist_entry(ioc->icq_list.first, + struct io_cq, ioc_node); + struct request_queue *this_q = icq->q; + + if (this_q != last_q) { + if (last_q && last_q != locked_q) + spin_unlock(last_q->queue_lock); + last_q = NULL; + + if (!spin_trylock(this_q->queue_lock)) + break; + last_q = this_q; + continue; + } + ioc_exit_icq(icq); } + + if (last_q && last_q != locked_q) + spin_unlock(last_q->queue_lock); + + spin_unlock_irqrestore(&ioc->lock, flags); + + /* if no icq is left, we're done; otherwise, kick release_work */ + if (hlist_empty(&ioc->icq_list)) + kmem_cache_free(iocontext_cachep, ioc); + else + schedule_work(&ioc->release_work); } EXPORT_SYMBOL(put_io_context); @@ -175,7 +236,7 @@ void exit_io_context(struct task_struct *task) task_unlock(task); atomic_dec(&ioc->nr_tasks); - put_io_context(ioc); + put_io_context(ioc, NULL); } /** diff --git a/trunk/block/blk-merge.c b/trunk/block/blk-merge.c index 160035f54882..cfcc37cb222b 100644 --- a/trunk/block/blk-merge.c +++ b/trunk/block/blk-merge.c @@ -471,40 +471,3 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq, { return attempt_merge(q, rq, next); } - -bool blk_rq_merge_ok(struct request *rq, struct bio *bio) -{ - if (!rq_mergeable(rq)) - return false; - - /* don't merge file system requests and discard requests */ - if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) - return false; - - /* don't merge discard requests and secure discard requests */ - if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) - return false; - - /* different data direction or already started, don't merge */ - if (bio_data_dir(bio) != rq_data_dir(rq)) - return false; - - /* must be same device and not a special request */ - if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) - return false; - - /* only merge integrity protected bio into ditto rq */ - if (bio_integrity(bio) != blk_integrity_rq(rq)) - return false; - - return true; -} - -int blk_try_merge(struct request *rq, struct bio *bio) -{ - if (blk_rq_pos(rq) + blk_rq_sectors(rq) == bio->bi_sector) - return ELEVATOR_BACK_MERGE; - else if (blk_rq_pos(rq) - bio_sectors(bio) == bio->bi_sector) - return ELEVATOR_FRONT_MERGE; - return ELEVATOR_NO_MERGE; -} diff --git a/trunk/block/blk.h b/trunk/block/blk.h index 9c12f80882b0..7efd772336de 100644 --- a/trunk/block/blk.h +++ b/trunk/block/blk.h @@ -137,8 +137,6 @@ int blk_attempt_req_merge(struct request_queue *q, struct request *rq, struct request *next); void blk_recalc_rq_segments(struct request *rq); void blk_rq_set_mixed_merge(struct request *rq); -bool blk_rq_merge_ok(struct request *rq, struct bio *bio); -int blk_try_merge(struct request *rq, struct bio *bio); void blk_queue_congestion_threshold(struct request_queue *q); diff --git a/trunk/block/bsg.c b/trunk/block/bsg.c index ff64ae3bacee..4cf703fd98bb 100644 --- a/trunk/block/bsg.c +++ b/trunk/block/bsg.c @@ -983,8 +983,7 @@ void bsg_unregister_queue(struct request_queue *q) mutex_lock(&bsg_mutex); idr_remove(&bsg_minor_idr, bcd->minor); - if (q->kobj.sd) - sysfs_remove_link(&q->kobj, "bsg"); + sysfs_remove_link(&q->kobj, "bsg"); device_unregister(bcd->class_dev); bcd->class_dev = NULL; kref_put(&bcd->ref, bsg_kref_release_function); diff --git a/trunk/block/cfq-iosched.c b/trunk/block/cfq-iosched.c index d0ba50533668..ee55019066a1 100644 --- a/trunk/block/cfq-iosched.c +++ b/trunk/block/cfq-iosched.c @@ -1699,11 +1699,18 @@ static int cfq_allow_merge(struct request_queue *q, struct request *rq, /* * Lookup the cfqq that this bio will be queued with and allow - * merge only if rq is queued there. + * merge only if rq is queued there. This function can be called + * from plug merge without queue_lock. In such cases, ioc of @rq + * and %current are guaranteed to be equal. Avoid lookup which + * requires queue_lock by using @rq's cic. */ - cic = cfq_cic_lookup(cfqd, current->io_context); - if (!cic) - return false; + if (current->io_context == RQ_CIC(rq)->icq.ioc) { + cic = RQ_CIC(rq); + } else { + cic = cfq_cic_lookup(cfqd, current->io_context); + if (!cic) + return false; + } cfqq = cic_to_cfqq(cic, cfq_bio_sync(bio)); return cfqq == RQ_CFQQ(rq); @@ -1787,7 +1794,7 @@ __cfq_slice_expired(struct cfq_data *cfqd, struct cfq_queue *cfqq, cfqd->active_queue = NULL; if (cfqd->active_cic) { - put_io_context(cfqd->active_cic->icq.ioc); + put_io_context(cfqd->active_cic->icq.ioc, cfqd->queue); cfqd->active_cic = NULL; } } @@ -3110,18 +3117,17 @@ cfq_should_preempt(struct cfq_data *cfqd, struct cfq_queue *new_cfqq, */ static void cfq_preempt_queue(struct cfq_data *cfqd, struct cfq_queue *cfqq) { - enum wl_type_t old_type = cfqq_type(cfqd->active_queue); - cfq_log_cfqq(cfqd, cfqq, "preempt"); - cfq_slice_expired(cfqd, 1); /* * workload type is changed, don't save slice, otherwise preempt * doesn't happen */ - if (old_type != cfqq_type(cfqq)) + if (cfqq_type(cfqd->active_queue) != cfqq_type(cfqq)) cfqq->cfqg->saved_workload_slice = 0; + cfq_slice_expired(cfqd, 1); + /* * Put the new queue at the front of the of the current list, * so we know that it will be selected next. diff --git a/trunk/block/elevator.c b/trunk/block/elevator.c index f016855a46b0..91e18f8af9be 100644 --- a/trunk/block/elevator.c +++ b/trunk/block/elevator.c @@ -70,9 +70,39 @@ static int elv_iosched_allow_merge(struct request *rq, struct bio *bio) /* * can we safely merge with this request? */ -bool elv_rq_merge_ok(struct request *rq, struct bio *bio) +int elv_rq_merge_ok(struct request *rq, struct bio *bio) { - if (!blk_rq_merge_ok(rq, bio)) + if (!rq_mergeable(rq)) + return 0; + + /* + * Don't merge file system requests and discard requests + */ + if ((bio->bi_rw & REQ_DISCARD) != (rq->bio->bi_rw & REQ_DISCARD)) + return 0; + + /* + * Don't merge discard requests and secure discard requests + */ + if ((bio->bi_rw & REQ_SECURE) != (rq->bio->bi_rw & REQ_SECURE)) + return 0; + + /* + * different data direction or already started, don't merge + */ + if (bio_data_dir(bio) != rq_data_dir(rq)) + return 0; + + /* + * must be same device and not a special request + */ + if (rq->rq_disk != bio->bi_bdev->bd_disk || rq->special) + return 0; + + /* + * only merge integrity protected bio into ditto rq + */ + if (bio_integrity(bio) != blk_integrity_rq(rq)) return 0; if (!elv_iosched_allow_merge(rq, bio)) @@ -82,6 +112,23 @@ bool elv_rq_merge_ok(struct request *rq, struct bio *bio) } EXPORT_SYMBOL(elv_rq_merge_ok); +int elv_try_merge(struct request *__rq, struct bio *bio) +{ + int ret = ELEVATOR_NO_MERGE; + + /* + * we can merge and sequence is ok, check if it's possible + */ + if (elv_rq_merge_ok(__rq, bio)) { + if (blk_rq_pos(__rq) + blk_rq_sectors(__rq) == bio->bi_sector) + ret = ELEVATOR_BACK_MERGE; + else if (blk_rq_pos(__rq) - bio_sectors(bio) == bio->bi_sector) + ret = ELEVATOR_FRONT_MERGE; + } + + return ret; +} + static struct elevator_type *elevator_find(const char *name) { struct elevator_type *e; @@ -431,8 +478,8 @@ int elv_merge(struct request_queue *q, struct request **req, struct bio *bio) /* * First try one-hit cache. */ - if (q->last_merge && elv_rq_merge_ok(q->last_merge, bio)) { - ret = blk_try_merge(q->last_merge, bio); + if (q->last_merge) { + ret = elv_try_merge(q->last_merge, bio); if (ret != ELEVATOR_NO_MERGE) { *req = q->last_merge; return ret; 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/base/regmap/regcache.c b/trunk/drivers/base/regmap/regcache.c index d1daa5e9fadf..1ead66186b7c 100644 --- a/trunk/drivers/base/regmap/regcache.c +++ b/trunk/drivers/base/regmap/regcache.c @@ -53,7 +53,7 @@ static int regcache_hw_init(struct regmap *map) for (count = 0, i = 0; i < map->num_reg_defaults_raw; i++) { val = regcache_get_val(map->reg_defaults_raw, i, map->cache_word_size); - if (regmap_volatile(map, i)) + if (!val) continue; count++; } @@ -70,7 +70,7 @@ static int regcache_hw_init(struct regmap *map) for (i = 0, j = 0; i < map->num_reg_defaults_raw; i++) { val = regcache_get_val(map->reg_defaults_raw, i, map->cache_word_size); - if (regmap_volatile(map, i)) + if (!val) continue; map->reg_defaults[j].reg = i; map->reg_defaults[j].def = val; diff --git a/trunk/drivers/block/floppy.c b/trunk/drivers/block/floppy.c index 9baf11e86362..510fb10ec45a 100644 --- a/trunk/drivers/block/floppy.c +++ b/trunk/drivers/block/floppy.c @@ -4368,14 +4368,8 @@ static int __init floppy_init(void) out_put_disk: while (dr--) { del_timer_sync(&motor_off_timer[dr]); - if (disks[dr]->queue) { + if (disks[dr]->queue) blk_cleanup_queue(disks[dr]->queue); - /* - * put_disk() is not paired with add_disk() and - * will put queue reference one extra time. fix it. - */ - disks[dr]->queue = NULL; - } put_disk(disks[dr]); } return err; @@ -4585,15 +4579,6 @@ static void __exit floppy_module_exit(void) platform_device_unregister(&floppy_device[drive]); } blk_cleanup_queue(disks[drive]->queue); - - /* - * These disks have not called add_disk(). Don't put down - * queue reference in put_disk(). - */ - if (!(allowed_drive_mask & (1 << drive)) || - fdc_state[FDC(drive)].version == FDC_NONE) - disks[drive]->queue = NULL; - put_disk(disks[drive]); } diff --git a/trunk/drivers/block/loop.c b/trunk/drivers/block/loop.c index cd504353b278..f00257782fcc 100644 --- a/trunk/drivers/block/loop.c +++ b/trunk/drivers/block/loop.c @@ -356,14 +356,14 @@ lo_direct_splice_actor(struct pipe_inode_info *pipe, struct splice_desc *sd) return __splice_from_pipe(pipe, sd, lo_splice_actor); } -static ssize_t +static int do_lo_receive(struct loop_device *lo, struct bio_vec *bvec, int bsize, loff_t pos) { struct lo_read_data cookie; struct splice_desc sd; struct file *file; - ssize_t retval; + long retval; cookie.lo = lo; cookie.page = bvec->bv_page; @@ -379,28 +379,26 @@ do_lo_receive(struct loop_device *lo, file = lo->lo_backing_file; retval = splice_direct_to_actor(file, &sd, lo_direct_splice_actor); - return retval; + if (retval < 0) + return retval; + if (retval != bvec->bv_len) + return -EIO; + return 0; } static int lo_receive(struct loop_device *lo, struct bio *bio, int bsize, loff_t pos) { struct bio_vec *bvec; - ssize_t s; - int i; + int i, ret = 0; bio_for_each_segment(bvec, bio, i) { - s = do_lo_receive(lo, bvec, bsize, pos); - if (s < 0) - return s; - - if (s != bvec->bv_len) { - zero_fill_bio(bio); + ret = do_lo_receive(lo, bvec, bsize, pos); + if (ret < 0) break; - } pos += bvec->bv_len; } - return 0; + return ret; } static int do_bio_filebacked(struct loop_device *lo, struct bio *bio) diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.c b/trunk/drivers/block/mtip32xx/mtip32xx.c index 8eb81c96608f..b74eab70c3d0 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.c +++ b/trunk/drivers/block/mtip32xx/mtip32xx.c @@ -2068,6 +2068,8 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, * when the read completes. * @data Callback data passed to the callback function * when the read completes. + * @barrier If non-zero, this command must be completed before + * issuing any other commands. * @dir Direction (read or write) * * return value @@ -2075,7 +2077,7 @@ static int mtip_hw_ioctl(struct driver_data *dd, unsigned int cmd, */ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, int nsect, int nents, int tag, void *callback, - void *data, int dir) + void *data, int barrier, int dir) { struct host_to_dev_fis *fis; struct mtip_port *port = dd->port; @@ -2106,6 +2108,8 @@ static void mtip_hw_submit_io(struct driver_data *dd, sector_t start, *((unsigned int *) &fis->lba_low) = (start & 0xFFFFFF); *((unsigned int *) &fis->lba_low_ex) = ((start >> 24) & 0xFFFFFF); fis->device = 1 << 6; + if (barrier) + fis->device |= FUA_BIT; fis->features = nsect & 0xFF; fis->features_ex = (nsect >> 8) & 0xFF; fis->sect_count = ((tag << 3) | (tag >> 5)); @@ -3083,6 +3087,7 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio) tag, bio_endio, bio, + bio->bi_rw & REQ_FUA, bio_data_dir(bio)); } else bio_io_error(bio); @@ -3182,10 +3187,6 @@ static int mtip_block_initialize(struct driver_data *dd) blk_queue_max_segments(dd->queue, MTIP_MAX_SG); blk_queue_physical_block_size(dd->queue, 4096); blk_queue_io_min(dd->queue, 4096); - /* - * write back cache is not supported in the device. FUA depends on - * write back cache support, hence setting flush support to zero. - */ blk_queue_flush(dd->queue, 0); /* Set the capacity of the device in 512 byte sectors. */ diff --git a/trunk/drivers/block/mtip32xx/mtip32xx.h b/trunk/drivers/block/mtip32xx/mtip32xx.h index e0554a8f2233..723d7c4946dc 100644 --- a/trunk/drivers/block/mtip32xx/mtip32xx.h +++ b/trunk/drivers/block/mtip32xx/mtip32xx.h @@ -104,6 +104,9 @@ /* BAR number used to access the HBA registers. */ #define MTIP_ABAR 5 +/* Forced Unit Access Bit */ +#define FUA_BIT 0x80 + #ifdef DEBUG #define dbg_printk(format, arg...) \ printk(pr_fmt(format), ##arg); @@ -412,6 +415,8 @@ struct driver_data { atomic_t resumeflag; /* Atomic variable to track suspend/resume */ + atomic_t eh_active; /* Flag for error handling tracking */ + struct task_struct *mtip_svc_handler; /* task_struct of svc thd */ }; diff --git a/trunk/drivers/cdrom/cdrom.c b/trunk/drivers/cdrom/cdrom.c index d620b4495745..55eaf474d32c 100644 --- a/trunk/drivers/cdrom/cdrom.c +++ b/trunk/drivers/cdrom/cdrom.c @@ -286,6 +286,8 @@ /* used to tell the module to turn on full debugging messages */ static bool debug; +/* used to keep tray locked at all times */ +static int keeplocked; /* default compatibility mode */ static bool autoclose=1; static bool autoeject; @@ -1202,7 +1204,7 @@ void cdrom_release(struct cdrom_device_info *cdi, fmode_t mode) cdinfo(CD_CLOSE, "Use count for \"/dev/%s\" now zero\n", cdi->name); cdrom_dvd_rw_close_write(cdi); - if ((cdo->capability & CDC_LOCK) && !cdi->keeplocked) { + if ((cdo->capability & CDC_LOCK) && !keeplocked) { cdinfo(CD_CLOSE, "Unlocking door!\n"); cdo->lock_door(cdi, 0); } @@ -1369,7 +1371,7 @@ static int cdrom_select_disc(struct cdrom_device_info *cdi, int slot) curslot = info->hdr.curslot; kfree(info); - if (cdi->use_count > 1 || cdi->keeplocked) { + if (cdi->use_count > 1 || keeplocked) { if (slot == CDSL_CURRENT) { return curslot; } else { @@ -2117,6 +2119,11 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, if (!nr) return -ENOMEM; + if (!access_ok(VERIFY_WRITE, ubuf, nframes * CD_FRAMESIZE_RAW)) { + ret = -EFAULT; + goto out; + } + cgc.data_direction = CGC_DATA_READ; while (nframes > 0) { if (nr > nframes) @@ -2125,7 +2132,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, ret = cdrom_read_block(cdi, &cgc, lba, nr, 1, CD_FRAMESIZE_RAW); if (ret) break; - if (copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { + if (__copy_to_user(ubuf, cgc.buffer, CD_FRAMESIZE_RAW * nr)) { ret = -EFAULT; break; } @@ -2133,6 +2140,7 @@ static int cdrom_read_cdda_old(struct cdrom_device_info *cdi, __u8 __user *ubuf, nframes -= nr; lba += nr; } +out: kfree(cgc.buffer); return ret; } @@ -2287,7 +2295,7 @@ static int cdrom_ioctl_eject(struct cdrom_device_info *cdi) if (!CDROM_CAN(CDC_OPEN_TRAY)) return -ENOSYS; - if (cdi->use_count != 1 || cdi->keeplocked) + if (cdi->use_count != 1 || keeplocked) return -EBUSY; if (CDROM_CAN(CDC_LOCK)) { int ret = cdi->ops->lock_door(cdi, 0); @@ -2314,7 +2322,7 @@ static int cdrom_ioctl_eject_sw(struct cdrom_device_info *cdi, if (!CDROM_CAN(CDC_OPEN_TRAY)) return -ENOSYS; - if (cdi->keeplocked) + if (keeplocked) return -EBUSY; cdi->options &= ~(CDO_AUTO_CLOSE | CDO_AUTO_EJECT); @@ -2445,7 +2453,7 @@ static int cdrom_ioctl_lock_door(struct cdrom_device_info *cdi, if (!CDROM_CAN(CDC_LOCK)) return -EDRIVE_CANT_DO_THIS; - cdi->keeplocked = arg ? 1 : 0; + keeplocked = arg ? 1 : 0; /* * Don't unlock the door on multiple opens by default, but allow 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/macintosh/adb.c b/trunk/drivers/macintosh/adb.c index b026896206ca..75049e765191 100644 --- a/trunk/drivers/macintosh/adb.c +++ b/trunk/drivers/macintosh/adb.c @@ -710,7 +710,7 @@ static ssize_t adb_read(struct file *file, char __user *buf, req = NULL; spin_lock_irqsave(&state->lock, flags); add_wait_queue(&state->wait_queue, &wait); - set_current_state(TASK_INTERRUPTIBLE); + current->state = TASK_INTERRUPTIBLE; for (;;) { req = state->completed; @@ -734,7 +734,7 @@ static ssize_t adb_read(struct file *file, char __user *buf, spin_lock_irqsave(&state->lock, flags); } - set_current_state(TASK_RUNNING); + current->state = TASK_RUNNING; remove_wait_queue(&state->wait_queue, &wait); spin_unlock_irqrestore(&state->lock, flags); 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/pinctrl/core.c b/trunk/drivers/pinctrl/core.c index 894cd5e103da..8fe15cf15ac8 100644 --- a/trunk/drivers/pinctrl/core.c +++ b/trunk/drivers/pinctrl/core.c @@ -189,7 +189,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, pindesc->pctldev = pctldev; /* Copy basic pin info */ - if (name) { + if (pindesc->name) { pindesc->name = name; } else { pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", number); 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/bio.c b/trunk/fs/bio.c index b980ecde026a..b1fe82cf88cf 100644 --- a/trunk/fs/bio.c +++ b/trunk/fs/bio.c @@ -505,9 +505,13 @@ EXPORT_SYMBOL(bio_clone); int bio_get_nr_vecs(struct block_device *bdev) { struct request_queue *q = bdev_get_queue(bdev); - return min_t(unsigned, - queue_max_segments(q), - queue_max_sectors(q) / (PAGE_SIZE >> 9) + 1); + int nr_pages; + + nr_pages = ((queue_max_sectors(q) << 9) + PAGE_SIZE - 1) >> PAGE_SHIFT; + if (nr_pages > queue_max_segments(q)) + nr_pages = queue_max_segments(q); + + return nr_pages; } EXPORT_SYMBOL(bio_get_nr_vecs); 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/ecryptfs/crypto.c b/trunk/fs/ecryptfs/crypto.c index ea9931281557..63ab24510649 100644 --- a/trunk/fs/ecryptfs/crypto.c +++ b/trunk/fs/ecryptfs/crypto.c @@ -1990,17 +1990,6 @@ void ecryptfs_encode_for_filename(unsigned char *dst, size_t *dst_size, return; } -static size_t ecryptfs_max_decoded_size(size_t encoded_size) -{ - /* Not exact; conservatively long. Every block of 4 - * encoded characters decodes into a block of 3 - * decoded characters. This segment of code provides - * the caller with the maximum amount of allocated - * space that @dst will need to point to in a - * subsequent call. */ - return ((encoded_size + 1) * 3) / 4; -} - /** * ecryptfs_decode_from_filename * @dst: If NULL, this function only sets @dst_size and returns. If @@ -2019,7 +2008,13 @@ ecryptfs_decode_from_filename(unsigned char *dst, size_t *dst_size, size_t dst_byte_offset = 0; if (dst == NULL) { - (*dst_size) = ecryptfs_max_decoded_size(src_size); + /* Not exact; conservatively long. Every block of 4 + * encoded characters decodes into a block of 3 + * decoded characters. This segment of code provides + * the caller with the maximum amount of allocated + * space that @dst will need to point to in a + * subsequent call. */ + (*dst_size) = (((src_size + 1) * 3) / 4); goto out; } while (src_byte_offset < src_size) { @@ -2244,52 +2239,3 @@ int ecryptfs_decode_and_decrypt_filename(char **plaintext_name, out: return rc; } - -#define ENC_NAME_MAX_BLOCKLEN_8_OR_16 143 - -int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat) -{ - struct blkcipher_desc desc; - struct mutex *tfm_mutex; - size_t cipher_blocksize; - int rc; - - if (!(mount_crypt_stat->flags & ECRYPTFS_GLOBAL_ENCRYPT_FILENAMES)) { - (*namelen) = lower_namelen; - return 0; - } - - rc = ecryptfs_get_tfm_and_mutex_for_cipher_name(&desc.tfm, &tfm_mutex, - mount_crypt_stat->global_default_fn_cipher_name); - if (unlikely(rc)) { - (*namelen) = 0; - return rc; - } - - mutex_lock(tfm_mutex); - cipher_blocksize = crypto_blkcipher_blocksize(desc.tfm); - mutex_unlock(tfm_mutex); - - /* Return an exact amount for the common cases */ - if (lower_namelen == NAME_MAX - && (cipher_blocksize == 8 || cipher_blocksize == 16)) { - (*namelen) = ENC_NAME_MAX_BLOCKLEN_8_OR_16; - return 0; - } - - /* Return a safe estimate for the uncommon cases */ - (*namelen) = lower_namelen; - (*namelen) -= ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX_SIZE; - /* Since this is the max decoded size, subtract 1 "decoded block" len */ - (*namelen) = ecryptfs_max_decoded_size(*namelen) - 3; - (*namelen) -= ECRYPTFS_TAG_70_MAX_METADATA_SIZE; - (*namelen) -= ECRYPTFS_FILENAME_MIN_RANDOM_PREPEND_BYTES; - /* Worst case is that the filename is padded nearly a full block size */ - (*namelen) -= cipher_blocksize - 1; - - if ((*namelen) < 0) - (*namelen) = 0; - - return 0; -} diff --git a/trunk/fs/ecryptfs/ecryptfs_kernel.h b/trunk/fs/ecryptfs/ecryptfs_kernel.h index 867b64c5d84f..a2362df58ae8 100644 --- a/trunk/fs/ecryptfs/ecryptfs_kernel.h +++ b/trunk/fs/ecryptfs/ecryptfs_kernel.h @@ -162,10 +162,6 @@ ecryptfs_get_key_payload_data(struct key *key) #define ECRYPTFS_NON_NULL 0x42 /* A reasonable substitute for NULL */ #define MD5_DIGEST_SIZE 16 #define ECRYPTFS_TAG_70_DIGEST_SIZE MD5_DIGEST_SIZE -#define ECRYPTFS_TAG_70_MIN_METADATA_SIZE (1 + ECRYPTFS_MIN_PKT_LEN_SIZE \ - + ECRYPTFS_SIG_SIZE + 1 + 1) -#define ECRYPTFS_TAG_70_MAX_METADATA_SIZE (1 + ECRYPTFS_MAX_PKT_LEN_SIZE \ - + ECRYPTFS_SIG_SIZE + 1 + 1) #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FEK_ENCRYPTED." #define ECRYPTFS_FEK_ENCRYPTED_FILENAME_PREFIX_SIZE 23 #define ECRYPTFS_FNEK_ENCRYPTED_FILENAME_PREFIX "ECRYPTFS_FNEK_ENCRYPTED." @@ -705,8 +701,6 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, size_t *packet_size, struct ecryptfs_mount_crypt_stat *mount_crypt_stat, char *data, size_t max_packet_size); -int ecryptfs_set_f_namelen(long *namelen, long lower_namelen, - struct ecryptfs_mount_crypt_stat *mount_crypt_stat); int ecryptfs_derive_iv(char *iv, struct ecryptfs_crypt_stat *crypt_stat, loff_t offset); diff --git a/trunk/fs/ecryptfs/inode.c b/trunk/fs/ecryptfs/inode.c index ab35b113003b..19892d7d2ed1 100644 --- a/trunk/fs/ecryptfs/inode.c +++ b/trunk/fs/ecryptfs/inode.c @@ -1085,8 +1085,6 @@ ecryptfs_setxattr(struct dentry *dentry, const char *name, const void *value, } rc = vfs_setxattr(lower_dentry, name, value, size, flags); - if (!rc) - fsstack_copy_attr_all(dentry->d_inode, lower_dentry->d_inode); out: return rc; } diff --git a/trunk/fs/ecryptfs/keystore.c b/trunk/fs/ecryptfs/keystore.c index 2333203a120b..8e3b943e330f 100644 --- a/trunk/fs/ecryptfs/keystore.c +++ b/trunk/fs/ecryptfs/keystore.c @@ -679,7 +679,10 @@ ecryptfs_write_tag_70_packet(char *dest, size_t *remaining_bytes, * Octets N3-N4: Block-aligned encrypted filename * - Consists of a minimum number of random characters, a \0 * separator, and then the filename */ - s->max_packet_size = (ECRYPTFS_TAG_70_MAX_METADATA_SIZE + s->max_packet_size = (1 /* Tag 70 identifier */ + + 3 /* Max Tag 70 packet size */ + + ECRYPTFS_SIG_SIZE /* FNEK sig */ + + 1 /* Cipher identifier */ + s->block_aligned_filename_size); if (dest == NULL) { (*packet_size) = s->max_packet_size; @@ -931,10 +934,10 @@ ecryptfs_parse_tag_70_packet(char **filename, size_t *filename_size, goto out; } s->desc.flags = CRYPTO_TFM_REQ_MAY_SLEEP; - if (max_packet_size < ECRYPTFS_TAG_70_MIN_METADATA_SIZE) { + if (max_packet_size < (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)) { printk(KERN_WARNING "%s: max_packet_size is [%zd]; it must be " "at least [%d]\n", __func__, max_packet_size, - ECRYPTFS_TAG_70_MIN_METADATA_SIZE); + (1 + 1 + ECRYPTFS_SIG_SIZE + 1 + 1)); rc = -EINVAL; goto out; } diff --git a/trunk/fs/ecryptfs/mmap.c b/trunk/fs/ecryptfs/mmap.c index a46b3a8fee1e..10ec695ccd68 100644 --- a/trunk/fs/ecryptfs/mmap.c +++ b/trunk/fs/ecryptfs/mmap.c @@ -150,7 +150,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, /* This is a header extent */ char *page_virt; - page_virt = kmap_atomic(page); + page_virt = kmap_atomic(page, KM_USER0); memset(page_virt, 0, PAGE_CACHE_SIZE); /* TODO: Support more than one header extent */ if (view_extent_num == 0) { @@ -163,7 +163,7 @@ ecryptfs_copy_up_encrypted_with_header(struct page *page, crypt_stat, &written); } - kunmap_atomic(page_virt); + kunmap_atomic(page_virt, KM_USER0); flush_dcache_page(page); if (rc) { printk(KERN_ERR "%s: Error reading xattr " diff --git a/trunk/fs/ecryptfs/read_write.c b/trunk/fs/ecryptfs/read_write.c index b2a34a192f4f..5c0106f75775 100644 --- a/trunk/fs/ecryptfs/read_write.c +++ b/trunk/fs/ecryptfs/read_write.c @@ -156,7 +156,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, ecryptfs_page_idx, rc); goto out; } - ecryptfs_page_virt = kmap_atomic(ecryptfs_page); + ecryptfs_page_virt = kmap_atomic(ecryptfs_page, KM_USER0); /* * pos: where we're now writing, offset: where the request was @@ -179,7 +179,7 @@ int ecryptfs_write(struct inode *ecryptfs_inode, char *data, loff_t offset, (data + data_offset), num_bytes); data_offset += num_bytes; } - kunmap_atomic(ecryptfs_page_virt); + kunmap_atomic(ecryptfs_page_virt, KM_USER0); flush_dcache_page(ecryptfs_page); SetPageUptodate(ecryptfs_page); unlock_page(ecryptfs_page); diff --git a/trunk/fs/ecryptfs/super.c b/trunk/fs/ecryptfs/super.c index cf152823bbf4..9df7fd6e0c39 100644 --- a/trunk/fs/ecryptfs/super.c +++ b/trunk/fs/ecryptfs/super.c @@ -30,8 +30,6 @@ #include #include #include -#include -#include #include "ecryptfs_kernel.h" struct kmem_cache *ecryptfs_inode_info_cache; @@ -104,20 +102,10 @@ static void ecryptfs_destroy_inode(struct inode *inode) static int ecryptfs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); - int rc; if (!lower_dentry->d_sb->s_op->statfs) return -ENOSYS; - - rc = lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); - if (rc) - return rc; - - buf->f_type = ECRYPTFS_SUPER_MAGIC; - rc = ecryptfs_set_f_namelen(&buf->f_namelen, buf->f_namelen, - &ecryptfs_superblock_to_private(dentry->d_sb)->mount_crypt_stat); - - return rc; + return lower_dentry->d_sb->s_op->statfs(lower_dentry, buf); } /** diff --git a/trunk/fs/ioprio.c b/trunk/fs/ioprio.c index 0f1b9515213b..f84b380d65e5 100644 --- a/trunk/fs/ioprio.c +++ b/trunk/fs/ioprio.c @@ -51,7 +51,7 @@ int set_task_ioprio(struct task_struct *task, int ioprio) ioc = get_task_io_context(task, GFP_ATOMIC, NUMA_NO_NODE); if (ioc) { ioc_ioprio_changed(ioc, ioprio); - put_io_context(ioc); + put_io_context(ioc, NULL); } return err; 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/blkdev.h b/trunk/include/linux/blkdev.h index 606cf339bb56..6c6a1f008065 100644 --- a/trunk/include/linux/blkdev.h +++ b/trunk/include/linux/blkdev.h @@ -399,6 +399,9 @@ struct request_queue { /* Throttle data */ struct throtl_data *td; #endif +#ifdef CONFIG_LOCKDEP + int ioc_release_depth; +#endif }; #define QUEUE_FLAG_QUEUED 1 /* uses generic tag queueing */ diff --git a/trunk/include/linux/cdrom.h b/trunk/include/linux/cdrom.h index 7c48029dffe6..35eae4b67503 100644 --- a/trunk/include/linux/cdrom.h +++ b/trunk/include/linux/cdrom.h @@ -952,8 +952,7 @@ struct cdrom_device_info { char name[20]; /* name of the device type */ /* per-device flags */ __u8 sanyo_slot : 2; /* Sanyo 3 CD changer support */ - __u8 keeplocked : 1; /* CDROM_LOCKDOOR status */ - __u8 reserved : 5; /* not used yet */ + __u8 reserved : 6; /* not used yet */ int cdda_method; /* see flags */ __u8 last_sense; __u8 media_written; /* dirty flag, DVD+RW bookkeeping */ diff --git a/trunk/include/linux/elevator.h b/trunk/include/linux/elevator.h index 7d4e0356f329..c24f3d7fbf1e 100644 --- a/trunk/include/linux/elevator.h +++ b/trunk/include/linux/elevator.h @@ -42,6 +42,12 @@ struct elevator_ops elevator_merged_fn *elevator_merged_fn; elevator_merge_req_fn *elevator_merge_req_fn; elevator_allow_merge_fn *elevator_allow_merge_fn; + + /* + * Used for both plugged list and elevator merging and in the + * former case called without queue_lock. Read comment on top of + * attempt_plug_merge() for details. + */ elevator_bio_merged_fn *elevator_bio_merged_fn; elevator_dispatch_fn *elevator_dispatch_fn; @@ -116,6 +122,7 @@ extern void elv_dispatch_add_tail(struct request_queue *, struct request *); extern void elv_add_request(struct request_queue *, struct request *, int); extern void __elv_add_request(struct request_queue *, struct request *, int); extern int elv_merge(struct request_queue *, struct request **, struct bio *); +extern int elv_try_merge(struct request *, struct bio *); extern void elv_merge_requests(struct request_queue *, struct request *, struct request *); extern void elv_merged_request(struct request_queue *, struct request *, int); @@ -148,7 +155,7 @@ extern ssize_t elv_iosched_store(struct request_queue *, const char *, size_t); extern int elevator_init(struct request_queue *, char *); extern void elevator_exit(struct elevator_queue *); extern int elevator_change(struct request_queue *, const char *); -extern bool elv_rq_merge_ok(struct request *, struct bio *); +extern int elv_rq_merge_ok(struct request *, struct bio *); /* * Helper functions. diff --git a/trunk/include/linux/iocontext.h b/trunk/include/linux/iocontext.h index 119773eebe31..7e1371c4bccf 100644 --- a/trunk/include/linux/iocontext.h +++ b/trunk/include/linux/iocontext.h @@ -133,7 +133,7 @@ static inline struct io_context *ioc_task_link(struct io_context *ioc) struct task_struct; #ifdef CONFIG_BLOCK -void put_io_context(struct io_context *ioc); +void put_io_context(struct io_context *ioc, struct request_queue *locked_q); void exit_io_context(struct task_struct *task); struct io_context *get_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node); @@ -141,7 +141,8 @@ void ioc_ioprio_changed(struct io_context *ioc, int ioprio); void ioc_cgroup_changed(struct io_context *ioc); #else struct io_context; -static inline void put_io_context(struct io_context *ioc) { } +static inline void put_io_context(struct io_context *ioc, + struct request_queue *locked_q) { } static inline void exit_io_context(struct task_struct *task) { } #endif 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/fork.c b/trunk/kernel/fork.c index b77fd559c78e..1b2ef3c23ae4 100644 --- a/trunk/kernel/fork.c +++ b/trunk/kernel/fork.c @@ -910,7 +910,7 @@ static int copy_io(unsigned long clone_flags, struct task_struct *tsk) return -ENOMEM; new_ioc->ioprio = ioc->ioprio; - put_io_context(new_ioc); + put_io_context(new_ioc, NULL); } #endif return 0; 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/kernel/relay.c b/trunk/kernel/relay.c index ab56a1764d4d..4335e1d7ee2d 100644 --- a/trunk/kernel/relay.c +++ b/trunk/kernel/relay.c @@ -164,14 +164,10 @@ static void *relay_alloc_buf(struct rchan_buf *buf, size_t *size) */ static struct rchan_buf *relay_create_buf(struct rchan *chan) { - struct rchan_buf *buf; - - if (chan->n_subbufs > UINT_MAX / sizeof(size_t *)) - return NULL; - - buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); + struct rchan_buf *buf = kzalloc(sizeof(struct rchan_buf), GFP_KERNEL); if (!buf) return NULL; + buf->padding = kmalloc(chan->n_subbufs * sizeof(size_t *), GFP_KERNEL); if (!buf->padding) goto free_buf; @@ -578,8 +574,6 @@ struct rchan *relay_open(const char *base_filename, if (!(subbuf_size && n_subbufs)) return NULL; - if (subbuf_size > UINT_MAX / n_subbufs) - return NULL; chan = kzalloc(sizeof(struct rchan), GFP_KERNEL); if (!chan) diff --git a/trunk/net/ipv4/tcp_input.c b/trunk/net/ipv4/tcp_input.c index 976034f82320..4e8a81fda65c 100644 --- a/trunk/net/ipv4/tcp_input.c +++ b/trunk/net/ipv4/tcp_input.c @@ -1307,25 +1307,26 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, return in_sack; } -static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk, - struct tcp_sacktag_state *state, +/* Mark the given newly-SACKed range as such, adjusting counters and hints. */ +static u8 tcp_sacktag_one(struct sock *sk, + struct tcp_sacktag_state *state, u8 sacked, + u32 start_seq, u32 end_seq, int dup_sack, int pcount) { struct tcp_sock *tp = tcp_sk(sk); - u8 sacked = TCP_SKB_CB(skb)->sacked; int fack_count = state->fack_count; /* Account D-SACK for retransmitted packet. */ if (dup_sack && (sacked & TCPCB_RETRANS)) { if (tp->undo_marker && tp->undo_retrans && - after(TCP_SKB_CB(skb)->end_seq, tp->undo_marker)) + after(end_seq, tp->undo_marker)) tp->undo_retrans--; if (sacked & TCPCB_SACKED_ACKED) state->reord = min(fack_count, state->reord); } /* Nothing to do; acked frame is about to be dropped (was ACKed). */ - if (!after(TCP_SKB_CB(skb)->end_seq, tp->snd_una)) + if (!after(end_seq, tp->snd_una)) return sacked; if (!(sacked & TCPCB_SACKED_ACKED)) { @@ -1344,13 +1345,13 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk, /* New sack for not retransmitted frame, * which was in hole. It is reordering. */ - if (before(TCP_SKB_CB(skb)->seq, + if (before(start_seq, tcp_highest_sack_seq(tp))) state->reord = min(fack_count, state->reord); /* SACK enhanced F-RTO (RFC4138; Appendix B) */ - if (!after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark)) + if (!after(end_seq, tp->frto_highmark)) state->flag |= FLAG_ONLY_ORIG_SACKED; } @@ -1368,8 +1369,7 @@ static u8 tcp_sacktag_one(const struct sk_buff *skb, struct sock *sk, /* Lost marker hint past SACKed? Tweak RFC3517 cnt */ if (!tcp_is_fack(tp) && (tp->lost_skb_hint != NULL) && - before(TCP_SKB_CB(skb)->seq, - TCP_SKB_CB(tp->lost_skb_hint)->seq)) + before(start_seq, TCP_SKB_CB(tp->lost_skb_hint)->seq)) tp->lost_cnt_hint += pcount; if (fack_count > tp->fackets_out) @@ -1425,7 +1425,11 @@ static int tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, } /* We discard results */ - tcp_sacktag_one(skb, sk, state, dup_sack, pcount); + tcp_sacktag_one(sk, state, + TCP_SKB_CB(skb)->sacked, + TCP_SKB_CB(skb)->seq, + TCP_SKB_CB(skb)->end_seq, + dup_sack, pcount); /* Difference in this won't matter, both ACKed by the same cumul. ACK */ TCP_SKB_CB(prev)->sacked |= (TCP_SKB_CB(skb)->sacked & TCPCB_EVER_RETRANS); @@ -1664,10 +1668,14 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk, break; if (in_sack) { - TCP_SKB_CB(skb)->sacked = tcp_sacktag_one(skb, sk, - state, - dup_sack, - tcp_skb_pcount(skb)); + TCP_SKB_CB(skb)->sacked = + tcp_sacktag_one(sk, + state, + TCP_SKB_CB(skb)->sacked, + TCP_SKB_CB(skb)->seq, + TCP_SKB_CB(skb)->end_seq, + dup_sack, + tcp_skb_pcount(skb)); if (!before(TCP_SKB_CB(skb)->seq, tcp_highest_sack_seq(tp))) 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 = {