diff options
196 files changed, 2199 insertions, 1186 deletions
diff --git a/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt new file mode 100644 index 00000000000..df70318a617 --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/egalax-ts.txt @@ -0,0 +1,19 @@ +* EETI eGalax Multiple Touch Controller + +Required properties: +- compatible: must be "eeti,egalax_ts" +- reg: i2c slave address +- interrupt-parent: the phandle for the interrupt controller +- interrupts: touch controller interrupt +- wakeup-gpios: the gpio pin to be used for waking up the controller +  as well as uased as irq pin + +Example: + +	egalax_ts@04 { +		compatible = "eeti,egalax_ts"; +		reg = <0x04>; +		interrupt-parent = <&gpio1>; +		interrupts = <9 2>; +		wakeup-gpios = <&gpio1 9 0>; +	}; diff --git a/Documentation/hwmon/fam15h_power b/Documentation/hwmon/fam15h_power index a92918e0bd6..80654813d04 100644 --- a/Documentation/hwmon/fam15h_power +++ b/Documentation/hwmon/fam15h_power @@ -10,7 +10,7 @@ Supported chips:    BIOS and Kernel Developer's Guide (BKDG) For AMD Family 15h Processors      (not yet published) -Author: Andreas Herrmann <andreas.herrmann3@amd.com> +Author: Andreas Herrmann <herrmann.der.user@googlemail.com>  Description  ----------- diff --git a/MAINTAINERS b/MAINTAINERS index 1fa907441f8..59203e77ce9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -503,7 +503,7 @@ F:	include/linux/altera_uart.h  F:	include/linux/altera_jtaguart.h  AMD FAM15H PROCESSOR POWER MONITORING DRIVER -M:	Andreas Herrmann <andreas.herrmann3@amd.com> +M:	Andreas Herrmann <herrmann.der.user@googlemail.com>  L:	lm-sensors@lm-sensors.org  S:	Maintained  F:	Documentation/hwmon/fam15h_power @@ -2507,6 +2507,7 @@ M:	Joonyoung Shim <jy0922.shim@samsung.com>  M:	Seung-Woo Kim <sw0312.kim@samsung.com>  M:	Kyungmin Park <kyungmin.park@samsung.com>  L:	dri-devel@lists.freedesktop.org +T:	git git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos.git  S:	Supported  F:	drivers/gpu/drm/exynos  F:	include/drm/exynos* @@ -5647,7 +5648,7 @@ S:	Maintained  F:	drivers/pinctrl/spear/  PKTCDVD DRIVER -M:	Peter Osterlund <petero2@telia.com> +M:	Jiri Kosina <jkosina@suse.cz>  S:	Maintained  F:	drivers/block/pktcdvd.c  F:	include/linux/pktcdvd.h @@ -1,7 +1,7 @@  VERSION = 3  PATCHLEVEL = 7  SUBLEVEL = 0 -EXTRAVERSION = -rc3 +EXTRAVERSION = -rc4  NAME = Terrified Chipmunk  # *DOCUMENTATION* diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S index 074f5ed101b..71f723984cb 100644 --- a/arch/arm/xen/hypercall.S +++ b/arch/arm/xen/hypercall.S @@ -48,20 +48,16 @@  #include <linux/linkage.h>  #include <asm/assembler.h> +#include <asm/opcodes-virt.h>  #include <xen/interface/xen.h> -/* HVC 0xEA1 */ -#ifdef CONFIG_THUMB2_KERNEL -#define xen_hvc .word 0xf7e08ea1 -#else -#define xen_hvc .word 0xe140ea71 -#endif +#define XEN_IMM 0xEA1  #define HYPERCALL_SIMPLE(hypercall)		\  ENTRY(HYPERVISOR_##hypercall)			\  	mov r12, #__HYPERVISOR_##hypercall;	\ -	xen_hvc;							\ +	__HVC(XEN_IMM);						\  	mov pc, lr;							\  ENDPROC(HYPERVISOR_##hypercall) @@ -76,7 +72,7 @@ ENTRY(HYPERVISOR_##hypercall)			\  	stmdb sp!, {r4}						\  	ldr r4, [sp, #4]					\  	mov r12, #__HYPERVISOR_##hypercall;	\ -	xen_hvc								\ +	__HVC(XEN_IMM);						\  	ldm sp!, {r4}						\  	mov pc, lr							\  ENDPROC(HYPERVISOR_##hypercall) @@ -100,7 +96,7 @@ ENTRY(privcmd_call)  	mov r2, r3  	ldr r3, [sp, #8]  	ldr r4, [sp, #4] -	xen_hvc +	__HVC(XEN_IMM)  	ldm sp!, {r4}  	mov pc, lr  ENDPROC(privcmd_call); diff --git a/arch/frv/Kconfig b/arch/frv/Kconfig index b7412504f08..df2eb4bd9fa 100644 --- a/arch/frv/Kconfig +++ b/arch/frv/Kconfig @@ -13,6 +13,7 @@ config FRV  	select GENERIC_CPU_DEVICES  	select ARCH_WANT_IPC_PARSE_VERSION  	select GENERIC_KERNEL_THREAD +	select GENERIC_KERNEL_EXECVE  config ZONE_DMA  	bool diff --git a/arch/frv/boot/Makefile b/arch/frv/boot/Makefile index 6ae3254da01..636d5bbcd53 100644 --- a/arch/frv/boot/Makefile +++ b/arch/frv/boot/Makefile @@ -17,6 +17,8 @@ PARAMS_PHYS	 = 0x0207c000  INITRD_PHYS	 = 0x02180000  INITRD_VIRT	 = 0x02180000 +OBJCOPYFLAGS	:=-O binary -R .note -R .note.gnu.build-id -R .comment +  #  # If you don't define ZRELADDR above,  # then it defaults to ZTEXTADDR @@ -32,18 +34,18 @@ Image: $(obj)/Image  targets: $(obj)/Image  $(obj)/Image: vmlinux FORCE -	$(OBJCOPY) -O binary -R .note -R .comment -S vmlinux $@ +	$(OBJCOPY) $(OBJCOPYFLAGS) -S vmlinux $@  #$(obj)/Image:	$(CONFIGURE) $(SYSTEM) -#	$(OBJCOPY) -O binary -R .note -R .comment -g -S $(SYSTEM) $@ +#	$(OBJCOPY) $(OBJCOPYFLAGS) -g -S $(SYSTEM) $@  bzImage: zImage  zImage:	$(CONFIGURE) compressed/$(LINUX) -	$(OBJCOPY) -O binary -R .note -R .comment -S compressed/$(LINUX) $@ +	$(OBJCOPY) $(OBJCOPYFLAGS) -S compressed/$(LINUX) $@  bootpImage: bootp/bootp -	$(OBJCOPY) -O binary -R .note -R .comment -S bootp/bootp $@ +	$(OBJCOPY) $(OBJCOPYFLAGS) -S bootp/bootp $@  compressed/$(LINUX): $(LINUX) dep  	@$(MAKE) -C compressed $(LINUX) diff --git a/arch/frv/include/asm/unistd.h b/arch/frv/include/asm/unistd.h index 266a5b25a0c..2358634cacc 100644 --- a/arch/frv/include/asm/unistd.h +++ b/arch/frv/include/asm/unistd.h @@ -30,7 +30,6 @@  #define __ARCH_WANT_SYS_RT_SIGACTION  #define __ARCH_WANT_SYS_RT_SIGSUSPEND  #define __ARCH_WANT_SYS_EXECVE -#define __ARCH_WANT_KERNEL_EXECVE  /*   * "Conditional" syscalls diff --git a/arch/frv/kernel/entry.S b/arch/frv/kernel/entry.S index ee0beb354e4..dfcd263c051 100644 --- a/arch/frv/kernel/entry.S +++ b/arch/frv/kernel/entry.S @@ -869,11 +869,6 @@ ret_from_kernel_thread:  	call		schedule_tail  	calll.p		@(gr21,gr0)  	or		gr20,gr20,gr8 -	bra		sys_exit - -	.globl		ret_from_kernel_execve -ret_from_kernel_execve: -	ori		gr28,0,sp  	bra		__syscall_exit  ################################################################################################### @@ -1080,27 +1075,10 @@ __entry_return_from_kernel_interrupt:  	subicc		gr5,#0,gr0,icc0  	beq		icc0,#0,__entry_return_direct -__entry_preempt_need_resched: -	ldi		@(gr15,#TI_FLAGS),gr4 -	andicc		gr4,#_TIF_NEED_RESCHED,gr0,icc0 -	beq		icc0,#1,__entry_return_direct - -	setlos		#PREEMPT_ACTIVE,gr5 -	sti		gr5,@(gr15,#TI_FLAGS) - -	andi		gr23,#~PSR_PIL,gr23 -	movgs		gr23,psr - -	call		schedule -	sti		gr0,@(gr15,#TI_PRE_COUNT) - -	movsg		psr,gr23 -	ori		gr23,#PSR_PIL_14,gr23 -	movgs		gr23,psr -	bra		__entry_preempt_need_resched -#else -	bra		__entry_return_direct +	subcc		gr0,gr0,gr0,icc2		/* set Z and clear C */ +	call		preempt_schedule_irq  #endif +	bra		__entry_return_direct  ############################################################################### diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index e1e3aa196aa..7e33215f1d8 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c @@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,  	childregs = (struct pt_regs *)  		(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE); +	/* set up the userspace frame (the only place that the USP is stored) */ +	*childregs = *__kernel_frame0_ptr; +  	p->set_child_tid = p->clear_child_tid = NULL;  	p->thread.frame	 = childregs; @@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,  	p->thread.frame0 = childregs;  	if (unlikely(!regs)) { -		memset(childregs, 0, sizeof(struct pt_regs));  		childregs->gr9 = usp; /* function */  		childregs->gr8 = arg; -		childregs->psr = PSR_S;  		p->thread.pc = (unsigned long) ret_from_kernel_thread;  		save_user_regs(p->thread.user);  		return 0; diff --git a/arch/frv/mb93090-mb00/pci-dma-nommu.c b/arch/frv/mb93090-mb00/pci-dma-nommu.c index e47857f889b..b99c2a7cc7a 100644 --- a/arch/frv/mb93090-mb00/pci-dma-nommu.c +++ b/arch/frv/mb93090-mb00/pci-dma-nommu.c @@ -11,6 +11,7 @@  #include <linux/types.h>  #include <linux/slab.h> +#include <linux/export.h>  #include <linux/dma-mapping.h>  #include <linux/list.h>  #include <linux/pci.h> diff --git a/arch/x86/include/asm/xen/hypervisor.h b/arch/x86/include/asm/xen/hypervisor.h index 66d0fff1ee8..125f344f06a 100644 --- a/arch/x86/include/asm/xen/hypervisor.h +++ b/arch/x86/include/asm/xen/hypervisor.h @@ -33,7 +33,6 @@  #ifndef _ASM_X86_XEN_HYPERVISOR_H  #define _ASM_X86_XEN_HYPERVISOR_H -/* arch/i386/kernel/setup.c */  extern struct shared_info *HYPERVISOR_shared_info;  extern struct start_info *xen_start_info; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1eefebe5d72..224a7e78cb6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -3779,7 +3779,7 @@ static int write_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,  {  	struct kvm_mmio_fragment *frag = &vcpu->mmio_fragments[0]; -	memcpy(vcpu->run->mmio.data, frag->data, frag->len); +	memcpy(vcpu->run->mmio.data, frag->data, min(8u, frag->len));  	return X86EMUL_CONTINUE;  } @@ -3832,18 +3832,11 @@ mmio:  	bytes -= handled;  	val += handled; -	while (bytes) { -		unsigned now = min(bytes, 8U); - -		frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; -		frag->gpa = gpa; -		frag->data = val; -		frag->len = now; - -		gpa += now; -		val += now; -		bytes -= now; -	} +	WARN_ON(vcpu->mmio_nr_fragments >= KVM_MAX_MMIO_FRAGMENTS); +	frag = &vcpu->mmio_fragments[vcpu->mmio_nr_fragments++]; +	frag->gpa = gpa; +	frag->data = val; +	frag->len = bytes;  	return X86EMUL_CONTINUE;  } @@ -3890,7 +3883,7 @@ int emulator_read_write(struct x86_emulate_ctxt *ctxt, unsigned long addr,  	vcpu->mmio_needed = 1;  	vcpu->mmio_cur_fragment = 0; -	vcpu->run->mmio.len = vcpu->mmio_fragments[0].len; +	vcpu->run->mmio.len = min(8u, vcpu->mmio_fragments[0].len);  	vcpu->run->mmio.is_write = vcpu->mmio_is_write = ops->write;  	vcpu->run->exit_reason = KVM_EXIT_MMIO;  	vcpu->run->mmio.phys_addr = gpa; @@ -5522,28 +5515,44 @@ static int complete_emulated_pio(struct kvm_vcpu *vcpu)   *   * read:   *   for each fragment - *     write gpa, len - *     exit - *     copy data + *     for each mmio piece in the fragment + *       write gpa, len + *       exit + *       copy data   *   execute insn   *   * write:   *   for each fragment - *      write gpa, len - *      copy data - *      exit + *     for each mmio piece in the fragment + *       write gpa, len + *       copy data + *       exit   */  static int complete_emulated_mmio(struct kvm_vcpu *vcpu)  {  	struct kvm_run *run = vcpu->run;  	struct kvm_mmio_fragment *frag; +	unsigned len;  	BUG_ON(!vcpu->mmio_needed);  	/* Complete previous fragment */ -	frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment++]; +	frag = &vcpu->mmio_fragments[vcpu->mmio_cur_fragment]; +	len = min(8u, frag->len);  	if (!vcpu->mmio_is_write) -		memcpy(frag->data, run->mmio.data, frag->len); +		memcpy(frag->data, run->mmio.data, len); + +	if (frag->len <= 8) { +		/* Switch to the next fragment. */ +		frag++; +		vcpu->mmio_cur_fragment++; +	} else { +		/* Go forward to the next mmio piece. */ +		frag->data += len; +		frag->gpa += len; +		frag->len -= len; +	} +  	if (vcpu->mmio_cur_fragment == vcpu->mmio_nr_fragments) {  		vcpu->mmio_needed = 0;  		if (vcpu->mmio_is_write) @@ -5551,13 +5560,12 @@ static int complete_emulated_mmio(struct kvm_vcpu *vcpu)  		vcpu->mmio_read_completed = 1;  		return complete_emulated_io(vcpu);  	} -	/* Initiate next fragment */ -	++frag; +  	run->exit_reason = KVM_EXIT_MMIO;  	run->mmio.phys_addr = frag->gpa;  	if (vcpu->mmio_is_write) -		memcpy(run->mmio.data, frag->data, frag->len); -	run->mmio.len = frag->len; +		memcpy(run->mmio.data, frag->data, min(8u, frag->len)); +	run->mmio.len = min(8u, frag->len);  	run->mmio.is_write = vcpu->mmio_is_write;  	vcpu->arch.complete_userspace_io = complete_emulated_mmio;  	return 0; diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index 6226c99729b..dcf5f2dd91e 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c @@ -1288,6 +1288,25 @@ unsigned long xen_read_cr2_direct(void)  	return this_cpu_read(xen_vcpu_info.arch.cr2);  } +void xen_flush_tlb_all(void) +{ +	struct mmuext_op *op; +	struct multicall_space mcs; + +	trace_xen_mmu_flush_tlb_all(0); + +	preempt_disable(); + +	mcs = xen_mc_entry(sizeof(*op)); + +	op = mcs.args; +	op->cmd = MMUEXT_TLB_FLUSH_ALL; +	MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF); + +	xen_mc_issue(PARAVIRT_LAZY_MMU); + +	preempt_enable(); +}  static void xen_flush_tlb(void)  {  	struct mmuext_op *op; @@ -2518,7 +2537,7 @@ int xen_remap_domain_mfn_range(struct vm_area_struct *vma,  	err = 0;  out: -	flush_tlb_all(); +	xen_flush_tlb_all();  	return err;  } diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index cdcb48adee4..0d1f36a22c9 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -13,6 +13,8 @@ config XTENSA  	select GENERIC_CPU_DEVICES  	select MODULES_USE_ELF_RELA  	select GENERIC_PCI_IOMAP +	select GENERIC_KERNEL_THREAD +	select GENERIC_KERNEL_EXECVE  	select ARCH_WANT_OPTIONAL_GPIOLIB  	help  	  Xtensa processors are 32-bit RISC machines designed by Tensilica diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h index e6be5b9091c..700c2e6f2d2 100644 --- a/arch/xtensa/include/asm/io.h +++ b/arch/xtensa/include/asm/io.h @@ -62,6 +62,10 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)  static inline void iounmap(volatile void __iomem *addr)  {  } + +#define virt_to_bus     virt_to_phys +#define bus_to_virt     phys_to_virt +  #endif /* CONFIG_MMU */  /* diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 5c371d8d452..2d630e7399c 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h @@ -152,6 +152,7 @@ struct thread_struct {  /* Clearing a0 terminates the backtrace. */  #define start_thread(regs, new_pc, new_sp) \ +	memset(regs, 0, sizeof(*regs)); \  	regs->pc = new_pc; \  	regs->ps = USER_PS_VALUE; \  	regs->areg[1] = new_sp; \ @@ -168,9 +169,6 @@ struct mm_struct;  /* Free all resources held by a thread. */  #define release_thread(thread) do { } while(0) -/* Create a kernel thread without removing it from tasklists */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); -  /* Copy and release all segment info associated with a VM */  #define copy_segments(p, mm)	do { } while(0)  #define release_segments(mm)	do { } while(0) diff --git a/arch/xtensa/include/asm/syscall.h b/arch/xtensa/include/asm/syscall.h index c1dacca312f..124aeee0d38 100644 --- a/arch/xtensa/include/asm/syscall.h +++ b/arch/xtensa/include/asm/syscall.h @@ -10,7 +10,7 @@  struct pt_regs;  struct sigaction; -asmlinkage long xtensa_execve(char*, char**, char**, struct pt_regs*); +asmlinkage long sys_execve(char*, char**, char**, struct pt_regs*);  asmlinkage long xtensa_clone(unsigned long, unsigned long, struct pt_regs*);  asmlinkage long xtensa_ptrace(long, long, long, long);  asmlinkage long xtensa_sigreturn(struct pt_regs*); diff --git a/arch/xtensa/include/asm/unistd.h b/arch/xtensa/include/asm/unistd.h index 9ef1c31d2c8..f4e6eaa40d1 100644 --- a/arch/xtensa/include/asm/unistd.h +++ b/arch/xtensa/include/asm/unistd.h @@ -1,16 +1,9 @@ -/* - * include/asm-xtensa/unistd.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2005 Tensilica Inc. - */ +#ifndef _XTENSA_UNISTD_H +#define _XTENSA_UNISTD_H +#define __ARCH_WANT_SYS_EXECVE  #include <uapi/asm/unistd.h> -  /*   * "Conditional" syscalls   * @@ -37,3 +30,5 @@  #define __IGNORE_mmap				/* use mmap2 */  #define __IGNORE_vfork				/* use clone */  #define __IGNORE_fadvise64			/* use fadvise64_64 */ + +#endif /* _XTENSA_UNISTD_H */ diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index 479abaea5aa..9f36d0e3e0a 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h @@ -1,14 +1,4 @@ -/* - * include/asm-xtensa/unistd.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License.  See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2001 - 2012 Tensilica Inc. - */ - -#ifndef _UAPI_XTENSA_UNISTD_H +#if !defined(_UAPI_XTENSA_UNISTD_H) || defined(__SYSCALL)  #define _UAPI_XTENSA_UNISTD_H  #ifndef __SYSCALL @@ -272,7 +262,7 @@ __SYSCALL(115, sys_sendmmsg, 4)  #define __NR_clone 				116  __SYSCALL(116, xtensa_clone, 5)  #define __NR_execve 				117 -__SYSCALL(117, xtensa_execve, 3) +__SYSCALL(117, sys_execve, 3)  #define __NR_exit 				118  __SYSCALL(118, sys_exit, 1)  #define __NR_exit_group 			119 @@ -759,4 +749,6 @@ __SYSCALL(331, sys_kcmp, 5)  #define SYS_XTENSA_COUNT                  5     /* count */ +#undef __SYSCALL +  #endif /* _UAPI_XTENSA_UNISTD_H */ diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 18453067c25..90bfc1dbc13 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S @@ -1833,50 +1833,6 @@ ENTRY(system_call)  /* - * Create a kernel thread - * - * int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) - * a2                    a2                 a3             a4 - */ - -ENTRY(kernel_thread) -	entry	a1, 16 - -	mov	a5, a2			# preserve fn over syscall -	mov	a7, a3			# preserve args over syscall - -	movi	a3, _CLONE_VM | _CLONE_UNTRACED -	movi	a2, __NR_clone -	or	a6, a4, a3		# arg0: flags -	mov	a3, a1			# arg1: sp -	syscall - -	beq	a3, a1, 1f		# branch if parent -	mov	a6, a7			# args -	callx4	a5			# fn(args) - -	movi	a2, __NR_exit -	syscall				# return value of fn(args) still in a6 - -1:	retw - -/* - * Do a system call from kernel instead of calling sys_execve, so we end up - * with proper pt_regs. - * - * int kernel_execve(const char *fname, char *const argv[], charg *const envp[]) - * a2                        a2               a3                  a4 - */ - -ENTRY(kernel_execve) -	entry	a1, 16 -	mov	a6, a2			# arg0 is in a6 -	movi	a2, __NR_execve -	syscall - -	retw - -/*   * Task switch.   *   * struct task*  _switch_to (struct task* prev, struct task* next) @@ -1958,3 +1914,16 @@ ENTRY(ret_from_fork)  	j	common_exception_return +/* + * Kernel thread creation helper + * On entry, set up by copy_thread: a2 = thread_fn, a3 = thread_fn arg + *           left from _switch_to: a6 = prev + */ +ENTRY(ret_from_kernel_thread) + +	call4	schedule_tail +	mov	a6, a3 +	callx4	a2 +	j	common_exception_return + +ENDPROC(ret_from_kernel_thread) diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 1908f6642d3..09ae7bfab9a 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -45,6 +45,7 @@  #include <asm/regs.h>  extern void ret_from_fork(void); +extern void ret_from_kernel_thread(void);  struct task_struct *current_set[NR_CPUS] = {&init_task, }; @@ -158,18 +159,30 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)  /*   * Copy thread.   * + * There are two modes in which this function is called: + * 1) Userspace thread creation, + *    regs != NULL, usp_thread_fn is userspace stack pointer. + *    It is expected to copy parent regs (in case CLONE_VM is not set + *    in the clone_flags) and set up passed usp in the childregs. + * 2) Kernel thread creation, + *    regs == NULL, usp_thread_fn is the function to run in the new thread + *    and thread_fn_arg is its parameter. + *    childregs are not used for the kernel threads. + *   * The stack layout for the new thread looks like this:   * - *	+------------------------+ <- sp in childregs (= tos) + *	+------------------------+   *	|       childregs        |   *	+------------------------+ <- thread.sp = sp in dummy-frame   *	|      dummy-frame       |    (saved in dummy-frame spill-area)   *	+------------------------+   * - * We create a dummy frame to return to ret_from_fork: - *   a0 points to ret_from_fork (simulating a call4) + * We create a dummy frame to return to either ret_from_fork or + *   ret_from_kernel_thread: + *   a0 points to ret_from_fork/ret_from_kernel_thread (simulating a call4)   *   sp points to itself (thread.sp) - *   a2, a3 are unused. + *   a2, a3 are unused for userspace threads, + *   a2 points to thread_fn, a3 holds thread_fn arg for kernel threads.   *   * Note: This is a pristine frame, so we don't need any spill region on top of   *       childregs. @@ -185,43 +198,63 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)   * involved.  Much simpler to just not copy those live frames across.   */ -int copy_thread(unsigned long clone_flags, unsigned long usp, -		unsigned long unused, -                struct task_struct * p, struct pt_regs * regs) +int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, +		unsigned long thread_fn_arg, +		struct task_struct *p, struct pt_regs *unused)  { -	struct pt_regs *childregs; -	unsigned long tos; -	int user_mode = user_mode(regs); +	struct pt_regs *childregs = task_pt_regs(p);  #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS)  	struct thread_info *ti;  #endif -	/* Set up new TSS. */ -	tos = (unsigned long)task_stack_page(p) + THREAD_SIZE; -	if (user_mode) -		childregs = (struct pt_regs*)(tos - PT_USER_SIZE); -	else -		childregs = (struct pt_regs*)tos - 1; - -	/* This does not copy all the regs.  In a bout of brilliance or madness, -	   ARs beyond a0-a15 exist past the end of the struct. */ -	*childregs = *regs; -  	/* Create a call4 dummy-frame: a0 = 0, a1 = childregs. */  	*((int*)childregs - 3) = (unsigned long)childregs;  	*((int*)childregs - 4) = 0; -	childregs->areg[2] = 0; -	p->set_child_tid = p->clear_child_tid = NULL; -	p->thread.ra = MAKE_RA_FOR_CALL((unsigned long)ret_from_fork, 0x1);  	p->thread.sp = (unsigned long)childregs; -	if (user_mode(regs)) { +	if (!(p->flags & PF_KTHREAD)) { +		struct pt_regs *regs = current_pt_regs(); +		unsigned long usp = usp_thread_fn ? +			usp_thread_fn : regs->areg[1]; + +		p->thread.ra = MAKE_RA_FOR_CALL( +				(unsigned long)ret_from_fork, 0x1); +		/* This does not copy all the regs. +		 * In a bout of brilliance or madness, +		 * ARs beyond a0-a15 exist past the end of the struct. +		 */ +		*childregs = *regs;  		childregs->areg[1] = usp; +		childregs->areg[2] = 0; + +		/* When sharing memory with the parent thread, the child +		   usually starts on a pristine stack, so we have to reset +		   windowbase, windowstart and wmask. +		   (Note that such a new thread is required to always create +		   an initial call4 frame) +		   The exception is vfork, where the new thread continues to +		   run on the parent's stack until it calls execve. This could +		   be a call8 or call12, which requires a legal stack frame +		   of the previous caller for the overflow handlers to work. +		   (Note that it's always legal to overflow live registers). +		   In this case, ensure to spill at least the stack pointer +		   of that frame. */ +  		if (clone_flags & CLONE_VM) { -			childregs->wmask = 1;	/* can't share live windows */ +			/* check that caller window is live and same stack */ +			int len = childregs->wmask & ~0xf; +			if (regs->areg[1] == usp && len != 0) { +				int callinc = (regs->areg[0] >> 30) & 3; +				int caller_ars = XCHAL_NUM_AREGS - callinc * 4; +				put_user(regs->areg[caller_ars+1], +					 (unsigned __user*)(usp - 12)); +			} +			childregs->wmask = 1; +			childregs->windowstart = 1; +			childregs->windowbase = 0;  		} else {  			int len = childregs->wmask & ~0xf;  			memcpy(&childregs->areg[XCHAL_NUM_AREGS - len/4], @@ -230,11 +263,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,  // FIXME: we need to set THREADPTR in thread_info...  		if (clone_flags & CLONE_SETTLS)  			childregs->areg[2] = childregs->areg[6]; -  	} else { -		/* In kernel space, we start a new thread with a new stack. */ -		childregs->wmask = 1; -		childregs->areg[1] = tos; +		p->thread.ra = MAKE_RA_FOR_CALL( +				(unsigned long)ret_from_kernel_thread, 1); + +		/* pass parameters to ret_from_kernel_thread: +		 * a2 = thread_fn, a3 = thread_fn arg +		 */ +		*((int *)childregs - 1) = thread_fn_arg; +		*((int *)childregs - 2) = usp_thread_fn; + +		/* Childregs are only used when we're going to userspace +		 * in which case start_thread will set them up. +		 */  	}  #if (XTENSA_HAVE_COPROCESSORS || XTENSA_HAVE_IO_PORTS) @@ -330,32 +371,5 @@ long xtensa_clone(unsigned long clone_flags, unsigned long newsp,                    void __user *child_tid, long a5,                    struct pt_regs *regs)  { -        if (!newsp) -                newsp = regs->areg[1];          return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid);  } - -/* - * xtensa_execve() executes a new program. - */ - -asmlinkage -long xtensa_execve(const char __user *name, -		   const char __user *const __user *argv, -                   const char __user *const __user *envp, -                   long a3, long a4, long a5, -                   struct pt_regs *regs) -{ -	long error; -	struct filename *filename; - -	filename = getname(name); -	error = PTR_ERR(filename); -	if (IS_ERR(filename)) -		goto out; -	error = do_execve(filename->name, argv, envp, regs); -	putname(filename); -out: -	return error; -} - diff --git a/arch/xtensa/kernel/syscall.c b/arch/xtensa/kernel/syscall.c index a5c01e74d5d..5702065f472 100644 --- a/arch/xtensa/kernel/syscall.c +++ b/arch/xtensa/kernel/syscall.c @@ -32,10 +32,8 @@ typedef void (*syscall_t)(void);  syscall_t sys_call_table[__NR_syscall_count] /* FIXME __cacheline_aligned */= {  	[0 ... __NR_syscall_count - 1] = (syscall_t)&sys_ni_syscall, -#undef __SYSCALL  #define __SYSCALL(nr,symbol,nargs) [ nr ] = (syscall_t)symbol, -#undef  __KERNEL_SYSCALLS__ -#include <asm/unistd.h> +#include <uapi/asm/unistd.h>  };  asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg) @@ -49,7 +47,8 @@ asmlinkage long xtensa_shmat(int shmid, char __user *shmaddr, int shmflg)  	return (long)ret;  } -asmlinkage long xtensa_fadvise64_64(int fd, int advice, unsigned long long offset, unsigned long long len) +asmlinkage long xtensa_fadvise64_64(int fd, int advice, +		unsigned long long offset, unsigned long long len)  {  	return sys_fadvise64_64(fd, offset, len, advice);  } diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index a8b9f1fd1e1..afe058b24e6 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c @@ -43,7 +43,6 @@ EXPORT_SYMBOL(__strncpy_user);  EXPORT_SYMBOL(clear_page);  EXPORT_SYMBOL(copy_page); -EXPORT_SYMBOL(kernel_thread);  EXPORT_SYMBOL(empty_zero_page);  /* diff --git a/block/Kconfig b/block/Kconfig index 09acf1b3990..a7e40a7c821 100644 --- a/block/Kconfig +++ b/block/Kconfig @@ -89,7 +89,7 @@ config BLK_DEV_INTEGRITY  config BLK_DEV_THROTTLING  	bool "Block layer bio throttling support" -	depends on BLK_CGROUP=y && EXPERIMENTAL +	depends on BLK_CGROUP=y  	default n  	---help---  	Block layer bio throttling support. It can be used to limit diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index cafcd743118..d0b770391ad 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -285,6 +285,13 @@ static void blkg_destroy_all(struct request_queue *q)  		blkg_destroy(blkg);  		spin_unlock(&blkcg->lock);  	} + +	/* +	 * root blkg is destroyed.  Just clear the pointer since +	 * root_rl does not take reference on root blkg. +	 */ +	q->root_blkg = NULL; +	q->root_rl.blkg = NULL;  }  static void blkg_rcu_free(struct rcu_head *rcu_head) @@ -326,6 +333,9 @@ struct request_list *__blk_queue_next_rl(struct request_list *rl,  	 */  	if (rl == &q->root_rl) {  		ent = &q->blkg_list; +		/* There are no more block groups, hence no request lists */ +		if (list_empty(ent)) +			return NULL;  	} else {  		blkg = container_of(rl, struct blkcg_gq, rl);  		ent = &blkg->q_node; diff --git a/block/blk-core.c b/block/blk-core.c index a33870b1847..3c95c4d6e31 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2868,7 +2868,8 @@ static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)  	struct request *rqa = container_of(a, struct request, queuelist);  	struct request *rqb = container_of(b, struct request, queuelist); -	return !(rqa->q <= rqb->q); +	return !(rqa->q < rqb->q || +		(rqa->q == rqb->q && blk_rq_pos(rqa) < blk_rq_pos(rqb)));  }  /* diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index f94d4c818fc..0230cb6cbb3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c @@ -1345,12 +1345,15 @@ static int  acpi_video_bus_get_devices(struct acpi_video_bus *video,  			   struct acpi_device *device)  { -	int status; +	int status = 0;  	struct acpi_device *dev; -	status = acpi_video_device_enumerate(video); -	if (status) -		return status; +	/* +	 * There are systems where video module known to work fine regardless +	 * of broken _DOD and ignoring returned value here doesn't cause +	 * any issues later. +	 */ +	acpi_video_device_enumerate(video);  	list_for_each_entry(dev, &device->children, node) { diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index f529407db93..824e09c4d0d 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -131,6 +131,7 @@ config BLK_CPQ_DA  config BLK_CPQ_CISS_DA  	tristate "Compaq Smart Array 5xxx support"  	depends on PCI +	select CHECK_SIGNATURE  	help  	  This is the driver for Compaq Smart Array 5xxx controllers.  	  Everyone using these boards should say Y here. @@ -166,8 +167,8 @@ config BLK_DEV_DAC960  	  module will be called DAC960.  config BLK_DEV_UMEM -	tristate "Micro Memory MM5415 Battery Backed RAM support (EXPERIMENTAL)" -	depends on PCI && EXPERIMENTAL +	tristate "Micro Memory MM5415 Battery Backed RAM support" +	depends on PCI  	---help---  	  Saying Y here will include support for the MM5415 family of  	  battery backed (Non-volatile) RAM cards. @@ -430,8 +431,8 @@ config CDROM_PKTCDVD_BUFFERS  	  a disc is opened for writing.  config CDROM_PKTCDVD_WCACHE -	bool "Enable write caching (EXPERIMENTAL)" -	depends on CDROM_PKTCDVD && EXPERIMENTAL +	bool "Enable write caching" +	depends on CDROM_PKTCDVD  	help  	  If enabled, write caching will be set for the CD-R/W device. For now  	  this option is dangerous unless the CD-RW media is known good, as we @@ -508,8 +509,8 @@ config XEN_BLKDEV_BACKEND  config VIRTIO_BLK -	tristate "Virtio block driver (EXPERIMENTAL)" -	depends on EXPERIMENTAL && VIRTIO +	tristate "Virtio block driver" +	depends on VIRTIO  	---help---  	  This is the virtual block driver for virtio.  It can be used with            lguest or QEMU based VMMs (like KVM or Xen).  Say Y or M. @@ -528,7 +529,7 @@ config BLK_DEV_HD  config BLK_DEV_RBD  	tristate "Rados block device (RBD)" -	depends on INET && EXPERIMENTAL && BLOCK +	depends on INET && BLOCK  	select CEPH_LIB  	select LIBCRC32C  	select CRYPTO_AES diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b0f553b26d0..ca83f96756a 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -5205,7 +5205,6 @@ static void cciss_shutdown(struct pci_dev *pdev)  		return;  	}  	/* write all data in the battery backed cache to disk */ -	memset(flush_buf, 0, 4);  	return_code = sendcmd_withirq(h, CCISS_CACHE_FLUSH, flush_buf,  		4, 0, CTLR_LUNID, TYPE_CMD);  	kfree(flush_buf); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 17c675c5229..1c49d717396 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4109,12 +4109,19 @@ static struct platform_driver floppy_driver = {  static struct platform_device floppy_device[N_DRIVE]; +static bool floppy_available(int drive) +{ +	if (!(allowed_drive_mask & (1 << drive))) +		return false; +	if (fdc_state[FDC(drive)].version == FDC_NONE) +		return false; +	return true; +} +  static struct kobject *floppy_find(dev_t dev, int *part, void *data)  {  	int drive = (*part & 3) | ((*part & 0x80) >> 5); -	if (drive >= N_DRIVE || -	    !(allowed_drive_mask & (1 << drive)) || -	    fdc_state[FDC(drive)].version == FDC_NONE) +	if (drive >= N_DRIVE || !floppy_available(drive))  		return NULL;  	if (((*part >> 2) & 0x1f) >= ARRAY_SIZE(floppy_type))  		return NULL; @@ -4124,8 +4131,7 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data)  static int __init do_floppy_init(void)  { -	int i, unit, drive; -	int err, dr; +	int i, unit, drive, err;  	set_debugt();  	interruptjiffies = resultjiffies = jiffies; @@ -4137,34 +4143,32 @@ static int __init do_floppy_init(void)  	raw_cmd = NULL; -	for (dr = 0; dr < N_DRIVE; dr++) { -		disks[dr] = alloc_disk(1); -		if (!disks[dr]) { -			err = -ENOMEM; -			goto out_put_disk; -		} +	floppy_wq = alloc_ordered_workqueue("floppy", 0); +	if (!floppy_wq) +		return -ENOMEM; -		floppy_wq = alloc_ordered_workqueue("floppy", 0); -		if (!floppy_wq) { +	for (drive = 0; drive < N_DRIVE; drive++) { +		disks[drive] = alloc_disk(1); +		if (!disks[drive]) {  			err = -ENOMEM;  			goto out_put_disk;  		} -		disks[dr]->queue = blk_init_queue(do_fd_request, &floppy_lock); -		if (!disks[dr]->queue) { +		disks[drive]->queue = blk_init_queue(do_fd_request, &floppy_lock); +		if (!disks[drive]->queue) {  			err = -ENOMEM; -			goto out_destroy_workq; +			goto out_put_disk;  		} -		blk_queue_max_hw_sectors(disks[dr]->queue, 64); -		disks[dr]->major = FLOPPY_MAJOR; -		disks[dr]->first_minor = TOMINOR(dr); -		disks[dr]->fops = &floppy_fops; -		sprintf(disks[dr]->disk_name, "fd%d", dr); +		blk_queue_max_hw_sectors(disks[drive]->queue, 64); +		disks[drive]->major = FLOPPY_MAJOR; +		disks[drive]->first_minor = TOMINOR(drive); +		disks[drive]->fops = &floppy_fops; +		sprintf(disks[drive]->disk_name, "fd%d", drive); -		init_timer(&motor_off_timer[dr]); -		motor_off_timer[dr].data = dr; -		motor_off_timer[dr].function = motor_off_callback; +		init_timer(&motor_off_timer[drive]); +		motor_off_timer[drive].data = drive; +		motor_off_timer[drive].function = motor_off_callback;  	}  	err = register_blkdev(FLOPPY_MAJOR, "fd"); @@ -4282,9 +4286,7 @@ static int __init do_floppy_init(void)  	}  	for (drive = 0; drive < N_DRIVE; drive++) { -		if (!(allowed_drive_mask & (1 << drive))) -			continue; -		if (fdc_state[FDC(drive)].version == FDC_NONE) +		if (!floppy_available(drive))  			continue;  		floppy_device[drive].name = floppy_device_name; @@ -4293,7 +4295,7 @@ static int __init do_floppy_init(void)  		err = platform_device_register(&floppy_device[drive]);  		if (err) -			goto out_release_dma; +			goto out_remove_drives;  		err = device_create_file(&floppy_device[drive].dev,  					 &dev_attr_cmos); @@ -4311,29 +4313,34 @@ static int __init do_floppy_init(void)  out_unreg_platform_dev:  	platform_device_unregister(&floppy_device[drive]); +out_remove_drives: +	while (drive--) { +		if (floppy_available(drive)) { +			del_gendisk(disks[drive]); +			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos); +			platform_device_unregister(&floppy_device[drive]); +		} +	}  out_release_dma:  	if (atomic_read(&usage_count))  		floppy_release_irq_and_dma();  out_unreg_region:  	blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256);  	platform_driver_unregister(&floppy_driver); -out_destroy_workq: -	destroy_workqueue(floppy_wq);  out_unreg_blkdev:  	unregister_blkdev(FLOPPY_MAJOR, "fd");  out_put_disk: -	while (dr--) { -		del_timer_sync(&motor_off_timer[dr]); -		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; +	for (drive = 0; drive < N_DRIVE; drive++) { +		if (!disks[drive]) +			break; +		if (disks[drive]->queue) { +			del_timer_sync(&motor_off_timer[drive]); +			blk_cleanup_queue(disks[drive]->queue); +			disks[drive]->queue = NULL;  		} -		put_disk(disks[dr]); +		put_disk(disks[drive]);  	} +	destroy_workqueue(floppy_wq);  	return err;  } @@ -4551,8 +4558,7 @@ static void __exit floppy_module_exit(void)  	for (drive = 0; drive < N_DRIVE; drive++) {  		del_timer_sync(&motor_off_timer[drive]); -		if ((allowed_drive_mask & (1 << drive)) && -		    fdc_state[FDC(drive)].version != FDC_NONE) { +		if (floppy_available(drive)) {  			del_gendisk(disks[drive]);  			device_remove_file(&floppy_device[drive].dev, &dev_attr_cmos);  			platform_device_unregister(&floppy_device[drive]); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index e9d594fd12c..54046e51160 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -976,8 +976,21 @@ static int loop_clr_fd(struct loop_device *lo)  	if (lo->lo_state != Lo_bound)  		return -ENXIO; -	if (lo->lo_refcnt > 1)	/* we needed one fd for the ioctl */ -		return -EBUSY; +	/* +	 * If we've explicitly asked to tear down the loop device, +	 * and it has an elevated reference count, set it for auto-teardown when +	 * the last reference goes away. This stops $!~#$@ udev from +	 * preventing teardown because it decided that it needs to run blkid on +	 * the loopback device whenever they appear. xfstests is notorious for +	 * failing tests because blkid via udev races with a losetup +	 * <dev>/do something like mkfs/losetup -d <dev> causing the losetup -d +	 * command to fail with EBUSY. +	 */ +	if (lo->lo_refcnt > 1) { +		lo->lo_flags |= LO_FLAGS_AUTOCLEAR; +		mutex_unlock(&lo->lo_ctl_mutex); +		return 0; +	}  	if (filp == NULL)  		return -EINVAL; diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index f946d31d691..adc6f36564c 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c @@ -2035,8 +2035,9 @@ static unsigned int implicit_sector(unsigned char command,  	}  	return rv;  } - -static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout) +static void mtip_set_timeout(struct driver_data *dd, +					struct host_to_dev_fis *fis, +					unsigned int *timeout, u8 erasemode)  {  	switch (fis->command) {  	case ATA_CMD_DOWNLOAD_MICRO: @@ -2044,7 +2045,10 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)  		break;  	case ATA_CMD_SEC_ERASE_UNIT:  	case 0xFC: -		*timeout = 240000; /* 4 minutes */ +		if (erasemode) +			*timeout = ((*(dd->port->identify + 90) * 2) * 60000); +		else +			*timeout = ((*(dd->port->identify + 89) * 2) * 60000);  		break;  	case ATA_CMD_STANDBYNOW1:  		*timeout = 120000;  /* 2 minutes */ @@ -2087,6 +2091,7 @@ static int exec_drive_taskfile(struct driver_data *dd,  	unsigned int transfer_size;  	unsigned long task_file_data;  	int intotal = outtotal + req_task->out_size; +	int erasemode = 0;  	taskout = req_task->out_size;  	taskin = req_task->in_size; @@ -2212,7 +2217,13 @@ static int exec_drive_taskfile(struct driver_data *dd,  		fis.lba_hi,  		fis.device); -	mtip_set_timeout(&fis, &timeout); +	/* check for erase mode support during secure erase.*/ +	if ((fis.command == ATA_CMD_SEC_ERASE_UNIT) +					&& (outbuf[0] & MTIP_SEC_ERASE_MODE)) { +		erasemode = 1; +	} + +	mtip_set_timeout(dd, &fis, &timeout, erasemode);  	/* Determine the correct transfer size.*/  	if (force_single_sector) diff --git a/drivers/block/mtip32xx/mtip32xx.h b/drivers/block/mtip32xx/mtip32xx.h index 18627a1d04c..5f4a917bd8b 100644 --- a/drivers/block/mtip32xx/mtip32xx.h +++ b/drivers/block/mtip32xx/mtip32xx.h @@ -33,6 +33,9 @@  /* offset of Device Control register in PCIe extended capabilites space */  #define PCIE_CONFIG_EXT_DEVICE_CONTROL_OFFSET	0x48 +/* check for erase mode support during secure erase */ +#define MTIP_SEC_ERASE_MODE     0x3 +  /* # of times to retry timed out/failed IOs */  #define MTIP_MAX_RETRIES	2 diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 9ad3b5ec1dc..9a54623e52d 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -158,8 +158,8 @@ struct xen_vbd {  	struct block_device	*bdev;  	/* Cached size parameter. */  	sector_t		size; -	bool			flush_support; -	bool			discard_secure; +	unsigned int		flush_support:1; +	unsigned int		discard_secure:1;  };  struct backend_info; diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 4f66171c668..f58434c2617 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -105,11 +105,10 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid)  {  	struct xen_blkif *blkif; -	blkif = kmem_cache_alloc(xen_blkif_cachep, GFP_KERNEL); +	blkif = kmem_cache_zalloc(xen_blkif_cachep, GFP_KERNEL);  	if (!blkif)  		return ERR_PTR(-ENOMEM); -	memset(blkif, 0, sizeof(*blkif));  	blkif->domid = domid;  	spin_lock_init(&blkif->blk_ring_lock);  	atomic_set(&blkif->refcnt, 1); @@ -196,7 +195,7 @@ static void xen_blkif_disconnect(struct xen_blkif *blkif)  	}  } -void xen_blkif_free(struct xen_blkif *blkif) +static void xen_blkif_free(struct xen_blkif *blkif)  {  	if (!atomic_dec_and_test(&blkif->refcnt))  		BUG(); @@ -257,7 +256,7 @@ static struct attribute_group xen_vbdstat_group = {  VBD_SHOW(physical_device, "%x:%x\n", be->major, be->minor);  VBD_SHOW(mode, "%s\n", be->mode); -int xenvbd_sysfs_addif(struct xenbus_device *dev) +static int xenvbd_sysfs_addif(struct xenbus_device *dev)  {  	int error; @@ -281,7 +280,7 @@ fail1:	device_remove_file(&dev->dev, &dev_attr_physical_device);  	return error;  } -void xenvbd_sysfs_delif(struct xenbus_device *dev) +static void xenvbd_sysfs_delif(struct xenbus_device *dev)  {  	sysfs_remove_group(&dev->dev.kobj, &xen_vbdstat_group);  	device_remove_file(&dev->dev, &dev_attr_mode); diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index c16a3a593ba..e3ebb4fa2c3 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -5,7 +5,7 @@   *  http://www.gnu.org/licenses/gpl.html   *   *  Maintainer: - *  Andreas Herrmann <andreas.herrmann3@amd.com> + *  Andreas Herrmann <herrmann.der.user@googlemail.com>   *   *  Based on the powernow-k7.c module written by Dave Jones.   *  (C) 2003 Dave Jones on behalf of SuSE Labs diff --git a/drivers/gpio/gpio-74x164.c b/drivers/gpio/gpio-74x164.c index ed3e55161bd..f05e54258ff 100644 --- a/drivers/gpio/gpio-74x164.c +++ b/drivers/gpio/gpio-74x164.c @@ -153,7 +153,7 @@ static int __devinit gen_74x164_probe(struct spi_device *spi)  	}  	chip->gpio_chip.ngpio = GEN_74X164_NUMBER_GPIOS * chip->registers; -	chip->buffer = devm_kzalloc(&spi->dev, chip->gpio_chip.ngpio, GFP_KERNEL); +	chip->buffer = devm_kzalloc(&spi->dev, chip->registers, GFP_KERNEL);  	if (!chip->buffer) {  		ret = -ENOMEM;  		goto exit_destroy; diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7a874129e5d..cf7afb9eb61 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -244,6 +244,8 @@ static int mvebu_gpio_direction_output(struct gpio_chip *chip, unsigned pin,  	if (ret)  		return ret; +	mvebu_gpio_set(chip, pin, value); +  	spin_lock_irqsave(&mvchip->lock, flags);  	u = readl_relaxed(mvebu_gpioreg_io_conf(mvchip));  	u &= ~(1 << pin); @@ -644,7 +646,7 @@ static int __devinit mvebu_gpio_probe(struct platform_device *pdev)  	ct->handler = handle_edge_irq;  	ct->chip.name = mvchip->chip.label; -	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), IRQ_GC_INIT_MASK_CACHE, +	irq_setup_generic_chip(gc, IRQ_MSK(ngpios), 0,  			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE);  	/* Setup irq domain on top of the generic chip. */ diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 94cbc842fbc..d335af1d4d8 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -251,6 +251,40 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio,  	}  } +/** + * _clear_gpio_debounce - clear debounce settings for a gpio + * @bank: the gpio bank we're acting upon + * @gpio: the gpio number on this @gpio + * + * If a gpio is using debounce, then clear the debounce enable bit and if + * this is the only gpio in this bank using debounce, then clear the debounce + * time too. The debounce clock will also be disabled when calling this function + * if this is the only gpio in the bank using debounce. + */ +static void _clear_gpio_debounce(struct gpio_bank *bank, unsigned gpio) +{ +	u32 gpio_bit = GPIO_BIT(bank, gpio); + +	if (!bank->dbck_flag) +		return; + +	if (!(bank->dbck_enable_mask & gpio_bit)) +		return; + +	bank->dbck_enable_mask &= ~gpio_bit; +	bank->context.debounce_en &= ~gpio_bit; +	__raw_writel(bank->context.debounce_en, +		     bank->base + bank->regs->debounce_en); + +	if (!bank->dbck_enable_mask) { +		bank->context.debounce = 0; +		__raw_writel(bank->context.debounce, bank->base + +			     bank->regs->debounce); +		clk_disable(bank->dbck); +		bank->dbck_enabled = false; +	} +} +  static inline void set_gpio_trigger(struct gpio_bank *bank, int gpio,  						unsigned trigger)  { @@ -539,6 +573,7 @@ static void _reset_gpio(struct gpio_bank *bank, int gpio)  	_set_gpio_irqenable(bank, gpio, 0);  	_clear_gpio_irqstatus(bank, gpio);  	_set_gpio_triggering(bank, GPIO_INDEX(bank, gpio), IRQ_TYPE_NONE); +	_clear_gpio_debounce(bank, gpio);  }  /* Use disable_irq_wake() and enable_irq_wake() functions from drivers */ diff --git a/drivers/gpio/gpio-timberdale.c b/drivers/gpio/gpio-timberdale.c index 031c6adf5b6..1a3e2b9b477 100644 --- a/drivers/gpio/gpio-timberdale.c +++ b/drivers/gpio/gpio-timberdale.c @@ -116,7 +116,7 @@ static void timbgpio_irq_disable(struct irq_data *d)  	unsigned long flags;  	spin_lock_irqsave(&tgpio->lock, flags); -	tgpio->last_ier &= ~(1 << offset); +	tgpio->last_ier &= ~(1UL << offset);  	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);  	spin_unlock_irqrestore(&tgpio->lock, flags);  } @@ -128,7 +128,7 @@ static void timbgpio_irq_enable(struct irq_data *d)  	unsigned long flags;  	spin_lock_irqsave(&tgpio->lock, flags); -	tgpio->last_ier |= 1 << offset; +	tgpio->last_ier |= 1UL << offset;  	iowrite32(tgpio->last_ier, tgpio->membase + TGPIO_IER);  	spin_unlock_irqrestore(&tgpio->lock, flags);  } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5d6c71edc73..1c8d9e3380e 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -623,9 +623,11 @@ static ssize_t export_store(struct class *class,  	 */  	status = gpio_request(gpio, "sysfs"); -	if (status < 0) +	if (status < 0) { +		if (status == -EPROBE_DEFER) +			status = -ENODEV;  		goto done; - +	}  	status = gpio_export(gpio, true);  	if (status < 0)  		gpio_free(gpio); @@ -1191,8 +1193,10 @@ int gpio_request(unsigned gpio, const char *label)  	spin_lock_irqsave(&gpio_lock, flags); -	if (!gpio_is_valid(gpio)) +	if (!gpio_is_valid(gpio)) { +		status = -EINVAL;  		goto done; +	}  	desc = &gpio_desc[gpio];  	chip = desc->chip;  	if (chip == NULL) diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 59a26e577b5..fc345d4ebb0 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -1,6 +1,6 @@  config DRM_EXYNOS  	tristate "DRM Support for Samsung SoC EXYNOS Series" -	depends on DRM && PLAT_SAMSUNG +	depends on DRM && (PLAT_SAMSUNG || ARCH_MULTIPLATFORM)  	select DRM_KMS_HELPER  	select FB_CFB_FILLRECT  	select FB_CFB_COPYAREA diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index 18c271862ca..0f68a287267 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c @@ -374,6 +374,7 @@ struct drm_connector *exynos_drm_connector_create(struct drm_device *dev,  	exynos_connector->encoder_id = encoder->base.id;  	exynos_connector->manager = manager;  	exynos_connector->dpms = DRM_MODE_DPMS_OFF; +	connector->dpms = DRM_MODE_DPMS_OFF;  	connector->encoder = encoder;  	err = drm_mode_connector_attach_encoder(connector, encoder); diff --git a/drivers/gpu/drm/exynos/exynos_drm_encoder.c b/drivers/gpu/drm/exynos/exynos_drm_encoder.c index e51503fbaf2..241ad1eeec6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_encoder.c +++ b/drivers/gpu/drm/exynos/exynos_drm_encoder.c @@ -43,12 +43,14 @@   * @manager: specific encoder has its own manager to control a hardware   *	appropriately and we can access a hardware drawing on this manager.   * @dpms: store the encoder dpms value. + * @updated: indicate whether overlay data updating is needed or not.   */  struct exynos_drm_encoder {  	struct drm_crtc			*old_crtc;  	struct drm_encoder		drm_encoder;  	struct exynos_drm_manager	*manager; -	int dpms; +	int				dpms; +	bool				updated;  };  static void exynos_drm_connector_power(struct drm_encoder *encoder, int mode) @@ -85,7 +87,9 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)  	switch (mode) {  	case DRM_MODE_DPMS_ON:  		if (manager_ops && manager_ops->apply) -			manager_ops->apply(manager->dev); +			if (!exynos_encoder->updated) +				manager_ops->apply(manager->dev); +  		exynos_drm_connector_power(encoder, mode);  		exynos_encoder->dpms = mode;  		break; @@ -94,6 +98,7 @@ static void exynos_drm_encoder_dpms(struct drm_encoder *encoder, int mode)  	case DRM_MODE_DPMS_OFF:  		exynos_drm_connector_power(encoder, mode);  		exynos_encoder->dpms = mode; +		exynos_encoder->updated = false;  		break;  	default:  		DRM_ERROR("unspecified mode %d\n", mode); @@ -205,13 +210,22 @@ static void exynos_drm_encoder_prepare(struct drm_encoder *encoder)  static void exynos_drm_encoder_commit(struct drm_encoder *encoder)  { -	struct exynos_drm_manager *manager = exynos_drm_get_manager(encoder); +	struct exynos_drm_encoder *exynos_encoder = to_exynos_encoder(encoder); +	struct exynos_drm_manager *manager = exynos_encoder->manager;  	struct exynos_drm_manager_ops *manager_ops = manager->ops;  	DRM_DEBUG_KMS("%s\n", __FILE__);  	if (manager_ops && manager_ops->commit)  		manager_ops->commit(manager->dev); + +	/* +	 * this will avoid one issue that overlay data is updated to +	 * real hardware two times. +	 * And this variable will be used to check if the data was +	 * already updated or not by exynos_drm_encoder_dpms function. +	 */ +	exynos_encoder->updated = true;  }  static void exynos_drm_encoder_disable(struct drm_encoder *encoder) @@ -401,19 +415,6 @@ void exynos_drm_encoder_crtc_dpms(struct drm_encoder *encoder, void *data)  		manager_ops->dpms(manager->dev, mode);  	/* -	 * set current mode to new one so that data aren't updated into -	 * registers by drm_helper_connector_dpms two times. -	 * -	 * in case that drm_crtc_helper_set_mode() is called, -	 * overlay_ops->commit() and manager_ops->commit() callbacks -	 * can be called two times, first at drm_crtc_helper_set_mode() -	 * and second at drm_helper_connector_dpms(). -	 * so with this setting, when drm_helper_connector_dpms() is called -	 * encoder->funcs->dpms() will be ignored. -	 */ -	exynos_encoder->dpms = mode; - -	/*  	 * if this condition is ok then it means that the crtc is already  	 * detached from encoder and last function for detaching is properly  	 * done, so clear pipe from manager to prevent repeated call. diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 614b2e9ac46..e7fbb823fd8 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -1142,7 +1142,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)  		const struct of_device_id *match;  		match = of_match_node(of_match_ptr(mixer_match_types),  							  pdev->dev.of_node); -		drv = match->data; +		drv = (struct mixer_drv_data *)match->data;  	} else {  		drv = (struct mixer_drv_data *)  			platform_get_device_id(pdev)->driver_data; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index c9bfd83dde6..61ae104dca8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1505,7 +1505,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)  		goto put_gmch;  	} -	i915_kick_out_firmware_fb(dev_priv); +	if (drm_core_check_feature(dev, DRIVER_MODESET)) +		i915_kick_out_firmware_fb(dev_priv);  	pci_set_master(dev->pdev); diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index f78061af704..b726b478a4f 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -729,7 +729,7 @@ void intel_crt_init(struct drm_device *dev)  	crt->base.type = INTEL_OUTPUT_ANALOG;  	crt->base.cloneable = true; -	if (IS_HASWELL(dev)) +	if (IS_HASWELL(dev) || IS_I830(dev))  		crt->base.crtc_mask = (1 << 0);  	else  		crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2); diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index 495625914e4..d7bc817f51a 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -341,9 +341,17 @@ static int intel_overlay_off(struct intel_overlay *overlay)  	intel_ring_emit(ring, flip_addr);  	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);  	/* turn overlay off */ -	intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); -	intel_ring_emit(ring, flip_addr); -	intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	if (IS_I830(dev)) { +		/* Workaround: Don't disable the overlay fully, since otherwise +		 * it dies on the next OVERLAY_ON cmd. */ +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +		intel_ring_emit(ring, MI_NOOP); +	} else { +		intel_ring_emit(ring, MI_OVERLAY_FLIP | MI_OVERLAY_OFF); +		intel_ring_emit(ring, flip_addr); +		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP); +	}  	intel_ring_advance(ring);  	return intel_overlay_do_wait_request(overlay, intel_overlay_off_tail); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index e019b236986..e2aacd32954 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -435,7 +435,7 @@ int intel_panel_setup_backlight(struct drm_device *dev)  	props.type = BACKLIGHT_RAW;  	props.max_brightness = _intel_panel_get_max_backlight(dev);  	if (props.max_brightness == 0) { -		DRM_ERROR("Failed to get maximum backlight value\n"); +		DRM_DEBUG_DRIVER("Failed to get maximum backlight value\n");  		return -ENODEV;  	}  	dev_priv->backlight = diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index c01d97db006..79d308da29f 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -894,6 +894,45 @@ static void intel_sdvo_dump_hdmi_buf(struct intel_sdvo *intel_sdvo)  }  #endif +static bool intel_sdvo_write_infoframe(struct intel_sdvo *intel_sdvo, +				       unsigned if_index, uint8_t tx_rate, +				       uint8_t *data, unsigned length) +{ +	uint8_t set_buf_index[2] = { if_index, 0 }; +	uint8_t hbuf_size, tmp[8]; +	int i; + +	if (!intel_sdvo_set_value(intel_sdvo, +				  SDVO_CMD_SET_HBUF_INDEX, +				  set_buf_index, 2)) +		return false; + +	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HBUF_INFO, +				  &hbuf_size, 1)) +		return false; + +	/* Buffer size is 0 based, hooray! */ +	hbuf_size++; + +	DRM_DEBUG_KMS("writing sdvo hbuf: %i, hbuf_size %i, hbuf_size: %i\n", +		      if_index, length, hbuf_size); + +	for (i = 0; i < hbuf_size; i += 8) { +		memset(tmp, 0, 8); +		if (i < length) +			memcpy(tmp, data + i, min_t(unsigned, 8, length - i)); + +		if (!intel_sdvo_set_value(intel_sdvo, +					  SDVO_CMD_SET_HBUF_DATA, +					  tmp, 8)) +			return false; +	} + +	return intel_sdvo_set_value(intel_sdvo, +				    SDVO_CMD_SET_HBUF_TXRATE, +				    &tx_rate, 1); +} +  static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  {  	struct dip_infoframe avi_if = { @@ -901,11 +940,7 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  		.ver = DIP_VERSION_AVI,  		.len = DIP_LEN_AVI,  	}; -	uint8_t tx_rate = SDVO_HBUF_TX_VSYNC; -	uint8_t set_buf_index[2] = { 1, 0 };  	uint8_t sdvo_data[4 + sizeof(avi_if.body.avi)]; -	uint64_t *data = (uint64_t *)sdvo_data; -	unsigned i;  	intel_dip_infoframe_csum(&avi_if); @@ -915,22 +950,9 @@ static bool intel_sdvo_set_avi_infoframe(struct intel_sdvo *intel_sdvo)  	sdvo_data[3] = avi_if.checksum;  	memcpy(&sdvo_data[4], &avi_if.body, sizeof(avi_if.body.avi)); -	if (!intel_sdvo_set_value(intel_sdvo, -				  SDVO_CMD_SET_HBUF_INDEX, -				  set_buf_index, 2)) -		return false; - -	for (i = 0; i < sizeof(sdvo_data); i += 8) { -		if (!intel_sdvo_set_value(intel_sdvo, -					  SDVO_CMD_SET_HBUF_DATA, -					  data, 8)) -			return false; -		data++; -	} - -	return intel_sdvo_set_value(intel_sdvo, -				    SDVO_CMD_SET_HBUF_TXRATE, -				    &tx_rate, 1); +	return intel_sdvo_write_infoframe(intel_sdvo, SDVO_HBUF_INDEX_AVI_IF, +					  SDVO_HBUF_TX_VSYNC, +					  sdvo_data, sizeof(sdvo_data));  }  static bool intel_sdvo_set_tv_format(struct intel_sdvo *intel_sdvo) diff --git a/drivers/gpu/drm/i915/intel_sdvo_regs.h b/drivers/gpu/drm/i915/intel_sdvo_regs.h index 9d030142ee4..770bdd6ecd9 100644 --- a/drivers/gpu/drm/i915/intel_sdvo_regs.h +++ b/drivers/gpu/drm/i915/intel_sdvo_regs.h @@ -708,6 +708,8 @@ struct intel_sdvo_enhancements_arg {  #define SDVO_CMD_SET_AUDIO_STAT		0x91  #define SDVO_CMD_GET_AUDIO_STAT		0x92  #define SDVO_CMD_SET_HBUF_INDEX		0x93 +  #define SDVO_HBUF_INDEX_ELD		0 +  #define SDVO_HBUF_INDEX_AVI_IF	1  #define SDVO_CMD_GET_HBUF_INDEX		0x94  #define SDVO_CMD_GET_HBUF_INFO		0x95  #define SDVO_CMD_SET_HBUF_AV_SPLIT	0x96 diff --git a/drivers/gpu/drm/nouveau/core/core/mm.c b/drivers/gpu/drm/nouveau/core/core/mm.c index 4d620644867..a6d3cd6490f 100644 --- a/drivers/gpu/drm/nouveau/core/core/mm.c +++ b/drivers/gpu/drm/nouveau/core/core/mm.c @@ -218,13 +218,16 @@ nouveau_mm_init(struct nouveau_mm *mm, u32 offset, u32 length, u32 block)  	node = kzalloc(sizeof(*node), GFP_KERNEL);  	if (!node)  		return -ENOMEM; -	node->offset = roundup(offset, mm->block_size); -	node->length = rounddown(offset + length, mm->block_size) - node->offset; + +	if (length) { +		node->offset  = roundup(offset, mm->block_size); +		node->length  = rounddown(offset + length, mm->block_size); +		node->length -= node->offset; +	}  	list_add_tail(&node->nl_entry, &mm->nodes);  	list_add_tail(&node->fl_entry, &mm->free);  	mm->heap_nodes++; -	mm->heap_size += length;  	return 0;  } diff --git a/drivers/gpu/drm/nouveau/core/include/core/mm.h b/drivers/gpu/drm/nouveau/core/include/core/mm.h index 9ee9bf4028c..975137ba34a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/mm.h +++ b/drivers/gpu/drm/nouveau/core/include/core/mm.h @@ -19,7 +19,6 @@ struct nouveau_mm {  	u32 block_size;  	int heap_nodes; -	u32 heap_size;  };  int  nouveau_mm_init(struct nouveau_mm *, u32 offset, u32 length, u32 block); diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 27fb1af7a77..5f570806143 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c @@ -219,13 +219,11 @@ nv50_fb_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  			     ((priv->base.ram.size & 0x000000ff) << 32);  	tags = nv_rd32(priv, 0x100320); -	if (tags) { -		ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); -		if (ret) -			return ret; +	ret = nouveau_mm_init(&priv->base.tags, 0, tags, 1); +	if (ret) +		return ret; -		nv_debug(priv, "%d compression tags\n", tags); -	} +	nv_debug(priv, "%d compression tags\n", tags);  	size = (priv->base.ram.size >> 12) - rsvd_head - rsvd_tail;  	switch (device->chipset) { diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 3d2c88310f9..dbfc2abf0cf 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c @@ -292,7 +292,7 @@ nouveau_i2c_ctor(struct nouveau_object *parent, struct nouveau_object *engine,  		case DCB_I2C_NVIO_BIT:  			port->drive = info.drive & 0x0f;  			if (device->card_type < NV_D0) { -				if (info.drive >= ARRAY_SIZE(nv50_i2c_port)) +				if (port->drive >= ARRAY_SIZE(nv50_i2c_port))  					break;  				port->drive = nv50_i2c_port[port->drive];  				port->sense = port->drive; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index d2f8ffeed74..86124b131f4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -290,6 +290,7 @@ nouveau_display_create(struct drm_device *dev)  	struct nouveau_drm *drm = nouveau_drm(dev);  	struct nouveau_disp *pdisp = nouveau_disp(drm->device);  	struct nouveau_display *disp; +	u32 pclass = dev->pdev->class >> 8;  	int ret, gen;  	disp = drm->display = kzalloc(sizeof(*disp), GFP_KERNEL); @@ -360,23 +361,27 @@ nouveau_display_create(struct drm_device *dev)  	drm_kms_helper_poll_init(dev);  	drm_kms_helper_poll_disable(dev); -	if (nv_device(drm->device)->card_type < NV_50) -		ret = nv04_display_create(dev); -	else -	if (nv_device(drm->device)->card_type < NV_D0) -		ret = nv50_display_create(dev); -	else -		ret = nvd0_display_create(dev); -	if (ret) -		goto disp_create_err; - -	if (dev->mode_config.num_crtc) { -		ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +	if (nouveau_modeset == 1 || +	    (nouveau_modeset < 0 && pclass == PCI_CLASS_DISPLAY_VGA)) { +		if (nv_device(drm->device)->card_type < NV_50) +			ret = nv04_display_create(dev); +		else +		if (nv_device(drm->device)->card_type < NV_D0) +			ret = nv50_display_create(dev); +		else +			ret = nvd0_display_create(dev);  		if (ret) -			goto vblank_err; +			goto disp_create_err; + +		if (dev->mode_config.num_crtc) { +			ret = drm_vblank_init(dev, dev->mode_config.num_crtc); +			if (ret) +				goto vblank_err; +		} + +		nouveau_backlight_init(dev);  	} -	nouveau_backlight_init(dev);  	return 0;  vblank_err: @@ -395,7 +400,8 @@ nouveau_display_destroy(struct drm_device *dev)  	nouveau_backlight_exit(dev);  	drm_vblank_cleanup(dev); -	disp->dtor(dev); +	if (disp->dtor) +		disp->dtor(dev);  	drm_kms_helper_poll_fini(dev);  	drm_mode_config_cleanup(dev); diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index ccae8c26ae2..0910125cbbc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -63,8 +63,9 @@ MODULE_PARM_DESC(noaccel, "disable kernel/abi16 acceleration");  static int nouveau_noaccel = 0;  module_param_named(noaccel, nouveau_noaccel, int, 0400); -MODULE_PARM_DESC(modeset, "enable driver"); -static int nouveau_modeset = -1; +MODULE_PARM_DESC(modeset, "enable driver (default: auto, " +		          "0 = disabled, 1 = enabled, 2 = headless)"); +int nouveau_modeset = -1;  module_param_named(modeset, nouveau_modeset, int, 0400);  static struct drm_driver driver; @@ -363,7 +364,8 @@ nouveau_drm_unload(struct drm_device *dev)  	nouveau_pm_fini(dev); -	nouveau_display_fini(dev); +	if (dev->mode_config.num_crtc) +		nouveau_display_fini(dev);  	nouveau_display_destroy(dev);  	nouveau_irq_fini(dev); @@ -403,13 +405,15 @@ nouveau_drm_suspend(struct pci_dev *pdev, pm_message_t pm_state)  	    pm_state.event == PM_EVENT_PRETHAW)  		return 0; -	NV_INFO(drm, "suspending fbcon...\n"); -	nouveau_fbcon_set_suspend(dev, 1); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "suspending fbcon...\n"); +		nouveau_fbcon_set_suspend(dev, 1); -	NV_INFO(drm, "suspending display...\n"); -	ret = nouveau_display_suspend(dev); -	if (ret) -		return ret; +		NV_INFO(drm, "suspending display...\n"); +		ret = nouveau_display_suspend(dev); +		if (ret) +			return ret; +	}  	NV_INFO(drm, "evicting buffers...\n");  	ttm_bo_evict_mm(&drm->ttm.bdev, TTM_PL_VRAM); @@ -445,8 +449,10 @@ fail_client:  		nouveau_client_init(&cli->base);  	} -	NV_INFO(drm, "resuming display...\n"); -	nouveau_display_resume(dev); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "resuming display...\n"); +		nouveau_display_resume(dev); +	}  	return ret;  } @@ -486,8 +492,10 @@ nouveau_drm_resume(struct pci_dev *pdev)  	nouveau_irq_postinstall(dev);  	nouveau_pm_resume(dev); -	NV_INFO(drm, "resuming display...\n"); -	nouveau_display_resume(dev); +	if (dev->mode_config.num_crtc) { +		NV_INFO(drm, "resuming display...\n"); +		nouveau_display_resume(dev); +	}  	return 0;  } @@ -662,9 +670,7 @@ nouveau_drm_init(void)  #ifdef CONFIG_VGA_CONSOLE  		if (vgacon_text_force())  			nouveau_modeset = 0; -		else  #endif -			nouveau_modeset = 1;  	}  	if (!nouveau_modeset) diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.h b/drivers/gpu/drm/nouveau/nouveau_drm.h index 81947121754..a1016992708 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.h +++ b/drivers/gpu/drm/nouveau/nouveau_drm.h @@ -141,4 +141,6 @@ int nouveau_drm_resume(struct pci_dev *);  		nv_info((cli), fmt, ##args);                                   \  } while (0) +extern int nouveau_modeset; +  #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 9ca8afdb554..1d8cb506a28 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c @@ -61,13 +61,15 @@ nouveau_irq_handler(DRM_IRQ_ARGS)  	nv_subdev(pmc)->intr(nv_subdev(pmc)); -	if (device->card_type >= NV_D0) { -		if (nv_rd32(device, 0x000100) & 0x04000000) -			nvd0_display_intr(dev); -	} else -	if (device->card_type >= NV_50) { -		if (nv_rd32(device, 0x000100) & 0x04000000) -			nv50_display_intr(dev); +	if (dev->mode_config.num_crtc) { +		if (device->card_type >= NV_D0) { +			if (nv_rd32(device, 0x000100) & 0x04000000) +				nvd0_display_intr(dev); +		} else +		if (device->card_type >= NV_50) { +			if (nv_rd32(device, 0x000100) & 0x04000000) +				nv50_display_intr(dev); +		}  	}  	return IRQ_HANDLED; diff --git a/drivers/gpu/drm/nouveau/nv04_dac.c b/drivers/gpu/drm/nouveau/nv04_dac.c index 347a3bd78d0..64f7020fb60 100644 --- a/drivers/gpu/drm/nouveau/nv04_dac.c +++ b/drivers/gpu/drm/nouveau/nv04_dac.c @@ -220,7 +220,7 @@ out:  	NVWriteVgaCrtc(dev, 0, NV_CIO_CR_MODE_INDEX, saved_cr_mode);  	if (blue == 0x18) { -		NV_INFO(drm, "Load detected on head A\n"); +		NV_DEBUG(drm, "Load detected on head A\n");  		return connector_status_connected;  	} @@ -338,8 +338,8 @@ nv17_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector)  	if (nv17_dac_sample_load(encoder) &  	    NV_PRAMDAC_TEST_CONTROL_SENSEB_ALLHI) { -		NV_INFO(drm, "Load detected on output %c\n", -			'@' + ffs(dcb->or)); +		NV_DEBUG(drm, "Load detected on output %c\n", +			 '@' + ffs(dcb->or));  		return connector_status_connected;  	} else {  		return connector_status_disconnected; @@ -413,9 +413,9 @@ static void nv04_dac_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), -		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  void nv04_dac_update_dacclk(struct drm_encoder *encoder, bool enable) @@ -461,8 +461,8 @@ static void nv04_dac_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on vga encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on vga encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	nv04_dac_update_dacclk(encoder, mode == DRM_MODE_DPMS_ON);  } diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index da55d7642c8..184cdf80676 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c @@ -476,9 +476,9 @@ static void nv04_dfp_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), -		nv_crtc->index, '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), +		 nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) @@ -520,8 +520,8 @@ static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on lvds encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	if (was_powersaving && is_powersaving_dpms(mode))  		return; @@ -565,8 +565,8 @@ static void nv04_tmds_dpms(struct drm_encoder *encoder, int mode)  		return;  	nv_encoder->last_dpms = mode; -	NV_INFO(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", -		     mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on tmds encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	nv04_dfp_update_backlight(encoder, mode);  	nv04_dfp_update_fp_control(encoder, mode); diff --git a/drivers/gpu/drm/nouveau/nv04_tv.c b/drivers/gpu/drm/nouveau/nv04_tv.c index 099fbeda6e2..62e826a139b 100644 --- a/drivers/gpu/drm/nouveau/nv04_tv.c +++ b/drivers/gpu/drm/nouveau/nv04_tv.c @@ -75,8 +75,8 @@ static void nv04_tv_dpms(struct drm_encoder *encoder, int mode)  	struct nv04_mode_state *state = &nv04_display(dev)->mode_reg;  	uint8_t crtc1A; -	NV_INFO(drm, "Setting dpms mode %d on TV encoder (output %d)\n", -		mode, nv_encoder->dcb->index); +	NV_DEBUG(drm, "Setting dpms mode %d on TV encoder (output %d)\n", +		 mode, nv_encoder->dcb->index);  	state->pllsel &= ~(PLLSEL_TV_CRTC1_MASK | PLLSEL_TV_CRTC2_MASK); @@ -167,9 +167,8 @@ static void nv04_tv_commit(struct drm_encoder *encoder)  	helper->dpms(encoder, DRM_MODE_DPMS_ON); -	NV_INFO(drm, "Output %s is running on CRTC %d using output %c\n", -		      drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, -		      '@' + ffs(nv_encoder->dcb->or)); +	NV_DEBUG(drm, "Output %s is running on CRTC %d using output %c\n", +		 drm_get_connector_name(&nouveau_encoder_connector_get(nv_encoder)->base), nv_crtc->index, '@' + ffs(nv_encoder->dcb->or));  }  static void nv04_tv_destroy(struct drm_encoder *encoder) diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 30271b64191..95e6318b626 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c @@ -264,7 +264,7 @@ static int evergreen_surface_check_2d(struct radeon_cs_parser *p,  	/* macro tile width & height */  	palign = (8 * surf->bankw * track->npipes) * surf->mtilea;  	halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; -	mtileb = (palign / 8) * (halign / 8) * tileb;; +	mtileb = (palign / 8) * (halign / 8) * tileb;  	mtile_pr = surf->nbx / palign;  	mtile_ps = (mtile_pr * surf->nby) / halign;  	surf->layer_size = mtile_ps * mtileb * slice_pt; diff --git a/drivers/gpu/drm/radeon/radeon_atpx_handler.c b/drivers/gpu/drm/radeon/radeon_atpx_handler.c index 37f6a907aea..15f5ded65e0 100644 --- a/drivers/gpu/drm/radeon/radeon_atpx_handler.c +++ b/drivers/gpu/drm/radeon/radeon_atpx_handler.c @@ -352,9 +352,9 @@ static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)  }  /** - * radeon_atpx_switchto - switch to the requested GPU + * radeon_atpx_power_state - power down/up the requested GPU   * - * @id: GPU to switch to + * @id: GPU to power down/up   * @state: requested power state (0 = off, 1 = on)   *   * Execute the necessary ATPX function to power down/up the discrete GPU diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 67cfc1795ec..b884c362a8c 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -941,7 +941,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  	struct drm_mode_object *obj;  	int i;  	enum drm_connector_status ret = connector_status_disconnected; -	bool dret = false; +	bool dret = false, broken_edid = false;  	if (!force && radeon_check_hpd_status_unchanged(connector))  		return connector->status; @@ -965,6 +965,9 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  				ret = connector_status_disconnected;  				DRM_ERROR("%s: detected RS690 floating bus bug, stopping ddc detect\n", drm_get_connector_name(connector));  				radeon_connector->ddc_bus = NULL; +			} else { +				ret = connector_status_connected; +				broken_edid = true; /* defer use_digital to later */  			}  		} else {  			radeon_connector->use_digital = !!(radeon_connector->edid->input & DRM_EDID_INPUT_DIGITAL); @@ -1047,13 +1050,24 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)  			encoder_funcs = encoder->helper_private;  			if (encoder_funcs->detect) { -				if (ret != connector_status_connected) { -					ret = encoder_funcs->detect(encoder, connector); -					if (ret == connector_status_connected) { -						radeon_connector->use_digital = false; +				if (!broken_edid) { +					if (ret != connector_status_connected) { +						/* deal with analog monitors without DDC */ +						ret = encoder_funcs->detect(encoder, connector); +						if (ret == connector_status_connected) { +							radeon_connector->use_digital = false; +						} +						if (ret != connector_status_disconnected) +							radeon_connector->detected_by_load = true;  					} -					if (ret != connector_status_disconnected) -						radeon_connector->detected_by_load = true; +				} else { +					enum drm_connector_status lret; +					/* assume digital unless load detected otherwise */ +					radeon_connector->use_digital = true; +					lret = encoder_funcs->detect(encoder, connector); +					DRM_DEBUG_KMS("load_detect %x returned: %x\n",encoder->encoder_type,lret); +					if (lret == connector_status_connected) +						radeon_connector->use_digital = false;  				}  				break;  			} diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index 5677a424b58..6857cb4efb7 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c @@ -295,6 +295,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);  	struct drm_device *dev = crtc->dev;  	struct radeon_device *rdev = dev->dev_private; +	uint32_t crtc_ext_cntl = 0;  	uint32_t mask;  	if (radeon_crtc->crtc_id) @@ -307,6 +308,16 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  			RADEON_CRTC_VSYNC_DIS |  			RADEON_CRTC_HSYNC_DIS); +	/* +	 * On all dual CRTC GPUs this bit controls the CRTC of the primary DAC. +	 * Therefore it is set in the DAC DMPS function. +	 * This is different for GPU's with a single CRTC but a primary and a +	 * TV DAC: here it controls the single CRTC no matter where it is +	 * routed. Therefore we set it here. +	 */ +	if (rdev->flags & RADEON_SINGLE_CRTC) +		crtc_ext_cntl = RADEON_CRTC_CRT_ON; +	  	switch (mode) {  	case DRM_MODE_DPMS_ON:  		radeon_crtc->enabled = true; @@ -317,7 +328,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  		else {  			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |  									 RADEON_CRTC_DISP_REQ_EN_B)); -			WREG32_P(RADEON_CRTC_EXT_CNTL, 0, ~mask); +			WREG32_P(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl, ~(mask | crtc_ext_cntl));  		}  		drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);  		radeon_crtc_load_lut(crtc); @@ -331,7 +342,7 @@ static void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)  		else {  			WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |  										    RADEON_CRTC_DISP_REQ_EN_B)); -			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~mask); +			WREG32_P(RADEON_CRTC_EXT_CNTL, mask, ~(mask | crtc_ext_cntl));  		}  		radeon_crtc->enabled = false;  		/* adjust pm to dpms changes AFTER disabling crtcs */ diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index 0063df9d166..f5ba2241dac 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c @@ -537,7 +537,9 @@ static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode  		break;  	} -	WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl); +	/* handled in radeon_crtc_dpms() */ +	if (!(rdev->flags & RADEON_SINGLE_CRTC)) +		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);  	WREG32(RADEON_DAC_CNTL, dac_cntl);  	WREG32(RADEON_DAC_MACRO_CNTL, dac_macro_cntl); @@ -662,6 +664,8 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc  	if (ASIC_IS_R300(rdev))  		tmp |= (0x1b6 << RADEON_DAC_FORCE_DATA_SHIFT); +	else if (ASIC_IS_RV100(rdev)) +		tmp |= (0x1ac << RADEON_DAC_FORCE_DATA_SHIFT);  	else  		tmp |= (0x180 << RADEON_DAC_FORCE_DATA_SHIFT); @@ -671,6 +675,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc  	tmp |= RADEON_DAC_RANGE_CNTL_PS2 | RADEON_DAC_CMP_EN;  	WREG32(RADEON_DAC_CNTL, tmp); +	tmp = dac_macro_cntl;  	tmp &= ~(RADEON_DAC_PDWN_R |  		 RADEON_DAC_PDWN_G |  		 RADEON_DAC_PDWN_B); @@ -1092,7 +1097,8 @@ static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)  	} else {  		if (is_tv)  			WREG32(RADEON_TV_MASTER_CNTL, tv_master_cntl); -		else +		/* handled in radeon_crtc_dpms() */ +		else if (!(rdev->flags & RADEON_SINGLE_CRTC))  			WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl);  		WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl);  	} @@ -1416,13 +1422,104 @@ static bool radeon_legacy_tv_detect(struct drm_encoder *encoder,  	return found;  } +static bool radeon_legacy_ext_dac_detect(struct drm_encoder *encoder, +					 struct drm_connector *connector) +{ +	struct drm_device *dev = encoder->dev; +	struct radeon_device *rdev = dev->dev_private; +	uint32_t gpio_monid, fp2_gen_cntl, disp_output_cntl, crtc2_gen_cntl; +	uint32_t disp_lin_trans_grph_a, disp_lin_trans_grph_b, disp_lin_trans_grph_c; +	uint32_t disp_lin_trans_grph_d, disp_lin_trans_grph_e, disp_lin_trans_grph_f; +	uint32_t tmp, crtc2_h_total_disp, crtc2_v_total_disp; +	uint32_t crtc2_h_sync_strt_wid, crtc2_v_sync_strt_wid; +	bool found = false; +	int i; + +	/* save the regs we need */ +	gpio_monid = RREG32(RADEON_GPIO_MONID); +	fp2_gen_cntl = RREG32(RADEON_FP2_GEN_CNTL); +	disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); +	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); +	disp_lin_trans_grph_a = RREG32(RADEON_DISP_LIN_TRANS_GRPH_A); +	disp_lin_trans_grph_b = RREG32(RADEON_DISP_LIN_TRANS_GRPH_B); +	disp_lin_trans_grph_c = RREG32(RADEON_DISP_LIN_TRANS_GRPH_C); +	disp_lin_trans_grph_d = RREG32(RADEON_DISP_LIN_TRANS_GRPH_D); +	disp_lin_trans_grph_e = RREG32(RADEON_DISP_LIN_TRANS_GRPH_E); +	disp_lin_trans_grph_f = RREG32(RADEON_DISP_LIN_TRANS_GRPH_F); +	crtc2_h_total_disp = RREG32(RADEON_CRTC2_H_TOTAL_DISP); +	crtc2_v_total_disp = RREG32(RADEON_CRTC2_V_TOTAL_DISP); +	crtc2_h_sync_strt_wid = RREG32(RADEON_CRTC2_H_SYNC_STRT_WID); +	crtc2_v_sync_strt_wid = RREG32(RADEON_CRTC2_V_SYNC_STRT_WID); + +	tmp = RREG32(RADEON_GPIO_MONID); +	tmp &= ~RADEON_GPIO_A_0; +	WREG32(RADEON_GPIO_MONID, tmp); + +	WREG32(RADEON_FP2_GEN_CNTL, (RADEON_FP2_ON | +				     RADEON_FP2_PANEL_FORMAT | +				     R200_FP2_SOURCE_SEL_TRANS_UNIT | +				     RADEON_FP2_DVO_EN | +				     R200_FP2_DVO_RATE_SEL_SDR)); + +	WREG32(RADEON_DISP_OUTPUT_CNTL, (RADEON_DISP_DAC_SOURCE_RMX | +					 RADEON_DISP_TRANS_MATRIX_GRAPHICS)); + +	WREG32(RADEON_CRTC2_GEN_CNTL, (RADEON_CRTC2_EN | +				       RADEON_CRTC2_DISP_REQ_EN_B)); + +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, 0x000003f0); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, 0x000003f0); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, 0x00000000); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, 0x000003f0); + +	WREG32(RADEON_CRTC2_H_TOTAL_DISP, 0x01000008); +	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, 0x00000800); +	WREG32(RADEON_CRTC2_V_TOTAL_DISP, 0x00080001); +	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, 0x00000080); + +	for (i = 0; i < 200; i++) { +		tmp = RREG32(RADEON_GPIO_MONID); +		if (tmp & RADEON_GPIO_Y_0) +			found = true; + +		if (found) +			break; + +		if (!drm_can_sleep()) +			mdelay(1); +		else +			msleep(1); +	} + +	/* restore the regs we used */ +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_A, disp_lin_trans_grph_a); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_B, disp_lin_trans_grph_b); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_C, disp_lin_trans_grph_c); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_D, disp_lin_trans_grph_d); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_E, disp_lin_trans_grph_e); +	WREG32(RADEON_DISP_LIN_TRANS_GRPH_F, disp_lin_trans_grph_f); +	WREG32(RADEON_CRTC2_H_TOTAL_DISP, crtc2_h_total_disp); +	WREG32(RADEON_CRTC2_V_TOTAL_DISP, crtc2_v_total_disp); +	WREG32(RADEON_CRTC2_H_SYNC_STRT_WID, crtc2_h_sync_strt_wid); +	WREG32(RADEON_CRTC2_V_SYNC_STRT_WID, crtc2_v_sync_strt_wid); +	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); +	WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); +	WREG32(RADEON_FP2_GEN_CNTL, fp2_gen_cntl); +	WREG32(RADEON_GPIO_MONID, gpio_monid); + +	return found; +} +  static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder *encoder,  							     struct drm_connector *connector)  {  	struct drm_device *dev = encoder->dev;  	struct radeon_device *rdev = dev->dev_private; -	uint32_t crtc2_gen_cntl, tv_dac_cntl, dac_cntl2, dac_ext_cntl; -	uint32_t disp_hw_debug, disp_output_cntl, gpiopad_a, pixclks_cntl, tmp; +	uint32_t crtc2_gen_cntl = 0, tv_dac_cntl, dac_cntl2, dac_ext_cntl; +	uint32_t gpiopad_a = 0, pixclks_cntl, tmp; +	uint32_t disp_output_cntl = 0, disp_hw_debug = 0, crtc_ext_cntl = 0;  	enum drm_connector_status found = connector_status_disconnected;  	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);  	struct radeon_encoder_tv_dac *tv_dac = radeon_encoder->enc_priv; @@ -1459,12 +1556,27 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  		return connector_status_disconnected;  	} +	/* R200 uses an external DAC for secondary DAC */ +	if (rdev->family == CHIP_R200) { +		if (radeon_legacy_ext_dac_detect(encoder, connector)) +			found = connector_status_connected; +		return found; +	} +  	/* save the regs we need */  	pixclks_cntl = RREG32_PLL(RADEON_PIXCLKS_CNTL); -	gpiopad_a = ASIC_IS_R300(rdev) ? RREG32(RADEON_GPIOPAD_A) : 0; -	disp_output_cntl = ASIC_IS_R300(rdev) ? RREG32(RADEON_DISP_OUTPUT_CNTL) : 0; -	disp_hw_debug = ASIC_IS_R300(rdev) ? 0 : RREG32(RADEON_DISP_HW_DEBUG); -	crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); + +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); +	} else { +		if (ASIC_IS_R300(rdev)) { +			gpiopad_a = RREG32(RADEON_GPIOPAD_A); +			disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL); +		} else { +			disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); +		} +		crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL); +	}  	tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);  	dac_ext_cntl = RREG32(RADEON_DAC_EXT_CNTL);  	dac_cntl2 = RREG32(RADEON_DAC_CNTL2); @@ -1473,22 +1585,24 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  			       | RADEON_PIX2CLK_DAC_ALWAYS_ONb);  	WREG32_PLL(RADEON_PIXCLKS_CNTL, tmp); -	if (ASIC_IS_R300(rdev)) -		WREG32_P(RADEON_GPIOPAD_A, 1, ~1); - -	tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; -	tmp |= RADEON_CRTC2_CRT2_ON | -		(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); - -	WREG32(RADEON_CRTC2_GEN_CNTL, tmp); - -	if (ASIC_IS_R300(rdev)) { -		tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; -		tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; -		WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		tmp = crtc_ext_cntl | RADEON_CRTC_CRT_ON; +		WREG32(RADEON_CRTC_EXT_CNTL, tmp);  	} else { -		tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; -		WREG32(RADEON_DISP_HW_DEBUG, tmp); +		tmp = crtc2_gen_cntl & ~RADEON_CRTC2_PIX_WIDTH_MASK; +		tmp |= RADEON_CRTC2_CRT2_ON | +			(2 << RADEON_CRTC2_PIX_WIDTH_SHIFT); +		WREG32(RADEON_CRTC2_GEN_CNTL, tmp); + +		if (ASIC_IS_R300(rdev)) { +			WREG32_P(RADEON_GPIOPAD_A, 1, ~1); +			tmp = disp_output_cntl & ~RADEON_DISP_TVDAC_SOURCE_MASK; +			tmp |= RADEON_DISP_TVDAC_SOURCE_CRTC2; +			WREG32(RADEON_DISP_OUTPUT_CNTL, tmp); +		} else { +			tmp = disp_hw_debug & ~RADEON_CRT2_DISP1_SEL; +			WREG32(RADEON_DISP_HW_DEBUG, tmp); +		}  	}  	tmp = RADEON_TV_DAC_NBLANK | @@ -1530,14 +1644,19 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder  	WREG32(RADEON_DAC_CNTL2, dac_cntl2);  	WREG32(RADEON_DAC_EXT_CNTL, dac_ext_cntl);  	WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); -	WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); -	if (ASIC_IS_R300(rdev)) { -		WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); -		WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); +	if (rdev->flags & RADEON_SINGLE_CRTC) { +		WREG32(RADEON_CRTC_EXT_CNTL, crtc_ext_cntl);  	} else { -		WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +		WREG32(RADEON_CRTC2_GEN_CNTL, crtc2_gen_cntl); +		if (ASIC_IS_R300(rdev)) { +			WREG32(RADEON_DISP_OUTPUT_CNTL, disp_output_cntl); +			WREG32_P(RADEON_GPIOPAD_A, gpiopad_a, ~1); +		} else { +			WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); +		}  	} +  	WREG32_PLL(RADEON_PIXCLKS_CNTL, pixclks_cntl);  	return found; diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index fccd361f7b5..87aa5f5d3c8 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -104,7 +104,7 @@ udl_fb_user_fb_create(struct drm_device *dev,  int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  		     const char *front, char **urb_buf_ptr, -		     u32 byte_offset, u32 byte_width, +		     u32 byte_offset, u32 device_byte_offset, u32 byte_width,  		     int *ident_ptr, int *sent_ptr);  int udl_dumb_create(struct drm_file *file_priv, diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 69a2b16f42a..d4ab3beaada 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -114,9 +114,10 @@ static void udlfb_dpy_deferred_io(struct fb_info *info,  	list_for_each_entry(cur, &fbdefio->pagelist, lru) {  		if (udl_render_hline(dev, (ufbdev->ufb.base.bits_per_pixel / 8), -				  &urb, (char *) info->fix.smem_start, -				  &cmd, cur->index << PAGE_SHIFT, -				  PAGE_SIZE, &bytes_identical, &bytes_sent)) +				     &urb, (char *) info->fix.smem_start, +				     &cmd, cur->index << PAGE_SHIFT, +				     cur->index << PAGE_SHIFT, +				     PAGE_SIZE, &bytes_identical, &bytes_sent))  			goto error;  		bytes_rendered += PAGE_SIZE;  	} @@ -187,10 +188,11 @@ int udl_handle_damage(struct udl_framebuffer *fb, int x, int y,  	for (i = y; i < y + height ; i++) {  		const int line_offset = fb->base.pitches[0] * i;  		const int byte_offset = line_offset + (x * bpp); - +		const int dev_byte_offset = (fb->base.width * bpp * i) + (x * bpp);  		if (udl_render_hline(dev, bpp, &urb,  				     (char *) fb->obj->vmapping, -				     &cmd, byte_offset, width * bpp, +				     &cmd, byte_offset, dev_byte_offset, +				     width * bpp,  				     &bytes_identical, &bytes_sent))  			goto error;  	} diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index dc095526ffb..142fee5f983 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -213,11 +213,12 @@ static void udl_compress_hline16(   */  int udl_render_hline(struct drm_device *dev, int bpp, struct urb **urb_ptr,  		     const char *front, char **urb_buf_ptr, -		     u32 byte_offset, u32 byte_width, +		     u32 byte_offset, u32 device_byte_offset, +		     u32 byte_width,  		     int *ident_ptr, int *sent_ptr)  {  	const u8 *line_start, *line_end, *next_pixel; -	u32 base16 = 0 + (byte_offset / bpp) * 2; +	u32 base16 = 0 + (device_byte_offset / bpp) * 2;  	struct urb *urb = *urb_ptr;  	u8 *cmd = *urb_buf_ptr;  	u8 *cmd_end = (u8 *) urb->transfer_buffer + urb->transfer_buffer_length; diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index 06ebdbb6ea0..fd7722aecf7 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -522,6 +522,12 @@ static const struct hid_device_id apple_devices[] = {  		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS),  		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), +		.driver_data = APPLE_HAS_FN }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), +		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS), +		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),  		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO), diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index bd3971bf31b..f4109fd657f 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1532,6 +1532,9 @@ static const struct hid_device_id hid_have_special_driver[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) }, @@ -2139,6 +2142,9 @@ static const struct hid_device_id hid_mouse_ignore_list[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_ISO) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7_JIS) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO) }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },  	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },  	{ } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 269b50912a4..9d7a42857ea 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -118,6 +118,9 @@  #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ANSI	0x0252  #define USB_DEVICE_ID_APPLE_WELLSPRING5A_ISO	0x0253  #define USB_DEVICE_ID_APPLE_WELLSPRING5A_JIS	0x0254 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI	0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO	0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS	0x025b  #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ANSI	0x0249  #define USB_DEVICE_ID_APPLE_WELLSPRING6A_ISO	0x024a  #define USB_DEVICE_ID_APPLE_WELLSPRING6A_JIS	0x024b diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 3acdcfcc17d..f676c01bb47 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -28,22 +28,30 @@  #define MS_RDESC		0x08  #define MS_NOGET		0x10  #define MS_DUPLICATE_USAGES	0x20 +#define MS_RDESC_3K		0x40 -/* - * Microsoft Wireless Desktop Receiver (Model 1028) has - * 'Usage Min/Max' where it ought to have 'Physical Min/Max' - */  static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc,  		unsigned int *rsize)  {  	unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); +	/* +	 * Microsoft Wireless Desktop Receiver (Model 1028) has +	 * 'Usage Min/Max' where it ought to have 'Physical Min/Max' +	 */  	if ((quirks & MS_RDESC) && *rsize == 571 && rdesc[557] == 0x19 &&  			rdesc[559] == 0x29) {  		hid_info(hdev, "fixing up Microsoft Wireless Receiver Model 1028 report descriptor\n");  		rdesc[557] = 0x35;  		rdesc[559] = 0x45;  	} +	/* the same as above (s/usage/physical/) */ +	if ((quirks & MS_RDESC_3K) && *rsize == 106 && +			!memcmp((char []){ 0x19, 0x00, 0x29, 0xff }, +				&rdesc[94], 4)) { +		rdesc[94] = 0x35; +		rdesc[96] = 0x45; +	}  	return rdesc;  } @@ -192,7 +200,7 @@ static const struct hid_device_id ms_devices[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB),  		.driver_data = MS_PRESENTER },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), -		.driver_data = MS_ERGONOMY }, +		.driver_data = MS_ERGONOMY | MS_RDESC_3K },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0),  		.driver_data = MS_NOGET },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3eb02b94fc8..7867d69f0ef 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -210,8 +210,7 @@ static struct mt_class mt_classes[] = {  	},  	{ .name	= MT_CLS_GENERALTOUCH_PWT_TENFINGERS,  		.quirks	= MT_QUIRK_NOT_SEEN_MEANS_UP | -			MT_QUIRK_SLOT_IS_CONTACTNUMBER, -		.maxcontacts = 10 +			MT_QUIRK_SLOT_IS_CONTACTNUMBER  	},  	{ .name = MT_CLS_FLATFROG, @@ -421,11 +420,11 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,  			 * contact max are global to the report */  			td->last_field_index = field->index;  			return -1; -		}  		case HID_DG_TOUCH:  			/* Legacy devices use TIPSWITCH and not TOUCH.  			 * Let's just ignore this field. */  			return -1; +		}  		/* let hid-input decide for the others */  		return 0; diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 68ad7d25551..4f411040738 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -2,7 +2,7 @@   * fam15h_power.c - AMD Family 15h processor power monitoring   *   * Copyright (c) 2011 Advanced Micro Devices, Inc. - * Author: Andreas Herrmann <andreas.herrmann3@amd.com> + * Author: Andreas Herrmann <herrmann.der.user@googlemail.com>   *   *   * This driver is free software; you can redistribute it and/or @@ -28,7 +28,7 @@  #include <asm/processor.h>  MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); -MODULE_AUTHOR("Andreas Herrmann <andreas.herrmann3@amd.com>"); +MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>");  MODULE_LICENSE("GPL");  /* D18F3 */ diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 36509ae3208..1381a2e3bbd 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -630,7 +630,9 @@ static struct platform_driver gpio_fan_driver = {  	.driver	= {  		.name	= "gpio-fan",  		.pm	= GPIO_FAN_PM, +#ifdef CONFIG_OF_GPIO  		.of_match_table = of_match_ptr(of_gpio_fan_match), +#endif  	},  }; diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index beee6b2d361..1722f50f247 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_I2C_SMBUS)		+= i2c-smbus.o  obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o  obj-$(CONFIG_I2C_MUX)		+= i2c-mux.o  obj-y				+= algos/ busses/ muxes/ +obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o  ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG  CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 65dd599a026..e9df4612b7e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -81,7 +81,6 @@ config I2C_I801  	tristate "Intel 82801 (ICH/PCH)"  	depends on PCI  	select CHECK_SIGNATURE if X86 && DMI -	select GPIOLIB if I2C_MUX  	help  	  If you say yes to this option, support will be included for the Intel  	  801 family of mainboard I2C interfaces.  Specifically, the following diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 2d33d62952c..395b516ffa0 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_I2C_ACORN)		+= i2c-acorn.o  obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o  obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o  obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o -obj-$(CONFIG_I2C_STUB)		+= i2c-stub.o  obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o  obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 37793156bd9..6abc00d5988 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -82,7 +82,8 @@  #include <linux/wait.h>  #include <linux/err.h> -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ +		defined CONFIG_DMI  #include <linux/gpio.h>  #include <linux/i2c-mux-gpio.h>  #include <linux/platform_device.h> @@ -192,7 +193,8 @@ struct i801_priv {  	int len;  	u8 *data; -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ +		defined CONFIG_DMI  	const struct i801_mux_config *mux_drvdata;  	struct platform_device *mux_pdev;  #endif @@ -921,7 +923,8 @@ static void __init input_apanel_init(void) {}  static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {}  #endif	/* CONFIG_X86 && CONFIG_DMI */ -#if defined CONFIG_I2C_MUX || defined CONFIG_I2C_MUX_MODULE +#if (defined CONFIG_I2C_MUX_GPIO || defined CONFIG_I2C_MUX_GPIO_MODULE) && \ +		defined CONFIG_DMI  static struct i801_mux_config i801_mux_config_asus_z8_d12 = {  	.gpio_chip = "gpio_ich",  	.values = { 0x02, 0x03 }, @@ -1059,7 +1062,7 @@ static unsigned int __devinit i801_get_adapter_class(struct i801_priv *priv)  	id = dmi_first_match(mux_dmi_table);  	if (id) { -		/* Remove from branch classes from trunk */ +		/* Remove branch classes from trunk */  		mux_config = id->driver_data;  		for (i = 0; i < mux_config->n_values; i++)  			class &= ~mux_config->classes[i]; diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1f58197062c..286ca191782 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c @@ -1,7 +1,7 @@  /*   * Freescale MXS I2C bus driver   * - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. + * Copyright (C) 2011-2012 Wolfram Sang, Pengutronix e.K.   *   * based on a (non-working) driver which was:   * @@ -35,10 +35,6 @@  #define DRIVER_NAME "mxs-i2c" -static bool use_pioqueue; -module_param(use_pioqueue, bool, 0); -MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA"); -  #define MXS_I2C_CTRL0		(0x00)  #define MXS_I2C_CTRL0_SET	(0x04) @@ -75,23 +71,6 @@ MODULE_PARM_DESC(use_pioqueue, "Use PIOQUEUE mode for transfer instead of DMA");  				 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \  				 MXS_I2C_CTRL1_SLAVE_IRQ) -#define MXS_I2C_QUEUECTRL	(0x60) -#define MXS_I2C_QUEUECTRL_SET	(0x64) -#define MXS_I2C_QUEUECTRL_CLR	(0x68) - -#define MXS_I2C_QUEUECTRL_QUEUE_RUN		0x20 -#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE	0x04 - -#define MXS_I2C_QUEUESTAT	(0x70) -#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000 -#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK	0x0000001F - -#define MXS_I2C_QUEUECMD	(0x80) - -#define MXS_I2C_QUEUEDATA	(0x90) - -#define MXS_I2C_DATA		(0xa0) -  #define MXS_CMD_I2C_SELECT	(MXS_I2C_CTRL0_RETAIN_CLOCK |	\  				 MXS_I2C_CTRL0_PRE_SEND_START |	\ @@ -153,7 +132,6 @@ struct mxs_i2c_dev {  	const struct mxs_i2c_speed_config *speed;  	/* DMA support components */ -	bool				dma_mode;  	int				dma_channel;  	struct dma_chan         	*dmach;  	struct mxs_dma_data		dma_data; @@ -172,99 +150,6 @@ static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)  	writel(i2c->speed->timing2, i2c->regs + MXS_I2C_TIMING2);  	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); -	if (i2c->dma_mode) -		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, -			i2c->regs + MXS_I2C_QUEUECTRL_CLR); -	else -		writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, -			i2c->regs + MXS_I2C_QUEUECTRL_SET); -} - -static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, -					int flags) -{ -	u32 data; - -	writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD); - -	data = (addr << 1) | I2C_SMBUS_READ; -	writel(data, i2c->regs + MXS_I2C_DATA); - -	data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags; -	writel(data, i2c->regs + MXS_I2C_QUEUECMD); -} - -static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, -				    u8 addr, u8 *buf, int len, int flags) -{ -	u32 data; -	int i, shifts_left; - -	data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags; -	writel(data, i2c->regs + MXS_I2C_QUEUECMD); - -	/* -	 * We have to copy the slave address (u8) and buffer (arbitrary number -	 * of u8) into the data register (u32). To achieve that, the u8 are put -	 * into the MSBs of 'data' which is then shifted for the next u8. When -	 * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 -	 * looks like this: -	 * -	 *  3          2          1          0 -	 * 10987654|32109876|54321098|76543210 -	 * --------+--------+--------+-------- -	 * buffer+2|buffer+1|buffer+0|slave_addr -	 */ - -	data = ((addr << 1) | I2C_SMBUS_WRITE) << 24; - -	for (i = 0; i < len; i++) { -		data >>= 8; -		data |= buf[i] << 24; -		if ((i & 3) == 2) -			writel(data, i2c->regs + MXS_I2C_DATA); -	} - -	/* Write out the remaining bytes if any */ -	shifts_left = 24 - (i & 3) * 8; -	if (shifts_left) -		writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA); -} - -/* - * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the - * rd_threshold to 1). Couldn't get this to work, though. - */ -static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) -{ -	unsigned long timeout = jiffies + msecs_to_jiffies(1000); - -	while (readl(i2c->regs + MXS_I2C_QUEUESTAT) -			& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) { -			if (time_after(jiffies, timeout)) -				return -ETIMEDOUT; -			cond_resched(); -	} - -	return 0; -} - -static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) -{ -	u32 uninitialized_var(data); -	int i; - -	for (i = 0; i < len; i++) { -		if ((i & 3) == 0) { -			if (mxs_i2c_wait_for_data(i2c)) -				return -ETIMEDOUT; -			data = readl(i2c->regs + MXS_I2C_QUEUEDATA); -		} -		buf[i] = data & 0xff; -		data >>= 8; -	} - -	return 0;  }  static void mxs_i2c_dma_finish(struct mxs_i2c_dev *i2c) @@ -432,39 +317,17 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,  	init_completion(&i2c->cmd_complete);  	i2c->cmd_err = 0; -	if (i2c->dma_mode) { -		ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); -		if (ret) -			return ret; -	} else { -		if (msg->flags & I2C_M_RD) { -			mxs_i2c_pioq_setup_read(i2c, msg->addr, -						msg->len, flags); -		} else { -			mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, -						msg->len, flags); -		} - -		writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, -			i2c->regs + MXS_I2C_QUEUECTRL_SET); -	} +	ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); +	if (ret) +		return ret;  	ret = wait_for_completion_timeout(&i2c->cmd_complete,  						msecs_to_jiffies(1000));  	if (ret == 0)  		goto timeout; -	if (!i2c->dma_mode && !i2c->cmd_err && (msg->flags & I2C_M_RD)) { -		ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); -		if (ret) -			goto timeout; -	} -  	if (i2c->cmd_err == -ENXIO)  		mxs_i2c_reset(i2c); -	else -		writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, -				i2c->regs + MXS_I2C_QUEUECTRL_CLR);  	dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err); @@ -472,8 +335,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,  timeout:  	dev_dbg(i2c->dev, "Timeout!\n"); -	if (i2c->dma_mode) -		mxs_i2c_dma_finish(i2c); +	mxs_i2c_dma_finish(i2c);  	mxs_i2c_reset(i2c);  	return -ETIMEDOUT;  } @@ -502,7 +364,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)  {  	struct mxs_i2c_dev *i2c = dev_id;  	u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; -	bool is_last_cmd;  	if (!stat)  		return IRQ_NONE; @@ -515,14 +376,6 @@ static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)  		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */  		i2c->cmd_err = -EIO; -	if (!i2c->dma_mode) { -		is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & -			MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; - -		if (is_last_cmd || i2c->cmd_err) -			complete(&i2c->cmd_complete); -	} -  	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);  	return IRQ_HANDLED; @@ -556,23 +409,14 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)  	int ret;  	/* -	 * The MXS I2C DMA mode is prefered and enabled by default. -	 * The PIO mode is still supported, but should be used only -	 * for debuging purposes etc. -	 */ -	i2c->dma_mode = !use_pioqueue; -	if (!i2c->dma_mode) -		dev_info(dev, "Using PIOQUEUE mode for I2C transfers!\n"); - -	/*  	 * TODO: This is a temporary solution and should be changed  	 * to use generic DMA binding later when the helpers get in.  	 */  	ret = of_property_read_u32(node, "fsl,i2c-dma-channel",  				   &i2c->dma_channel);  	if (ret) { -		dev_warn(dev, "Failed to get DMA channel, using PIOQUEUE!\n"); -		i2c->dma_mode = 0; +		dev_err(dev, "Failed to get DMA channel!\n"); +		return -ENODEV;  	}  	ret = of_property_read_u32(node, "clock-frequency", &speed); @@ -634,15 +478,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)  	}  	/* Setup the DMA */ -	if (i2c->dma_mode) { -		dma_cap_zero(mask); -		dma_cap_set(DMA_SLAVE, mask); -		i2c->dma_data.chan_irq = dmairq; -		i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); -		if (!i2c->dmach) { -			dev_err(dev, "Failed to request dma\n"); -			return -ENODEV; -		} +	dma_cap_zero(mask); +	dma_cap_set(DMA_SLAVE, mask); +	i2c->dma_data.chan_irq = dmairq; +	i2c->dmach = dma_request_channel(mask, mxs_i2c_dma_filter, i2c); +	if (!i2c->dmach) { +		dev_err(dev, "Failed to request dma\n"); +		return -ENODEV;  	}  	platform_set_drvdata(pdev, i2c); diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index 698d7acb0f0..02c3115a2df 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -644,7 +644,11 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,  	pm_runtime_get_sync(&dev->adev->dev); -	clk_enable(dev->clk); +	status = clk_prepare_enable(dev->clk); +	if (status) { +		dev_err(&dev->adev->dev, "can't prepare_enable clock\n"); +		goto out_clk; +	}  	status = init_hw(dev);  	if (status) @@ -671,7 +675,8 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap,  	}  out: -	clk_disable(dev->clk); +	clk_disable_unprepare(dev->clk); +out_clk:  	pm_runtime_put_sync(&dev->adev->dev);  	dev->busy = false; diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4e678..dcea77bf6f5 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)  	}  	ret = devm_request_irq(&pdev->dev, i2c_dev->irq, -			tegra_i2c_isr, 0, pdev->name, i2c_dev); +			tegra_i2c_isr, 0, dev_name(&pdev->dev), i2c_dev);  	if (ret) {  		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);  		return ret; diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/i2c-stub.c index b1b3447942c..d0a9c590c3c 100644 --- a/drivers/i2c/busses/i2c-stub.c +++ b/drivers/i2c/i2c-stub.c @@ -2,7 +2,7 @@      i2c-stub.c - I2C/SMBus chip emulator      Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> -    Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> +    Copyright (C) 2007, 2012 Jean Delvare <khali@linux-fr.org>      This program is free software; you can redistribute it and/or modify      it under the terms of the GNU General Public License as published by @@ -51,8 +51,8 @@ struct stub_chip {  static struct stub_chip *stub_chips;  /* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, -	char read_write, u8 command, int size, union i2c_smbus_data * data) +static s32 stub_xfer(struct i2c_adapter *adap, u16 addr, unsigned short flags, +	char read_write, u8 command, int size, union i2c_smbus_data *data)  {  	s32 ret;  	int i, len; @@ -78,14 +78,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  	case I2C_SMBUS_BYTE:  		if (read_write == I2C_SMBUS_WRITE) {  			chip->pointer = command; -			dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " -					"wrote 0x%02x.\n", -					addr, command); +			dev_dbg(&adap->dev, +				"smbus byte - addr 0x%02x, wrote 0x%02x.\n", +				addr, command);  		} else {  			data->byte = chip->words[chip->pointer++] & 0xff; -			dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " -					"read  0x%02x.\n", -					addr, data->byte); +			dev_dbg(&adap->dev, +				"smbus byte - addr 0x%02x, read  0x%02x.\n", +				addr, data->byte);  		}  		ret = 0; @@ -95,14 +95,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  		if (read_write == I2C_SMBUS_WRITE) {  			chip->words[command] &= 0xff00;  			chip->words[command] |= data->byte; -			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " -					"wrote 0x%02x at 0x%02x.\n", -					addr, data->byte, command); +			dev_dbg(&adap->dev, +				"smbus byte data - addr 0x%02x, wrote 0x%02x at 0x%02x.\n", +				addr, data->byte, command);  		} else {  			data->byte = chip->words[command] & 0xff; -			dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " -					"read  0x%02x at 0x%02x.\n", -					addr, data->byte, command); +			dev_dbg(&adap->dev, +				"smbus byte data - addr 0x%02x, read  0x%02x at 0x%02x.\n", +				addr, data->byte, command);  		}  		chip->pointer = command + 1; @@ -112,14 +112,14 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  	case I2C_SMBUS_WORD_DATA:  		if (read_write == I2C_SMBUS_WRITE) {  			chip->words[command] = data->word; -			dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " -					"wrote 0x%04x at 0x%02x.\n", -					addr, data->word, command); +			dev_dbg(&adap->dev, +				"smbus word data - addr 0x%02x, wrote 0x%04x at 0x%02x.\n", +				addr, data->word, command);  		} else {  			data->word = chip->words[command]; -			dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " -					"read  0x%04x at 0x%02x.\n", -					addr, data->word, command); +			dev_dbg(&adap->dev, +				"smbus word data - addr 0x%02x, read  0x%04x at 0x%02x.\n", +				addr, data->word, command);  		}  		ret = 0; @@ -132,17 +132,17 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,  				chip->words[command + i] &= 0xff00;  				chip->words[command + i] |= data->block[1 + i];  			} -			dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " -					"wrote %d bytes at 0x%02x.\n", -					addr, len, command); +			dev_dbg(&adap->dev, +				"i2c block data - addr 0x%02x, wrote %d bytes at 0x%02x.\n", +				addr, len, command);  		} else {  			for (i = 0; i < len; i++) {  				data->block[1 + i] =  					chip->words[command + i] & 0xff;  			} -			dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " -					"read  %d bytes at 0x%02x.\n", -					addr, len, command); +			dev_dbg(&adap->dev, +				"i2c block data - addr 0x%02x, read  %d bytes at 0x%02x.\n", +				addr, len, command);  		}  		ret = 0; @@ -179,25 +179,24 @@ static int __init i2c_stub_init(void)  	int i, ret;  	if (!chip_addr[0]) { -		printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); +		pr_err("i2c-stub: Please specify a chip address\n");  		return -ENODEV;  	}  	for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) {  		if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { -			printk(KERN_ERR "i2c-stub: Invalid chip address " -			       "0x%02x\n", chip_addr[i]); +			pr_err("i2c-stub: Invalid chip address 0x%02x\n", +			       chip_addr[i]);  			return -EINVAL;  		} -		printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", -		       chip_addr[i]); +		pr_info("i2c-stub: Virtual chip at 0x%02x\n", chip_addr[i]);  	}  	/* Allocate memory for all chips at once */  	stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL);  	if (!stub_chips) { -		printk(KERN_ERR "i2c-stub: Out of memory\n"); +		pr_err("i2c-stub: Out of memory\n");  		return -ENOMEM;  	} @@ -219,4 +218,3 @@ MODULE_LICENSE("GPL");  module_init(i2c_stub_init);  module_exit(i2c_stub_exit); - diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index b4b65af8612..de0874054e9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -335,6 +335,7 @@ config KEYBOARD_LOCOMO  config KEYBOARD_LPC32XX  	tristate "LPC32XX matrix key scanner support"  	depends on ARCH_LPC32XX && OF +	select INPUT_MATRIXKMAP  	help  	  Say Y here if you want to use NXP LPC32XX SoC key scanner interface,  	  connected to a key matrix. diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c index 803ff6fe021..cad9d5dd597 100644 --- a/drivers/input/keyboard/pxa27x_keypad.c +++ b/drivers/input/keyboard/pxa27x_keypad.c @@ -368,6 +368,9 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)  	unsigned int mask = 0, direct_key_num = 0;  	unsigned long kpc = 0; +	/* clear pending interrupt bit */ +	keypad_readl(KPC); +  	/* enable matrix keys with automatic scan */  	if (pdata->matrix_key_rows && pdata->matrix_key_cols) {  		kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL; diff --git a/drivers/input/misc/xen-kbdfront.c b/drivers/input/misc/xen-kbdfront.c index 02ca8680ea5..6f7d9901303 100644 --- a/drivers/input/misc/xen-kbdfront.c +++ b/drivers/input/misc/xen-kbdfront.c @@ -311,7 +311,6 @@ static void xenkbd_backend_changed(struct xenbus_device *dev,  	case XenbusStateReconfiguring:  	case XenbusStateReconfigured:  	case XenbusStateUnknown: -	case XenbusStateClosed:  		break;  	case XenbusStateInitWait: @@ -350,6 +349,10 @@ InitWait:  		break; +	case XenbusStateClosed: +		if (dev->state == XenbusStateClosed) +			break; +		/* Missed the backend's CLOSING state -- fallthrough */  	case XenbusStateClosing:  		xenbus_frontend_closed(dev);  		break; diff --git a/drivers/input/mouse/bcm5974.c b/drivers/input/mouse/bcm5974.c index 3a78f235fa3..2baff1b79a5 100644 --- a/drivers/input/mouse/bcm5974.c +++ b/drivers/input/mouse/bcm5974.c @@ -84,6 +84,10 @@  #define USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI	0x0262  #define USB_DEVICE_ID_APPLE_WELLSPRING7_ISO	0x0263  #define USB_DEVICE_ID_APPLE_WELLSPRING7_JIS	0x0264 +/* MacbookPro10,2 (unibody, October 2012) */ +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI	0x0259 +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO	0x025a +#define USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS	0x025b  #define BCM5974_DEVICE(prod) {					\  	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\ @@ -137,6 +141,10 @@ static const struct usb_device_id bcm5974_table[] = {  	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ANSI),  	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_ISO),  	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7_JIS), +	/* MacbookPro10,2 */ +	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI), +	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO), +	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS),  	/* Terminating entry */  	{}  }; @@ -379,6 +387,19 @@ static const struct bcm5974_config bcm5974_config_table[] = {  		{ SN_COORD, -150, 6730 },  		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION }  	}, +	{ +		USB_DEVICE_ID_APPLE_WELLSPRING7A_ANSI, +		USB_DEVICE_ID_APPLE_WELLSPRING7A_ISO, +		USB_DEVICE_ID_APPLE_WELLSPRING7A_JIS, +		HAS_INTEGRATED_BUTTON, +		0x84, sizeof(struct bt_data), +		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS, +		{ SN_PRESSURE, 0, 300 }, +		{ SN_WIDTH, 0, 2048 }, +		{ SN_COORD, -4750, 5280 }, +		{ SN_COORD, -150, 6730 }, +		{ SN_ORIENT, -MAX_FINGER_ORIENTATION, MAX_FINGER_ORIENTATION } +	},  	{}  }; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index 2c1e12bf2ab..858ad446de9 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -391,7 +391,7 @@ static int wacom_parse_hid(struct usb_interface *intf,  							features->pktlen = WACOM_PKGLEN_TPC2FG;  						} -						if (features->type == MTSCREEN || WACOM_24HDT) +						if (features->type == MTSCREEN || features->type == WACOM_24HDT)  							features->pktlen = WACOM_PKGLEN_MTOUCH;  						if (features->type == BAMBOO_PT) { diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index aa601013117..0a67031ffc1 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -1518,6 +1518,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev,  		input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0);  		input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); + +		__set_bit(INPUT_PROP_DIRECT, input_dev->propbit); +  		wacom_setup_cintiq(wacom_wac);  		break; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 1ba232cbc09..f7668b24c37 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -239,7 +239,7 @@ config TOUCHSCREEN_EETI  config TOUCHSCREEN_EGALAX  	tristate "EETI eGalax multi-touch panel support" -	depends on I2C +	depends on I2C && OF  	help  	  Say Y here to enable support for I2C connected EETI  	  eGalax multi-touch panels. diff --git a/drivers/input/touchscreen/egalax_ts.c b/drivers/input/touchscreen/egalax_ts.c index c1e3460f119..13fa62fdfb0 100644 --- a/drivers/input/touchscreen/egalax_ts.c +++ b/drivers/input/touchscreen/egalax_ts.c @@ -28,6 +28,7 @@  #include <linux/slab.h>  #include <linux/bitops.h>  #include <linux/input/mt.h> +#include <linux/of_gpio.h>  /*   * Mouse Mode: some panel may configure the controller to mouse mode, @@ -122,9 +123,17 @@ static irqreturn_t egalax_ts_interrupt(int irq, void *dev_id)  /* wake up controller by an falling edge of interrupt gpio.  */  static int egalax_wake_up_device(struct i2c_client *client)  { -	int gpio = irq_to_gpio(client->irq); +	struct device_node *np = client->dev.of_node; +	int gpio;  	int ret; +	if (!np) +		return -ENODEV; + +	gpio = of_get_named_gpio(np, "wakeup-gpios", 0); +	if (!gpio_is_valid(gpio)) +		return -ENODEV; +  	ret = gpio_request(gpio, "egalax_irq");  	if (ret < 0) {  		dev_err(&client->dev, @@ -181,7 +190,11 @@ static int __devinit egalax_ts_probe(struct i2c_client *client,  	ts->input_dev = input_dev;  	/* controller may be in sleep, wake it up. */ -	egalax_wake_up_device(client); +	error = egalax_wake_up_device(client); +	if (error) { +		dev_err(&client->dev, "Failed to wake up the controller\n"); +		goto err_free_dev; +	}  	ret = egalax_firmware_version(client);  	if (ret < 0) { @@ -274,11 +287,17 @@ static int egalax_ts_resume(struct device *dev)  static SIMPLE_DEV_PM_OPS(egalax_ts_pm_ops, egalax_ts_suspend, egalax_ts_resume); +static struct of_device_id egalax_ts_dt_ids[] = { +	{ .compatible = "eeti,egalax_ts" }, +	{ /* sentinel */ } +}; +  static struct i2c_driver egalax_ts_driver = {  	.driver = {  		.name	= "egalax_ts",  		.owner	= THIS_MODULE,  		.pm	= &egalax_ts_pm_ops, +		.of_match_table	= of_match_ptr(egalax_ts_dt_ids),  	},  	.id_table	= egalax_ts_id,  	.probe		= egalax_ts_probe, diff --git a/drivers/input/touchscreen/tsc40.c b/drivers/input/touchscreen/tsc40.c index 63209aaa55f..eb96f168fb9 100644 --- a/drivers/input/touchscreen/tsc40.c +++ b/drivers/input/touchscreen/tsc40.c @@ -107,7 +107,6 @@ static int tsc_connect(struct serio *serio, struct serio_driver *drv)  	__set_bit(BTN_TOUCH, input_dev->keybit);  	input_set_abs_params(ptsc->dev, ABS_X, 0, 0x3ff, 0, 0);  	input_set_abs_params(ptsc->dev, ABS_Y, 0, 0x3ff, 0, 0); -	input_set_abs_params(ptsc->dev, ABS_PRESSURE, 0, 0, 0, 0);  	serio_set_drvdata(serio, ptsc); diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 45135f69509..5e7dc772f5d 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -315,8 +315,11 @@ static int run(struct mddev *mddev)  	}  	conf->nfaults = 0; -	rdev_for_each(rdev, mddev) +	rdev_for_each(rdev, mddev) {  		conf->rdev = rdev; +		disk_stack_limits(mddev->gendisk, rdev->bdev, +				  rdev->data_offset << 9); +	}  	md_set_array_sectors(mddev, faulty_size(mddev, 0, 0));  	mddev->private = conf; diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 8034fbd6190..636bae0405e 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -2710,7 +2710,7 @@ static struct r1conf *setup_conf(struct mddev *mddev)  		    || disk_idx < 0)  			continue;  		if (test_bit(Replacement, &rdev->flags)) -			disk = conf->mirrors + conf->raid_disks + disk_idx; +			disk = conf->mirrors + mddev->raid_disks + disk_idx;  		else  			disk = conf->mirrors + disk_idx; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 906ccbd0f7d..d1295aff417 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -1783,7 +1783,7 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)  		clear_bit(Unmerged, &rdev->flags);  	}  	md_integrity_add_rdev(rdev, mddev); -	if (blk_queue_discard(bdev_get_queue(rdev->bdev))) +	if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))  		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);  	print_conf(conf); @@ -3613,11 +3613,14 @@ static int run(struct mddev *mddev)  			discard_supported = true;  	} -	if (discard_supported) -		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); -	else -		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, mddev->queue); - +	if (mddev->queue) { +		if (discard_supported) +			queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, +						mddev->queue); +		else +			queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, +						  mddev->queue); +	}  	/* need to check that every block has at least one working mirror */  	if (!enough(conf, -1)) {  		printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n", diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index dc15d248443..ef8d2a080d1 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c @@ -1060,7 +1060,7 @@ static ssize_t bonding_store_primary(struct device *d,  		goto out;  	} -	sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ +	sscanf(buf, "%15s", ifname); /* IFNAMSIZ */  	/* check to see if we are clearing primary */  	if (!strlen(ifname) || buf[0] == '\n') { @@ -1237,7 +1237,7 @@ static ssize_t bonding_store_active_slave(struct device *d,  		goto out;  	} -	sscanf(buf, "%16s", ifname); /* IFNAMSIZ */ +	sscanf(buf, "%15s", ifname); /* IFNAMSIZ */  	/* check to see if we are clearing active */  	if (!strlen(ifname) || buf[0] == '\n') { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index e2e45ee5df3..6dd0dd076cc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c @@ -137,7 +137,16 @@  #define LINK_20GTFD		LINK_STATUS_SPEED_AND_DUPLEX_20GTFD  #define LINK_20GXFD		LINK_STATUS_SPEED_AND_DUPLEX_20GXFD - +#define LINK_UPDATE_MASK \ +			(LINK_STATUS_SPEED_AND_DUPLEX_MASK | \ +			 LINK_STATUS_LINK_UP | \ +			 LINK_STATUS_PHYSICAL_LINK_FLAG | \ +			 LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | \ +			 LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | \ +			 LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | \ +			 LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | \ +			 LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | \ +			 LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE)  #define SFP_EEPROM_CON_TYPE_ADDR		0x2  	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7 @@ -3295,6 +3304,21 @@ static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port)  	       DEFAULT_PHY_DEV_ADDR);  } +static void bnx2x_xgxs_specific_func(struct bnx2x_phy *phy, +				     struct link_params *params, +				     u32 action) +{ +	struct bnx2x *bp = params->bp; +	switch (action) { +	case PHY_INIT: +		/* Set correct devad */ +		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + params->port*0x18, 0); +		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + params->port*0x18, +		       phy->def_md_devad); +		break; +	} +} +  static void bnx2x_xgxs_deassert(struct link_params *params)  {  	struct bnx2x *bp = params->bp; @@ -3309,10 +3333,8 @@ static void bnx2x_xgxs_deassert(struct link_params *params)  	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val);  	udelay(500);  	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); - -	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0); -	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, -	       params->phy[INT_PHY].def_md_devad); +	bnx2x_xgxs_specific_func(¶ms->phy[INT_PHY], params, +				 PHY_INIT);  }  static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy, @@ -3545,14 +3567,11 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,  static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  					struct link_params *params,  					struct link_vars *vars) { -	u16 val16 = 0, lane, i; +	u16 lane, i, cl72_ctrl, an_adv = 0; +	u16 ucode_ver;  	struct bnx2x *bp = params->bp;  	static struct bnx2x_reg_set reg_set[] = {  		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, -		{MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0}, -		{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, 0}, -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0xff}, -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0x5555},  		{MDIO_PMA_DEVAD, MDIO_WC_REG_IEEE0BLK_AUTONEGNP, 0x0},  		{MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},  		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, @@ -3565,12 +3584,19 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,  				 reg_set[i].val); +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +		MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); +	cl72_ctrl &= 0xf8ff; +	cl72_ctrl |= 0x3800; +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +		MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); +  	/* Check adding advertisement for 1G KX */  	if (((vars->line_speed == SPEED_AUTO_NEG) &&  	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) ||  	    (vars->line_speed == SPEED_1000)) {  		u32 addr = MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2; -		val16 |= (1<<5); +		an_adv |= (1<<5);  		/* Enable CL37 1G Parallel Detect */  		bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, addr, 0x1); @@ -3580,11 +3606,14 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  	     (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) ||  	    (vars->line_speed ==  SPEED_10000)) {  		/* Check adding advertisement for 10G KR */ -		val16 |= (1<<7); +		an_adv |= (1<<7);  		/* Enable 10G Parallel Detect */ +		CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, +				  MDIO_AER_BLOCK_AER_REG, 0); +  		bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,  				 MDIO_WC_REG_PAR_DET_10G_CTRL, 1); - +		bnx2x_set_aer_mmd(params, phy);  		DP(NETIF_MSG_LINK, "Advertize 10G\n");  	} @@ -3604,7 +3633,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  	/* Advertised speeds */  	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, -			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, val16); +			 MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, an_adv);  	/* Advertised and set FEC (Forward Error Correction) */  	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, @@ -3628,9 +3657,10 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,  	/* Set KR Autoneg Work-Around flag for Warpcore version older than D108  	 */  	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, -			MDIO_WC_REG_UC_INFO_B1_VERSION, &val16); -	if (val16 < 0xd108) { -		DP(NETIF_MSG_LINK, "Enable AN KR work-around\n"); +			MDIO_WC_REG_UC_INFO_B1_VERSION, &ucode_ver); +	if (ucode_ver < 0xd108) { +		DP(NETIF_MSG_LINK, "Enable AN KR work-around. WC ver:0x%x\n", +			       ucode_ver);  		vars->rx_tx_asic_rst = MAX_KR_LINK_RETRY;  	}  	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, @@ -3651,21 +3681,16 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,  				      struct link_vars *vars)  {  	struct bnx2x *bp = params->bp; -	u16 i; +	u16 val16, i, lane;  	static struct bnx2x_reg_set reg_set[] = {  		/* Disable Autoneg */  		{MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_CONTROL1000X2, 0x7}, -		{MDIO_AN_DEVAD, MDIO_WC_REG_PAR_DET_10G_CTRL, 0},  		{MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL,  			0x3f00},  		{MDIO_AN_DEVAD, MDIO_WC_REG_AN_IEEE1BLK_AN_ADVERTISEMENT1, 0},  		{MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x0},  		{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},  		{MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, -		/* Disable CL36 PCS Tx */ -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL0, 0x0}, -		/* Double Wide Single Data Rate @ pll rate */ -		{MDIO_WC_DEVAD, MDIO_WC_REG_XGXSBLK1_LANECTRL1, 0xFFFF},  		/* Leave cl72 training enable, needed for KR */  		{MDIO_PMA_DEVAD,  		MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150, @@ -3676,11 +3701,24 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,  		bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,  				 reg_set[i].val); -	/* Leave CL72 enabled */ -	bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, -				 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, -				 0x3800); +	lane = bnx2x_get_warpcore_lane(phy, params); +	/* Global registers */ +	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, +			  MDIO_AER_BLOCK_AER_REG, 0); +	/* Disable CL36 PCS Tx */ +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); +	val16 &= ~(0x0011 << lane); +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); +	val16 |= (0x0303 << (lane << 1)); +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); +	/* Restore AER */ +	bnx2x_set_aer_mmd(params, phy);  	/* Set speed via PMA/PMD register */  	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD,  			 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x2040); @@ -4303,7 +4341,7 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,  				      struct link_params *params)  {  	struct bnx2x *bp = params->bp; -	u16 val16; +	u16 val16, lane;  	bnx2x_sfp_e3_set_transmitter(params, phy, 0);  	bnx2x_set_mdio_clk(bp, params->chip_id, params->port);  	bnx2x_set_aer_mmd(params, phy); @@ -4340,6 +4378,30 @@ static void bnx2x_warpcore_link_reset(struct bnx2x_phy *phy,  			 MDIO_WC_REG_XGXSBLK1_LANECTRL2,  			 val16 & 0xff00); +	lane = bnx2x_get_warpcore_lane(phy, params); +	/* Disable CL36 PCS Tx */ +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL0, &val16); +	val16 |= (0x11 << lane); +	if (phy->flags & FLAGS_WC_DUAL_MODE) +		val16 |= (0x22 << lane); +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL0, val16); + +	bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, +			MDIO_WC_REG_XGXSBLK1_LANECTRL1, &val16); +	val16 &= ~(0x0303 << (lane << 1)); +	val16 |= (0x0101 << (lane << 1)); +	if (phy->flags & FLAGS_WC_DUAL_MODE) { +		val16 &= ~(0x0c0c << (lane << 1)); +		val16 |= (0x0404 << (lane << 1)); +	} + +	bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, +			 MDIO_WC_REG_XGXSBLK1_LANECTRL1, val16); +	/* Restore AER */ +	bnx2x_set_aer_mmd(params, phy); +  }  static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy, @@ -6296,15 +6358,7 @@ static int bnx2x_update_link_down(struct link_params *params,  	vars->mac_type = MAC_TYPE_NONE;  	/* Update shared memory */ -	vars->link_status &= ~(LINK_STATUS_SPEED_AND_DUPLEX_MASK | -			       LINK_STATUS_LINK_UP | -			       LINK_STATUS_PHYSICAL_LINK_FLAG | -			       LINK_STATUS_AUTO_NEGOTIATE_COMPLETE | -			       LINK_STATUS_RX_FLOW_CONTROL_FLAG_MASK | -			       LINK_STATUS_TX_FLOW_CONTROL_FLAG_MASK | -			       LINK_STATUS_PARALLEL_DETECTION_FLAG_MASK | -			       LINK_STATUS_LINK_PARTNER_SYMMETRIC_PAUSE | -			       LINK_STATUS_LINK_PARTNER_ASYMMETRIC_PAUSE); +	vars->link_status &= ~LINK_UPDATE_MASK;  	vars->line_speed = 0;  	bnx2x_update_mng(params, vars->link_status); @@ -6452,6 +6506,7 @@ int bnx2x_link_update(struct link_params *params, struct link_vars *vars)  	u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed;  	u8 active_external_phy = INT_PHY;  	vars->phy_flags &= ~PHY_HALF_OPEN_CONN_FLAG; +	vars->link_status &= ~LINK_UPDATE_MASK;  	for (phy_index = INT_PHY; phy_index < params->num_phys;  	      phy_index++) {  		phy_vars[phy_index].flow_ctrl = 0; @@ -7579,7 +7634,7 @@ static void bnx2x_warpcore_power_module(struct link_params *params,  static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,  						 struct link_params *params,  						 u16 addr, u8 byte_cnt, -						 u8 *o_buf) +						 u8 *o_buf, u8 is_init)  {  	int rc = 0;  	u8 i, j = 0, cnt = 0; @@ -7596,10 +7651,10 @@ static int bnx2x_warpcore_read_sfp_module_eeprom(struct bnx2x_phy *phy,  	/* 4 byte aligned address */  	addr32 = addr & (~0x3);  	do { -		if (cnt == I2C_WA_PWR_ITER) { +		if ((!is_init) && (cnt == I2C_WA_PWR_ITER)) {  			bnx2x_warpcore_power_module(params, phy, 0);  			/* Note that 100us are not enough here */ -			usleep_range(1000,1000); +			usleep_range(1000, 2000);  			bnx2x_warpcore_power_module(params, phy, 1);  		}  		rc = bnx2x_bsc_read(params, phy, 0xa0, addr32, 0, byte_cnt, @@ -7719,7 +7774,7 @@ int bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,  	break;  	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT:  		rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, params, addr, -							   byte_cnt, o_buf); +							   byte_cnt, o_buf, 0);  	break;  	}  	return rc; @@ -7923,6 +7978,7 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,  {  	u8 val; +	int rc;  	struct bnx2x *bp = params->bp;  	u16 timeout;  	/* Initialization time after hot-plug may take up to 300ms for @@ -7930,8 +7986,14 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,  	 */  	for (timeout = 0; timeout < 60; timeout++) { -		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) -		    == 0) { +		if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) +			rc = bnx2x_warpcore_read_sfp_module_eeprom(phy, +								   params, 1, +								   1, &val, 1); +		else +			rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, +							  &val); +		if (rc == 0) {  			DP(NETIF_MSG_LINK,  			   "SFP+ module initialization took %d ms\n",  			   timeout * 5); @@ -7939,7 +8001,8 @@ static int bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy,  		}  		usleep_range(5000, 10000);  	} -	return -EINVAL; +	rc = bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val); +	return rc;  }  static void bnx2x_8727_power_module(struct bnx2x *bp, @@ -10993,7 +11056,7 @@ static struct bnx2x_phy phy_xgxs = {  	.format_fw_ver	= (format_fw_ver_t)NULL,  	.hw_reset	= (hw_reset_t)NULL,  	.set_link_led	= (set_link_led_t)NULL, -	.phy_specific_func = (phy_specific_func_t)NULL +	.phy_specific_func = (phy_specific_func_t)bnx2x_xgxs_specific_func  };  static struct bnx2x_phy phy_warpcore = {  	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT, @@ -11465,6 +11528,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,  			phy->media_type = ETH_PHY_BASE_T;  			break;  		case PORT_HW_CFG_NET_SERDES_IF_XFI: +			phy->supported &= (SUPPORTED_1000baseT_Full | +					   SUPPORTED_10000baseT_Full | +					   SUPPORTED_FIBRE | +					   SUPPORTED_Pause | +					   SUPPORTED_Asym_Pause);  			phy->media_type = ETH_PHY_XFP_FIBER;  			break;  		case PORT_HW_CFG_NET_SERDES_IF_SFI: diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index d5648fc666b..bd1fd3d87c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -6794,8 +6794,9 @@ static int bnx2x_init_hw_port(struct bnx2x *bp)  	bnx2x_init_block(bp, BLOCK_DORQ, init_phase); +	bnx2x_init_block(bp, BLOCK_BRB1, init_phase); +  	if (CHIP_IS_E1(bp) || CHIP_IS_E1H(bp)) { -		bnx2x_init_block(bp, BLOCK_BRB1, init_phase);  		if (IS_MF(bp))  			low = ((bp->flags & ONE_PORT_FLAG) ? 160 : 246); @@ -11902,7 +11903,15 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,  	/* disable FCOE L2 queue for E1x */  	if (CHIP_IS_E1x(bp))  		bp->flags |= NO_FCOE_FLAG; - +	/* disable FCOE for 57840 device, until FW supports it */ +	switch (ent->driver_data) { +	case BCM57840_O: +	case BCM57840_4_10: +	case BCM57840_2_20: +	case BCM57840_MFO: +	case BCM57840_MF: +		bp->flags |= NO_FCOE_FLAG; +	}  #endif diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c1cde11b0c6..0df1284df49 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -3416,16 +3416,6 @@ static int adap_init0_config(struct adapter *adapter, int reset)  			 finicsum, cfcsum);  	/* -	 * If we're a pure NIC driver then disable all offloading facilities. -	 * This will allow the firmware to optimize aspects of the hardware -	 * configuration which will result in improved performance. -	 */ -	caps_cmd.ofldcaps = 0; -	caps_cmd.iscsicaps = 0; -	caps_cmd.rdmacaps = 0; -	caps_cmd.fcoecaps = 0; - -	/*  	 * And now tell the firmware to use the configuration we just loaded.  	 */  	caps_cmd.op_to_write = diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e..116f0e901be 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2673,6 +2673,9 @@ static int ixgbe_get_ts_info(struct net_device *dev,  	case ixgbe_mac_X540:  	case ixgbe_mac_82599EB:  		info->so_timestamping = +			SOF_TIMESTAMPING_TX_SOFTWARE | +			SOF_TIMESTAMPING_RX_SOFTWARE | +			SOF_TIMESTAMPING_SOFTWARE |  			SOF_TIMESTAMPING_TX_HARDWARE |  			SOF_TIMESTAMPING_RX_HARDWARE |  			SOF_TIMESTAMPING_RAW_HARDWARE; diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index 53743f7a2ca..af8b4142088 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c @@ -1524,6 +1524,7 @@ static int lpc_eth_drv_remove(struct platform_device *pdev)  				  pldat->dma_buff_base_p);  	free_irq(ndev->irq, ndev);  	iounmap(pldat->net_base); +	mdiobus_unregister(pldat->mii_bus);  	mdiobus_free(pldat->mii_bus);  	clk_disable(pldat->clk);  	clk_put(pldat->clk); diff --git a/drivers/net/phy/mdio-bitbang.c b/drivers/net/phy/mdio-bitbang.c index daec9b05d16..6428fcbbdd4 100644 --- a/drivers/net/phy/mdio-bitbang.c +++ b/drivers/net/phy/mdio-bitbang.c @@ -234,6 +234,7 @@ void free_mdio_bitbang(struct mii_bus *bus)  	struct mdiobb_ctrl *ctrl = bus->priv;  	module_put(ctrl->ops->owner); +	mdiobus_unregister(bus);  	mdiobus_free(bus);  }  EXPORT_SYMBOL(free_mdio_bitbang); diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index ce9d4f2c977..0ae1bcc6da7 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c @@ -744,28 +744,43 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,  	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {  		const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; +		u32 buf_size; -		tbi = tq->buf_info + tq->tx_ring.next2fill; -		tbi->map_type = VMXNET3_MAP_PAGE; -		tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, -						 0, skb_frag_size(frag), -						 DMA_TO_DEVICE); +		buf_offset = 0; +		len = skb_frag_size(frag); +		while (len) { +			tbi = tq->buf_info + tq->tx_ring.next2fill; +			if (len < VMXNET3_MAX_TX_BUF_SIZE) { +				buf_size = len; +				dw2 |= len; +			} else { +				buf_size = VMXNET3_MAX_TX_BUF_SIZE; +				/* spec says that for TxDesc.len, 0 == 2^14 */ +			} +			tbi->map_type = VMXNET3_MAP_PAGE; +			tbi->dma_addr = skb_frag_dma_map(&adapter->pdev->dev, frag, +							 buf_offset, buf_size, +							 DMA_TO_DEVICE); -		tbi->len = skb_frag_size(frag); +			tbi->len = buf_size; -		gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; -		BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); +			gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; +			BUG_ON(gdesc->txd.gen == tq->tx_ring.gen); -		gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); -		gdesc->dword[2] = cpu_to_le32(dw2 | skb_frag_size(frag)); -		gdesc->dword[3] = 0; +			gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); +			gdesc->dword[2] = cpu_to_le32(dw2); +			gdesc->dword[3] = 0; -		dev_dbg(&adapter->netdev->dev, -			"txd[%u]: 0x%llu %u %u\n", -			tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), -			le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); -		vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); -		dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; +			dev_dbg(&adapter->netdev->dev, +				"txd[%u]: 0x%llu %u %u\n", +				tq->tx_ring.next2fill, le64_to_cpu(gdesc->txd.addr), +				le32_to_cpu(gdesc->dword[2]), gdesc->dword[3]); +			vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); +			dw2 = tq->tx_ring.gen << VMXNET3_TXD_GEN_SHIFT; + +			len -= buf_size; +			buf_offset += buf_size; +		}  	}  	ctx->eop_txd = gdesc; @@ -886,6 +901,18 @@ vmxnet3_prepare_tso(struct sk_buff *skb,  	}  } +static int txd_estimate(const struct sk_buff *skb) +{ +	int count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + 1; +	int i; + +	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { +		const struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i]; + +		count += VMXNET3_TXD_NEEDED(skb_frag_size(frag)); +	} +	return count; +}  /*   * Transmits a pkt thru a given tq @@ -914,9 +941,7 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,  	union Vmxnet3_GenericDesc tempTxDesc;  #endif -	/* conservatively estimate # of descriptors to use */ -	count = VMXNET3_TXD_NEEDED(skb_headlen(skb)) + -		skb_shinfo(skb)->nr_frags + 1; +	count = txd_estimate(skb);  	ctx.ipv4 = (vlan_get_protocol(skb) == cpu_to_be16(ETH_P_IP)); diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 607976c0016..7b4adde93c0 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -816,7 +816,7 @@ static void vxlan_cleanup(unsigned long arg)  				= container_of(p, struct vxlan_fdb, hlist);  			unsigned long timeout; -			if (f->state == NUD_PERMANENT) +			if (f->state & NUD_PERMANENT)  				continue;  			timeout = f->used + vxlan->age_interval * HZ; diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 378bd70256b..741918a2027 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -312,6 +312,7 @@ static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc)  	}  	bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); +	bf->bf_next = NULL;  	list_del(&bf->list);  	spin_unlock_bh(&sc->tx.txbuflock); @@ -393,7 +394,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0, seq_first;  	u32 ba[WME_BA_BMP_SIZE >> 5];  	int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; -	bool rc_update = true; +	bool rc_update = true, isba;  	struct ieee80211_tx_rate rates[4];  	struct ath_frame_info *fi;  	int nframes; @@ -437,13 +438,17 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,  	tidno = ieee80211_get_qos_ctl(hdr)[0] & IEEE80211_QOS_CTL_TID_MASK;  	tid = ATH_AN_2_TID(an, tidno);  	seq_first = tid->seq_start; +	isba = ts->ts_flags & ATH9K_TX_BA;  	/*  	 * The hardware occasionally sends a tx status for the wrong TID.  	 * In this case, the BA status cannot be considered valid and all  	 * subframes need to be retransmitted +	 * +	 * Only BlockAcks have a TID and therefore normal Acks cannot be +	 * checked  	 */ -	if (tidno != ts->tid) +	if (isba && tidno != ts->tid)  		txok = false;  	isaggr = bf_isaggr(bf); @@ -1774,6 +1779,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,  	list_add_tail(&bf->list, &bf_head);  	bf->bf_state.bf_type = 0; +	bf->bf_next = NULL;  	bf->bf_lastbf = bf;  	ath_tx_fill_desc(sc, bf, txq, fi->framelen);  	ath_tx_txqaddbuf(sc, txq, &bf_head, false); diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c index 01dc8891070..59474ae0aec 100644 --- a/drivers/net/wireless/rt2x00/rt2800lib.c +++ b/drivers/net/wireless/rt2x00/rt2800lib.c @@ -2449,7 +2449,7 @@ static int rt2800_get_gain_calibration_delta(struct rt2x00_dev *rt2x00dev)  	/*  	 * Check if temperature compensation is supported.  	 */ -	if (tssi_bounds[4] == 0xff) +	if (tssi_bounds[4] == 0xff || step == 0xff)  		return 0;  	/* diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index bd4708a422c..20fd974f903 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -149,6 +149,7 @@ qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha)  int  qla24xx_disable_vp(scsi_qla_host_t *vha)  { +	unsigned long flags;  	int ret;  	ret = qla24xx_control_vp(vha, VCE_COMMAND_DISABLE_VPS_LOGO_ALL); @@ -156,7 +157,9 @@ qla24xx_disable_vp(scsi_qla_host_t *vha)  	atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);  	/* Remove port id from vp target map */ +	spin_lock_irqsave(&vha->hw->vport_slock, flags);  	qlt_update_vp_map(vha, RESET_AL_PA); +	spin_unlock_irqrestore(&vha->hw->vport_slock, flags);  	qla2x00_mark_vp_devices_dead(vha);  	atomic_set(&vha->vp_state, VP_FAILED); diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c index 0e09d8f433d..62aa5584f64 100644 --- a/drivers/scsi/qla2xxx/qla_target.c +++ b/drivers/scsi/qla2xxx/qla_target.c @@ -557,6 +557,7 @@ static bool qlt_check_fcport_exist(struct scsi_qla_host *vha,  	int pmap_len;  	fc_port_t *fcport;  	int global_resets; +	unsigned long flags;  retry:  	global_resets = atomic_read(&ha->tgt.qla_tgt->tgt_global_resets_count); @@ -625,10 +626,10 @@ retry:  	    sess->s_id.b.area, sess->loop_id, fcport->d_id.b.domain,  	    fcport->d_id.b.al_pa, fcport->d_id.b.area, fcport->loop_id); -	sess->s_id = fcport->d_id; -	sess->loop_id = fcport->loop_id; -	sess->conf_compl_supported = !!(fcport->flags & -	    FCF_CONF_COMP_SUPPORTED); +	spin_lock_irqsave(&ha->hardware_lock, flags); +	ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +				(fcport->flags & FCF_CONF_COMP_SUPPORTED)); +	spin_unlock_irqrestore(&ha->hardware_lock, flags);  	res = true; @@ -740,10 +741,9 @@ static struct qla_tgt_sess *qlt_create_sess(  				qlt_undelete_sess(sess);  			kref_get(&sess->se_sess->sess_kref); -			sess->s_id = fcport->d_id; -			sess->loop_id = fcport->loop_id; -			sess->conf_compl_supported = !!(fcport->flags & -			    FCF_CONF_COMP_SUPPORTED); +			ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +						(fcport->flags & FCF_CONF_COMP_SUPPORTED)); +  			if (sess->local && !local)  				sess->local = 0;  			spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -796,8 +796,7 @@ static struct qla_tgt_sess *qlt_create_sess(  	 */  	kref_get(&sess->se_sess->sess_kref); -	sess->conf_compl_supported = !!(fcport->flags & -	    FCF_CONF_COMP_SUPPORTED); +	sess->conf_compl_supported = (fcport->flags & FCF_CONF_COMP_SUPPORTED);  	BUILD_BUG_ON(sizeof(sess->port_name) != sizeof(fcport->port_name));  	memcpy(sess->port_name, fcport->port_name, sizeof(sess->port_name)); @@ -869,10 +868,8 @@ void qlt_fc_port_added(struct scsi_qla_host *vha, fc_port_t *fcport)  			ql_dbg(ql_dbg_tgt_mgt, vha, 0xf007,  			    "Reappeared sess %p\n", sess);  		} -		sess->s_id = fcport->d_id; -		sess->loop_id = fcport->loop_id; -		sess->conf_compl_supported = !!(fcport->flags & -		    FCF_CONF_COMP_SUPPORTED); +		ha->tgt.tgt_ops->update_sess(sess, fcport->d_id, fcport->loop_id, +					(fcport->flags & FCF_CONF_COMP_SUPPORTED));  	}  	if (sess && sess->local) { diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h index 170af157121..bad749561ec 100644 --- a/drivers/scsi/qla2xxx/qla_target.h +++ b/drivers/scsi/qla2xxx/qla_target.h @@ -648,6 +648,7 @@ struct qla_tgt_func_tmpl {  	int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,  					void *, uint8_t *, uint16_t); +	void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);  	struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,  						const uint16_t);  	struct qla_tgt_sess *(*find_sess_by_s_id)(struct scsi_qla_host *, diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c index 2358c16c4c8..3d74f2f39ae 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c @@ -237,7 +237,7 @@ static char *tcm_qla2xxx_get_fabric_wwn(struct se_portal_group *se_tpg)  				struct tcm_qla2xxx_tpg, se_tpg);  	struct tcm_qla2xxx_lport *lport = tpg->lport; -	return &lport->lport_name[0]; +	return lport->lport_naa_name;  }  static char *tcm_qla2xxx_npiv_get_fabric_wwn(struct se_portal_group *se_tpg) @@ -1457,6 +1457,78 @@ static int tcm_qla2xxx_check_initiator_node_acl(  	return 0;  } +static void tcm_qla2xxx_update_sess(struct qla_tgt_sess *sess, port_id_t s_id, +				    uint16_t loop_id, bool conf_compl_supported) +{ +	struct qla_tgt *tgt = sess->tgt; +	struct qla_hw_data *ha = tgt->ha; +	struct tcm_qla2xxx_lport *lport = ha->tgt.target_lport_ptr; +	struct se_node_acl *se_nacl = sess->se_sess->se_node_acl; +	struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl, +			struct tcm_qla2xxx_nacl, se_node_acl); +	u32 key; + + +	if (sess->loop_id != loop_id || sess->s_id.b24 != s_id.b24) +		pr_info("Updating session %p from port %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x loop_id %d -> %d s_id %x:%x:%x -> %x:%x:%x\n", +			sess, +			sess->port_name[0], sess->port_name[1], +			sess->port_name[2], sess->port_name[3], +			sess->port_name[4], sess->port_name[5], +			sess->port_name[6], sess->port_name[7], +			sess->loop_id, loop_id, +			sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa, +			s_id.b.domain, s_id.b.area, s_id.b.al_pa); + +	if (sess->loop_id != loop_id) { +		/* +		 * Because we can shuffle loop IDs around and we +		 * update different sessions non-atomically, we might +		 * have overwritten this session's old loop ID +		 * already, and we might end up overwriting some other +		 * session that will be updated later.  So we have to +		 * be extra careful and we can't warn about those things... +		 */ +		if (lport->lport_loopid_map[sess->loop_id].se_nacl == se_nacl) +			lport->lport_loopid_map[sess->loop_id].se_nacl = NULL; + +		lport->lport_loopid_map[loop_id].se_nacl = se_nacl; + +		sess->loop_id = loop_id; +	} + +	if (sess->s_id.b24 != s_id.b24) { +		key = (((u32) sess->s_id.b.domain << 16) | +		       ((u32) sess->s_id.b.area   <<  8) | +		       ((u32) sess->s_id.b.al_pa)); + +		if (btree_lookup32(&lport->lport_fcport_map, key)) +			WARN(btree_remove32(&lport->lport_fcport_map, key) != se_nacl, +			     "Found wrong se_nacl when updating s_id %x:%x:%x\n", +			     sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); +		else +			WARN(1, "No lport_fcport_map entry for s_id %x:%x:%x\n", +			     sess->s_id.b.domain, sess->s_id.b.area, sess->s_id.b.al_pa); + +		key = (((u32) s_id.b.domain << 16) | +		       ((u32) s_id.b.area   <<  8) | +		       ((u32) s_id.b.al_pa)); + +		if (btree_lookup32(&lport->lport_fcport_map, key)) { +			WARN(1, "Already have lport_fcport_map entry for s_id %x:%x:%x\n", +			     s_id.b.domain, s_id.b.area, s_id.b.al_pa); +			btree_update32(&lport->lport_fcport_map, key, se_nacl); +		} else { +			btree_insert32(&lport->lport_fcport_map, key, se_nacl, GFP_ATOMIC); +		} + +		sess->s_id = s_id; +		nacl->nport_id = key; +	} + +	sess->conf_compl_supported = conf_compl_supported; +} +  /*   * Calls into tcm_qla2xxx used by qla2xxx LLD I/O path.   */ @@ -1467,6 +1539,7 @@ static struct qla_tgt_func_tmpl tcm_qla2xxx_template = {  	.free_cmd		= tcm_qla2xxx_free_cmd,  	.free_mcmd		= tcm_qla2xxx_free_mcmd,  	.free_session		= tcm_qla2xxx_free_session, +	.update_sess		= tcm_qla2xxx_update_sess,  	.check_initiator_node_acl = tcm_qla2xxx_check_initiator_node_acl,  	.find_sess_by_s_id	= tcm_qla2xxx_find_sess_by_s_id,  	.find_sess_by_loop_id	= tcm_qla2xxx_find_sess_by_loop_id, @@ -1534,6 +1607,7 @@ static struct se_wwn *tcm_qla2xxx_make_lport(  	lport->lport_wwpn = wwpn;  	tcm_qla2xxx_format_wwn(&lport->lport_name[0], TCM_QLA2XXX_NAMELEN,  				wwpn); +	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) wwpn);  	ret = tcm_qla2xxx_init_lport(lport);  	if (ret != 0) @@ -1601,6 +1675,7 @@ static struct se_wwn *tcm_qla2xxx_npiv_make_lport(  	lport->lport_npiv_wwnn = npiv_wwnn;  	tcm_qla2xxx_npiv_format_wwn(&lport->lport_npiv_name[0],  			TCM_QLA2XXX_NAMELEN, npiv_wwpn, npiv_wwnn); +	sprintf(lport->lport_naa_name, "naa.%016llx", (unsigned long long) npiv_wwpn);  /* FIXME: tcm_qla2xxx_npiv_make_lport */  	ret = -ENOSYS; diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.h b/drivers/scsi/qla2xxx/tcm_qla2xxx.h index 82549810335..9ba075fe978 100644 --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.h +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.h @@ -61,6 +61,8 @@ struct tcm_qla2xxx_lport {  	u64 lport_npiv_wwnn;  	/* ASCII formatted WWPN for FC Target Lport */  	char lport_name[TCM_QLA2XXX_NAMELEN]; +	/* ASCII formatted naa WWPN for VPD page 83 etc */ +	char lport_naa_name[TCM_QLA2XXX_NAMELEN];  	/* ASCII formatted WWPN+WWNN for NPIV FC Target Lport */  	char lport_npiv_name[TCM_QLA2XXX_NPIV_NAMELEN];  	/* map for fc_port pointers in 24-bit FC Port ID space */ diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 51046332677..643e7e27aa4 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -324,18 +324,13 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,  	struct omap2_mcspi	*mcspi;  	struct omap2_mcspi_dma  *mcspi_dma;  	unsigned int		count; -	u8			* rx;  	const u8		* tx; -	void __iomem		*chstat_reg; -	struct omap2_mcspi_cs	*cs = spi->controller_state;  	mcspi = spi_master_get_devdata(spi->master);  	mcspi_dma = &mcspi->dma_channels[spi->chip_select];  	count = xfer->len; -	rx = xfer->rx_buf;  	tx = xfer->tx_buf; -	chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0;  	if (mcspi_dma->dma_tx) {  		struct dma_async_tx_descriptor *tx; @@ -360,19 +355,6 @@ static void omap2_mcspi_tx_dma(struct spi_device *spi,  	dma_async_issue_pending(mcspi_dma->dma_tx);  	omap2_mcspi_set_dma_req(spi, 0, 1); -	wait_for_completion(&mcspi_dma->dma_tx_completion); -	dma_unmap_single(mcspi->dev, xfer->tx_dma, count, -			 DMA_TO_DEVICE); - -	/* for TX_ONLY mode, be sure all words have shifted out */ -	if (rx == NULL) { -		if (mcspi_wait_for_reg_bit(chstat_reg, -					OMAP2_MCSPI_CHSTAT_TXS) < 0) -			dev_err(&spi->dev, "TXS timed out\n"); -		else if (mcspi_wait_for_reg_bit(chstat_reg, -					OMAP2_MCSPI_CHSTAT_EOT) < 0) -			dev_err(&spi->dev, "EOT timed out\n"); -	}  }  static unsigned @@ -493,6 +475,7 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)  	struct dma_slave_config	cfg;  	enum dma_slave_buswidth width;  	unsigned es; +	void __iomem		*chstat_reg;  	mcspi = spi_master_get_devdata(spi->master);  	mcspi_dma = &mcspi->dma_channels[spi->chip_select]; @@ -527,8 +510,24 @@ omap2_mcspi_txrx_dma(struct spi_device *spi, struct spi_transfer *xfer)  		omap2_mcspi_tx_dma(spi, xfer, cfg);  	if (rx != NULL) -		return omap2_mcspi_rx_dma(spi, xfer, cfg, es); +		count = omap2_mcspi_rx_dma(spi, xfer, cfg, es); +	if (tx != NULL) { +		chstat_reg = cs->base + OMAP2_MCSPI_CHSTAT0; +		wait_for_completion(&mcspi_dma->dma_tx_completion); +		dma_unmap_single(mcspi->dev, xfer->tx_dma, xfer->len, +				 DMA_TO_DEVICE); + +		/* for TX_ONLY mode, be sure all words have shifted out */ +		if (rx == NULL) { +			if (mcspi_wait_for_reg_bit(chstat_reg, +						OMAP2_MCSPI_CHSTAT_TXS) < 0) +				dev_err(&spi->dev, "TXS timed out\n"); +			else if (mcspi_wait_for_reg_bit(chstat_reg, +						OMAP2_MCSPI_CHSTAT_EOT) < 0) +				dev_err(&spi->dev, "EOT timed out\n"); +		} +	}  	return count;  } diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d6ce2182e67..035c2c76253 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -3719,7 +3719,9 @@ restart:  		 */  		iscsit_thread_check_cpumask(conn, current, 1); -		schedule_timeout_interruptible(MAX_SCHEDULE_TIMEOUT); +		wait_event_interruptible(conn->queues_wq, +					 !iscsit_conn_all_queues_empty(conn) || +					 ts->status == ISCSI_THREAD_SET_RESET);  		if ((ts->status == ISCSI_THREAD_SET_RESET) ||  		     signal_pending(current)) diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 2ba9f9b9435..21048dbf7d1 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h @@ -486,6 +486,7 @@ struct iscsi_tmr_req {  };  struct iscsi_conn { +	wait_queue_head_t	queues_wq;  	/* Authentication Successful for this connection */  	u8			auth_complete;  	/* State connection is currently in */ diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c index cdc8a10939c..f8dbec05d5e 100644 --- a/drivers/target/iscsi/iscsi_target_login.c +++ b/drivers/target/iscsi/iscsi_target_login.c @@ -41,6 +41,7 @@  static int iscsi_login_init_conn(struct iscsi_conn *conn)  { +	init_waitqueue_head(&conn->queues_wq);  	INIT_LIST_HEAD(&conn->conn_list);  	INIT_LIST_HEAD(&conn->conn_cmd_list);  	INIT_LIST_HEAD(&conn->immed_queue_list); diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index afd98ccd40a..1a91195ab61 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c @@ -488,7 +488,7 @@ void iscsit_add_cmd_to_immediate_queue(  	atomic_set(&conn->check_immediate_queue, 1);  	spin_unlock_bh(&conn->immed_queue_lock); -	wake_up_process(conn->thread_set->tx_thread); +	wake_up(&conn->queues_wq);  }  struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_conn *conn) @@ -562,7 +562,7 @@ void iscsit_add_cmd_to_response_queue(  	atomic_inc(&cmd->response_queue_count);  	spin_unlock_bh(&conn->response_queue_lock); -	wake_up_process(conn->thread_set->tx_thread); +	wake_up(&conn->queues_wq);  }  struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *conn) @@ -616,6 +616,24 @@ static void iscsit_remove_cmd_from_response_queue(  	}  } +bool iscsit_conn_all_queues_empty(struct iscsi_conn *conn) +{ +	bool empty; + +	spin_lock_bh(&conn->immed_queue_lock); +	empty = list_empty(&conn->immed_queue_list); +	spin_unlock_bh(&conn->immed_queue_lock); + +	if (!empty) +		return empty; + +	spin_lock_bh(&conn->response_queue_lock); +	empty = list_empty(&conn->response_queue_list); +	spin_unlock_bh(&conn->response_queue_lock); + +	return empty; +} +  void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *conn)  {  	struct iscsi_queue_req *qr, *qr_tmp; diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h index 44054bd3543..894d0f83792 100644 --- a/drivers/target/iscsi/iscsi_target_util.h +++ b/drivers/target/iscsi/iscsi_target_util.h @@ -25,6 +25,7 @@ extern struct iscsi_queue_req *iscsit_get_cmd_from_immediate_queue(struct iscsi_  extern void iscsit_add_cmd_to_response_queue(struct iscsi_cmd *, struct iscsi_conn *, u8);  extern struct iscsi_queue_req *iscsit_get_cmd_from_response_queue(struct iscsi_conn *);  extern void iscsit_remove_cmd_from_tx_queues(struct iscsi_cmd *, struct iscsi_conn *); +extern bool iscsit_conn_all_queues_empty(struct iscsi_conn *);  extern void iscsit_free_queue_reqs_for_conn(struct iscsi_conn *);  extern void iscsit_release_cmd(struct iscsi_cmd *);  extern void iscsit_free_cmd(struct iscsi_cmd *); diff --git a/drivers/target/target_core_configfs.c b/drivers/target/target_core_configfs.c index 015f5be27bf..c123327499a 100644 --- a/drivers/target/target_core_configfs.c +++ b/drivers/target/target_core_configfs.c @@ -3206,7 +3206,8 @@ static int __init target_core_init_configfs(void)  	if (ret < 0)  		goto out; -	if (core_dev_setup_virtual_lun0() < 0) +	ret = core_dev_setup_virtual_lun0(); +	if (ret < 0)  		goto out;  	return 0; diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index 8d774da1632..9abef9f8eb7 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c @@ -850,20 +850,20 @@ int se_dev_check_shutdown(struct se_device *dev)  static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)  { -	u32 tmp, aligned_max_sectors; +	u32 aligned_max_sectors; +	u32 alignment;  	/*  	 * Limit max_sectors to a PAGE_SIZE aligned value for modern  	 * transport_allocate_data_tasks() operation.  	 */ -	tmp = rounddown((max_sectors * block_size), PAGE_SIZE); -	aligned_max_sectors = (tmp / block_size); -	if (max_sectors != aligned_max_sectors) { -		printk(KERN_INFO "Rounding down aligned max_sectors from %u" -				" to %u\n", max_sectors, aligned_max_sectors); -		return aligned_max_sectors; -	} +	alignment = max(1ul, PAGE_SIZE / block_size); +	aligned_max_sectors = rounddown(max_sectors, alignment); + +	if (max_sectors != aligned_max_sectors) +		pr_info("Rounding down aligned max_sectors from %u to %u\n", +			max_sectors, aligned_max_sectors); -	return max_sectors; +	return aligned_max_sectors;  }  void se_dev_set_default_attribs( diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 868f8aa04f1..a6e27d967c7 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c @@ -135,6 +135,12 @@ static int sbc_emulate_verify(struct se_cmd *cmd)  	return 0;  } +static int sbc_emulate_noop(struct se_cmd *cmd) +{ +	target_complete_cmd(cmd, GOOD); +	return 0; +} +  static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)  {  	return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors; @@ -531,6 +537,18 @@ int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)  		size = 0;  		cmd->execute_cmd = sbc_emulate_verify;  		break; +	case REZERO_UNIT: +	case SEEK_6: +	case SEEK_10: +		/* +		 * There are still clients out there which use these old SCSI-2 +		 * commands. This mainly happens when running VMs with legacy +		 * guest systems, connected via SCSI command pass-through to +		 * iSCSI targets. Make them happy and return status GOOD. +		 */ +		size = 0; +		cmd->execute_cmd = sbc_emulate_noop; +		break;  	default:  		ret = spc_parse_cdb(cmd, &size);  		if (ret) diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 9229bd9ad61..6fd434d3d7e 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c @@ -605,6 +605,8 @@ static int spc_emulate_inquiry(struct se_cmd *cmd)  	unsigned char buf[SE_INQUIRY_BUF];  	int p, ret; +	memset(buf, 0, SE_INQUIRY_BUF); +  	if (dev == tpg->tpg_virt_lun0.lun_se_dev)  		buf[0] = 0x3f; /* Not connected */  	else diff --git a/drivers/target/target_core_tmr.c b/drivers/target/target_core_tmr.c index 1c59a3c23b2..be75c4331a9 100644 --- a/drivers/target/target_core_tmr.c +++ b/drivers/target/target_core_tmr.c @@ -140,15 +140,15 @@ void core_tmr_abort_task(  		printk("ABORT_TASK: Found referenced %s task_tag: %u\n",  			se_cmd->se_tfo->get_fabric_name(), ref_tag); -		spin_lock_irq(&se_cmd->t_state_lock); +		spin_lock(&se_cmd->t_state_lock);  		if (se_cmd->transport_state & CMD_T_COMPLETE) {  			printk("ABORT_TASK: ref_tag: %u already complete, skipping\n", ref_tag); -			spin_unlock_irq(&se_cmd->t_state_lock); +			spin_unlock(&se_cmd->t_state_lock);  			spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);  			goto out;  		}  		se_cmd->transport_state |= CMD_T_ABORTED; -		spin_unlock_irq(&se_cmd->t_state_lock); +		spin_unlock(&se_cmd->t_state_lock);  		list_del_init(&se_cmd->se_cmd_list);  		kref_get(&se_cmd->cmd_kref); diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c33baff86aa..9097155e9eb 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c @@ -1616,7 +1616,6 @@ static void target_complete_tmr_failure(struct work_struct *work)  	se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;  	se_cmd->se_tfo->queue_tm_rsp(se_cmd); -	transport_generic_free_cmd(se_cmd, 0);  }  /** diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index fd03e8581af..6dd29e4ce36 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c @@ -815,7 +815,7 @@ static struct platform_device_id exynos_tmu_driver_ids[] = {  	},  	{ },  }; -MODULE_DEVICE_TABLE(platform, exynos4_tmu_driver_ids); +MODULE_DEVICE_TABLE(platform, exynos_tmu_driver_ids);  static inline struct  exynos_tmu_platform_data *exynos_get_driver_data(  			struct platform_device *pdev) diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index d4452716aaa..f7a1b574a30 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -210,7 +210,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)  		goto error_free_priv;  	} -	zone = thermal_zone_device_register("rcar_thermal", 0, priv, +	zone = thermal_zone_device_register("rcar_thermal", 0, 0, priv,  					    &rcar_thermal_zone_ops, 0, 0);  	if (IS_ERR(zone)) {  		dev_err(&pdev->dev, "thermal zone device is NULL\n"); diff --git a/drivers/video/xen-fbfront.c b/drivers/video/xen-fbfront.c index b7f5173ff9e..917bb568168 100644 --- a/drivers/video/xen-fbfront.c +++ b/drivers/video/xen-fbfront.c @@ -641,7 +641,6 @@ static void xenfb_backend_changed(struct xenbus_device *dev,  	case XenbusStateReconfiguring:  	case XenbusStateReconfigured:  	case XenbusStateUnknown: -	case XenbusStateClosed:  		break;  	case XenbusStateInitWait: @@ -670,6 +669,10 @@ InitWait:  		info->feature_resize = val;  		break; +	case XenbusStateClosed: +		if (dev->state == XenbusStateClosed) +			break; +		/* Missed the backend's CLOSING state -- fallthrough */  	case XenbusStateClosing:  		xenbus_frontend_closed(dev);  		break; diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 610bfc6be17..2e22df2f7a3 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -105,6 +105,21 @@ static void gntdev_print_maps(struct gntdev_priv *priv,  #endif  } +static void gntdev_free_map(struct grant_map *map) +{ +	if (map == NULL) +		return; + +	if (map->pages) +		free_xenballooned_pages(map->count, map->pages); +	kfree(map->pages); +	kfree(map->grants); +	kfree(map->map_ops); +	kfree(map->unmap_ops); +	kfree(map->kmap_ops); +	kfree(map); +} +  static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)  {  	struct grant_map *add; @@ -142,12 +157,7 @@ static struct grant_map *gntdev_alloc_map(struct gntdev_priv *priv, int count)  	return add;  err: -	kfree(add->pages); -	kfree(add->grants); -	kfree(add->map_ops); -	kfree(add->unmap_ops); -	kfree(add->kmap_ops); -	kfree(add); +	gntdev_free_map(add);  	return NULL;  } @@ -198,17 +208,9 @@ static void gntdev_put_map(struct grant_map *map)  		evtchn_put(map->notify.event);  	} -	if (map->pages) { -		if (!use_ptemod) -			unmap_grant_pages(map, 0, map->count); - -		free_xenballooned_pages(map->count, map->pages); -	} -	kfree(map->pages); -	kfree(map->grants); -	kfree(map->map_ops); -	kfree(map->unmap_ops); -	kfree(map); +	if (map->pages && !use_ptemod) +		unmap_grant_pages(map, 0, map->count); +	gntdev_free_map(map);  }  /* ------------------------------------------------------------------ */ diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 89f76252a16..ac727028e65 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -458,7 +458,7 @@ static ssize_t xenbus_file_write(struct file *filp,  		goto out;  	/* Can't write a xenbus message larger we can buffer */ -	if ((len + u->len) > sizeof(u->u.buffer)) { +	if (len > sizeof(u->u.buffer) - u->len) {  		/* On error, dump existing buffer */  		u->len = 0;  		rc = -EINVAL; @@ -75,6 +75,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)  	unsigned int sz = sizeof(struct bio) + extra_size;  	struct kmem_cache *slab = NULL;  	struct bio_slab *bslab, *new_bio_slabs; +	unsigned int new_bio_slab_max;  	unsigned int i, entry = -1;  	mutex_lock(&bio_slab_lock); @@ -97,12 +98,13 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)  		goto out_unlock;  	if (bio_slab_nr == bio_slab_max && entry == -1) { -		bio_slab_max <<= 1; +		new_bio_slab_max = bio_slab_max << 1;  		new_bio_slabs = krealloc(bio_slabs, -					 bio_slab_max * sizeof(struct bio_slab), +					 new_bio_slab_max * sizeof(struct bio_slab),  					 GFP_KERNEL);  		if (!new_bio_slabs)  			goto out_unlock; +		bio_slab_max = new_bio_slab_max;  		bio_slabs = new_bio_slabs;  	}  	if (entry == -1) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 02ce90972d8..9349bb37a2f 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -90,6 +90,8 @@ static int ceph_encode_fh(struct inode *inode, u32 *rawfh, int *max_len,  		*max_len = handle_length;  		type = 255;  	} +	if (dentry) +		dput(dentry);  	return type;  } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 4facdd29a35..3a100e7a62a 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -725,6 +725,10 @@ repeat_in_this_group:  				   "inode=%lu", ino + 1);  			continue;  		} +		BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); +		err = ext4_journal_get_write_access(handle, inode_bitmap_bh); +		if (err) +			goto fail;  		ext4_lock_group(sb, group);  		ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data);  		ext4_unlock_group(sb, group); @@ -738,6 +742,11 @@ repeat_in_this_group:  	goto out;  got: +	BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); +	err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); +	if (err) +		goto fail; +  	/* We may have to initialize the block bitmap if it isn't already */  	if (ext4_has_group_desc_csum(sb) &&  	    gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { @@ -771,11 +780,6 @@ got:  			goto fail;  	} -	BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); -	err = ext4_journal_get_write_access(handle, inode_bitmap_bh); -	if (err) -		goto fail; -  	BUFFER_TRACE(group_desc_bh, "get_write_access");  	err = ext4_journal_get_write_access(handle, group_desc_bh);  	if (err) @@ -823,11 +827,6 @@ got:  	}  	ext4_unlock_group(sb, group); -	BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); -	err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); -	if (err) -		goto fail; -  	BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata");  	err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh);  	if (err) diff --git a/fs/file.c b/fs/file.c index d3b5fa80b71..708d997a774 100644 --- a/fs/file.c +++ b/fs/file.c @@ -900,7 +900,7 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)  		return __close_fd(files, fd);  	if (fd >= rlimit(RLIMIT_NOFILE)) -		return -EMFILE; +		return -EBADF;  	spin_lock(&files->file_lock);  	err = expand_files(files, fd); @@ -926,7 +926,7 @@ SYSCALL_DEFINE3(dup3, unsigned int, oldfd, unsigned int, newfd, int, flags)  		return -EINVAL;  	if (newfd >= rlimit(RLIMIT_NOFILE)) -		return -EMFILE; +		return -EBADF;  	spin_lock(&files->file_lock);  	err = expand_files(files, newfd); diff --git a/fs/nfs/dns_resolve.c b/fs/nfs/dns_resolve.c index 31c26c4dcc2..ca4b11ec87a 100644 --- a/fs/nfs/dns_resolve.c +++ b/fs/nfs/dns_resolve.c @@ -217,7 +217,7 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)  {  	char buf1[NFS_DNS_HOSTNAME_MAXLEN+1];  	struct nfs_dns_ent key, *item; -	unsigned long ttl; +	unsigned int ttl;  	ssize_t len;  	int ret = -EINVAL; @@ -240,7 +240,8 @@ static int nfs_dns_parse(struct cache_detail *cd, char *buf, int buflen)  	key.namelen = len;  	memset(&key.h, 0, sizeof(key.h)); -	ttl = get_expiry(&buf); +	if (get_uint(&buf, &ttl) < 0) +		goto out;  	if (ttl == 0)  		goto out;  	key.h.expiry_time = ttl + seconds_since_boot(); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5c7325c5c5e..6fa01aea248 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync)  	if (ctx->cred != NULL)  		put_rpccred(ctx->cred);  	dput(ctx->dentry); -	nfs_sb_deactive(sb); +	if (is_sync) +		nfs_sb_deactive(sb); +	else +		nfs_sb_deactive_async(sb);  	kfree(ctx->mdsthreshold);  	kfree(ctx);  } diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 59b133c5d65..05521cadac2 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h @@ -351,10 +351,12 @@ extern int __init register_nfs_fs(void);  extern void __exit unregister_nfs_fs(void);  extern void nfs_sb_active(struct super_block *sb);  extern void nfs_sb_deactive(struct super_block *sb); +extern void nfs_sb_deactive_async(struct super_block *sb);  /* namespace.c */ +#define NFS_PATH_CANONICAL 1  extern char *nfs_path(char **p, struct dentry *dentry, -		      char *buffer, ssize_t buflen); +		      char *buffer, ssize_t buflen, unsigned flags);  extern struct vfsmount *nfs_d_automount(struct path *path);  struct vfsmount *nfs_submount(struct nfs_server *, struct dentry *,  			      struct nfs_fh *, struct nfs_fattr *); @@ -498,7 +500,7 @@ static inline char *nfs_devname(struct dentry *dentry,  				char *buffer, ssize_t buflen)  {  	char *dummy; -	return nfs_path(&dummy, dentry, buffer, buflen); +	return nfs_path(&dummy, dentry, buffer, buflen, NFS_PATH_CANONICAL);  }  /* diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c index 8e65c7f1f87..015f71f8f62 100644 --- a/fs/nfs/mount_clnt.c +++ b/fs/nfs/mount_clnt.c @@ -181,7 +181,7 @@ int nfs_mount(struct nfs_mount_request *info)  	else  		msg.rpc_proc = &mnt_clnt->cl_procinfo[MOUNTPROC_MNT]; -	status = rpc_call_sync(mnt_clnt, &msg, 0); +	status = rpc_call_sync(mnt_clnt, &msg, RPC_TASK_SOFT|RPC_TASK_TIMEOUT);  	rpc_shutdown_client(mnt_clnt);  	if (status < 0) diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c index 655925373b9..dd057bc6b65 100644 --- a/fs/nfs/namespace.c +++ b/fs/nfs/namespace.c @@ -33,6 +33,7 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;   * @dentry - pointer to dentry   * @buffer - result buffer   * @buflen - length of buffer + * @flags - options (see below)   *   * Helper function for constructing the server pathname   * by arbitrary hashed dentry. @@ -40,8 +41,14 @@ int nfs_mountpoint_expiry_timeout = 500 * HZ;   * This is mainly for use in figuring out the path on the   * server side when automounting on top of an existing partition   * and in generating /proc/mounts and friends. + * + * Supported flags: + * NFS_PATH_CANONICAL: ensure there is exactly one slash after + *		       the original device (export) name + *		       (if unset, the original name is returned verbatim)   */ -char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen) +char *nfs_path(char **p, struct dentry *dentry, char *buffer, ssize_t buflen, +	       unsigned flags)  {  	char *end;  	int namelen; @@ -74,7 +81,7 @@ rename_retry:  		rcu_read_unlock();  		goto rename_retry;  	} -	if (*end != '/') { +	if ((flags & NFS_PATH_CANONICAL) && *end != '/') {  		if (--buflen < 0) {  			spin_unlock(&dentry->d_lock);  			rcu_read_unlock(); @@ -91,9 +98,11 @@ rename_retry:  		return end;  	}  	namelen = strlen(base); -	/* Strip off excess slashes in base string */ -	while (namelen > 0 && base[namelen - 1] == '/') -		namelen--; +	if (flags & NFS_PATH_CANONICAL) { +		/* Strip off excess slashes in base string */ +		while (namelen > 0 && base[namelen - 1] == '/') +			namelen--; +	}  	buflen -= namelen;  	if (buflen < 0) {  		spin_unlock(&dentry->d_lock); diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c index 79fbb61ce20..1e09eb78543 100644 --- a/fs/nfs/nfs4namespace.c +++ b/fs/nfs/nfs4namespace.c @@ -81,7 +81,8 @@ static char *nfs_path_component(const char *nfspath, const char *end)  static char *nfs4_path(struct dentry *dentry, char *buffer, ssize_t buflen)  {  	char *limit; -	char *path = nfs_path(&limit, dentry, buffer, buflen); +	char *path = nfs_path(&limit, dentry, buffer, buflen, +			      NFS_PATH_CANONICAL);  	if (!IS_ERR(path)) {  		char *path_component = nfs_path_component(path, limit);  		if (path_component) diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 68b21d81b7a..5eec4429970 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -339,8 +339,7 @@ static int nfs4_handle_exception(struct nfs_server *server, int errorcode, struc  			dprintk("%s ERROR: %d Reset session\n", __func__,  				errorcode);  			nfs4_schedule_session_recovery(clp->cl_session, errorcode); -			exception->retry = 1; -			break; +			goto wait_on_recovery;  #endif /* defined(CONFIG_NFS_V4_1) */  		case -NFS4ERR_FILE_OPEN:  			if (exception->timeout > HZ) { @@ -1572,9 +1571,11 @@ static void nfs4_open_prepare(struct rpc_task *task, void *calldata)  	data->timestamp = jiffies;  	if (nfs4_setup_sequence(data->o_arg.server,  				&data->o_arg.seq_args, -				&data->o_res.seq_res, task)) -		return; -	rpc_call_start(task); +				&data->o_res.seq_res, +				task) != 0) +		nfs_release_seqid(data->o_arg.seqid); +	else +		rpc_call_start(task);  	return;  unlock_no_action:  	rcu_read_unlock(); @@ -1748,7 +1749,7 @@ static int nfs4_opendata_access(struct rpc_cred *cred,  	/* even though OPEN succeeded, access is denied. Close the file */  	nfs4_close_state(state, fmode); -	return -NFS4ERR_ACCESS; +	return -EACCES;  }  /* @@ -2196,7 +2197,7 @@ static void nfs4_free_closedata(void *data)  	nfs4_put_open_state(calldata->state);  	nfs_free_seqid(calldata->arg.seqid);  	nfs4_put_state_owner(sp); -	nfs_sb_deactive(sb); +	nfs_sb_deactive_async(sb);  	kfree(calldata);  } @@ -2296,9 +2297,10 @@ static void nfs4_close_prepare(struct rpc_task *task, void *data)  	if (nfs4_setup_sequence(NFS_SERVER(inode),  				&calldata->arg.seq_args,  				&calldata->res.seq_res, -				task)) -		goto out; -	rpc_call_start(task); +				task) != 0) +		nfs_release_seqid(calldata->arg.seqid); +	else +		rpc_call_start(task);  out:  	dprintk("%s: done!\n", __func__);  } @@ -4529,6 +4531,7 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)  			if (nfs4_async_handle_error(task, calldata->server, NULL) == -EAGAIN)  				rpc_restart_call_prepare(task);  	} +	nfs_release_seqid(calldata->arg.seqid);  }  static void nfs4_locku_prepare(struct rpc_task *task, void *data) @@ -4545,9 +4548,11 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)  	calldata->timestamp = jiffies;  	if (nfs4_setup_sequence(calldata->server,  				&calldata->arg.seq_args, -				&calldata->res.seq_res, task)) -		return; -	rpc_call_start(task); +				&calldata->res.seq_res, +				task) != 0) +		nfs_release_seqid(calldata->arg.seqid); +	else +		rpc_call_start(task);  }  static const struct rpc_call_ops nfs4_locku_ops = { @@ -4692,7 +4697,7 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)  	/* Do we need to do an open_to_lock_owner? */  	if (!(data->arg.lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)) {  		if (nfs_wait_on_sequence(data->arg.open_seqid, task) != 0) -			return; +			goto out_release_lock_seqid;  		data->arg.open_stateid = &state->stateid;  		data->arg.new_lock_owner = 1;  		data->res.open_seqid = data->arg.open_seqid; @@ -4701,10 +4706,15 @@ static void nfs4_lock_prepare(struct rpc_task *task, void *calldata)  	data->timestamp = jiffies;  	if (nfs4_setup_sequence(data->server,  				&data->arg.seq_args, -				&data->res.seq_res, task)) +				&data->res.seq_res, +				task) == 0) { +		rpc_call_start(task);  		return; -	rpc_call_start(task); -	dprintk("%s: done!, ret = %d\n", __func__, data->rpc_status); +	} +	nfs_release_seqid(data->arg.open_seqid); +out_release_lock_seqid: +	nfs_release_seqid(data->arg.lock_seqid); +	dprintk("%s: done!, ret = %d\n", __func__, task->tk_status);  }  static void nfs4_recover_lock_prepare(struct rpc_task *task, void *calldata) @@ -5667,7 +5677,7 @@ static void nfs4_add_and_init_slots(struct nfs4_slot_table *tbl,  		tbl->slots = new;  		tbl->max_slots = max_slots;  	} -	tbl->highest_used_slotid = -1;	/* no slot is currently used */ +	tbl->highest_used_slotid = NFS4_NO_SLOT;  	for (i = 0; i < tbl->max_slots; i++)  		tbl->slots[i].seq_nr = ivalue;  	spin_unlock(&tbl->slot_tbl_lock); diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index fe624c91bd0..2878f97bd78 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -925,8 +925,8 @@ pnfs_find_alloc_layout(struct inode *ino,  	if (likely(nfsi->layout == NULL)) {	/* Won the race? */  		nfsi->layout = new;  		return new; -	} -	pnfs_free_layout_hdr(new); +	} else if (new != NULL) +		pnfs_free_layout_hdr(new);  out_existing:  	pnfs_get_layout_hdr(nfsi->layout);  	return nfsi->layout; diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e831bce4976..652d3f7176a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -54,6 +54,7 @@  #include <linux/parser.h>  #include <linux/nsproxy.h>  #include <linux/rcupdate.h> +#include <linux/kthread.h>  #include <asm/uaccess.h> @@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)  }  EXPORT_SYMBOL_GPL(nfs_sb_deactive); +static int nfs_deactivate_super_async_work(void *ptr) +{ +	struct super_block *sb = ptr; + +	deactivate_super(sb); +	module_put_and_exit(0); +	return 0; +} + +/* + * same effect as deactivate_super, but will do final unmount in kthread + * context + */ +static void nfs_deactivate_super_async(struct super_block *sb) +{ +	struct task_struct *task; +	char buf[INET6_ADDRSTRLEN + 1]; +	struct nfs_server *server = NFS_SB(sb); +	struct nfs_client *clp = server->nfs_client; + +	if (!atomic_add_unless(&sb->s_active, -1, 1)) { +		rcu_read_lock(); +		snprintf(buf, sizeof(buf), +			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); +		rcu_read_unlock(); + +		__module_get(THIS_MODULE); +		task = kthread_run(nfs_deactivate_super_async_work, sb, +				"%s-deactivate-super", buf); +		if (IS_ERR(task)) { +			pr_err("%s: kthread_run: %ld\n", +				__func__, PTR_ERR(task)); +			/* make synchronous call and hope for the best */ +			deactivate_super(sb); +			module_put(THIS_MODULE); +		} +	} +} + +void nfs_sb_deactive_async(struct super_block *sb) +{ +	struct nfs_server *server = NFS_SB(sb); + +	if (atomic_dec_and_test(&server->active)) +		nfs_deactivate_super_async(sb); +} +EXPORT_SYMBOL_GPL(nfs_sb_deactive_async); +  /*   * Deliver file system statistics to userspace   */ @@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)  	int err = 0;  	if (!page)  		return -ENOMEM; -	devname = nfs_path(&dummy, root, page, PAGE_SIZE); +	devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);  	if (IS_ERR(devname))  		err = PTR_ERR(devname);  	else diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 13cea637eff..3f79c77153b 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c @@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata)  	nfs_dec_sillycount(data->dir);  	nfs_free_unlinkdata(data); -	nfs_sb_deactive(sb); +	nfs_sb_deactive_async(sb);  }  static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) diff --git a/include/linux/hashtable.h b/include/linux/hashtable.h new file mode 100644 index 00000000000..227c62424f3 --- /dev/null +++ b/include/linux/hashtable.h @@ -0,0 +1,192 @@ +/* + * Statically sized hash table implementation + * (C) 2012  Sasha Levin <levinsasha928@gmail.com> + */ + +#ifndef _LINUX_HASHTABLE_H +#define _LINUX_HASHTABLE_H + +#include <linux/list.h> +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/hash.h> +#include <linux/rculist.h> + +#define DEFINE_HASHTABLE(name, bits)						\ +	struct hlist_head name[1 << (bits)] =					\ +			{ [0 ... ((1 << (bits)) - 1)] = HLIST_HEAD_INIT } + +#define DECLARE_HASHTABLE(name, bits)                                   	\ +	struct hlist_head name[1 << (bits)] + +#define HASH_SIZE(name) (ARRAY_SIZE(name)) +#define HASH_BITS(name) ilog2(HASH_SIZE(name)) + +/* Use hash_32 when possible to allow for fast 32bit hashing in 64bit kernels. */ +#define hash_min(val, bits)							\ +	(sizeof(val) <= 4 ? hash_32(val, bits) : hash_long(val, bits)) + +static inline void __hash_init(struct hlist_head *ht, unsigned int sz) +{ +	unsigned int i; + +	for (i = 0; i < sz; i++) +		INIT_HLIST_HEAD(&ht[i]); +} + +/** + * hash_init - initialize a hash table + * @hashtable: hashtable to be initialized + * + * Calculates the size of the hashtable from the given parameter, otherwise + * same as hash_init_size. + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_init(hashtable) __hash_init(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_add - add an object to a hashtable + * @hashtable: hashtable to add to + * @node: the &struct hlist_node of the object to be added + * @key: the key of the object to be added + */ +#define hash_add(hashtable, node, key)						\ +	hlist_add_head(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_add_rcu - add an object to a rcu enabled hashtable + * @hashtable: hashtable to add to + * @node: the &struct hlist_node of the object to be added + * @key: the key of the object to be added + */ +#define hash_add_rcu(hashtable, node, key)					\ +	hlist_add_head_rcu(node, &hashtable[hash_min(key, HASH_BITS(hashtable))]) + +/** + * hash_hashed - check whether an object is in any hashtable + * @node: the &struct hlist_node of the object to be checked + */ +static inline bool hash_hashed(struct hlist_node *node) +{ +	return !hlist_unhashed(node); +} + +static inline bool __hash_empty(struct hlist_head *ht, unsigned int sz) +{ +	unsigned int i; + +	for (i = 0; i < sz; i++) +		if (!hlist_empty(&ht[i])) +			return false; + +	return true; +} + +/** + * hash_empty - check whether a hashtable is empty + * @hashtable: hashtable to check + * + * This has to be a macro since HASH_BITS() will not work on pointers since + * it calculates the size during preprocessing. + */ +#define hash_empty(hashtable) __hash_empty(hashtable, HASH_SIZE(hashtable)) + +/** + * hash_del - remove an object from a hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del(struct hlist_node *node) +{ +	hlist_del_init(node); +} + +/** + * hash_del_rcu - remove an object from a rcu enabled hashtable + * @node: &struct hlist_node of the object to remove + */ +static inline void hash_del_rcu(struct hlist_node *node) +{ +	hlist_del_init_rcu(node); +} + +/** + * hash_for_each - iterate over a hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each(name, bkt, node, obj, member)				\ +	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ +		hlist_for_each_entry(obj, node, &name[bkt], member) + +/** + * hash_for_each_rcu - iterate over a rcu enabled hashtable + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_rcu(name, bkt, node, obj, member)				\ +	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ +		hlist_for_each_entry_rcu(obj, node, &name[bkt], member) + +/** + * hash_for_each_safe - iterate over a hashtable safe against removal of + * hash entry + * @name: hashtable to iterate + * @bkt: integer to use as bucket loop cursor + * @node: the &struct list_head to use as a loop cursor for each entry + * @tmp: a &struct used for temporary storage + * @obj: the type * to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + */ +#define hash_for_each_safe(name, bkt, node, tmp, obj, member)			\ +	for ((bkt) = 0, node = NULL; node == NULL && (bkt) < HASH_SIZE(name); (bkt)++)\ +		hlist_for_each_entry_safe(obj, node, tmp, &name[bkt], member) + +/** + * hash_for_each_possible - iterate over all possible objects hashing to the + * same bucket + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible(name, obj, node, member, key)			\ +	hlist_for_each_entry(obj, node,	&name[hash_min(key, HASH_BITS(name))], member) + +/** + * hash_for_each_possible_rcu - iterate over all possible objects hashing to the + * same bucket in an rcu enabled hashtable + * in a rcu enabled hashtable + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible_rcu(name, obj, node, member, key)		\ +	hlist_for_each_entry_rcu(obj, node, &name[hash_min(key, HASH_BITS(name))], member) + +/** + * hash_for_each_possible_safe - iterate over all possible objects hashing to the + * same bucket safe against removals + * @name: hashtable to iterate + * @obj: the type * to use as a loop cursor for each entry + * @node: the &struct list_head to use as a loop cursor for each entry + * @tmp: a &struct used for temporary storage + * @member: the name of the hlist_node within the struct + * @key: the key of the objects to iterate over + */ +#define hash_for_each_possible_safe(name, obj, node, tmp, member, key)		\ +	hlist_for_each_entry_safe(obj, node, tmp,				\ +		&name[hash_min(key, HASH_BITS(name))], member) + + +#endif diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 93bfc9f9815..ecc554374e4 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -42,19 +42,8 @@   */  #define KVM_MEMSLOT_INVALID	(1UL << 16) -/* - * If we support unaligned MMIO, at most one fragment will be split into two: - */ -#ifdef KVM_UNALIGNED_MMIO -#  define KVM_EXTRA_MMIO_FRAGMENTS 1 -#else -#  define KVM_EXTRA_MMIO_FRAGMENTS 0 -#endif - -#define KVM_USER_MMIO_SIZE 8 - -#define KVM_MAX_MMIO_FRAGMENTS \ -	(KVM_MMIO_SIZE / KVM_USER_MMIO_SIZE + KVM_EXTRA_MMIO_FRAGMENTS) +/* Two fragments for cross MMIO pages. */ +#define KVM_MAX_MMIO_FRAGMENTS	2  /*   * For the normal pfn, the highest 12 bits should be zero, diff --git a/include/linux/raid/Kbuild b/include/linux/raid/Kbuild index 2415a64c5e5..e69de29bb2d 100644 --- a/include/linux/raid/Kbuild +++ b/include/linux/raid/Kbuild @@ -1,2 +0,0 @@ -header-y += md_p.h -header-y += md_u.h diff --git a/include/linux/raid/md_u.h b/include/linux/raid/md_u.h index fb1abb3367e..358c04bfbe2 100644 --- a/include/linux/raid/md_u.h +++ b/include/linux/raid/md_u.h @@ -11,149 +11,10 @@     (for example /usr/src/linux/COPYING); if not, write to the Free     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    */ -  #ifndef _MD_U_H  #define _MD_U_H -/* - * Different major versions are not compatible. - * Different minor versions are only downward compatible. - * Different patchlevel versions are downward and upward compatible. - */ -#define MD_MAJOR_VERSION                0 -#define MD_MINOR_VERSION                90 -/* - * MD_PATCHLEVEL_VERSION indicates kernel functionality. - * >=1 means different superblock formats are selectable using SET_ARRAY_INFO - *     and major_version/minor_version accordingly - * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT - *     in the super status byte - * >=3 means that bitmap superblock version 4 is supported, which uses - *     little-ending representation rather than host-endian - */ -#define MD_PATCHLEVEL_VERSION           3 - -/* ioctls */ - -/* status */ -#define RAID_VERSION		_IOR (MD_MAJOR, 0x10, mdu_version_t) -#define GET_ARRAY_INFO		_IOR (MD_MAJOR, 0x11, mdu_array_info_t) -#define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t) -#define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13) -#define RAID_AUTORUN		_IO (MD_MAJOR, 0x14) -#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) - -/* configuration */ -#define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20) -#define ADD_NEW_DISK		_IOW (MD_MAJOR, 0x21, mdu_disk_info_t) -#define HOT_REMOVE_DISK		_IO (MD_MAJOR, 0x22) -#define SET_ARRAY_INFO		_IOW (MD_MAJOR, 0x23, mdu_array_info_t) -#define SET_DISK_INFO		_IO (MD_MAJOR, 0x24) -#define WRITE_RAID_INFO		_IO (MD_MAJOR, 0x25) -#define UNPROTECT_ARRAY		_IO (MD_MAJOR, 0x26) -#define PROTECT_ARRAY		_IO (MD_MAJOR, 0x27) -#define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28) -#define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29) -#define HOT_GENERATE_ERROR	_IO (MD_MAJOR, 0x2a) -#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int) +#include <uapi/linux/raid/md_u.h> -/* usage */ -#define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t) -/*  0x31 was START_ARRAY  */ -#define STOP_ARRAY		_IO (MD_MAJOR, 0x32) -#define STOP_ARRAY_RO		_IO (MD_MAJOR, 0x33) -#define RESTART_ARRAY_RW	_IO (MD_MAJOR, 0x34) - -/* 63 partitions with the alternate major number (mdp) */ -#define MdpMinorShift 6 -#ifdef __KERNEL__  extern int mdp_major; -#endif - -typedef struct mdu_version_s { -	int major; -	int minor; -	int patchlevel; -} mdu_version_t; - -typedef struct mdu_array_info_s { -	/* -	 * Generic constant information -	 */ -	int major_version; -	int minor_version; -	int patch_version; -	int ctime; -	int level; -	int size; -	int nr_disks; -	int raid_disks; -	int md_minor; -	int not_persistent; - -	/* -	 * Generic state information -	 */ -	int utime;		/*  0 Superblock update time		      */ -	int state;		/*  1 State bits (clean, ...)		      */ -	int active_disks;	/*  2 Number of currently active disks	      */ -	int working_disks;	/*  3 Number of working disks		      */ -	int failed_disks;	/*  4 Number of failed disks		      */ -	int spare_disks;	/*  5 Number of spare disks		      */ - -	/* -	 * Personality information -	 */ -	int layout;		/*  0 the array's physical layout	      */ -	int chunk_size;	/*  1 chunk size in bytes		      */ - -} mdu_array_info_t; - -/* non-obvious values for 'level' */ -#define	LEVEL_MULTIPATH		(-4) -#define	LEVEL_LINEAR		(-1) -#define	LEVEL_FAULTY		(-5) - -/* we need a value for 'no level specified' and 0 - * means 'raid0', so we need something else.  This is - * for internal use only - */ -#define	LEVEL_NONE		(-1000000) - -typedef struct mdu_disk_info_s { -	/* -	 * configuration/status of one particular disk -	 */ -	int number; -	int major; -	int minor; -	int raid_disk; -	int state; - -} mdu_disk_info_t; - -typedef struct mdu_start_info_s { -	/* -	 * configuration/status of one particular disk -	 */ -	int major; -	int minor; -	int raid_disk; -	int state; - -} mdu_start_info_t; - -typedef struct mdu_bitmap_file_s -{ -	char pathname[4096]; -} mdu_bitmap_file_t; - -typedef struct mdu_param_s -{ -	int			personality;	/* 1,2,3,4 */ -	int			chunk_size;	/* in bytes */ -	int			max_fault;	/* unused for now */ -} mdu_param_t; -  #endif  - diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index f8cd4cf3fad..7d5b6000378 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -2652,6 +2652,15 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb);  unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc);  /** + * ieee80211_get_mesh_hdrlen - get mesh extension header length + * @meshhdr: the mesh extension header, only the flags field + *	(first byte) will be accessed + * Returns the length of the extension header, which is always at + * least 6 bytes and at most 18 if address 5 and 6 are present. + */ +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr); + +/**   * DOC: Data path helpers   *   * In addition to generic utilities, cfg80211 also offers diff --git a/include/sound/core.h b/include/sound/core.h index bc056687f64..93896ad1fcd 100644 --- a/include/sound/core.h +++ b/include/sound/core.h @@ -132,6 +132,7 @@ struct snd_card {  	int shutdown;			/* this card is going down */  	int free_on_last_close;		/* free in context of file_release */  	wait_queue_head_t shutdown_sleep; +	atomic_t refcount;		/* refcount for disconnection */  	struct device *dev;		/* device assigned to this card */  	struct device *card_dev;	/* cardX object for sysfs */ @@ -189,6 +190,7 @@ struct snd_minor {  	const struct file_operations *f_ops;	/* file operations */  	void *private_data;		/* private data for f_ops->open */  	struct device *dev;		/* device for sysfs */ +	struct snd_card *card_ptr;	/* assigned card instance */  };  /* return a device pointer linked to each sound device as a parent */ @@ -295,6 +297,7 @@ int snd_card_info_done(void);  int snd_component_add(struct snd_card *card, const char *component);  int snd_card_file_add(struct snd_card *card, struct file *file);  int snd_card_file_remove(struct snd_card *card, struct file *file); +void snd_card_unref(struct snd_card *card);  #define snd_card_set_dev(card, devptr) ((card)->dev = (devptr)) diff --git a/include/trace/events/xen.h b/include/trace/events/xen.h index 15ba03bdd7c..d06b6da5c1e 100644 --- a/include/trace/events/xen.h +++ b/include/trace/events/xen.h @@ -377,6 +377,14 @@ DECLARE_EVENT_CLASS(xen_mmu_pgd,  DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_pin);  DEFINE_XEN_MMU_PGD_EVENT(xen_mmu_pgd_unpin); +TRACE_EVENT(xen_mmu_flush_tlb_all, +	    TP_PROTO(int x), +	    TP_ARGS(x), +	    TP_STRUCT__entry(__array(char, x, 0)), +	    TP_fast_assign((void)x), +	    TP_printk("%s", "") +	); +  TRACE_EVENT(xen_mmu_flush_tlb,  	    TP_PROTO(int x),  	    TP_ARGS(x), diff --git a/include/uapi/linux/raid/Kbuild b/include/uapi/linux/raid/Kbuild index aafaa5aa54d..e2c3d25405d 100644 --- a/include/uapi/linux/raid/Kbuild +++ b/include/uapi/linux/raid/Kbuild @@ -1 +1,3 @@  # UAPI Header export list +header-y += md_p.h +header-y += md_u.h diff --git a/include/linux/raid/md_p.h b/include/uapi/linux/raid/md_p.h index ee753536ab7..ee753536ab7 100644 --- a/include/linux/raid/md_p.h +++ b/include/uapi/linux/raid/md_p.h diff --git a/include/uapi/linux/raid/md_u.h b/include/uapi/linux/raid/md_u.h new file mode 100644 index 00000000000..4133e744e4e --- /dev/null +++ b/include/uapi/linux/raid/md_u.h @@ -0,0 +1,155 @@ +/* +   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers +          Copyright (C) 1998 Ingo Molnar +	   +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 2, or (at your option) +   any later version. +    +   You should have received a copy of the GNU General Public License +   (for example /usr/src/linux/COPYING); if not, write to the Free +   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   +*/ + +#ifndef _UAPI_MD_U_H +#define _UAPI_MD_U_H + +/* + * Different major versions are not compatible. + * Different minor versions are only downward compatible. + * Different patchlevel versions are downward and upward compatible. + */ +#define MD_MAJOR_VERSION                0 +#define MD_MINOR_VERSION                90 +/* + * MD_PATCHLEVEL_VERSION indicates kernel functionality. + * >=1 means different superblock formats are selectable using SET_ARRAY_INFO + *     and major_version/minor_version accordingly + * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT + *     in the super status byte + * >=3 means that bitmap superblock version 4 is supported, which uses + *     little-ending representation rather than host-endian + */ +#define MD_PATCHLEVEL_VERSION           3 + +/* ioctls */ + +/* status */ +#define RAID_VERSION		_IOR (MD_MAJOR, 0x10, mdu_version_t) +#define GET_ARRAY_INFO		_IOR (MD_MAJOR, 0x11, mdu_array_info_t) +#define GET_DISK_INFO		_IOR (MD_MAJOR, 0x12, mdu_disk_info_t) +#define PRINT_RAID_DEBUG	_IO (MD_MAJOR, 0x13) +#define RAID_AUTORUN		_IO (MD_MAJOR, 0x14) +#define GET_BITMAP_FILE		_IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t) + +/* configuration */ +#define CLEAR_ARRAY		_IO (MD_MAJOR, 0x20) +#define ADD_NEW_DISK		_IOW (MD_MAJOR, 0x21, mdu_disk_info_t) +#define HOT_REMOVE_DISK		_IO (MD_MAJOR, 0x22) +#define SET_ARRAY_INFO		_IOW (MD_MAJOR, 0x23, mdu_array_info_t) +#define SET_DISK_INFO		_IO (MD_MAJOR, 0x24) +#define WRITE_RAID_INFO		_IO (MD_MAJOR, 0x25) +#define UNPROTECT_ARRAY		_IO (MD_MAJOR, 0x26) +#define PROTECT_ARRAY		_IO (MD_MAJOR, 0x27) +#define HOT_ADD_DISK		_IO (MD_MAJOR, 0x28) +#define SET_DISK_FAULTY		_IO (MD_MAJOR, 0x29) +#define HOT_GENERATE_ERROR	_IO (MD_MAJOR, 0x2a) +#define SET_BITMAP_FILE		_IOW (MD_MAJOR, 0x2b, int) + +/* usage */ +#define RUN_ARRAY		_IOW (MD_MAJOR, 0x30, mdu_param_t) +/*  0x31 was START_ARRAY  */ +#define STOP_ARRAY		_IO (MD_MAJOR, 0x32) +#define STOP_ARRAY_RO		_IO (MD_MAJOR, 0x33) +#define RESTART_ARRAY_RW	_IO (MD_MAJOR, 0x34) + +/* 63 partitions with the alternate major number (mdp) */ +#define MdpMinorShift 6 + +typedef struct mdu_version_s { +	int major; +	int minor; +	int patchlevel; +} mdu_version_t; + +typedef struct mdu_array_info_s { +	/* +	 * Generic constant information +	 */ +	int major_version; +	int minor_version; +	int patch_version; +	int ctime; +	int level; +	int size; +	int nr_disks; +	int raid_disks; +	int md_minor; +	int not_persistent; + +	/* +	 * Generic state information +	 */ +	int utime;		/*  0 Superblock update time		      */ +	int state;		/*  1 State bits (clean, ...)		      */ +	int active_disks;	/*  2 Number of currently active disks	      */ +	int working_disks;	/*  3 Number of working disks		      */ +	int failed_disks;	/*  4 Number of failed disks		      */ +	int spare_disks;	/*  5 Number of spare disks		      */ + +	/* +	 * Personality information +	 */ +	int layout;		/*  0 the array's physical layout	      */ +	int chunk_size;	/*  1 chunk size in bytes		      */ + +} mdu_array_info_t; + +/* non-obvious values for 'level' */ +#define	LEVEL_MULTIPATH		(-4) +#define	LEVEL_LINEAR		(-1) +#define	LEVEL_FAULTY		(-5) + +/* we need a value for 'no level specified' and 0 + * means 'raid0', so we need something else.  This is + * for internal use only + */ +#define	LEVEL_NONE		(-1000000) + +typedef struct mdu_disk_info_s { +	/* +	 * configuration/status of one particular disk +	 */ +	int number; +	int major; +	int minor; +	int raid_disk; +	int state; + +} mdu_disk_info_t; + +typedef struct mdu_start_info_s { +	/* +	 * configuration/status of one particular disk +	 */ +	int major; +	int minor; +	int raid_disk; +	int state; + +} mdu_start_info_t; + +typedef struct mdu_bitmap_file_s +{ +	char pathname[4096]; +} mdu_bitmap_file_t; + +typedef struct mdu_param_s +{ +	int			personality;	/* 1,2,3,4 */ +	int			chunk_size;	/* in bytes */ +	int			max_fault;	/* unused for now */ +} mdu_param_t; + +#endif /* _UAPI_MD_U_H */ diff --git a/init/main.c b/init/main.c index 9cf77ab138a..e33e09df3cb 100644 --- a/init/main.c +++ b/init/main.c @@ -442,9 +442,11 @@ void __init __weak smp_setup_processor_id(void)  {  } +# if THREAD_SIZE >= PAGE_SIZE  void __init __weak thread_info_cache_init(void)  {  } +#endif  /*   * Set up kernel memory allocators diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 159aa8bef9e..3ef1759403b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c @@ -2300,10 +2300,11 @@ restart:  			mutex_unlock(&con->mutex);  			return;  		} else { -			con->ops->put(con);  			dout("con_work %p FAILED to back off %lu\n", con,  			     con->delay); +			set_bit(CON_FLAG_BACKOFF, &con->flags);  		} +		goto done;  	}  	if (con->state == CON_STATE_STANDBY) { @@ -2749,7 +2750,8 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip)  		msg = con->ops->alloc_msg(con, hdr, skip);  		mutex_lock(&con->mutex);  		if (con->state != CON_STATE_OPEN) { -			ceph_msg_put(msg); +			if (msg) +				ceph_msg_put(msg);  			return -EAGAIN;  		}  		con->in_msg = msg; diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c index 9e0ffaf1d94..a82047282db 100644 --- a/net/ipv4/netfilter/iptable_nat.c +++ b/net/ipv4/netfilter/iptable_nat.c @@ -184,7 +184,8 @@ nf_nat_ipv4_out(unsigned int hooknum,  		if ((ct->tuplehash[dir].tuple.src.u3.ip !=  		     ct->tuplehash[!dir].tuple.dst.u3.ip) || -		    (ct->tuplehash[dir].tuple.src.u.all != +		    (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP && +		     ct->tuplehash[dir].tuple.src.u.all !=  		     ct->tuplehash[!dir].tuple.dst.u.all))  			if (nf_xfrm_me_harder(skb, AF_INET) < 0)  				ret = NF_DROP; @@ -221,6 +222,7 @@ nf_nat_ipv4_local_fn(unsigned int hooknum,  		}  #ifdef CONFIG_XFRM  		else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && +			 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMP &&  			 ct->tuplehash[dir].tuple.dst.u.all !=  			 ct->tuplehash[!dir].tuple.src.u.all)  			if (nf_xfrm_me_harder(skb, AF_INET) < 0) diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index 813b43a76fe..834857f3c87 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c @@ -313,11 +313,13 @@ static void tcp_illinois_info(struct sock *sk, u32 ext,  			.tcpv_rttcnt = ca->cnt_rtt,  			.tcpv_minrtt = ca->base_rtt,  		}; -		u64 t = ca->sum_rtt; -		do_div(t, ca->cnt_rtt); -		info.tcpv_rtt = t; +		if (info.tcpv_rttcnt > 0) { +			u64 t = ca->sum_rtt; +			do_div(t, info.tcpv_rttcnt); +			info.tcpv_rtt = t; +		}  		nla_put(skb, INET_DIAG_VEGASINFO, sizeof(info), &info);  	}  } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 1db66398358..2c2b13a999e 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -4529,6 +4529,9 @@ int tcp_send_rcvq(struct sock *sk, struct msghdr *msg, size_t size)  	struct tcphdr *th;  	bool fragstolen; +	if (size == 0) +		return 0; +  	skb = alloc_skb(size + sizeof(*th), sk->sk_allocation);  	if (!skb)  		goto err; diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4c752a6e0bc..53bc5847bfa 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c @@ -864,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,  	}  	a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];  	if (a) { -		if (nla_len(a) != sizeof(sizeof(struct in6_addr))) +		if (nla_len(a) != sizeof(struct in6_addr))  			return -EINVAL;  		addr->family = AF_INET6;  		memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6)); diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c index e418bd6350a..d57dab17a18 100644 --- a/net/ipv6/netfilter/ip6table_nat.c +++ b/net/ipv6/netfilter/ip6table_nat.c @@ -186,7 +186,8 @@ nf_nat_ipv6_out(unsigned int hooknum,  		if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,  				      &ct->tuplehash[!dir].tuple.dst.u3) || -		    (ct->tuplehash[dir].tuple.src.u.all != +		    (ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 && +		     ct->tuplehash[dir].tuple.src.u.all !=  		     ct->tuplehash[!dir].tuple.dst.u.all))  			if (nf_xfrm_me_harder(skb, AF_INET6) < 0)  				ret = NF_DROP; @@ -222,6 +223,7 @@ nf_nat_ipv6_local_fn(unsigned int hooknum,  		}  #ifdef CONFIG_XFRM  		else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && +			 ct->tuplehash[dir].tuple.dst.protonum != IPPROTO_ICMPV6 &&  			 ct->tuplehash[dir].tuple.dst.u.all !=  			 ct->tuplehash[!dir].tuple.src.u.all)  			if (nf_xfrm_me_harder(skb, AF_INET6)) diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 18bd9bbbd1c..22c8ea95118 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -85,7 +85,7 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = {  	{ }  }; -static int __net_init nf_ct_frag6_sysctl_register(struct net *net) +static int nf_ct_frag6_sysctl_register(struct net *net)  {  	struct ctl_table *table;  	struct ctl_table_header *hdr; @@ -127,7 +127,7 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net)  }  #else -static int __net_init nf_ct_frag6_sysctl_register(struct net *net) +static int nf_ct_frag6_sysctl_register(struct net *net)  {  	return 0;  } diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 37b8b8ba31f..76125c57ee6 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c @@ -291,6 +291,7 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p  out_del_dev:  	free_netdev(dev); +	spriv->dev = NULL;  out_del_session:  	l2tp_session_delete(session);  out: diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5f3620f0bc0..bf87c70ac6c 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c @@ -1108,7 +1108,7 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,  	sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;  	sdata->u.ibss.ibss_join_req = jiffies; -	memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN); +	memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);  	sdata->u.ibss.ssid_len = params->ssid_len;  	mutex_unlock(&sdata->u.ibss.mtx); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 61c621e9273..00ade7feb2e 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -531,6 +531,11 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)  		if (ieee80211_is_action(hdr->frame_control)) {  			u8 category; + +			/* make sure category field is present */ +			if (rx->skb->len < IEEE80211_MIN_ACTION_SIZE) +				return RX_DROP_MONITOR; +  			mgmt = (struct ieee80211_mgmt *)hdr;  			category = mgmt->u.action.category;  			if (category != WLAN_CATEGORY_MESH_ACTION && @@ -883,14 +888,16 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)  		 */  		if (rx->sta && rx->sdata->vif.type == NL80211_IFTYPE_STATION &&  		    ieee80211_is_data_present(hdr->frame_control)) { -			u16 ethertype; -			u8 *payload; +			unsigned int hdrlen; +			__be16 ethertype; -			payload = rx->skb->data + -				ieee80211_hdrlen(hdr->frame_control); -			ethertype = (payload[6] << 8) | payload[7]; -			if (cpu_to_be16(ethertype) == -			    rx->sdata->control_port_protocol) +			hdrlen = ieee80211_hdrlen(hdr->frame_control); + +			if (rx->skb->len < hdrlen + 8) +				return RX_DROP_MONITOR; + +			skb_copy_bits(rx->skb, hdrlen + 6, ðertype, 2); +			if (ethertype == rx->sdata->control_port_protocol)  				return RX_CONTINUE;  		} @@ -1462,11 +1469,14 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)  	hdr = (struct ieee80211_hdr *)rx->skb->data;  	fc = hdr->frame_control; + +	if (ieee80211_is_ctl(fc)) +		return RX_CONTINUE; +  	sc = le16_to_cpu(hdr->seq_ctrl);  	frag = sc & IEEE80211_SCTL_FRAG;  	if (likely((!ieee80211_has_morefrags(fc) && frag == 0) || -		   (rx->skb)->len < 24 ||  		   is_multicast_ether_addr(hdr->addr1))) {  		/* not fragmented */  		goto out; @@ -1889,6 +1899,20 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	hdr = (struct ieee80211_hdr *) skb->data;  	hdrlen = ieee80211_hdrlen(hdr->frame_control); + +	/* make sure fixed part of mesh header is there, also checks skb len */ +	if (!pskb_may_pull(rx->skb, hdrlen + 6)) +		return RX_DROP_MONITOR; + +	mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); + +	/* make sure full mesh header is there, also checks skb len */ +	if (!pskb_may_pull(rx->skb, +			   hdrlen + ieee80211_get_mesh_hdrlen(mesh_hdr))) +		return RX_DROP_MONITOR; + +	/* reload pointers */ +	hdr = (struct ieee80211_hdr *) skb->data;  	mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen);  	/* frame is in RMC, don't forward */ @@ -1897,7 +1921,8 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	    mesh_rmc_check(hdr->addr3, mesh_hdr, rx->sdata))  		return RX_DROP_MONITOR; -	if (!ieee80211_is_data(hdr->frame_control)) +	if (!ieee80211_is_data(hdr->frame_control) || +	    !(status->rx_flags & IEEE80211_RX_RA_MATCH))  		return RX_CONTINUE;  	if (!mesh_hdr->ttl) @@ -1911,9 +1936,12 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  		if (is_multicast_ether_addr(hdr->addr1)) {  			mpp_addr = hdr->addr3;  			proxied_addr = mesh_hdr->eaddr1; -		} else { +		} else if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6) { +			/* has_a4 already checked in ieee80211_rx_mesh_check */  			mpp_addr = hdr->addr4;  			proxied_addr = mesh_hdr->eaddr2; +		} else { +			return RX_DROP_MONITOR;  		}  		rcu_read_lock(); @@ -1941,12 +1969,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)  	}  	skb_set_queue_mapping(skb, q); -	if (!(status->rx_flags & IEEE80211_RX_RA_MATCH)) -		goto out; -  	if (!--mesh_hdr->ttl) {  		IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl); -		return RX_DROP_MONITOR; +		goto out;  	}  	if (!ifmsh->mshcfg.dot11MeshForwarding) @@ -2353,6 +2378,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		}  		break;  	case WLAN_CATEGORY_SELF_PROTECTED: +		if (len < (IEEE80211_MIN_ACTION_SIZE + +			   sizeof(mgmt->u.action.u.self_prot.action_code))) +			break; +  		switch (mgmt->u.action.u.self_prot.action_code) {  		case WLAN_SP_MESH_PEERING_OPEN:  		case WLAN_SP_MESH_PEERING_CLOSE: @@ -2371,6 +2400,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)  		}  		break;  	case WLAN_CATEGORY_MESH_ACTION: +		if (len < (IEEE80211_MIN_ACTION_SIZE + +			   sizeof(mgmt->u.action.u.mesh_action.action_code))) +			break; +  		if (!ieee80211_vif_is_mesh(&sdata->vif))  			break;  		if (mesh_action_is_path_sel(mgmt) && @@ -2913,10 +2946,15 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,  	if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))  		local->dot11ReceivedFragmentCount++; -	if (ieee80211_is_mgmt(fc)) -		err = skb_linearize(skb); -	else +	if (ieee80211_is_mgmt(fc)) { +		/* drop frame if too short for header */ +		if (skb->len < ieee80211_hdrlen(fc)) +			err = -ENOBUFS; +		else +			err = skb_linearize(skb); +	} else {  		err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); +	}  	if (err) {  		dev_kfree_skb(skb); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 94e58687397..239391807ca 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -643,13 +643,41 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,  			break;  		} -		if (id != WLAN_EID_VENDOR_SPECIFIC && -		    id != WLAN_EID_QUIET && -		    test_bit(id, seen_elems)) { -			elems->parse_error = true; -			left -= elen; -			pos += elen; -			continue; +		switch (id) { +		case WLAN_EID_SSID: +		case WLAN_EID_SUPP_RATES: +		case WLAN_EID_FH_PARAMS: +		case WLAN_EID_DS_PARAMS: +		case WLAN_EID_CF_PARAMS: +		case WLAN_EID_TIM: +		case WLAN_EID_IBSS_PARAMS: +		case WLAN_EID_CHALLENGE: +		case WLAN_EID_RSN: +		case WLAN_EID_ERP_INFO: +		case WLAN_EID_EXT_SUPP_RATES: +		case WLAN_EID_HT_CAPABILITY: +		case WLAN_EID_HT_OPERATION: +		case WLAN_EID_VHT_CAPABILITY: +		case WLAN_EID_VHT_OPERATION: +		case WLAN_EID_MESH_ID: +		case WLAN_EID_MESH_CONFIG: +		case WLAN_EID_PEER_MGMT: +		case WLAN_EID_PREQ: +		case WLAN_EID_PREP: +		case WLAN_EID_PERR: +		case WLAN_EID_RANN: +		case WLAN_EID_CHANNEL_SWITCH: +		case WLAN_EID_EXT_CHANSWITCH_ANN: +		case WLAN_EID_COUNTRY: +		case WLAN_EID_PWR_CONSTRAINT: +		case WLAN_EID_TIMEOUT_INTERVAL: +			if (test_bit(id, seen_elems)) { +				elems->parse_error = true; +				left -= elen; +				pos += elen; +				continue; +			} +			break;  		}  		if (calc_crc && id < 64 && (filter & (1ULL << id))) diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 1b30b0dee70..962795e839a 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -753,7 +753,8 @@ static int callforward_do_filter(const union nf_inet_addr *src,  				   flowi4_to_flowi(&fl1), false)) {  			if (!afinfo->route(&init_net, (struct dst_entry **)&rt2,  					   flowi4_to_flowi(&fl2), false)) { -				if (rt1->rt_gateway == rt2->rt_gateway && +				if (rt_nexthop(rt1, fl1.daddr) == +				    rt_nexthop(rt2, fl2.daddr) &&  				    rt1->dst.dev  == rt2->dst.dev)  					ret = 1;  				dst_release(&rt2->dst); diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 59d16ea927f..a60d1f8b41c 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -974,7 +974,7 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk,  	void *addr_buf;  	struct sctp_af *af; -	SCTP_DEBUG_PRINTK("sctp_setsocktopt_bindx: sk %p addrs %p" +	SCTP_DEBUG_PRINTK("sctp_setsockopt_bindx: sk %p addrs %p"  			  " addrs_size %d opt %d\n", sk, addrs, addrs_size, op);  	if (unlikely(addrs_size <= 0)) diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index 5a3d675d2f2..a9c0bbccad6 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c @@ -172,7 +172,7 @@ out_free:  		xprt_free_allocation(req);  	dprintk("RPC:       setup backchannel transport failed\n"); -	return -1; +	return -ENOMEM;  }  EXPORT_SYMBOL_GPL(xprt_setup_backchannel); diff --git a/net/wireless/core.c b/net/wireless/core.c index 443d4d7deea..3f725305208 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -526,8 +526,7 @@ int wiphy_register(struct wiphy *wiphy)  		for (i = 0; i < sband->n_channels; i++) {  			sband->channels[i].orig_flags =  				sband->channels[i].flags; -			sband->channels[i].orig_mag = -				sband->channels[i].max_antenna_gain; +			sband->channels[i].orig_mag = INT_MAX;  			sband->channels[i].orig_mpwr =  				sband->channels[i].max_power;  			sband->channels[i].band = band; diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 3b8cbbc214d..bcc7d7ee5a5 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -908,7 +908,7 @@ static void handle_channel(struct wiphy *wiphy,  			map_regdom_flags(reg_rule->flags) | bw_flags;  		chan->max_antenna_gain = chan->orig_mag =  			(int) MBI_TO_DBI(power_rule->max_antenna_gain); -		chan->max_power = chan->orig_mpwr = +		chan->max_reg_power = chan->max_power = chan->orig_mpwr =  			(int) MBM_TO_DBM(power_rule->max_eirp);  		return;  	} @@ -1331,7 +1331,8 @@ static void handle_channel_custom(struct wiphy *wiphy,  	chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;  	chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); -	chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); +	chan->max_reg_power = chan->max_power = +		(int) MBM_TO_DBM(power_rule->max_eirp);  }  static void handle_band_custom(struct wiphy *wiphy, enum ieee80211_band band, diff --git a/net/wireless/util.c b/net/wireless/util.c index ef35f4ef2aa..2762e832998 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -309,23 +309,21 @@ unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)  }  EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); -static int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) +unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)  {  	int ae = meshhdr->flags & MESH_FLAGS_AE; -	/* 7.1.3.5a.2 */ +	/* 802.11-2012, 8.2.4.7.3 */  	switch (ae) { +	default:  	case 0:  		return 6;  	case MESH_FLAGS_AE_A4:  		return 12;  	case MESH_FLAGS_AE_A5_A6:  		return 18; -	case (MESH_FLAGS_AE_A4 | MESH_FLAGS_AE_A5_A6): -		return 24; -	default: -		return 6;  	}  } +EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);  int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,  			   enum nl80211_iftype iftype) @@ -373,6 +371,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,  			/* make sure meshdr->flags is on the linear part */  			if (!pskb_may_pull(skb, hdrlen + 1))  				return -1; +			if (meshdr->flags & MESH_FLAGS_AE_A4) +				return -1;  			if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {  				skb_copy_bits(skb, hdrlen +  					offsetof(struct ieee80211s_hdr, eaddr1), @@ -397,6 +397,8 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,  			/* make sure meshdr->flags is on the linear part */  			if (!pskb_may_pull(skb, hdrlen + 1))  				return -1; +			if (meshdr->flags & MESH_FLAGS_AE_A5_A6) +				return -1;  			if (meshdr->flags & MESH_FLAGS_AE_A4)  				skb_copy_bits(skb, hdrlen +  					offsetof(struct ieee80211s_hdr, eaddr1), diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c index c40ae573346..ad11dc99479 100644 --- a/sound/core/compress_offload.c +++ b/sound/core/compress_offload.c @@ -100,12 +100,15 @@ static int snd_compr_open(struct inode *inode, struct file *f)  	if (dirn != compr->direction) {  		pr_err("this device doesn't support this direction\n"); +		snd_card_unref(compr->card);  		return -EINVAL;  	}  	data = kzalloc(sizeof(*data), GFP_KERNEL); -	if (!data) +	if (!data) { +		snd_card_unref(compr->card);  		return -ENOMEM; +	}  	data->stream.ops = compr->ops;  	data->stream.direction = dirn;  	data->stream.private_data = compr->private_data; @@ -113,6 +116,7 @@ static int snd_compr_open(struct inode *inode, struct file *f)  	runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);  	if (!runtime) {  		kfree(data); +		snd_card_unref(compr->card);  		return -ENOMEM;  	}  	runtime->state = SNDRV_PCM_STATE_OPEN; @@ -126,7 +130,8 @@ static int snd_compr_open(struct inode *inode, struct file *f)  		kfree(runtime);  		kfree(data);  	} -	return ret; +	snd_card_unref(compr->card); +	return 0;  }  static int snd_compr_free(struct inode *inode, struct file *f) diff --git a/sound/core/control.c b/sound/core/control.c index 7e86a5b9f3b..8c7c2c9bba6 100644 --- a/sound/core/control.c +++ b/sound/core/control.c @@ -86,6 +86,7 @@ static int snd_ctl_open(struct inode *inode, struct file *file)  	write_lock_irqsave(&card->ctl_files_rwlock, flags);  	list_add_tail(&ctl->list, &card->ctl_files);  	write_unlock_irqrestore(&card->ctl_files_rwlock, flags); +	snd_card_unref(card);  	return 0;        __error: @@ -93,6 +94,8 @@ static int snd_ctl_open(struct inode *inode, struct file *file)        __error2:  	snd_card_file_remove(card, file);        __error1: +	if (card) +		snd_card_unref(card);        	return err;  } @@ -1434,6 +1437,8 @@ static ssize_t snd_ctl_read(struct file *file, char __user *buffer,  			spin_unlock_irq(&ctl->read_lock);  			schedule();  			remove_wait_queue(&ctl->change_sleep, &wait); +			if (ctl->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return -ERESTARTSYS;  			spin_lock_irq(&ctl->read_lock); diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c index 75ea16f35b1..3f7f6628cf7 100644 --- a/sound/core/hwdep.c +++ b/sound/core/hwdep.c @@ -100,8 +100,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)  	if (hw == NULL)  		return -ENODEV; -	if (!try_module_get(hw->card->module)) +	if (!try_module_get(hw->card->module)) { +		snd_card_unref(hw->card);  		return -EFAULT; +	}  	init_waitqueue_entry(&wait, current);  	add_wait_queue(&hw->open_wait, &wait); @@ -129,6 +131,10 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)  		mutex_unlock(&hw->open_mutex);  		schedule();  		mutex_lock(&hw->open_mutex); +		if (hw->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -148,6 +154,7 @@ static int snd_hwdep_open(struct inode *inode, struct file * file)  	mutex_unlock(&hw->open_mutex);  	if (err < 0)  		module_put(hw->card->module); +	snd_card_unref(hw->card);  	return err;  } @@ -459,12 +466,15 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)  		mutex_unlock(®ister_mutex);  		return -EINVAL;  	} +	mutex_lock(&hwdep->open_mutex); +	wake_up(&hwdep->open_wait);  #ifdef CONFIG_SND_OSSEMUL  	if (hwdep->ossreg)  		snd_unregister_oss_device(hwdep->oss_type, hwdep->card, hwdep->device);  #endif  	snd_unregister_device(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card, hwdep->device);  	list_del_init(&hwdep->list); +	mutex_unlock(&hwdep->open_mutex);  	mutex_unlock(®ister_mutex);  	return 0;  } diff --git a/sound/core/init.c b/sound/core/init.c index d8ec849af12..7b012d15c2c 100644 --- a/sound/core/init.c +++ b/sound/core/init.c @@ -213,6 +213,7 @@ int snd_card_create(int idx, const char *xid,  	spin_lock_init(&card->files_lock);  	INIT_LIST_HEAD(&card->files_list);  	init_waitqueue_head(&card->shutdown_sleep); +	atomic_set(&card->refcount, 0);  #ifdef CONFIG_PM  	mutex_init(&card->power_lock);  	init_waitqueue_head(&card->power_sleep); @@ -446,21 +447,36 @@ static int snd_card_do_free(struct snd_card *card)  	return 0;  } +/** + * snd_card_unref - release the reference counter + * @card: the card instance + * + * Decrements the reference counter.  When it reaches to zero, wake up + * the sleeper and call the destructor if needed. + */ +void snd_card_unref(struct snd_card *card) +{ +	if (atomic_dec_and_test(&card->refcount)) { +		wake_up(&card->shutdown_sleep); +		if (card->free_on_last_close) +			snd_card_do_free(card); +	} +} +EXPORT_SYMBOL(snd_card_unref); +  int snd_card_free_when_closed(struct snd_card *card)  { -	int free_now = 0; -	int ret = snd_card_disconnect(card); -	if (ret) -		return ret; +	int ret; -	spin_lock(&card->files_lock); -	if (list_empty(&card->files_list)) -		free_now = 1; -	else -		card->free_on_last_close = 1; -	spin_unlock(&card->files_lock); +	atomic_inc(&card->refcount); +	ret = snd_card_disconnect(card); +	if (ret) { +		atomic_dec(&card->refcount); +		return ret; +	} -	if (free_now) +	card->free_on_last_close = 1; +	if (atomic_dec_and_test(&card->refcount))  		snd_card_do_free(card);  	return 0;  } @@ -474,7 +490,7 @@ int snd_card_free(struct snd_card *card)  		return ret;  	/* wait, until all devices are ready for the free operation */ -	wait_event(card->shutdown_sleep, list_empty(&card->files_list)); +	wait_event(card->shutdown_sleep, !atomic_read(&card->refcount));  	snd_card_do_free(card);  	return 0;  } @@ -886,6 +902,7 @@ int snd_card_file_add(struct snd_card *card, struct file *file)  		return -ENODEV;  	}  	list_add(&mfile->list, &card->files_list); +	atomic_inc(&card->refcount);  	spin_unlock(&card->files_lock);  	return 0;  } @@ -908,7 +925,6 @@ EXPORT_SYMBOL(snd_card_file_add);  int snd_card_file_remove(struct snd_card *card, struct file *file)  {  	struct snd_monitor_file *mfile, *found = NULL; -	int last_close = 0;  	spin_lock(&card->files_lock);  	list_for_each_entry(mfile, &card->files_list, list) { @@ -923,19 +939,13 @@ int snd_card_file_remove(struct snd_card *card, struct file *file)  			break;  		}  	} -	if (list_empty(&card->files_list)) -		last_close = 1;  	spin_unlock(&card->files_lock); -	if (last_close) { -		wake_up(&card->shutdown_sleep); -		if (card->free_on_last_close) -			snd_card_do_free(card); -	}  	if (!found) {  		snd_printk(KERN_ERR "ALSA card file remove problem (%p)\n", file);  		return -ENOENT;  	}  	kfree(found); +	snd_card_unref(card);  	return 0;  } diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c index 29f6ded0255..a9a2e63c022 100644 --- a/sound/core/oss/mixer_oss.c +++ b/sound/core/oss/mixer_oss.c @@ -52,14 +52,19 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)  					 SNDRV_OSS_DEVICE_TYPE_MIXER);  	if (card == NULL)  		return -ENODEV; -	if (card->mixer_oss == NULL) +	if (card->mixer_oss == NULL) { +		snd_card_unref(card);  		return -ENODEV; +	}  	err = snd_card_file_add(card, file); -	if (err < 0) +	if (err < 0) { +		snd_card_unref(card);  		return err; +	}  	fmixer = kzalloc(sizeof(*fmixer), GFP_KERNEL);  	if (fmixer == NULL) {  		snd_card_file_remove(card, file); +		snd_card_unref(card);  		return -ENOMEM;  	}  	fmixer->card = card; @@ -68,6 +73,7 @@ static int snd_mixer_oss_open(struct inode *inode, struct file *file)  	if (!try_module_get(card->module)) {  		kfree(fmixer);  		snd_card_file_remove(card, file); +		snd_card_unref(card);  		return -EFAULT;  	}  	return 0; diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c index 08fde0060fd..f337b66a020 100644 --- a/sound/core/oss/pcm_oss.c +++ b/sound/core/oss/pcm_oss.c @@ -2441,6 +2441,10 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)  		mutex_unlock(&pcm->open_mutex);  		schedule();  		mutex_lock(&pcm->open_mutex); +		if (pcm->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -2457,6 +2461,8 @@ static int snd_pcm_oss_open(struct inode *inode, struct file *file)        __error2:        	snd_card_file_remove(pcm->card, file);        __error1: +	if (pcm) +		snd_card_unref(pcm->card);  	return err;  } diff --git a/sound/core/pcm.c b/sound/core/pcm.c index f2991940b27..030102caeee 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -1086,11 +1086,19 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)  	if (list_empty(&pcm->list))  		goto unlock; +	mutex_lock(&pcm->open_mutex); +	wake_up(&pcm->open_wait);  	list_del_init(&pcm->list);  	for (cidx = 0; cidx < 2; cidx++) -		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) -			if (substream->runtime) +		for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) { +			snd_pcm_stream_lock_irq(substream); +			if (substream->runtime) {  				substream->runtime->status->state = SNDRV_PCM_STATE_DISCONNECTED; +				wake_up(&substream->runtime->sleep); +				wake_up(&substream->runtime->tsleep); +			} +			snd_pcm_stream_unlock_irq(substream); +		}  	list_for_each_entry(notify, &snd_pcm_notify_list, list) {  		notify->n_disconnect(pcm);  	} @@ -1110,6 +1118,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)  			pcm->streams[cidx].chmap_kctl = NULL;  		}  	} +	mutex_unlock(&pcm->open_mutex);   unlock:  	mutex_unlock(®ister_mutex);  	return 0; diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c index 5e12e5bacbb..6e8872de5ba 100644 --- a/sound/core/pcm_native.c +++ b/sound/core/pcm_native.c @@ -369,6 +369,14 @@ static int period_to_usecs(struct snd_pcm_runtime *runtime)  	return usecs;  } +static void snd_pcm_set_state(struct snd_pcm_substream *substream, int state) +{ +	snd_pcm_stream_lock_irq(substream); +	if (substream->runtime->status->state != SNDRV_PCM_STATE_DISCONNECTED) +		substream->runtime->status->state = state; +	snd_pcm_stream_unlock_irq(substream); +} +  static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  			     struct snd_pcm_hw_params *params)  { @@ -452,7 +460,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  		runtime->boundary *= 2;  	snd_pcm_timer_resolution_change(substream); -	runtime->status->state = SNDRV_PCM_STATE_SETUP; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_SETUP);  	if (pm_qos_request_active(&substream->latency_pm_qos_req))  		pm_qos_remove_request(&substream->latency_pm_qos_req); @@ -464,7 +472,7 @@ static int snd_pcm_hw_params(struct snd_pcm_substream *substream,  	/* hardware might be unusable from this time,  	   so we force application to retry to set  	   the correct hardware parameter settings */ -	runtime->status->state = SNDRV_PCM_STATE_OPEN; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);  	if (substream->ops->hw_free != NULL)  		substream->ops->hw_free(substream);  	return err; @@ -512,7 +520,7 @@ static int snd_pcm_hw_free(struct snd_pcm_substream *substream)  		return -EBADFD;  	if (substream->ops->hw_free)  		result = substream->ops->hw_free(substream); -	runtime->status->state = SNDRV_PCM_STATE_OPEN; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_OPEN);  	pm_qos_remove_request(&substream->latency_pm_qos_req);  	return result;  } @@ -1320,7 +1328,7 @@ static void snd_pcm_post_prepare(struct snd_pcm_substream *substream, int state)  {  	struct snd_pcm_runtime *runtime = substream->runtime;  	runtime->control->appl_ptr = runtime->status->hw_ptr; -	runtime->status->state = SNDRV_PCM_STATE_PREPARED; +	snd_pcm_set_state(substream, SNDRV_PCM_STATE_PREPARED);  }  static struct action_ops snd_pcm_action_prepare = { @@ -1510,6 +1518,10 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,  		down_read(&snd_pcm_link_rwsem);  		snd_pcm_stream_lock_irq(substream);  		remove_wait_queue(&to_check->sleep, &wait); +		if (card->shutdown) { +			result = -ENODEV; +			break; +		}  		if (tout == 0) {  			if (substream->runtime->status->state == SNDRV_PCM_STATE_SUSPENDED)  				result = -ESTRPIPE; @@ -1634,6 +1646,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)  	write_unlock_irq(&snd_pcm_link_rwlock);  	up_write(&snd_pcm_link_rwsem);   _nolock: +	snd_card_unref(substream1->pcm->card);  	fput_light(file, fput_needed);  	if (res < 0)  		kfree(group); @@ -2108,7 +2121,9 @@ static int snd_pcm_playback_open(struct inode *inode, struct file *file)  		return err;  	pcm = snd_lookup_minor_data(iminor(inode),  				    SNDRV_DEVICE_TYPE_PCM_PLAYBACK); -	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); +	err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_PLAYBACK); +	snd_card_unref(pcm->card); +	return err;  }  static int snd_pcm_capture_open(struct inode *inode, struct file *file) @@ -2119,7 +2134,9 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)  		return err;  	pcm = snd_lookup_minor_data(iminor(inode),  				    SNDRV_DEVICE_TYPE_PCM_CAPTURE); -	return snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); +	err = snd_pcm_open(file, pcm, SNDRV_PCM_STREAM_CAPTURE); +	snd_card_unref(pcm->card); +	return err;  }  static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream) @@ -2156,6 +2173,10 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)  		mutex_unlock(&pcm->open_mutex);  		schedule();  		mutex_lock(&pcm->open_mutex); +		if (pcm->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c index ebf6e49ad3d..1bb95aeea08 100644 --- a/sound/core/rawmidi.c +++ b/sound/core/rawmidi.c @@ -379,8 +379,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  	if (rmidi == NULL)  		return -ENODEV; -	if (!try_module_get(rmidi->card->module)) +	if (!try_module_get(rmidi->card->module)) { +		snd_card_unref(rmidi->card);  		return -ENXIO; +	}  	mutex_lock(&rmidi->open_mutex);  	card = rmidi->card; @@ -422,6 +424,10 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  		mutex_unlock(&rmidi->open_mutex);  		schedule();  		mutex_lock(&rmidi->open_mutex); +		if (rmidi->card->shutdown) { +			err = -ENODEV; +			break; +		}  		if (signal_pending(current)) {  			err = -ERESTARTSYS;  			break; @@ -440,6 +446,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)  #endif  	file->private_data = rawmidi_file;  	mutex_unlock(&rmidi->open_mutex); +	snd_card_unref(rmidi->card);  	return 0;   __error: @@ -447,6 +454,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)   __error_card:  	mutex_unlock(&rmidi->open_mutex);  	module_put(rmidi->card->module); +	snd_card_unref(rmidi->card);  	return err;  } @@ -991,6 +999,8 @@ static ssize_t snd_rawmidi_read(struct file *file, char __user *buf, size_t coun  			spin_unlock_irq(&runtime->lock);  			schedule();  			remove_wait_queue(&runtime->sleep, &wait); +			if (rfile->rmidi->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return result > 0 ? result : -ERESTARTSYS;  			if (!runtime->avail) @@ -1234,6 +1244,8 @@ static ssize_t snd_rawmidi_write(struct file *file, const char __user *buf,  			spin_unlock_irq(&runtime->lock);  			timeout = schedule_timeout(30 * HZ);  			remove_wait_queue(&runtime->sleep, &wait); +			if (rfile->rmidi->card->shutdown) +				return -ENODEV;  			if (signal_pending(current))  				return result > 0 ? result : -ERESTARTSYS;  			if (!runtime->avail && !timeout) @@ -1609,9 +1621,20 @@ static int snd_rawmidi_dev_register(struct snd_device *device)  static int snd_rawmidi_dev_disconnect(struct snd_device *device)  {  	struct snd_rawmidi *rmidi = device->device_data; +	int dir;  	mutex_lock(®ister_mutex); +	mutex_lock(&rmidi->open_mutex); +	wake_up(&rmidi->open_wait);  	list_del_init(&rmidi->list); +	for (dir = 0; dir < 2; dir++) { +		struct snd_rawmidi_substream *s; +		list_for_each_entry(s, &rmidi->streams[dir].substreams, list) { +			if (s->runtime) +				wake_up(&s->runtime->sleep); +		} +	} +  #ifdef CONFIG_SND_OSSEMUL  	if (rmidi->ossreg) {  		if ((int)rmidi->device == midi_map[rmidi->card->number]) { @@ -1626,6 +1649,7 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)  	}  #endif /* CONFIG_SND_OSSEMUL */  	snd_unregister_device(SNDRV_DEVICE_TYPE_RAWMIDI, rmidi->card, rmidi->device); +	mutex_unlock(&rmidi->open_mutex);  	mutex_unlock(®ister_mutex);  	return 0;  } diff --git a/sound/core/sound.c b/sound/core/sound.c index 643976000ce..89780c323f1 100644 --- a/sound/core/sound.c +++ b/sound/core/sound.c @@ -98,6 +98,10 @@ static void snd_request_other(int minor)   *   * Checks that a minor device with the specified type is registered, and returns   * its user data pointer. + * + * This function increments the reference counter of the card instance + * if an associated instance with the given minor number and type is found. + * The caller must call snd_card_unref() appropriately later.   */  void *snd_lookup_minor_data(unsigned int minor, int type)  { @@ -108,9 +112,11 @@ void *snd_lookup_minor_data(unsigned int minor, int type)  		return NULL;  	mutex_lock(&sound_mutex);  	mreg = snd_minors[minor]; -	if (mreg && mreg->type == type) +	if (mreg && mreg->type == type) {  		private_data = mreg->private_data; -	else +		if (mreg->card_ptr) +			atomic_inc(&mreg->card_ptr->refcount); +	} else  		private_data = NULL;  	mutex_unlock(&sound_mutex);  	return private_data; @@ -275,6 +281,7 @@ int snd_register_device_for_dev(int type, struct snd_card *card, int dev,  	preg->device = dev;  	preg->f_ops = f_ops;  	preg->private_data = private_data; +	preg->card_ptr = card;  	mutex_lock(&sound_mutex);  #ifdef CONFIG_SND_DYNAMIC_MINORS  	minor = snd_find_free_minor(type); diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c index e9528333e36..e1d79ee3590 100644 --- a/sound/core/sound_oss.c +++ b/sound/core/sound_oss.c @@ -40,6 +40,9 @@  static struct snd_minor *snd_oss_minors[SNDRV_OSS_MINORS];  static DEFINE_MUTEX(sound_oss_mutex); +/* NOTE: This function increments the refcount of the associated card like + * snd_lookup_minor_data(); the caller must call snd_card_unref() appropriately + */  void *snd_lookup_oss_minor_data(unsigned int minor, int type)  {  	struct snd_minor *mreg; @@ -49,9 +52,11 @@ void *snd_lookup_oss_minor_data(unsigned int minor, int type)  		return NULL;  	mutex_lock(&sound_oss_mutex);  	mreg = snd_oss_minors[minor]; -	if (mreg && mreg->type == type) +	if (mreg && mreg->type == type) {  		private_data = mreg->private_data; -	else +		if (mreg->card_ptr) +			atomic_inc(&mreg->card_ptr->refcount); +	} else  		private_data = NULL;  	mutex_unlock(&sound_oss_mutex);  	return private_data; @@ -123,6 +128,7 @@ int snd_register_oss_device(int type, struct snd_card *card, int dev,  	preg->device = dev;  	preg->f_ops = f_ops;  	preg->private_data = private_data; +	preg->card_ptr = card;  	mutex_lock(&sound_oss_mutex);  	snd_oss_minors[minor] = preg;  	minor_unit = SNDRV_MINOR_OSS_DEVICE(minor); diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 770013ff556..9ba8af05617 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -1763,6 +1763,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {  			  "HP", STAC_HP_ZEPHYR),  	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3660,  			  "HP Mini", STAC_92HD83XXX_HP_LED), +	SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x144E, +			  "HP Pavilion dv5", STAC_92HD83XXX_HP_INV_LED),  	{} /* terminator */  }; diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c index 3050a527925..245d874891b 100644 --- a/sound/pci/ice1712/ice1724.c +++ b/sound/pci/ice1712/ice1724.c @@ -2859,7 +2859,12 @@ static int snd_vt1724_resume(struct device *dev)  		ice->set_spdif_clock(ice, 0);  	} else {  		/* internal on-card clock */ -		snd_vt1724_set_pro_rate(ice, ice->pro_rate_default, 1); +		int rate; +		if (ice->cur_rate) +			rate = ice->cur_rate; +		else +			rate = ice->pro_rate_default; +		snd_vt1724_set_pro_rate(ice, rate, 1);  	}  	update_spdif_bits(ice, ice->pm_saved_spdif_ctrl); diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c index 68f2cd1a920..5a6aeaf552a 100644 --- a/sound/soc/omap/omap-dmic.c +++ b/sound/soc/omap/omap-dmic.c @@ -464,9 +464,9 @@ static __devinit int asoc_dmic_probe(struct platform_device *pdev)  	mutex_init(&dmic->mutex); -	dmic->fclk = clk_get(dmic->dev, "dmic_fck"); +	dmic->fclk = clk_get(dmic->dev, "fck");  	if (IS_ERR(dmic->fclk)) { -		dev_err(dmic->dev, "cant get dmic_fck\n"); +		dev_err(dmic->dev, "cant get fck\n");  		return -ENODEV;  	} diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index 677b567935f..1ff6bb9ade5 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c @@ -21,15 +21,14 @@  #include <linux/clk.h>  #include <linux/platform_device.h> +#include <linux/gpio.h>  #include <sound/core.h>  #include <sound/pcm.h>  #include <sound/soc.h>  #include <asm/mach-types.h> -#include <mach/hardware.h> -#include <mach/gpio.h> -#include <mach/board-zoom.h>  #include <linux/platform_data/asoc-ti-mcbsp.h> +#include <linux/platform_data/gpio-omap.h>  /* Register descriptions for twl4030 codec part */  #include <linux/mfd/twl4030-audio.h> diff --git a/sound/usb/card.c b/sound/usb/card.c index 561bb74fd36..282f0fc9fed 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -339,7 +339,7 @@ static int snd_usb_audio_create(struct usb_device *dev, int idx,  	}  	mutex_init(&chip->mutex); -	mutex_init(&chip->shutdown_mutex); +	init_rwsem(&chip->shutdown_rwsem);  	chip->index = idx;  	chip->dev = dev;  	chip->card = card; @@ -560,7 +560,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,  	card = chip->card;  	mutex_lock(®ister_mutex); -	mutex_lock(&chip->shutdown_mutex); +	down_write(&chip->shutdown_rwsem);  	chip->shutdown = 1;  	chip->num_interfaces--;  	if (chip->num_interfaces <= 0) { @@ -582,11 +582,11 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,  			snd_usb_mixer_disconnect(p);  		}  		usb_chip[chip->index] = NULL; -		mutex_unlock(&chip->shutdown_mutex); +		up_write(&chip->shutdown_rwsem);  		mutex_unlock(®ister_mutex);  		snd_card_free_when_closed(card);  	} else { -		mutex_unlock(&chip->shutdown_mutex); +		up_write(&chip->shutdown_rwsem);  		mutex_unlock(®ister_mutex);  	}  } @@ -618,16 +618,20 @@ int snd_usb_autoresume(struct snd_usb_audio *chip)  {  	int err = -ENODEV; +	down_read(&chip->shutdown_rwsem);  	if (!chip->shutdown && !chip->probing)  		err = usb_autopm_get_interface(chip->pm_intf); +	up_read(&chip->shutdown_rwsem);  	return err;  }  void snd_usb_autosuspend(struct snd_usb_audio *chip)  { +	down_read(&chip->shutdown_rwsem);  	if (!chip->shutdown && !chip->probing)  		usb_autopm_put_interface(chip->pm_intf); +	up_read(&chip->shutdown_rwsem);  }  static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message) diff --git a/sound/usb/card.h b/sound/usb/card.h index afa4f9e9b27..814cb357ff8 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -126,6 +126,7 @@ struct snd_usb_substream {  	struct snd_usb_endpoint *sync_endpoint;  	unsigned long flags;  	bool need_setup_ep;		/* (re)configure EP at prepare? */ +	unsigned int speed;		/* USB_SPEED_XXX */  	u64 formats;			/* format bitmasks (all or'ed) */  	unsigned int num_formats;		/* number of supported audio formats (list) */ diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index fe56c9da38e..298070e8f2d 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -287,25 +287,32 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v  	unsigned char buf[2];  	int val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1;  	int timeout = 10; -	int err; +	int idx = 0, err;  	err = snd_usb_autoresume(cval->mixer->chip);  	if (err < 0)  		return -EIO; +	down_read(&chip->shutdown_rwsem);  	while (timeout-- > 0) { +		if (chip->shutdown) +			break; +		idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);  		if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,  				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), -				    buf, val_len) >= val_len) { +				    validx, idx, buf, val_len) >= val_len) {  			*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len)); -			snd_usb_autosuspend(cval->mixer->chip); -			return 0; +			err = 0; +			goto out;  		}  	} -	snd_usb_autosuspend(cval->mixer->chip);  	snd_printdd(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", -		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); -	return -EINVAL; +		    request, validx, idx, cval->val_type); +	err = -EINVAL; + + out: +	up_read(&chip->shutdown_rwsem); +	snd_usb_autosuspend(cval->mixer->chip); +	return err;  }  static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int validx, int *value_ret) @@ -313,7 +320,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v  	struct snd_usb_audio *chip = cval->mixer->chip;  	unsigned char buf[2 + 3*sizeof(__u16)]; /* enough space for one range */  	unsigned char *val; -	int ret, size; +	int idx = 0, ret, size;  	__u8 bRequest;  	if (request == UAC_GET_CUR) { @@ -330,16 +337,22 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v  	if (ret)  		goto error; -	ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest, +	down_read(&chip->shutdown_rwsem); +	if (chip->shutdown) +		ret = -ENODEV; +	else { +		idx = snd_usb_ctrl_intf(chip) | (cval->id << 8); +		ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,  			      USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, -			      validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), -			      buf, size); +			      validx, idx, buf, size); +	} +	up_read(&chip->shutdown_rwsem);  	snd_usb_autosuspend(chip);  	if (ret < 0) {  error:  		snd_printk(KERN_ERR "cannot get ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d\n", -			   request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type); +			   request, validx, idx, cval->val_type);  		return ret;  	} @@ -417,7 +430,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,  {  	struct snd_usb_audio *chip = cval->mixer->chip;  	unsigned char buf[2]; -	int val_len, err, timeout = 10; +	int idx = 0, val_len, err, timeout = 10;  	if (cval->mixer->protocol == UAC_VERSION_1) {  		val_len = cval->val_type >= USB_MIXER_S16 ? 2 : 1; @@ -440,19 +453,27 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,  	err = snd_usb_autoresume(chip);  	if (err < 0)  		return -EIO; -	while (timeout-- > 0) +	down_read(&chip->shutdown_rwsem); +	while (timeout-- > 0) { +		if (chip->shutdown) +			break; +		idx = snd_usb_ctrl_intf(chip) | (cval->id << 8);  		if (snd_usb_ctl_msg(chip->dev,  				    usb_sndctrlpipe(chip->dev, 0), request,  				    USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, -				    validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), -				    buf, val_len) >= 0) { -			snd_usb_autosuspend(chip); -			return 0; +				    validx, idx, buf, val_len) >= 0) { +			err = 0; +			goto out;  		} -	snd_usb_autosuspend(chip); +	}  	snd_printdd(KERN_ERR "cannot set ctl value: req = %#x, wValue = %#x, wIndex = %#x, type = %d, data = %#x/%#x\n", -		    request, validx, snd_usb_ctrl_intf(chip) | (cval->id << 8), cval->val_type, buf[0], buf[1]); -	return -EINVAL; +		    request, validx, idx, cval->val_type, buf[0], buf[1]); +	err = -EINVAL; + + out: +	up_read(&chip->shutdown_rwsem); +	snd_usb_autosuspend(chip); +	return err;  }  static int set_cur_ctl_value(struct usb_mixer_elem_info *cval, int validx, int value) diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 690000db0ec..ae2b7143522 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -283,6 +283,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e  	if (value > 1)  		return -EINVAL;  	changed = value != mixer->audigy2nx_leds[index]; +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) { +		err = -ENODEV; +		goto out; +	}  	if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))  		err = snd_usb_ctl_msg(mixer->chip->dev,  			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, @@ -299,6 +304,8 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e  			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,  			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,  			      value, index + 2, NULL, 0); + out: +	up_read(&mixer->chip->shutdown_rwsem);  	if (err < 0)  		return err;  	mixer->audigy2nx_leds[index] = value; @@ -392,11 +399,16 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,  	for (i = 0; jacks[i].name; ++i) {  		snd_iprintf(buffer, "%s: ", jacks[i].name); -		err = snd_usb_ctl_msg(mixer->chip->dev, +		down_read(&mixer->chip->shutdown_rwsem); +		if (mixer->chip->shutdown) +			err = 0; +		else +			err = snd_usb_ctl_msg(mixer->chip->dev,  				      usb_rcvctrlpipe(mixer->chip->dev, 0),  				      UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |  				      USB_RECIP_INTERFACE, 0,  				      jacks[i].unitid << 8, buf, 3); +		up_read(&mixer->chip->shutdown_rwsem);  		if (err == 3 && (buf[0] == 3 || buf[0] == 6))  			snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);  		else @@ -426,10 +438,15 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,  	else  		new_status = old_status & ~0x02;  	changed = new_status != old_status; -	err = snd_usb_ctl_msg(mixer->chip->dev, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		err = -ENODEV; +	else +		err = snd_usb_ctl_msg(mixer->chip->dev,  			      usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,  			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,  			      50, 0, &new_status, 1); +	up_read(&mixer->chip->shutdown_rwsem);  	if (err < 0)  		return err;  	mixer->xonar_u1_status = new_status; @@ -468,11 +485,17 @@ static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,  	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;  	u16 wIndex = kcontrol->private_value & 0xffff;  	u8 tmp; +	int ret; -	int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		ret = -ENODEV; +	else +		ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,  				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,  				  0, cpu_to_le16(wIndex),  				  &tmp, sizeof(tmp), 1000); +	up_read(&mixer->chip->shutdown_rwsem);  	if (ret < 0) {  		snd_printk(KERN_ERR @@ -493,11 +516,17 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,  	u8 bRequest = (kcontrol->private_value >> 16) & 0xff;  	u16 wIndex = kcontrol->private_value & 0xffff;  	u16 wValue = ucontrol->value.integer.value[0]; +	int ret; -	int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		ret = -ENODEV; +	else +		ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,  				  USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,  				  cpu_to_le16(wValue), cpu_to_le16(wIndex),  				  NULL, 0, 1000); +	up_read(&mixer->chip->shutdown_rwsem);  	if (ret < 0) {  		snd_printk(KERN_ERR @@ -656,11 +685,16 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,  		return -EINVAL; -	err = snd_usb_ctl_msg(chip->dev, +	down_read(&mixer->chip->shutdown_rwsem); +	if (mixer->chip->shutdown) +		err = -ENODEV; +	else +		err = snd_usb_ctl_msg(chip->dev,  			usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,  			USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,  			validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),  			value, val_len); +	up_read(&mixer->chip->shutdown_rwsem);  	if (err < 0)  		return err; @@ -703,11 +737,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,  	if (!pval->is_cached) {  		/* Read current value */ -		err = snd_usb_ctl_msg(chip->dev, +		down_read(&mixer->chip->shutdown_rwsem); +		if (mixer->chip->shutdown) +			err = -ENODEV; +		else +			err = snd_usb_ctl_msg(chip->dev,  				usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,  				USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,  				validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),  				value, val_len); +		up_read(&mixer->chip->shutdown_rwsem);  		if (err < 0)  			return err; @@ -719,11 +758,16 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,  	if (cur_val != new_val) {  		value[0] = new_val;  		value[1] = 0; -		err = snd_usb_ctl_msg(chip->dev, +		down_read(&mixer->chip->shutdown_rwsem); +		if (mixer->chip->shutdown) +			err = -ENODEV; +		else +			err = snd_usb_ctl_msg(chip->dev,  				usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,  				USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,  				validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),  				value, val_len); +		up_read(&mixer->chip->shutdown_rwsem);  		if (err < 0)  			return err; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 55e19e1b80e..37428f74dbb 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -71,6 +71,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream  	unsigned int hwptr_done;  	subs = (struct snd_usb_substream *)substream->runtime->private_data; +	if (subs->stream->chip->shutdown) +		return SNDRV_PCM_POS_XRUN;  	spin_lock(&subs->lock);  	hwptr_done = subs->hwptr_done;  	substream->runtime->delay = snd_usb_pcm_delay(subs, @@ -444,7 +446,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)  {  	int ret; -	mutex_lock(&subs->stream->chip->shutdown_mutex);  	/* format changed */  	stop_endpoints(subs, 0, 0, 0);  	ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -455,7 +456,7 @@ static int configure_endpoint(struct snd_usb_substream *subs)  					  subs->cur_audiofmt,  					  subs->sync_endpoint);  	if (ret < 0) -		goto unlock; +		return ret;  	if (subs->sync_endpoint)  		ret = snd_usb_endpoint_set_params(subs->data_endpoint, @@ -465,9 +466,6 @@ static int configure_endpoint(struct snd_usb_substream *subs)  						  subs->cur_rate,  						  subs->cur_audiofmt,  						  NULL); - -unlock: -	mutex_unlock(&subs->stream->chip->shutdown_mutex);  	return ret;  } @@ -505,7 +503,13 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,  		return -EINVAL;  	} -	if ((ret = set_format(subs, fmt)) < 0) +	down_read(&subs->stream->chip->shutdown_rwsem); +	if (subs->stream->chip->shutdown) +		ret = -ENODEV; +	else +		ret = set_format(subs, fmt); +	up_read(&subs->stream->chip->shutdown_rwsem); +	if (ret < 0)  		return ret;  	subs->interface = fmt->iface; @@ -527,10 +531,12 @@ static int snd_usb_hw_free(struct snd_pcm_substream *substream)  	subs->cur_audiofmt = NULL;  	subs->cur_rate = 0;  	subs->period_bytes = 0; -	mutex_lock(&subs->stream->chip->shutdown_mutex); -	stop_endpoints(subs, 0, 1, 1); -	deactivate_endpoints(subs); -	mutex_unlock(&subs->stream->chip->shutdown_mutex); +	down_read(&subs->stream->chip->shutdown_rwsem); +	if (!subs->stream->chip->shutdown) { +		stop_endpoints(subs, 0, 1, 1); +		deactivate_endpoints(subs); +	} +	up_read(&subs->stream->chip->shutdown_rwsem);  	return snd_pcm_lib_free_vmalloc_buffer(substream);  } @@ -552,12 +558,19 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  		return -ENXIO;  	} -	if (snd_BUG_ON(!subs->data_endpoint)) -		return -EIO; +	down_read(&subs->stream->chip->shutdown_rwsem); +	if (subs->stream->chip->shutdown) { +		ret = -ENODEV; +		goto unlock; +	} +	if (snd_BUG_ON(!subs->data_endpoint)) { +		ret = -EIO; +		goto unlock; +	}  	ret = set_format(subs, subs->cur_audiofmt);  	if (ret < 0) -		return ret; +		goto unlock;  	iface = usb_ifnum_to_if(subs->dev, subs->cur_audiofmt->iface);  	alts = &iface->altsetting[subs->cur_audiofmt->altset_idx]; @@ -567,12 +580,12 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  				       subs->cur_audiofmt,  				       subs->cur_rate);  	if (ret < 0) -		return ret; +		goto unlock;  	if (subs->need_setup_ep) {  		ret = configure_endpoint(subs);  		if (ret < 0) -			return ret; +			goto unlock;  		subs->need_setup_ep = false;  	} @@ -592,9 +605,11 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)  	/* for playback, submit the URBs now; otherwise, the first hwptr_done  	 * updates for all URBs would happen at the same time when starting */  	if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) -		return start_endpoints(subs, 1); +		ret = start_endpoints(subs, 1); -	return 0; + unlock: +	up_read(&subs->stream->chip->shutdown_rwsem); +	return ret;  }  static struct snd_pcm_hardware snd_usb_hardware = @@ -647,7 +662,7 @@ static int hw_check_valid_format(struct snd_usb_substream *subs,  		return 0;  	}  	/* check whether the period time is >= the data packet interval */ -	if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) { +	if (subs->speed != USB_SPEED_FULL) {  		ptime = 125 * (1 << fp->datainterval);  		if (ptime > pt->max || (ptime == pt->max && pt->openmax)) {  			hwc_debug("   > check: ptime %u > max %u\n", ptime, pt->max); @@ -925,7 +940,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre  		return err;  	param_period_time_if_needed = SNDRV_PCM_HW_PARAM_PERIOD_TIME; -	if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL) +	if (subs->speed == USB_SPEED_FULL)  		/* full speed devices have fixed data packet interval */  		ptmin = 1000;  	if (ptmin == 1000) diff --git a/sound/usb/proc.c b/sound/usb/proc.c index ebc1a5b5b3f..d218f763501 100644 --- a/sound/usb/proc.c +++ b/sound/usb/proc.c @@ -108,7 +108,7 @@ static void proc_dump_substream_formats(struct snd_usb_substream *subs, struct s  			}  			snd_iprintf(buffer, "\n");  		} -		if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL) +		if (subs->speed != USB_SPEED_FULL)  			snd_iprintf(buffer, "    Data packet interval: %d us\n",  				    125 * (1 << fp->datainterval));  		// snd_iprintf(buffer, "    Max Packet Size = %d\n", fp->maxpacksize); @@ -124,7 +124,7 @@ static void proc_dump_ep_status(struct snd_usb_substream *subs,  		return;  	snd_iprintf(buffer, "    Packet Size = %d\n", ep->curpacksize);  	snd_iprintf(buffer, "    Momentary freq = %u Hz (%#x.%04x)\n", -		    snd_usb_get_speed(subs->dev) == USB_SPEED_FULL +		    subs->speed == USB_SPEED_FULL  		    ? get_full_speed_hz(ep->freqm)  		    : get_high_speed_hz(ep->freqm),  		    ep->freqm >> 16, ep->freqm & 0xffff); diff --git a/sound/usb/stream.c b/sound/usb/stream.c index 083ed81160e..1de0c8c002a 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -90,6 +90,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,  	subs->direction = stream;  	subs->dev = as->chip->dev;  	subs->txfr_quirk = as->chip->txfr_quirk; +	subs->speed = snd_usb_get_speed(subs->dev);  	snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index b8233ebe250..ef42797f56f 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -37,7 +37,7 @@ struct snd_usb_audio {  	struct usb_interface *pm_intf;  	u32 usb_id;  	struct mutex mutex; -	struct mutex shutdown_mutex; +	struct rw_semaphore shutdown_rwsem;  	unsigned int shutdown:1;  	unsigned int probing:1;  	unsigned int autosuspended:1;	  |