diff options
53 files changed, 629 insertions, 310 deletions
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 43268f15004e..6d422979ebaf 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h @@ -142,6 +142,11 @@ static inline const char *eeh_pci_name(struct pci_dev *pdev) return pdev ? pci_name(pdev) : "<null>"; } +static inline const char *eeh_driver_name(struct pci_dev *pdev) +{ + return (pdev && pdev->driver) ? pdev->driver->name : "<null>"; +} + #endif /* CONFIG_EEH */ #else /* CONFIG_PCI */ diff --git a/arch/powerpc/include/asm/ptrace.h b/arch/powerpc/include/asm/ptrace.h index 78a205162fd7..84cc7840cd18 100644 --- a/arch/powerpc/include/asm/ptrace.h +++ b/arch/powerpc/include/asm/ptrace.h @@ -83,8 +83,18 @@ struct pt_regs { #ifndef __ASSEMBLY__ -#define instruction_pointer(regs) ((regs)->nip) -#define user_stack_pointer(regs) ((regs)->gpr[1]) +#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 <asm-generic/ptrace.h> + #define kernel_stack_pointer(regs) ((regs)->gpr[1]) static inline int is_syscall_success(struct pt_regs *regs) { @@ -99,12 +109,6 @@ 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/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 701d4aceb4f4..01e2877e8e04 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c @@ -118,10 +118,14 @@ 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 = &__get_cpu_var(decrementers_next_tb); + u64 *next_tb; + + preempt_disable(); + 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/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 517b1d8f455b..9f843cdfee9e 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c @@ -716,7 +716,6 @@ 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) && @@ -732,7 +731,6 @@ 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) { @@ -846,6 +844,7 @@ 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 @@ -858,6 +857,8 @@ 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/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index a70bc1e385eb..f92b9ef7340e 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c @@ -52,32 +52,38 @@ 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 int id; + unsigned long flags; + unsigned int id, rc; + + spin_lock_irqsave(&phb->lock, flags); - 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) { - spin_unlock(&phb->lock); - return 0; + rc = 0; + goto out; } __set_bit(id, phb->msi_map); - spin_unlock(&phb->lock); - return id + phb->msi_base; + rc = id + phb->msi_base; +out: + spin_unlock_irqrestore(&phb->lock, flags); + return rc; } 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(&phb->lock); + + spin_lock_irqsave(&phb->lock, flags); __clear_bit(id, phb->msi_map); - spin_unlock(&phb->lock); + spin_unlock_irqrestore(&phb->lock, flags); } static int pnv_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) diff --git a/arch/powerpc/platforms/pseries/eeh.c b/arch/powerpc/platforms/pseries/eeh.c index 565869022e3d..c0b40af4ce4f 100644 --- a/arch/powerpc/platforms/pseries/eeh.c +++ b/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, - dev->driver->name, eeh_pci_name(dev)); + eeh_driver_name(dev), eeh_pci_name(dev)); printk (KERN_ERR "EEH: Might be infinite loop in %s driver\n", - dev->driver->name); + eeh_driver_name(dev)); dump_stack(); } goto dn_unlock; diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index b84a8b2238dd..47226e04126d 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c @@ -24,6 +24,7 @@ #include <asm/machdep.h> #include <asm/mmu.h> #include <asm/rtas.h> +#include <asm/topology.h> static u64 stream_id; static struct device suspend_dev; @@ -138,8 +139,11 @@ static ssize_t store_hibernate(struct device *dev, ssleep(1); } while (rc == -EAGAIN); - if (!rc) + if (!rc) { + stop_topology_update(); rc = pm_suspend(PM_SUSPEND_MEM); + start_topology_update(); + } stream_id = 0; diff --git a/arch/powerpc/platforms/wsp/ics.c b/arch/powerpc/platforms/wsp/ics.c index 576874392543..97fe82ee8633 100644 --- a/arch/powerpc/platforms/wsp/ics.c +++ b/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, d->irq, cpumask); + ret = cache_hwirq_map(ics, hw_irq, cpumask); if (ret == -1) { char cpulist[128]; cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask); diff --git a/arch/powerpc/platforms/wsp/wsp_pci.c b/arch/powerpc/platforms/wsp/wsp_pci.c index e0262cd0e2d3..d24b3acf858e 100644 --- a/arch/powerpc/platforms/wsp/wsp_pci.c +++ b/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)) -#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 */ + /* + * Some WSP variants 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/arch/x86/include/asm/i387.h b/arch/x86/include/asm/i387.h index a29571821b99..a850b4d8d14d 100644 --- a/arch/x86/include/asm/i387.h +++ b/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 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,19 +212,11 @@ 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 + * These must be called with preempt disabled. Returns + * 'true' if the FPU state is still intact. */ -static inline void fpu_save_init(struct fpu *fpu) +static inline int fpu_save_init(struct fpu *fpu) { if (use_xsave()) { fpu_xsave(fpu); @@ -233,33 +225,33 @@ static inline void 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; + return 1; } else if (use_fxsr()) { fpu_fxsave(fpu); } else { asm volatile("fnsave %[fx]; fwait" : [fx] "=m" (fpu->state->fsave)); - return; + return 0; } - if (unlikely(fpu->state->fxsave.swd & X87_FSW_ES)) + /* + * 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)) { asm volatile("fnclex"); - - /* 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)); + return 0; + } + return 1; } -static inline void __save_init_fpu(struct task_struct *tsk) +static inline int __save_init_fpu(struct task_struct *tsk) { - fpu_save_init(&tsk->thread.fpu); - task_thread_info(tsk)->status &= ~TS_USEDFPU; + return fpu_save_init(&tsk->thread.fpu); } static inline int fpu_fxrstor_checking(struct fpu *fpu) @@ -281,29 +273,128 @@ static inline int restore_fpu_checking(struct task_struct *tsk) } /* - * Signal frame handlers... + * Software FPU state helpers. Careful: these need to + * be preemption protection *and* they need to be + * properly paired with the CR0.TS changes! */ -extern int save_i387_xstate(void __user *buf); -extern int restore_i387_xstate(void __user *buf); +static inline int __thread_has_fpu(struct task_struct *tsk) +{ + return tsk->thread.has_fpu; +} -static inline void __unlazy_fpu(struct task_struct *tsk) +/* Must be paired with an 'stts' after! */ +static inline void __thread_clear_has_fpu(struct task_struct *tsk) { - if (task_thread_info(tsk)->status & TS_USEDFPU) { - __save_init_fpu(tsk); - stts(); - } else - tsk->fpu_counter = 0; + 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 __clear_fpu(struct task_struct *tsk) { - if (task_thread_info(tsk)->status & TS_USEDFPU) { + if (__thread_has_fpu(tsk)) { /* Ignore delayed exceptions from user space */ asm volatile("1: fwait\n" "2:\n" _ASM_EXTABLE(1b, 2b)); - task_thread_info(tsk)->status &= ~TS_USEDFPU; - stts(); + __thread_fpu_end(tsk); } } @@ -311,14 +402,14 @@ static inline void __clear_fpu(struct task_struct *tsk) * 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: TS_USEDFPU must be clear (so + * 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 !(current_thread_info()->status & TS_USEDFPU) && + return !__thread_has_fpu(current) && (read_cr0() & X86_CR0_TS); } @@ -352,13 +443,15 @@ static inline bool irq_fpu_usable(void) static inline void kernel_fpu_begin(void) { - struct thread_info *me = current_thread_info(); + struct task_struct *me = current; WARN_ON_ONCE(!irq_fpu_usable()); preempt_disable(); - if (me->status & TS_USEDFPU) - __save_init_fpu(me->task); - else + if (__thread_has_fpu(me)) { + __save_init_fpu(me); + __thread_clear_has_fpu(me); + /* We do 'stts()' in kernel_fpu_end() */ + } else clts(); } @@ -400,21 +493,64 @@ static inline void irq_ts_restore(int TS_state) } /* + * 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(task_thread_info(tsk)->status & TS_USEDFPU); + WARN_ON_ONCE(!__thread_has_fpu(tsk)); preempt_disable(); __save_init_fpu(tsk); - stts(); + __thread_fpu_end(tsk); preempt_enable(); } static inline void unlazy_fpu(struct task_struct *tsk) { preempt_disable(); - __unlazy_fpu(tsk); + if (__thread_has_fpu(tsk)) { + __save_init_fpu(tsk); + __thread_fpu_end(tsk); + } else + tsk->fpu_counter = 0; preempt_enable(); } diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index aa9088c26931..f7c89e231c6c 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -454,6 +454,7 @@ 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/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h index bc817cd8b443..cfd8144d5527 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h @@ -247,8 +247,6 @@ 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/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 485204f58cda..80bfe1ab0031 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -299,22 +299,11 @@ __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); - bool preload_fpu; + fpu_switch_t fpu; /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ - /* - * 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); + fpu = switch_fpu_prepare(prev_p, next_p); /* * Reload esp0. @@ -354,11 +343,6 @@ __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 @@ -368,15 +352,14 @@ __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/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 9b9fe4a85c87..1fd94bc4279d 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -386,18 +386,9 @@ __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; - bool preload_fpu; + fpu_switch_t fpu; - /* - * 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); + fpu = switch_fpu_prepare(prev_p, next_p); /* * Reload esp0, LDT and the page table pointer: @@ -427,13 +418,6 @@ __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 @@ -474,6 +458,8 @@ __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. */ @@ -492,13 +478,6 @@ __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/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 8ba27dbc107a..77da5b475ad2 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -571,25 +571,34 @@ asmlinkage void __attribute__((weak)) smp_threshold_interrupt(void) } /* - * __math_state_restore assumes that cr0.TS is already clear and the - * fpu state is all ready for use. Used during context switch. + * 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. */ -void __math_state_restore(void) +void __math_state_restore(struct task_struct *tsk) { - struct thread_info *thread = current_thread_info(); - struct task_struct *tsk = thread->task; + /* 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)); /* * Paranoid restore. send a SIGSEGV if we fail to restore the state. */ if (unlikely(restore_fpu_checking(tsk))) { - stts(); + __thread_fpu_end(tsk); force_sig(SIGSEGV, tsk); return; } - - thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ - tsk->fpu_counter++; } /* @@ -604,8 +613,7 @@ void __math_state_restore(void) */ void math_state_restore(void) { - struct thread_info *thread = current_thread_info(); - struct task_struct *tsk = thread->task; + struct task_struct *tsk = current; if (!tsk_used_math(tsk)) { local_irq_enable(); @@ -622,16 +630,16 @@ void math_state_restore(void) local_irq_disable(); } - clts(); /* Allow maths ops (or we recurse) */ + __thread_fpu_begin(tsk); + __math_state_restore(tsk); - __math_state_restore(); + tsk->fpu_counter++; } EXPORT_SYMBOL_GPL(math_state_restore); dotraplinkage void __kprobes do_device_not_available(struct pt_regs *regs, long error_code) { - WARN_ON_ONCE(!user_mode_vm(regs)); #ifdef CONFIG_MATH_EMULATION if (read_cr0() & X86_CR0_EM) { struct math_emu_info info = { }; diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index a3911343976b..711091114119 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c @@ -47,7 +47,7 @@ void __sanitize_i387_state(struct task_struct *tsk) if (!fx) return; - BUG_ON(task_thread_info(tsk)->status & TS_USEDFPU); + BUG_ON(__thread_has_fpu(tsk)); 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 (task_thread_info(tsk)->status & TS_USEDFPU) { + if (user_has_fpu()) { if (use_xsave()) err = xsave_user(buf); else @@ -176,8 +176,7 @@ int save_i387_xstate(void __user *buf) if (err) return err; - task_thread_info(tsk)->status &= ~TS_USEDFPU; - stts(); + user_fpu_end(); } else { sanitize_i387_state(tsk); if (__copy_to_user(buf, &tsk->thread.fpu.state->fxsave, @@ -292,10 +291,7 @@ int restore_i387_xstate(void __user *buf) return err; } - if (!(task_thread_info(current)->status & TS_USEDFPU)) { - clts(); - task_thread_info(current)->status |= TS_USEDFPU; - } + user_fpu_begin(); if (use_xsave()) err = restore_user_xstate(buf); else diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d29216c462b3..3b4c8d8ad906 100644 --- a/arch/x86/kvm/vmx.c +++ b/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 (current_thread_info()->status & TS_USEDFPU) + if (__thread_has_fpu(current)) clts(); load_gdt(&__get_cpu_var(host_gdt)); } diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c index 492ade8c978e..d99346ea8fdb 100644 --- a/arch/x86/pci/xen.c +++ b/arch/x86/pci/xen.c @@ -374,7 +374,7 @@ int __init pci_xen_init(void) int __init pci_xen_hvm_init(void) { - if (!xen_feature(XENFEAT_hvm_pirqs)) + if (!xen_have_vector_callback || !xen_feature(XENFEAT_hvm_pirqs)) return 0; #ifdef CONFIG_ACPI diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c index 041d4fe9dfe4..501d4e0244ba 100644 --- a/arch/x86/xen/smp.c +++ b/arch/x86/xen/smp.c @@ -409,6 +409,13 @@ 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/crypto/sha512_generic.c b/crypto/sha512_generic.c index f04af931a682..107f6f7be5e1 100644 --- a/crypto/sha512_generic.c +++ b/crypto/sha512_generic.c @@ -31,11 +31,6 @@ 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, @@ -66,10 +61,10 @@ static const u64 sha512_K[80] = { 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL, }; -#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)) +#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)) static inline void LOAD_OP(int I, u64 *W, const u8 *input) { diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 0cad48a284a8..c6a383d0244d 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -1694,6 +1694,7 @@ 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/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index f545a3e6eb80..690255c7d4dc 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -290,8 +290,11 @@ 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) + if (host->ops->pre_req) { + mmc_host_clk_hold(host); host->ops->pre_req(host, mrq, is_first_req); + mmc_host_clk_release(host); + } } /** @@ -306,8 +309,11 @@ 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) + if (host->ops->post_req) { + mmc_host_clk_hold(host); host->ops->post_req(host, mrq, err); + mmc_host_clk_release(host); + } } /** @@ -620,7 +626,9 @@ 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) { @@ -640,7 +648,9 @@ 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) { @@ -1121,6 +1131,10 @@ 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) @@ -1203,8 +1217,11 @@ 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) + if (host->ops->start_signal_voltage_switch) { + mmc_host_clk_hold(host); err = host->ops->start_signal_voltage_switch(host, &host->ios); + mmc_host_clk_release(host); + } return err; } @@ -1239,6 +1256,7 @@ 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 @@ -1269,6 +1287,7 @@ 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); } /* @@ -1327,12 +1346,28 @@ 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; - mmc_poweroff_notify(host); + /* + * 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); + } /* * Reset ocr mask to be the highest possible voltage supported for @@ -2386,12 +2421,6 @@ 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/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index fb8a5cd2e4a1..08a7852ade44 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h @@ -14,27 +14,6 @@ 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/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 59b9ba52e66a..a48066344fa8 100644 --- a/drivers/mmc/core/mmc.c +++ b/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_PARTITION_ATTRIBUTE]; + ext_csd[EXT_CSD_HC_WP_GRP_SIZE]; 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,7 +1006,8 @@ 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, 0); + EXT_CSD_HS_TIMING, 1, + card->ext_csd.generic_cmd6_time); if (err && err != -EBADMSG) goto free_card; @@ -1116,7 +1117,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_3) && + (card->csd.mmca_vsn >= CSD_SPEC_VER_4) && (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 }, @@ -1315,11 +1316,13 @@ 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); - else if (!mmc_host_is_spi(host)) + if (!err) + mmc_card_set_sleep(host->card); + } else if (!mmc_host_is_spi(host)) mmc_deselect_cards(host); - host->card->state &= ~MMC_STATE_HIGHSPEED; + host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); mmc_release_host(host); return err; @@ -1339,7 +1342,11 @@ static int mmc_resume(struct mmc_host *host) BUG_ON(!host->card); mmc_claim_host(host); - err = mmc_init_card(host, host->ocr, host->card); + 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); mmc_release_host(host); return err; @@ -1349,7 +1356,8 @@ static int mmc_power_restore(struct mmc_host *host) { int ret; - host->card->state &= ~MMC_STATE_HIGHSPEED; + host->card->state &= ~(MMC_STATE_HIGHSPEED | MMC_STATE_HIGHSPEED_200); + mmc_card_clr_sleep(host->card); mmc_claim_host(host); ret = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index c63ad03c29c7..5017f9354ce2 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -451,9 +451,11 @@ 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) @@ -660,9 +662,12 @@ 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) + if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) { + mmc_host_clk_hold(card->host); err = card->host->ops->execute_tuning(card->host, MMC_SEND_TUNING_BLOCK); + mmc_host_clk_release(card->host); + } out: kfree(status); @@ -850,8 +855,11 @@ int mmc_sd_setup_card(struct mmc_host *host, struct mmc_card *card, if (!reinit) { int ro = -1; - if (host->ops->get_ro) + if (host->ops->get_ro) { + mmc_host_clk_hold(card->host); ro = host->ops->get_ro(host); + mmc_host_clk_release(card->host); + } if (ro < 0) { pr_warning("%s: host does not " @@ -967,8 +975,11 @@ 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) + if (host->ops->enable_preset_value) { + mmc_host_clk_hold(card->host); host->ops->enable_preset_value(host, true); + mmc_host_clk_release(card->host); + } } else { /* * Attempt to change to high-speed (if supported) @@ -1151,8 +1162,11 @@ 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) + if (host->ops->enable_preset_value) { + mmc_host_clk_hold(host); 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/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index bd7bacc950dc..12cde6ee17f5 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c @@ -98,10 +98,11 @@ fail: return ret; } -static int sdio_read_cccr(struct mmc_card *card) +static int sdio_read_cccr(struct mmc_card *card, u32 ocr) { int ret; int cccr_vsn; + int uhs = ocr & R4_18V_PRESENT; unsigned char data; unsigned char speed; @@ -149,7 +150,7 @@ static int sdio_read_cccr(struct mmc_card *card) 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) { + if (cccr_vsn >= SDIO_CCCR_REV_3_00 && uhs) { card->scr.sda_spec3 = 1; ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_UHS, 0, &data); @@ -712,7 +713,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, /* * Read the common registers. */ - err = sdio_read_cccr(card); + err = sdio_read_cccr(card, ocr); if (err) goto remove; diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index 68f81b9ee0fb..f573e7f9f740 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c @@ -146,15 +146,21 @@ static int sdio_irq_thread(void *_host) } set_current_state(TASK_INTERRUPTIBLE); - if (host->caps & MMC_CAP_SDIO_IRQ) + if (host->caps & MMC_CAP_SDIO_IRQ) { + mmc_host_clk_hold(host); 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) + if (host->caps & MMC_CAP_SDIO_IRQ) { + mmc_host_clk_hold(host); 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/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index fcfe1eb5acc8..6985cdb0bb26 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -969,11 +969,14 @@ 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/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index 0e342793ff14..8bec1c36b159 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -22,7 +22,6 @@ #include <linux/ioport.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <linux/scatterlist.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/stat.h> @@ -502,8 +501,14 @@ 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; @@ -972,6 +977,7 @@ 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; @@ -1311,54 +1317,44 @@ 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 scatterlist *sg = host->sg; - void *buf = sg_virt(sg); - unsigned int offset = host->pio_offset; + struct sg_mapping_iter *sg_miter = &host->sg_miter; + void *buf; + unsigned int offset; struct mmc_data *data = host->data; int shift = host->data_shift; u32 status; unsigned int nbytes = 0, len; + unsigned int remain, fcnt; do { - len = host->part_buf_count + - (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); - if (offset + len <= sg->length) { + 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; dw_mci_pull_data(host, (void *)(buf + offset), len); - offset += len; nbytes += len; - - 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; - } + remain -= len; + } while (remain); + sg_miter->consumed = 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); @@ -1367,65 +1363,66 @@ 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 scatterlist *sg = host->sg; - void *buf = sg_virt(sg); - unsigned int offset = host->pio_offset; + struct sg_mapping_iter *sg_miter = &host->sg_miter; + void *buf; + unsigned int 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 { - len = ((host->fifo_depth - - SDMMC_GET_FCNT(mci_readl(host, STATUS))) << shift) - - host->part_buf_count; - if (offset + len <= sg->length) { + 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; host->push_data(host, (void *)(buf + offset), len); - offset += len; nbytes += len; - 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; - } + remain -= len; + } while (remain); + sg_miter->consumed = 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(); @@ -1435,12 +1432,20 @@ 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); } @@ -1643,6 +1648,7 @@ 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/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index ab66f2454dc4..1534b582c419 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/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(voltage_ranges[j], - voltage_ranges[j + 1]); + mask = mmc_vddrange_to_ocrmask(be32_to_cpu(voltage_ranges[j]), + be32_to_cpu(voltage_ranges[j + 1])); if (!mask) { ret = -EINVAL; dev_err(dev, "OF: voltage-range #%d is invalid\n", i); diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index ff4adc018041..5d876ff86f37 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -38,6 +38,23 @@ 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; } @@ -56,6 +73,21 @@ 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/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 7165e6a09274..6ebdc4010e7c 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/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; + slot->host->mmc->caps |= MMC_CAP_POWER_OFF_CARD | MMC_CAP_NONREMOVABLE; return 0; } diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 03970bcb3495..c5c2a48bdd94 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/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 Freescale Semiconductor, Inc. + * Copyright (c) 2007, 2011 Freescale Semiconductor, Inc. * Copyright (c) 2009 MontaVista Software, Inc. * * Authors: Xiaobo Xie <X.Xie@freescale.com> @@ -71,6 +71,14 @@ 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/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c index f5d8b53be333..352d4797865b 100644 --- a/drivers/mmc/host/sh_mmcif.c +++ b/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; - mmc_add_host(mmc); + INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL); @@ -1338,22 +1338,24 @@ 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_up3; + goto clean_up4; } - INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work); - - mmc_detect_change(host->mmc, 0); + ret = mmc_add_host(mmc); + if (ret < 0) + goto clean_up5; 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/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h index a95e6d901726..f96c536d130a 100644 --- a/drivers/mmc/host/tmio_mmc.h +++ b/drivers/mmc/host/tmio_mmc.h @@ -20,8 +20,8 @@ #include <linux/mmc/tmio.h> #include <linux/mutex.h> #include <linux/pagemap.h> -#include <linux/spinlock.h> #include <linux/scatterlist.h> +#include <linux/spinlock.h> /* Definitions for values the CTRL_SDIO_STATUS register can take. */ #define TMIO_SDIO_STAT_IOIRQ 0x0001 @@ -120,6 +120,7 @@ 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) @@ -140,6 +141,10 @@ 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/drivers/mmc/host/tmio_mmc_dma.c b/drivers/mmc/host/tmio_mmc_dma.c index 7a6e6cc8f8b8..8253ec12003e 100644 --- a/drivers/mmc/host/tmio_mmc_dma.c +++ b/drivers/mmc/host/tmio_mmc_dma.c @@ -34,6 +34,18 @@ 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/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c index abad01b37cfb..5f9ad74fbf80 100644 --- a/drivers/mmc/host/tmio_mmc_pio.c +++ b/drivers/mmc/host/tmio_mmc_pio.c @@ -41,8 +41,8 @@ #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/scatterlist.h> -#include <linux/workqueue.h> #include <linux/spinlock.h> +#include <linux/workqueue.h> #include "tmio_mmc.h" @@ -246,6 +246,7 @@ 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); } @@ -272,6 +273,9 @@ 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/drivers/pci/xen-pcifront.c b/drivers/pci/xen-pcifront.c index 7cf3d2fcf56a..1620088a0e7e 100644 --- a/drivers/pci/xen-pcifront.c +++ b/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.%01x - offset %x size %d\n", + "read dev=%04x:%02x:%02x.%d - 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.%01x - " + "write dev=%04x:%02x:%02x.%d - " "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.%02x found.\n", domain, bus, + "%04x:%02x:%02x.%d 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.%02x\n", + "Cannot get PCI device %04x:%02x:%02x.%d\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.%02x removed.\n", + "PCI device %04x:%02x:%02x.%d removed.\n", domain, bus, slot, func); } diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index b06a2399587c..d0e1180ad961 100644 --- a/drivers/regulator/max8649.c +++ b/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)ret); /* uV */ + voltage = max8649_list_voltage(rdev, (unsigned char)val); /* uV */ /* get rate */ ret = regmap_read(info->regmap, MAX8649_RAMP, &val); diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 80ecafef1bc3..62dcd0a432bb 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c @@ -254,6 +254,7 @@ 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, @@ -291,6 +292,7 @@ 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/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 14e2d995e958..4dcfced107f5 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c @@ -30,7 +30,8 @@ static int vcpu_online(unsigned int cpu) sprintf(dir, "cpu/%u", cpu); err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); if (err != 1) { - printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); + if (!xen_initial_domain()) + printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); return err; } diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 7944a17f5cbf..19834d1c7c36 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/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.%1x-%08x:%1x:%08x", domain, bus, slot, + sscanf(buf, " %04x:%02x:%02x.%d-%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.%01x\n", + pr_debug(DRV_NAME ": wants to seize %04x:%02x:%02x.%d\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.%01x from " + pr_debug(DRV_NAME ": removed %04x:%02x:%02x.%d 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.%01x\n", + "%04x:%02x:%02x.%d\n", pci_dev_id->domain, pci_dev_id->bus, PCI_SLOT(pci_dev_id->devfn), PCI_FUNC(pci_dev_id->devfn)); diff --git a/drivers/xen/xen-pciback/xenbus.c b/drivers/xen/xen-pciback/xenbus.c index d5dcf8d5d3d9..64b11f99eacc 100644 --- a/drivers/xen/xen-pciback/xenbus.c +++ b/drivers/xen/xen-pciback/xenbus.c @@ -206,6 +206,7 @@ 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)); @@ -229,7 +230,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.%01x)! " + "(%04x:%02x:%02x.%d)! " "perhaps already in-use?", domain, bus, slot, func); goto out; @@ -274,7 +275,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.%01x)! not owned by this domain\n", + "(%04x:%02x:%02x.%d)! not owned by this domain\n", domain, bus, slot, func); goto out; } diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 527dc2a3b89f..89f76252a16f 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -369,6 +369,10 @@ 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/include/linux/bitops.h b/include/linux/bitops.h index 3c1063acb2ab..94300fe46cce 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -56,6 +56,26 @@ static inline unsigned long hweight_long(unsigned long 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 * @shift: bits to roll diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 9f22ba572de0..19a41d1737af 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h @@ -217,6 +217,7 @@ 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 */ @@ -382,6 +383,7 @@ 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) @@ -393,7 +395,9 @@ 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/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index e8779c6d1759..aae5d1f1bb39 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -14,6 +14,8 @@ #ifndef LINUX_MMC_DW_MMC_H #define LINUX_MMC_DW_MMC_H +#include <linux/scatterlist.h> + #define MAX_MCI_SLOTS 2 enum dw_mci_state { @@ -40,7 +42,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. - * @pio_offset: Offset into the current scatterlist entry. + * @sg_miter: PIO mapping scatterlist iterator. * @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. @@ -115,7 +117,7 @@ struct dw_mci { void __iomem *regs; struct scatterlist *sg; - unsigned int pio_offset; + struct sg_mapping_iter sg_miter; struct dw_mci_slot *cur_slot; struct mmc_request *mrq; diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 0beba1e5e1ed..ee2b0363c040 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -257,6 +257,7 @@ 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; @@ -444,4 +445,23 @@ 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/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 9350f3c3bdf8..1358987c49d8 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4374,6 +4374,7 @@ 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, @@ -4427,6 +4428,23 @@ 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, @@ -4574,6 +4592,10 @@ 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[] = { @@ -4598,6 +4620,7 @@ 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/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 948f0be2f4f3..6345df131a00 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/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_HIZ : AC_PINCTL_VREF_GRD; + AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD; muted_lvl = spec->gpio_led_polarity ? - AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ; + AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_50; spec->vref_led = muted ? muted_lvl : notmtd_lvl; stac_vrefout_set(codec, spec->vref_mute_led_nid, spec->vref_led); diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 284e311040fe..dff9a00ee8fb 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -666,6 +666,9 @@ 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/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 9f3b01bb72c8..e0a4263baa20 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -2102,6 +2102,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = { }, { .subvendor = 0x161f, + .subdevice = 0x202f, + .name = "Gateway M520", + .type = AC97_TUNE_INV_EAPD + }, + { + .subvendor = 0x161f, .subdevice = 0x203a, .name = "Gateway 4525GZ", /* AD1981B */ .type = AC97_TUNE_INV_EAPD diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index db6c89a28bda..ea4a82d01160 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c @@ -1152,12 +1152,8 @@ 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; - if (samples_pos < 0) - samples_pos = 0; - - return fsi_sample2frame(fsi, samples_pos); + return fsi_sample2frame(fsi, io->buff_sample_pos); } static struct snd_pcm_ops fsi_pcm_ops = { |