diff options
166 files changed, 2346 insertions, 1509 deletions
diff --git a/Documentation/virtual/kvm/locking.txt b/Documentation/virtual/kvm/locking.txt index f2491a8c68b4..e5dd9f4d6100 100644 --- a/Documentation/virtual/kvm/locking.txt +++ b/Documentation/virtual/kvm/locking.txt @@ -4,7 +4,17 @@ KVM Lock Overview  1. Acquisition Orders  --------------------- -(to be written) +The acquisition orders for mutexes are as follows: + +- kvm->lock is taken outside vcpu->mutex + +- kvm->lock is taken outside kvm->slots_lock and kvm->irq_lock + +- kvm->slots_lock is taken outside kvm->irq_lock, though acquiring +  them together is quite rare. + +For spinlocks, kvm_lock is taken outside kvm->mmu_lock.  Everything +else is a leaf: no other lock is taken inside the critical sections.  2: Exception  ------------ diff --git a/MAINTAINERS b/MAINTAINERS index 4012c2f98617..411e3b87b8c2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7925,6 +7925,10 @@ F:	mm/  MEMORY TECHNOLOGY DEVICES (MTD)  M:	David Woodhouse <dwmw2@infradead.org>  M:	Brian Norris <computersforpeace@gmail.com> +M:	Boris Brezillon <boris.brezillon@free-electrons.com> +M:	Marek Vasut <marek.vasut@gmail.com> +M:	Richard Weinberger <richard@nod.at> +M:	Cyrille Pitchen <cyrille.pitchen@atmel.com>  L:	linux-mtd@lists.infradead.org  W:	http://www.linux-mtd.infradead.org/  Q:	http://patchwork.ozlabs.org/project/linux-mtd/list/ @@ -11404,6 +11408,17 @@ W:	http://www.st.com/spear  S:	Maintained  F:	drivers/clk/spear/ +SPI NOR SUBSYSTEM +M:	Cyrille Pitchen <cyrille.pitchen@atmel.com> +M:	Marek Vasut <marek.vasut@gmail.com> +L:	linux-mtd@lists.infradead.org +W:	http://www.linux-mtd.infradead.org/ +Q:	http://patchwork.ozlabs.org/project/linux-mtd/list/ +T:	git git://github.com/spi-nor/linux.git +S:	Maintained +F:	drivers/mtd/spi-nor/ +F:	include/linux/mtd/spi-nor.h +  SPI SUBSYSTEM  M:	Mark Brown <broonie@kernel.org>  L:	linux-spi@vger.kernel.org @@ -12783,6 +12798,7 @@ F:	include/uapi/linux/virtio_console.h  VIRTIO CORE, NET AND BLOCK DRIVERS  M:	"Michael S. Tsirkin" <mst@redhat.com> +M:	Jason Wang <jasowang@redhat.com>  L:	virtualization@lists.linux-foundation.org  S:	Maintained  F:	Documentation/devicetree/bindings/virtio/ @@ -12813,6 +12829,7 @@ F:	include/uapi/linux/virtio_gpu.h  VIRTIO HOST (VHOST)  M:	"Michael S. Tsirkin" <mst@redhat.com> +M:	Jason Wang <jasowang@redhat.com>  L:	kvm@vger.kernel.org  L:	virtualization@lists.linux-foundation.org  L:	netdev@vger.kernel.org diff --git a/arch/mips/Makefile b/arch/mips/Makefile index fbf40d3c8123..1a6bac7b076f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -263,7 +263,7 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0)  bootvars-y	= VMLINUX_LOAD_ADDRESS=$(load-y) \  		  VMLINUX_ENTRY_ADDRESS=$(entry-y) \ -		  PLATFORM=$(platform-y) +		  PLATFORM="$(platform-y)"  ifdef CONFIG_32BIT  bootvars-y	+= ADDR_BITS=32  endif diff --git a/arch/mips/boot/dts/mti/malta.dts b/arch/mips/boot/dts/mti/malta.dts index f604a272d91d..ffe3a1508e72 100644 --- a/arch/mips/boot/dts/mti/malta.dts +++ b/arch/mips/boot/dts/mti/malta.dts @@ -84,12 +84,13 @@  	fpga_regs: system-controller@1f000000 {  		compatible = "mti,malta-fpga", "syscon", "simple-mfd";  		reg = <0x1f000000 0x1000>; +		native-endian;  		reboot {  			compatible = "syscon-reboot";  			regmap = <&fpga_regs>;  			offset = <0x500>; -			mask = <0x4d>; +			mask = <0x42>;  		};  	}; diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c index 0ea73e845440..d493ccbf274a 100644 --- a/arch/mips/generic/init.c +++ b/arch/mips/generic/init.c @@ -30,9 +30,19 @@ static __initdata const void *mach_match_data;  void __init prom_init(void)  { +	plat_get_fdt(); +	BUG_ON(!fdt); +} + +void __init *plat_get_fdt(void) +{  	const struct mips_machine *check_mach;  	const struct of_device_id *match; +	if (fdt) +		/* Already set up */ +		return (void *)fdt; +  	if ((fw_arg0 == -2) && !fdt_check_header((void *)fw_arg1)) {  		/*  		 * We booted using the UHI boot protocol, so we have been @@ -75,12 +85,6 @@ void __init prom_init(void)  		/* Retrieve the machine's FDT */  		fdt = mach->fdt;  	} - -	BUG_ON(!fdt); -} - -void __init *plat_get_fdt(void) -{  	return (void *)fdt;  } diff --git a/arch/mips/include/asm/fpu_emulator.h b/arch/mips/include/asm/fpu_emulator.h index 355dc25172e7..c05369e0b8d6 100644 --- a/arch/mips/include/asm/fpu_emulator.h +++ b/arch/mips/include/asm/fpu_emulator.h @@ -63,6 +63,8 @@ do {									\  extern int fpu_emulator_cop1Handler(struct pt_regs *xcp,  				    struct mips_fpu_struct *ctx, int has_fpu,  				    void *__user *fault_addr); +void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, +		     struct task_struct *tsk);  int process_fpemu_return(int sig, void __user *fault_addr,  			 unsigned long fcr31);  int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn, @@ -81,4 +83,15 @@ static inline void fpu_emulator_init_fpu(void)  		set_fpr64(&t->thread.fpu.fpr[i], 0, SIGNALLING_NAN);  } +/* + * Mask the FCSR Cause bits according to the Enable bits, observing + * that Unimplemented is always enabled. + */ +static inline unsigned long mask_fcr31_x(unsigned long fcr31) +{ +	return fcr31 & (FPU_CSR_UNI_X | +			((fcr31 & FPU_CSR_ALL_E) << +			 (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)))); +} +  #endif /* _ASM_FPU_EMULATOR_H */ diff --git a/arch/mips/include/asm/kvm_host.h b/arch/mips/include/asm/kvm_host.h index 07f58cfc1ab9..bebec370324f 100644 --- a/arch/mips/include/asm/kvm_host.h +++ b/arch/mips/include/asm/kvm_host.h @@ -293,7 +293,10 @@ struct kvm_vcpu_arch {  	/* Host KSEG0 address of the EI/DI offset */  	void *kseg0_commpage; -	u32 io_gpr;		/* GPR used as IO source/target */ +	/* Resume PC after MMIO completion */ +	unsigned long io_pc; +	/* GPR used as IO source/target */ +	u32 io_gpr;  	struct hrtimer comparecount_timer;  	/* Count timer control KVM register */ @@ -315,8 +318,6 @@ struct kvm_vcpu_arch {  	/* Bitmask of pending exceptions to be cleared */  	unsigned long pending_exceptions_clr; -	u32 pending_load_cause; -  	/* Save/Restore the entryhi register when are are preempted/scheduled back in */  	unsigned long preempt_entryhi; diff --git a/arch/mips/include/asm/switch_to.h b/arch/mips/include/asm/switch_to.h index ebb5c0f2f90d..c0ae27971e31 100644 --- a/arch/mips/include/asm/switch_to.h +++ b/arch/mips/include/asm/switch_to.h @@ -76,6 +76,22 @@ do {	if (cpu_has_rw_llb) {						\  } while (0)  /* + * Check FCSR for any unmasked exceptions pending set with `ptrace', + * clear them and send a signal. + */ +#define __sanitize_fcr31(next)						\ +do {									\ +	unsigned long fcr31 = mask_fcr31_x(next->thread.fpu.fcr31);	\ +	void __user *pc;						\ +									\ +	if (unlikely(fcr31)) {						\ +		pc = (void __user *)task_pt_regs(next)->cp0_epc;	\ +		next->thread.fpu.fcr31 &= ~fcr31;			\ +		force_fcr31_sig(fcr31, pc, next);			\ +	}								\ +} while (0) + +/*   * For newly created kernel threads switch_to() will return to   * ret_from_kernel_thread, newly created user threads to ret_from_fork.   * That is, everything following resume() will be skipped for new threads. @@ -85,6 +101,8 @@ do {	if (cpu_has_rw_llb) {						\  do {									\  	__mips_mt_fpaff_switch_to(prev);				\  	lose_fpu_inatomic(1, prev);					\ +	if (tsk_used_math(next))					\ +		__sanitize_fcr31(next);					\  	if (cpu_has_dsp) {						\  		__save_dsp(prev);					\  		__restore_dsp(next);					\ diff --git a/arch/mips/kernel/mips-cpc.c b/arch/mips/kernel/mips-cpc.c index 2a45867d3b4f..a4964c334cab 100644 --- a/arch/mips/kernel/mips-cpc.c +++ b/arch/mips/kernel/mips-cpc.c @@ -21,6 +21,11 @@ static DEFINE_PER_CPU_ALIGNED(spinlock_t, cpc_core_lock);  static DEFINE_PER_CPU_ALIGNED(unsigned long, cpc_core_lock_flags); +phys_addr_t __weak mips_cpc_default_phys_base(void) +{ +	return 0; +} +  /**   * mips_cpc_phys_base - retrieve the physical base address of the CPC   * @@ -43,8 +48,12 @@ static phys_addr_t mips_cpc_phys_base(void)  	if (cpc_base & CM_GCR_CPC_BASE_CPCEN_MSK)  		return cpc_base & CM_GCR_CPC_BASE_CPCBASE_MSK; -	/* Otherwise, give it the default address & enable it */ +	/* Otherwise, use the default address */  	cpc_base = mips_cpc_default_phys_base(); +	if (!cpc_base) +		return cpc_base; + +	/* Enable the CPC, mapped at the default address */  	write_gcr_cpc_base(cpc_base | CM_GCR_CPC_BASE_CPCEN_MSK);  	return cpc_base;  } diff --git a/arch/mips/kernel/mips-r2-to-r6-emul.c b/arch/mips/kernel/mips-r2-to-r6-emul.c index 22dedd62818a..bd09853aecdf 100644 --- a/arch/mips/kernel/mips-r2-to-r6-emul.c +++ b/arch/mips/kernel/mips-r2-to-r6-emul.c @@ -899,7 +899,7 @@ static inline int mipsr2_find_op_func(struct pt_regs *regs, u32 inst,   * mipsr2_decoder: Decode and emulate a MIPS R2 instruction   * @regs: Process register set   * @inst: Instruction to decode and emulate - * @fcr31: Floating Point Control and Status Register returned + * @fcr31: Floating Point Control and Status Register Cause bits returned   */  int mipsr2_decoder(struct pt_regs *regs, u32 inst, unsigned long *fcr31)  { @@ -1172,13 +1172,13 @@ fpu_emul:  		err = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0,  					       &fault_addr); -		*fcr31 = current->thread.fpu.fcr31;  		/* -		 * We can't allow the emulated instruction to leave any of -		 * the cause bits set in $fcr31. +		 * We can't allow the emulated instruction to leave any +		 * enabled Cause bits set in $fcr31.  		 */ -		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; +		*fcr31 = res = mask_fcr31_x(current->thread.fpu.fcr31); +		current->thread.fpu.fcr31 &= ~res;  		/*  		 * this is a tricky issue - lose_fpu() uses LL/SC atomics diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index 6103b24d1bfc..a92994d60e91 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -79,16 +79,15 @@ void ptrace_disable(struct task_struct *child)  }  /* - * Poke at FCSR according to its mask.  Don't set the cause bits as - * this is currently not handled correctly in FP context restoration - * and will cause an oops if a corresponding enable bit is set. + * Poke at FCSR according to its mask.  Set the Cause bits even + * if a corresponding Enable bit is set.  This will be noticed at + * the time the thread is switched to and SIGFPE thrown accordingly.   */  static void ptrace_setfcr31(struct task_struct *child, u32 value)  {  	u32 fcr31;  	u32 mask; -	value &= ~FPU_CSR_ALL_X;  	fcr31 = child->thread.fpu.fcr31;  	mask = boot_cpu_data.fpu_msk31;  	child->thread.fpu.fcr31 = (value & ~mask) | (fcr31 & mask); @@ -817,6 +816,7 @@ long arch_ptrace(struct task_struct *child, long request,  			break;  #endif  		case FPC_CSR: +			init_fp_ctx(child);  			ptrace_setfcr31(child, data);  			break;  		case DSP_BASE ... DSP_BASE + 5: { diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S index b4ac6374a38f..918f2f6d3861 100644 --- a/arch/mips/kernel/r2300_fpu.S +++ b/arch/mips/kernel/r2300_fpu.S @@ -21,106 +21,84 @@  #define EX(a,b)							\  9:	a,##b;							\  	.section __ex_table,"a";				\ +	PTR	9b,fault;					\ +	.previous + +#define EX2(a,b)						\ +9:	a,##b;							\ +	.section __ex_table,"a";				\  	PTR	9b,bad_stack;					\ +	PTR	9b+4,bad_stack;					\  	.previous  	.set	noreorder  	.set	mips1 -	/* Save floating point context */ + +/** + * _save_fp_context() - save FP context from the FPU + * @a0 - pointer to fpregs field of sigcontext + * @a1 - pointer to fpc_csr field of sigcontext + * + * Save FP context, including the 32 FP data registers and the FP + * control & status register, from the FPU to signal context. + */  LEAF(_save_fp_context)  	.set	push  	SET_HARDFLOAT  	li	v0, 0					# assume success -	cfc1	t1,fcr31 -	EX(swc1 $f0,(SC_FPREGS+0)(a0)) -	EX(swc1 $f1,(SC_FPREGS+8)(a0)) -	EX(swc1 $f2,(SC_FPREGS+16)(a0)) -	EX(swc1 $f3,(SC_FPREGS+24)(a0)) -	EX(swc1 $f4,(SC_FPREGS+32)(a0)) -	EX(swc1 $f5,(SC_FPREGS+40)(a0)) -	EX(swc1 $f6,(SC_FPREGS+48)(a0)) -	EX(swc1 $f7,(SC_FPREGS+56)(a0)) -	EX(swc1 $f8,(SC_FPREGS+64)(a0)) -	EX(swc1 $f9,(SC_FPREGS+72)(a0)) -	EX(swc1 $f10,(SC_FPREGS+80)(a0)) -	EX(swc1 $f11,(SC_FPREGS+88)(a0)) -	EX(swc1 $f12,(SC_FPREGS+96)(a0)) -	EX(swc1 $f13,(SC_FPREGS+104)(a0)) -	EX(swc1 $f14,(SC_FPREGS+112)(a0)) -	EX(swc1 $f15,(SC_FPREGS+120)(a0)) -	EX(swc1 $f16,(SC_FPREGS+128)(a0)) -	EX(swc1 $f17,(SC_FPREGS+136)(a0)) -	EX(swc1 $f18,(SC_FPREGS+144)(a0)) -	EX(swc1 $f19,(SC_FPREGS+152)(a0)) -	EX(swc1 $f20,(SC_FPREGS+160)(a0)) -	EX(swc1 $f21,(SC_FPREGS+168)(a0)) -	EX(swc1 $f22,(SC_FPREGS+176)(a0)) -	EX(swc1 $f23,(SC_FPREGS+184)(a0)) -	EX(swc1 $f24,(SC_FPREGS+192)(a0)) -	EX(swc1 $f25,(SC_FPREGS+200)(a0)) -	EX(swc1 $f26,(SC_FPREGS+208)(a0)) -	EX(swc1 $f27,(SC_FPREGS+216)(a0)) -	EX(swc1 $f28,(SC_FPREGS+224)(a0)) -	EX(swc1 $f29,(SC_FPREGS+232)(a0)) -	EX(swc1 $f30,(SC_FPREGS+240)(a0)) -	EX(swc1 $f31,(SC_FPREGS+248)(a0)) -	EX(sw	t1,(SC_FPC_CSR)(a0)) -	cfc1	t0,$0				# implementation/version +	cfc1	t1, fcr31 +	EX2(s.d $f0, 0(a0)) +	EX2(s.d $f2, 16(a0)) +	EX2(s.d $f4, 32(a0)) +	EX2(s.d $f6, 48(a0)) +	EX2(s.d $f8, 64(a0)) +	EX2(s.d $f10, 80(a0)) +	EX2(s.d $f12, 96(a0)) +	EX2(s.d $f14, 112(a0)) +	EX2(s.d $f16, 128(a0)) +	EX2(s.d $f18, 144(a0)) +	EX2(s.d $f20, 160(a0)) +	EX2(s.d $f22, 176(a0)) +	EX2(s.d $f24, 192(a0)) +	EX2(s.d $f26, 208(a0)) +	EX2(s.d $f28, 224(a0)) +	EX2(s.d $f30, 240(a0))  	jr	ra +	 EX(sw	t1, (a1))  	.set	pop -	.set	nomacro -	 EX(sw	t0,(SC_FPC_EIR)(a0)) -	.set	macro  	END(_save_fp_context) -/* - * Restore FPU state: - *  - fp gp registers - *  - cp1 status/control register +/** + * _restore_fp_context() - restore FP context to the FPU + * @a0 - pointer to fpregs field of sigcontext + * @a1 - pointer to fpc_csr field of sigcontext   * - * We base the decision which registers to restore from the signal stack - * frame on the current content of c0_status, not on the content of the - * stack frame which might have been changed by the user. + * Restore FP context, including the 32 FP data registers and the FP + * control & status register, from signal context to the FPU.   */  LEAF(_restore_fp_context)  	.set	push  	SET_HARDFLOAT  	li	v0, 0					# assume success -	EX(lw t0,(SC_FPC_CSR)(a0)) -	EX(lwc1 $f0,(SC_FPREGS+0)(a0)) -	EX(lwc1 $f1,(SC_FPREGS+8)(a0)) -	EX(lwc1 $f2,(SC_FPREGS+16)(a0)) -	EX(lwc1 $f3,(SC_FPREGS+24)(a0)) -	EX(lwc1 $f4,(SC_FPREGS+32)(a0)) -	EX(lwc1 $f5,(SC_FPREGS+40)(a0)) -	EX(lwc1 $f6,(SC_FPREGS+48)(a0)) -	EX(lwc1 $f7,(SC_FPREGS+56)(a0)) -	EX(lwc1 $f8,(SC_FPREGS+64)(a0)) -	EX(lwc1 $f9,(SC_FPREGS+72)(a0)) -	EX(lwc1 $f10,(SC_FPREGS+80)(a0)) -	EX(lwc1 $f11,(SC_FPREGS+88)(a0)) -	EX(lwc1 $f12,(SC_FPREGS+96)(a0)) -	EX(lwc1 $f13,(SC_FPREGS+104)(a0)) -	EX(lwc1 $f14,(SC_FPREGS+112)(a0)) -	EX(lwc1 $f15,(SC_FPREGS+120)(a0)) -	EX(lwc1 $f16,(SC_FPREGS+128)(a0)) -	EX(lwc1 $f17,(SC_FPREGS+136)(a0)) -	EX(lwc1 $f18,(SC_FPREGS+144)(a0)) -	EX(lwc1 $f19,(SC_FPREGS+152)(a0)) -	EX(lwc1 $f20,(SC_FPREGS+160)(a0)) -	EX(lwc1 $f21,(SC_FPREGS+168)(a0)) -	EX(lwc1 $f22,(SC_FPREGS+176)(a0)) -	EX(lwc1 $f23,(SC_FPREGS+184)(a0)) -	EX(lwc1 $f24,(SC_FPREGS+192)(a0)) -	EX(lwc1 $f25,(SC_FPREGS+200)(a0)) -	EX(lwc1 $f26,(SC_FPREGS+208)(a0)) -	EX(lwc1 $f27,(SC_FPREGS+216)(a0)) -	EX(lwc1 $f28,(SC_FPREGS+224)(a0)) -	EX(lwc1 $f29,(SC_FPREGS+232)(a0)) -	EX(lwc1 $f30,(SC_FPREGS+240)(a0)) -	EX(lwc1 $f31,(SC_FPREGS+248)(a0)) +	EX(lw t0, (a1)) +	EX2(l.d $f0, 0(a0)) +	EX2(l.d $f2, 16(a0)) +	EX2(l.d $f4, 32(a0)) +	EX2(l.d $f6, 48(a0)) +	EX2(l.d $f8, 64(a0)) +	EX2(l.d $f10, 80(a0)) +	EX2(l.d $f12, 96(a0)) +	EX2(l.d $f14, 112(a0)) +	EX2(l.d $f16, 128(a0)) +	EX2(l.d $f18, 144(a0)) +	EX2(l.d $f20, 160(a0)) +	EX2(l.d $f22, 176(a0)) +	EX2(l.d $f24, 192(a0)) +	EX2(l.d $f26, 208(a0)) +	EX2(l.d $f28, 224(a0)) +	EX2(l.d $f30, 240(a0))  	jr	ra -	 ctc1	t0,fcr31 +	 ctc1	t0, fcr31  	.set	pop  	END(_restore_fp_context)  	.set	reorder diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S index 47077380c15c..9cc7bfab3419 100644 --- a/arch/mips/kernel/r6000_fpu.S +++ b/arch/mips/kernel/r6000_fpu.S @@ -21,7 +21,14 @@  	.set	push  	SET_HARDFLOAT -	/* Save floating point context */ +/** + * _save_fp_context() - save FP context from the FPU + * @a0 - pointer to fpregs field of sigcontext + * @a1 - pointer to fpc_csr field of sigcontext + * + * Save FP context, including the 32 FP data registers and the FP + * control & status register, from the FPU to signal context. + */  	LEAF(_save_fp_context)  	mfc0	t0,CP0_STATUS  	sll	t0,t0,2 @@ -30,59 +37,59 @@  	cfc1	t1,fcr31  	/* Store the 16 double precision registers */ -	sdc1	$f0,(SC_FPREGS+0)(a0) -	sdc1	$f2,(SC_FPREGS+16)(a0) -	sdc1	$f4,(SC_FPREGS+32)(a0) -	sdc1	$f6,(SC_FPREGS+48)(a0) -	sdc1	$f8,(SC_FPREGS+64)(a0) -	sdc1	$f10,(SC_FPREGS+80)(a0) -	sdc1	$f12,(SC_FPREGS+96)(a0) -	sdc1	$f14,(SC_FPREGS+112)(a0) -	sdc1	$f16,(SC_FPREGS+128)(a0) -	sdc1	$f18,(SC_FPREGS+144)(a0) -	sdc1	$f20,(SC_FPREGS+160)(a0) -	sdc1	$f22,(SC_FPREGS+176)(a0) -	sdc1	$f24,(SC_FPREGS+192)(a0) -	sdc1	$f26,(SC_FPREGS+208)(a0) -	sdc1	$f28,(SC_FPREGS+224)(a0) -	sdc1	$f30,(SC_FPREGS+240)(a0) +	sdc1	$f0,0(a0) +	sdc1	$f2,16(a0) +	sdc1	$f4,32(a0) +	sdc1	$f6,48(a0) +	sdc1	$f8,64(a0) +	sdc1	$f10,80(a0) +	sdc1	$f12,96(a0) +	sdc1	$f14,112(a0) +	sdc1	$f16,128(a0) +	sdc1	$f18,144(a0) +	sdc1	$f20,160(a0) +	sdc1	$f22,176(a0) +	sdc1	$f24,192(a0) +	sdc1	$f26,208(a0) +	sdc1	$f28,224(a0) +	sdc1	$f30,240(a0)  	jr	ra -	 sw	t0,SC_FPC_CSR(a0) +	 sw	t0,(a1)  1:	jr	ra  	 nop  	END(_save_fp_context) -/* Restore FPU state: - *  - fp gp registers - *  - cp1 status/control register +/** + * _restore_fp_context() - restore FP context to the FPU + * @a0 - pointer to fpregs field of sigcontext + * @a1 - pointer to fpc_csr field of sigcontext   * - * We base the decision which registers to restore from the signal stack - * frame on the current content of c0_status, not on the content of the - * stack frame which might have been changed by the user. + * Restore FP context, including the 32 FP data registers and the FP + * control & status register, from signal context to the FPU.   */  	LEAF(_restore_fp_context)  	mfc0	t0,CP0_STATUS  	sll	t0,t0,2  	bgez	t0,1f -	 lw	t0,SC_FPC_CSR(a0) +	 lw	t0,(a1)  	/* Restore the 16 double precision registers */ -	ldc1	$f0,(SC_FPREGS+0)(a0) -	ldc1	$f2,(SC_FPREGS+16)(a0) -	ldc1	$f4,(SC_FPREGS+32)(a0) -	ldc1	$f6,(SC_FPREGS+48)(a0) -	ldc1	$f8,(SC_FPREGS+64)(a0) -	ldc1	$f10,(SC_FPREGS+80)(a0) -	ldc1	$f12,(SC_FPREGS+96)(a0) -	ldc1	$f14,(SC_FPREGS+112)(a0) -	ldc1	$f16,(SC_FPREGS+128)(a0) -	ldc1	$f18,(SC_FPREGS+144)(a0) -	ldc1	$f20,(SC_FPREGS+160)(a0) -	ldc1	$f22,(SC_FPREGS+176)(a0) -	ldc1	$f24,(SC_FPREGS+192)(a0) -	ldc1	$f26,(SC_FPREGS+208)(a0) -	ldc1	$f28,(SC_FPREGS+224)(a0) -	ldc1	$f30,(SC_FPREGS+240)(a0) +	ldc1	$f0,0(a0) +	ldc1	$f2,16(a0) +	ldc1	$f4,32(a0) +	ldc1	$f6,48(a0) +	ldc1	$f8,64(a0) +	ldc1	$f10,80(a0) +	ldc1	$f12,96(a0) +	ldc1	$f14,112(a0) +	ldc1	$f16,128(a0) +	ldc1	$f18,144(a0) +	ldc1	$f20,160(a0) +	ldc1	$f22,176(a0) +	ldc1	$f24,192(a0) +	ldc1	$f26,208(a0) +	ldc1	$f28,224(a0) +	ldc1	$f30,240(a0)  	jr	ra  	 ctc1	t0,fcr31  1:	jr	ra diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/relocate.c index ca1cc30c0891..1958910b75c0 100644 --- a/arch/mips/kernel/relocate.c +++ b/arch/mips/kernel/relocate.c @@ -200,7 +200,7 @@ static inline __init unsigned long get_random_boot(void)  #if defined(CONFIG_USE_OF)  	/* Get any additional entropy passed in device tree */ -	{ +	if (initial_boot_params) {  		int node, len;  		u64 *prop; diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 0d57909d9026..f66e5ce505b2 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -368,6 +368,19 @@ static void __init bootmem_init(void)  		end = PFN_DOWN(boot_mem_map.map[i].addr  				+ boot_mem_map.map[i].size); +#ifndef CONFIG_HIGHMEM +		/* +		 * Skip highmem here so we get an accurate max_low_pfn if low +		 * memory stops short of high memory. +		 * If the region overlaps HIGHMEM_START, end is clipped so +		 * max_pfn excludes the highmem portion. +		 */ +		if (start >= PFN_DOWN(HIGHMEM_START)) +			continue; +		if (end > PFN_DOWN(HIGHMEM_START)) +			end = PFN_DOWN(HIGHMEM_START); +#endif +  		if (end > max_low_pfn)  			max_low_pfn = end;  		if (start < min_low_pfn) diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 1f5fdee1dfc3..3905003dfe2b 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -156,7 +156,7 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)  		print_ip_sym(pc);  		pc = unwind_stack(task, &sp, pc, &ra);  	} while (pc); -	printk("\n"); +	pr_cont("\n");  }  /* @@ -174,22 +174,24 @@ static void show_stacktrace(struct task_struct *task,  	printk("Stack :");  	i = 0;  	while ((unsigned long) sp & (PAGE_SIZE - 1)) { -		if (i && ((i % (64 / field)) == 0)) -			printk("\n	 "); +		if (i && ((i % (64 / field)) == 0)) { +			pr_cont("\n"); +			printk("       "); +		}  		if (i > 39) { -			printk(" ..."); +			pr_cont(" ...");  			break;  		}  		if (__get_user(stackdata, sp++)) { -			printk(" (Bad stack address)"); +			pr_cont(" (Bad stack address)");  			break;  		} -		printk(" %0*lx", field, stackdata); +		pr_cont(" %0*lx", field, stackdata);  		i++;  	} -	printk("\n"); +	pr_cont("\n");  	show_backtrace(task, regs);  } @@ -229,18 +231,19 @@ static void show_code(unsigned int __user *pc)  	long i;  	unsigned short __user *pc16 = NULL; -	printk("\nCode:"); +	printk("Code:");  	if ((unsigned long)pc & 1)  		pc16 = (unsigned short __user *)((unsigned long)pc & ~1);  	for(i = -3 ; i < 6 ; i++) {  		unsigned int insn;  		if (pc16 ? __get_user(insn, pc16 + i) : __get_user(insn, pc + i)) { -			printk(" (Bad address in epc)\n"); +			pr_cont(" (Bad address in epc)\n");  			break;  		} -		printk("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>')); +		pr_cont("%c%0*x%c", (i?' ':'<'), pc16 ? 4 : 8, insn, (i?' ':'>'));  	} +	pr_cont("\n");  }  static void __show_regs(const struct pt_regs *regs) @@ -259,15 +262,15 @@ static void __show_regs(const struct pt_regs *regs)  		if ((i % 4) == 0)  			printk("$%2d   :", i);  		if (i == 0) -			printk(" %0*lx", field, 0UL); +			pr_cont(" %0*lx", field, 0UL);  		else if (i == 26 || i == 27) -			printk(" %*s", field, ""); +			pr_cont(" %*s", field, "");  		else -			printk(" %0*lx", field, regs->regs[i]); +			pr_cont(" %0*lx", field, regs->regs[i]);  		i++;  		if ((i % 4) == 0) -			printk("\n"); +			pr_cont("\n");  	}  #ifdef CONFIG_CPU_HAS_SMARTMIPS @@ -288,46 +291,46 @@ static void __show_regs(const struct pt_regs *regs)  	if (cpu_has_3kex) {  		if (regs->cp0_status & ST0_KUO) -			printk("KUo "); +			pr_cont("KUo ");  		if (regs->cp0_status & ST0_IEO) -			printk("IEo "); +			pr_cont("IEo ");  		if (regs->cp0_status & ST0_KUP) -			printk("KUp "); +			pr_cont("KUp ");  		if (regs->cp0_status & ST0_IEP) -			printk("IEp "); +			pr_cont("IEp ");  		if (regs->cp0_status & ST0_KUC) -			printk("KUc "); +			pr_cont("KUc ");  		if (regs->cp0_status & ST0_IEC) -			printk("IEc "); +			pr_cont("IEc ");  	} else if (cpu_has_4kex) {  		if (regs->cp0_status & ST0_KX) -			printk("KX "); +			pr_cont("KX ");  		if (regs->cp0_status & ST0_SX) -			printk("SX "); +			pr_cont("SX ");  		if (regs->cp0_status & ST0_UX) -			printk("UX "); +			pr_cont("UX ");  		switch (regs->cp0_status & ST0_KSU) {  		case KSU_USER: -			printk("USER "); +			pr_cont("USER ");  			break;  		case KSU_SUPERVISOR: -			printk("SUPERVISOR "); +			pr_cont("SUPERVISOR ");  			break;  		case KSU_KERNEL: -			printk("KERNEL "); +			pr_cont("KERNEL ");  			break;  		default: -			printk("BAD_MODE "); +			pr_cont("BAD_MODE ");  			break;  		}  		if (regs->cp0_status & ST0_ERL) -			printk("ERL "); +			pr_cont("ERL ");  		if (regs->cp0_status & ST0_EXL) -			printk("EXL "); +			pr_cont("EXL ");  		if (regs->cp0_status & ST0_IE) -			printk("IE "); +			pr_cont("IE ");  	} -	printk("\n"); +	pr_cont("\n");  	exccode = (cause & CAUSEF_EXCCODE) >> CAUSEB_EXCCODE;  	printk("Cause : %08x (ExcCode %02x)\n", cause, exccode); @@ -705,6 +708,32 @@ asmlinkage void do_ov(struct pt_regs *regs)  	exception_exit(prev_state);  } +/* + * Send SIGFPE according to FCSR Cause bits, which must have already + * been masked against Enable bits.  This is impotant as Inexact can + * happen together with Overflow or Underflow, and `ptrace' can set + * any bits. + */ +void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr, +		     struct task_struct *tsk) +{ +	struct siginfo si = { .si_addr = fault_addr, .si_signo = SIGFPE }; + +	if (fcr31 & FPU_CSR_INV_X) +		si.si_code = FPE_FLTINV; +	else if (fcr31 & FPU_CSR_DIV_X) +		si.si_code = FPE_FLTDIV; +	else if (fcr31 & FPU_CSR_OVF_X) +		si.si_code = FPE_FLTOVF; +	else if (fcr31 & FPU_CSR_UDF_X) +		si.si_code = FPE_FLTUND; +	else if (fcr31 & FPU_CSR_INE_X) +		si.si_code = FPE_FLTRES; +	else +		si.si_code = __SI_FAULT; +	force_sig_info(SIGFPE, &si, tsk); +} +  int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)  {  	struct siginfo si = { 0 }; @@ -715,27 +744,7 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)  		return 0;  	case SIGFPE: -		si.si_addr = fault_addr; -		si.si_signo = sig; -		/* -		 * Inexact can happen together with Overflow or Underflow. -		 * Respect the mask to deliver the correct exception. -		 */ -		fcr31 &= (fcr31 & FPU_CSR_ALL_E) << -			 (ffs(FPU_CSR_ALL_X) - ffs(FPU_CSR_ALL_E)); -		if (fcr31 & FPU_CSR_INV_X) -			si.si_code = FPE_FLTINV; -		else if (fcr31 & FPU_CSR_DIV_X) -			si.si_code = FPE_FLTDIV; -		else if (fcr31 & FPU_CSR_OVF_X) -			si.si_code = FPE_FLTOVF; -		else if (fcr31 & FPU_CSR_UDF_X) -			si.si_code = FPE_FLTUND; -		else if (fcr31 & FPU_CSR_INE_X) -			si.si_code = FPE_FLTRES; -		else -			si.si_code = __SI_FAULT; -		force_sig_info(sig, &si, current); +		force_fcr31_sig(fcr31, fault_addr, current);  		return 1;  	case SIGBUS: @@ -799,13 +808,13 @@ static int simulate_fp(struct pt_regs *regs, unsigned int opcode,  	/* Run the emulator */  	sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,  				       &fault_addr); -	fcr31 = current->thread.fpu.fcr31;  	/* -	 * We can't allow the emulated instruction to leave any of -	 * the cause bits set in $fcr31. +	 * We can't allow the emulated instruction to leave any +	 * enabled Cause bits set in $fcr31.  	 */ -	current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; +	fcr31 = mask_fcr31_x(current->thread.fpu.fcr31); +	current->thread.fpu.fcr31 &= ~fcr31;  	/* Restore the hardware register state */  	own_fpu(1); @@ -831,7 +840,7 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  		goto out;  	/* Clear FCSR.Cause before enabling interrupts */ -	write_32bit_cp1_register(CP1_STATUS, fcr31 & ~FPU_CSR_ALL_X); +	write_32bit_cp1_register(CP1_STATUS, fcr31 & ~mask_fcr31_x(fcr31));  	local_irq_enable();  	die_if_kernel("FP exception in kernel code", regs); @@ -853,13 +862,13 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)  		/* Run the emulator */  		sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 1,  					       &fault_addr); -		fcr31 = current->thread.fpu.fcr31;  		/* -		 * We can't allow the emulated instruction to leave any of -		 * the cause bits set in $fcr31. +		 * We can't allow the emulated instruction to leave any +		 * enabled Cause bits set in $fcr31.  		 */ -		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; +		fcr31 = mask_fcr31_x(current->thread.fpu.fcr31); +		current->thread.fpu.fcr31 &= ~fcr31;  		/* Restore the hardware register state */  		own_fpu(1);	/* Using the FPU again.	 */ @@ -1424,13 +1433,13 @@ asmlinkage void do_cpu(struct pt_regs *regs)  		sig = fpu_emulator_cop1Handler(regs, ¤t->thread.fpu, 0,  					       &fault_addr); -		fcr31 = current->thread.fpu.fcr31;  		/*  		 * We can't allow the emulated instruction to leave -		 * any of the cause bits set in $fcr31. +		 * any enabled Cause bits set in $fcr31.  		 */ -		current->thread.fpu.fcr31 &= ~FPU_CSR_ALL_X; +		fcr31 = mask_fcr31_x(current->thread.fpu.fcr31); +		current->thread.fpu.fcr31 &= ~fcr31;  		/* Send a signal if required.  */  		if (!process_fpemu_return(sig, fault_addr, fcr31) && !err) diff --git a/arch/mips/kvm/emulate.c b/arch/mips/kvm/emulate.c index 8770f32c9e0b..aa0937423e28 100644 --- a/arch/mips/kvm/emulate.c +++ b/arch/mips/kvm/emulate.c @@ -790,15 +790,15 @@ enum emulation_result kvm_mips_emul_eret(struct kvm_vcpu *vcpu)  	struct mips_coproc *cop0 = vcpu->arch.cop0;  	enum emulation_result er = EMULATE_DONE; -	if (kvm_read_c0_guest_status(cop0) & ST0_EXL) { +	if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { +		kvm_clear_c0_guest_status(cop0, ST0_ERL); +		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0); +	} else if (kvm_read_c0_guest_status(cop0) & ST0_EXL) {  		kvm_debug("[%#lx] ERET to %#lx\n", vcpu->arch.pc,  			  kvm_read_c0_guest_epc(cop0));  		kvm_clear_c0_guest_status(cop0, ST0_EXL);  		vcpu->arch.pc = kvm_read_c0_guest_epc(cop0); -	} else if (kvm_read_c0_guest_status(cop0) & ST0_ERL) { -		kvm_clear_c0_guest_status(cop0, ST0_ERL); -		vcpu->arch.pc = kvm_read_c0_guest_errorepc(cop0);  	} else {  		kvm_err("[%#lx] ERET when MIPS_SR_EXL|MIPS_SR_ERL == 0\n",  			vcpu->arch.pc); @@ -1528,13 +1528,25 @@ enum emulation_result kvm_mips_emulate_load(union mips_instruction inst,  					    struct kvm_vcpu *vcpu)  {  	enum emulation_result er = EMULATE_DO_MMIO; +	unsigned long curr_pc;  	u32 op, rt;  	u32 bytes;  	rt = inst.i_format.rt;  	op = inst.i_format.opcode; -	vcpu->arch.pending_load_cause = cause; +	/* +	 * Find the resume PC now while we have safe and easy access to the +	 * prior branch instruction, and save it for +	 * kvm_mips_complete_mmio_load() to restore later. +	 */ +	curr_pc = vcpu->arch.pc; +	er = update_pc(vcpu, cause); +	if (er == EMULATE_FAIL) +		return er; +	vcpu->arch.io_pc = vcpu->arch.pc; +	vcpu->arch.pc = curr_pc; +  	vcpu->arch.io_gpr = rt;  	switch (op) { @@ -2494,9 +2506,8 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,  		goto done;  	} -	er = update_pc(vcpu, vcpu->arch.pending_load_cause); -	if (er == EMULATE_FAIL) -		return er; +	/* Restore saved resume PC */ +	vcpu->arch.pc = vcpu->arch.io_pc;  	switch (run->mmio.len) {  	case 4: @@ -2518,11 +2529,6 @@ enum emulation_result kvm_mips_complete_mmio_load(struct kvm_vcpu *vcpu,  		break;  	} -	if (vcpu->arch.pending_load_cause & CAUSEF_BD) -		kvm_debug("[%#lx] Completing %d byte BD Load to gpr %d (0x%08lx) type %d\n", -			  vcpu->arch.pc, run->mmio.len, vcpu->arch.io_gpr, *gpr, -			  vcpu->mmio_needed); -  done:  	return er;  } diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c index 622037d851a3..06a60b19acfb 100644 --- a/arch/mips/kvm/mips.c +++ b/arch/mips/kvm/mips.c @@ -426,7 +426,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,  static void kvm_mips_check_asids(struct kvm_vcpu *vcpu)  {  	struct mips_coproc *cop0 = vcpu->arch.cop0; -	int cpu = smp_processor_id(); +	int i, cpu = smp_processor_id();  	unsigned int gasid;  	/* @@ -442,6 +442,9 @@ static void kvm_mips_check_asids(struct kvm_vcpu *vcpu)  						vcpu);  			vcpu->arch.guest_user_asid[cpu] =  				vcpu->arch.guest_user_mm.context.asid[cpu]; +			for_each_possible_cpu(i) +				if (i != cpu) +					vcpu->arch.guest_user_asid[cpu] = 0;  			vcpu->arch.last_user_gasid = gasid;  		}  	} diff --git a/arch/mips/kvm/mmu.c b/arch/mips/kvm/mmu.c index 03883ba806e2..3b677c851be0 100644 --- a/arch/mips/kvm/mmu.c +++ b/arch/mips/kvm/mmu.c @@ -260,13 +260,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)  	if ((vcpu->arch.guest_user_asid[cpu] ^ asid_cache(cpu)) &  						asid_version_mask(cpu)) { -		u32 gasid = kvm_read_c0_guest_entryhi(vcpu->arch.cop0) & -				KVM_ENTRYHI_ASID; -  		kvm_get_new_mmu_context(&vcpu->arch.guest_user_mm, cpu, vcpu);  		vcpu->arch.guest_user_asid[cpu] =  		    vcpu->arch.guest_user_mm.context.asid[cpu]; -		vcpu->arch.last_user_gasid = gasid;  		newasid++;  		kvm_debug("[%d]: cpu_context: %#lx\n", cpu, diff --git a/arch/mips/lib/dump_tlb.c b/arch/mips/lib/dump_tlb.c index 0f80b936e75e..6eb50a7137db 100644 --- a/arch/mips/lib/dump_tlb.c +++ b/arch/mips/lib/dump_tlb.c @@ -135,42 +135,42 @@ static void dump_tlb(int first, int last)  		c0 = (entrylo0 & ENTRYLO_C) >> ENTRYLO_C_SHIFT;  		c1 = (entrylo1 & ENTRYLO_C) >> ENTRYLO_C_SHIFT; -		printk("va=%0*lx asid=%0*lx", -		       vwidth, (entryhi & ~0x1fffUL), -		       asidwidth, entryhi & asidmask); +		pr_cont("va=%0*lx asid=%0*lx", +			vwidth, (entryhi & ~0x1fffUL), +			asidwidth, entryhi & asidmask);  		if (cpu_has_guestid) -			printk(" gid=%02lx", -			       (guestctl1 & MIPS_GCTL1_RID) +			pr_cont(" gid=%02lx", +				(guestctl1 & MIPS_GCTL1_RID)  					>> MIPS_GCTL1_RID_SHIFT);  		/* RI/XI are in awkward places, so mask them off separately */  		pa = entrylo0 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);  		if (xpa)  			pa |= (unsigned long long)readx_c0_entrylo0() << 30;  		pa = (pa << 6) & PAGE_MASK; -		printk("\n\t["); +		pr_cont("\n\t[");  		if (cpu_has_rixi) -			printk("ri=%d xi=%d ", -			       (entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0, -			       (entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0); -		printk("pa=%0*llx c=%d d=%d v=%d g=%d] [", -		       pwidth, pa, c0, -		       (entrylo0 & ENTRYLO_D) ? 1 : 0, -		       (entrylo0 & ENTRYLO_V) ? 1 : 0, -		       (entrylo0 & ENTRYLO_G) ? 1 : 0); +			pr_cont("ri=%d xi=%d ", +				(entrylo0 & MIPS_ENTRYLO_RI) ? 1 : 0, +				(entrylo0 & MIPS_ENTRYLO_XI) ? 1 : 0); +		pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d] [", +			pwidth, pa, c0, +			(entrylo0 & ENTRYLO_D) ? 1 : 0, +			(entrylo0 & ENTRYLO_V) ? 1 : 0, +			(entrylo0 & ENTRYLO_G) ? 1 : 0);  		/* RI/XI are in awkward places, so mask them off separately */  		pa = entrylo1 & ~(MIPS_ENTRYLO_RI | MIPS_ENTRYLO_XI);  		if (xpa)  			pa |= (unsigned long long)readx_c0_entrylo1() << 30;  		pa = (pa << 6) & PAGE_MASK;  		if (cpu_has_rixi) -			printk("ri=%d xi=%d ", -			       (entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0, -			       (entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0); -		printk("pa=%0*llx c=%d d=%d v=%d g=%d]\n", -		       pwidth, pa, c1, -		       (entrylo1 & ENTRYLO_D) ? 1 : 0, -		       (entrylo1 & ENTRYLO_V) ? 1 : 0, -		       (entrylo1 & ENTRYLO_G) ? 1 : 0); +			pr_cont("ri=%d xi=%d ", +				(entrylo1 & MIPS_ENTRYLO_RI) ? 1 : 0, +				(entrylo1 & MIPS_ENTRYLO_XI) ? 1 : 0); +		pr_cont("pa=%0*llx c=%d d=%d v=%d g=%d]\n", +			pwidth, pa, c1, +			(entrylo1 & ENTRYLO_D) ? 1 : 0, +			(entrylo1 & ENTRYLO_V) ? 1 : 0, +			(entrylo1 & ENTRYLO_G) ? 1 : 0);  	}  	printk("\n"); diff --git a/arch/mips/lib/r3k_dump_tlb.c b/arch/mips/lib/r3k_dump_tlb.c index 744f4a7bc49d..85b4086e553e 100644 --- a/arch/mips/lib/r3k_dump_tlb.c +++ b/arch/mips/lib/r3k_dump_tlb.c @@ -53,15 +53,15 @@ static void dump_tlb(int first, int last)  			 */  			printk("Index: %2d ", i); -			printk("va=%08lx asid=%08lx" -			       "  [pa=%06lx n=%d d=%d v=%d g=%d]", -			       entryhi & PAGE_MASK, -			       entryhi & asid_mask, -			       entrylo0 & PAGE_MASK, -			       (entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, -			       (entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, -			       (entrylo0 & R3K_ENTRYLO_V) ? 1 : 0, -			       (entrylo0 & R3K_ENTRYLO_G) ? 1 : 0); +			pr_cont("va=%08lx asid=%08lx" +				"  [pa=%06lx n=%d d=%d v=%d g=%d]", +				entryhi & PAGE_MASK, +				entryhi & asid_mask, +				entrylo0 & PAGE_MASK, +				(entrylo0 & R3K_ENTRYLO_N) ? 1 : 0, +				(entrylo0 & R3K_ENTRYLO_D) ? 1 : 0, +				(entrylo0 & R3K_ENTRYLO_V) ? 1 : 0, +				(entrylo0 & R3K_ENTRYLO_G) ? 1 : 0);  		}  	}  	printk("\n"); diff --git a/arch/parisc/include/uapi/asm/unistd.h b/arch/parisc/include/uapi/asm/unistd.h index a9b9407f38f7..6b0741e7a7ed 100644 --- a/arch/parisc/include/uapi/asm/unistd.h +++ b/arch/parisc/include/uapi/asm/unistd.h @@ -368,7 +368,9 @@  #define __IGNORE_select		/* newselect */  #define __IGNORE_fadvise64	/* fadvise64_64 */ - +#define __IGNORE_pkey_mprotect +#define __IGNORE_pkey_alloc +#define __IGNORE_pkey_free  #define LINUX_GATEWAY_ADDR      0x100 diff --git a/arch/parisc/kernel/drivers.c b/arch/parisc/kernel/drivers.c index f8150669b8c6..700e2d2da096 100644 --- a/arch/parisc/kernel/drivers.c +++ b/arch/parisc/kernel/drivers.c @@ -873,11 +873,11 @@ static void print_parisc_device(struct parisc_device *dev)  	if (dev->num_addrs) {  		int k; -		printk(", additional addresses: "); +		pr_cont(", additional addresses: ");  		for (k = 0; k < dev->num_addrs; k++) -			printk("0x%lx ", dev->addr[k]); +			pr_cont("0x%lx ", dev->addr[k]);  	} -	printk("\n"); +	pr_cont("\n");  }  /** diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index d03422e5f188..23de307c3052 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -100,14 +100,12 @@ set_thread_pointer:  	.endr  /* This address must remain fixed at 0x100 for glibc's syscalls to work */ -	.align 256 +	.align LINUX_GATEWAY_ADDR  linux_gateway_entry:  	gate	.+8, %r0			/* become privileged */  	mtsp	%r0,%sr4			/* get kernel space into sr4 */  	mtsp	%r0,%sr5			/* get kernel space into sr5 */  	mtsp	%r0,%sr6			/* get kernel space into sr6 */ -	mfsp    %sr7,%r1                        /* save user sr7 */ -	mtsp    %r1,%sr3                        /* and store it in sr3 */  #ifdef CONFIG_64BIT  	/* for now we can *always* set the W bit on entry to the syscall @@ -133,6 +131,14 @@ linux_gateway_entry:  	depdi	0, 31, 32, %r21  1:	  #endif + +	/* We use a rsm/ssm pair to prevent sr3 from being clobbered +	 * by external interrupts. +	 */ +	mfsp    %sr7,%r1                        /* save user sr7 */ +	rsm	PSW_SM_I, %r0			/* disable interrupts */ +	mtsp    %r1,%sr3                        /* and store it in sr3 */ +  	mfctl   %cr30,%r1  	xor     %r1,%r30,%r30                   /* ye olde xor trick */  	xor     %r1,%r30,%r1 @@ -147,6 +153,7 @@ linux_gateway_entry:  	 */  	mtsp	%r0,%sr7			/* get kernel space into sr7 */ +	ssm	PSW_SM_I, %r0			/* enable interrupts */  	STREGM	%r1,FRAME_SIZE(%r30)		/* save r1 (usp) here for now */  	mfctl	%cr30,%r1			/* get task ptr in %r1 */  	LDREG	TI_TASK(%r1),%r1 @@ -474,11 +481,6 @@ lws_start:  	comiclr,>>	__NR_lws_entries, %r20, %r0  	b,n	lws_exit_nosys -	/* WARNING: Trashing sr2 and sr3 */ -	mfsp	%sr7,%r1			/* get userspace into sr3 */ -	mtsp	%r1,%sr3 -	mtsp	%r0,%sr2			/* get kernel space into sr2 */ -  	/* Load table start */  	ldil	L%lws_table, %r1  	ldo	R%lws_table(%r1), %r28	/* Scratch use of r28 */ @@ -627,9 +629,9 @@ cas_action:  	stw	%r1, 4(%sr2,%r20)  #endif  	/* The load and store could fail */ -1:	ldw,ma	0(%sr3,%r26), %r28 +1:	ldw,ma	0(%r26), %r28  	sub,<>	%r28, %r25, %r0 -2:	stw,ma	%r24, 0(%sr3,%r26) +2:	stw,ma	%r24, 0(%r26)  	/* Free lock */  	stw,ma	%r20, 0(%sr2,%r20)  #if ENABLE_LWS_DEBUG @@ -706,9 +708,9 @@ lws_compare_and_swap_2:  	nop  	/* 8bit load */ -4:	ldb	0(%sr3,%r25), %r25 +4:	ldb	0(%r25), %r25  	b	cas2_lock_start -5:	ldb	0(%sr3,%r24), %r24 +5:	ldb	0(%r24), %r24  	nop  	nop  	nop @@ -716,9 +718,9 @@ lws_compare_and_swap_2:  	nop  	/* 16bit load */ -6:	ldh	0(%sr3,%r25), %r25 +6:	ldh	0(%r25), %r25  	b	cas2_lock_start -7:	ldh	0(%sr3,%r24), %r24 +7:	ldh	0(%r24), %r24  	nop  	nop  	nop @@ -726,9 +728,9 @@ lws_compare_and_swap_2:  	nop  	/* 32bit load */ -8:	ldw	0(%sr3,%r25), %r25 +8:	ldw	0(%r25), %r25  	b	cas2_lock_start -9:	ldw	0(%sr3,%r24), %r24 +9:	ldw	0(%r24), %r24  	nop  	nop  	nop @@ -737,14 +739,14 @@ lws_compare_and_swap_2:  	/* 64bit load */  #ifdef CONFIG_64BIT -10:	ldd	0(%sr3,%r25), %r25 -11:	ldd	0(%sr3,%r24), %r24 +10:	ldd	0(%r25), %r25 +11:	ldd	0(%r24), %r24  #else  	/* Load new value into r22/r23 - high/low */ -10:	ldw	0(%sr3,%r25), %r22 -11:	ldw	4(%sr3,%r25), %r23 +10:	ldw	0(%r25), %r22 +11:	ldw	4(%r25), %r23  	/* Load new value into fr4 for atomic store later */ -12:	flddx	0(%sr3,%r24), %fr4 +12:	flddx	0(%r24), %fr4  #endif  cas2_lock_start: @@ -794,30 +796,30 @@ cas2_action:  	ldo	1(%r0),%r28  	/* 8bit CAS */ -13:	ldb,ma	0(%sr3,%r26), %r29 +13:	ldb,ma	0(%r26), %r29  	sub,=	%r29, %r25, %r0  	b,n	cas2_end -14:	stb,ma	%r24, 0(%sr3,%r26) +14:	stb,ma	%r24, 0(%r26)  	b	cas2_end  	copy	%r0, %r28  	nop  	nop  	/* 16bit CAS */ -15:	ldh,ma	0(%sr3,%r26), %r29 +15:	ldh,ma	0(%r26), %r29  	sub,=	%r29, %r25, %r0  	b,n	cas2_end -16:	sth,ma	%r24, 0(%sr3,%r26) +16:	sth,ma	%r24, 0(%r26)  	b	cas2_end  	copy	%r0, %r28  	nop  	nop  	/* 32bit CAS */ -17:	ldw,ma	0(%sr3,%r26), %r29 +17:	ldw,ma	0(%r26), %r29  	sub,=	%r29, %r25, %r0  	b,n	cas2_end -18:	stw,ma	%r24, 0(%sr3,%r26) +18:	stw,ma	%r24, 0(%r26)  	b	cas2_end  	copy	%r0, %r28  	nop @@ -825,22 +827,22 @@ cas2_action:  	/* 64bit CAS */  #ifdef CONFIG_64BIT -19:	ldd,ma	0(%sr3,%r26), %r29 +19:	ldd,ma	0(%r26), %r29  	sub,*=	%r29, %r25, %r0  	b,n	cas2_end -20:	std,ma	%r24, 0(%sr3,%r26) +20:	std,ma	%r24, 0(%r26)  	copy	%r0, %r28  #else  	/* Compare first word */ -19:	ldw,ma	0(%sr3,%r26), %r29 +19:	ldw,ma	0(%r26), %r29  	sub,=	%r29, %r22, %r0  	b,n	cas2_end  	/* Compare second word */ -20:	ldw,ma	4(%sr3,%r26), %r29 +20:	ldw,ma	4(%r26), %r29  	sub,=	%r29, %r23, %r0  	b,n	cas2_end  	/* Perform the store */ -21:	fstdx	%fr4, 0(%sr3,%r26) +21:	fstdx	%fr4, 0(%r26)  	copy	%r0, %r28  #endif diff --git a/arch/s390/kvm/sthyi.c b/arch/s390/kvm/sthyi.c index bd98b7d25200..05c98bb853cf 100644 --- a/arch/s390/kvm/sthyi.c +++ b/arch/s390/kvm/sthyi.c @@ -315,7 +315,7 @@ static void fill_diag(struct sthyi_sctns *sctns)  	if (r < 0)  		goto out; -	diag224_buf = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA); +	diag224_buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);  	if (!diag224_buf || diag224(diag224_buf))  		goto out; @@ -378,7 +378,7 @@ static void fill_diag(struct sthyi_sctns *sctns)  	sctns->par.infpval1 |= PAR_WGHT_VLD;  out: -	kfree(diag224_buf); +	free_page((unsigned long)diag224_buf);  	vfree(diag204_buf);  } diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index 4b20f7304b9c..bdde80731f49 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -948,7 +948,6 @@ struct kvm_x86_ops {  	int (*get_lpage_level)(void);  	bool (*rdtscp_supported)(void);  	bool (*invpcid_supported)(void); -	void (*adjust_tsc_offset_guest)(struct kvm_vcpu *vcpu, s64 adjustment);  	void (*set_tdp_cr3)(struct kvm_vcpu *vcpu, unsigned long cr3); @@ -958,8 +957,6 @@ struct kvm_x86_ops {  	void (*write_tsc_offset)(struct kvm_vcpu *vcpu, u64 offset); -	u64 (*read_l1_tsc)(struct kvm_vcpu *vcpu, u64 host_tsc); -  	void (*get_exit_info)(struct kvm_vcpu *vcpu, u64 *info1, u64 *info2);  	int (*check_intercept)(struct kvm_vcpu *vcpu, diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 4e95d3eb2955..cbd7b92585bb 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -5045,7 +5045,7 @@ done_prefixes:  	/* Decode and fetch the destination operand: register or memory. */  	rc = decode_operand(ctxt, &ctxt->dst, (ctxt->d >> DstShift) & OpMask); -	if (ctxt->rip_relative) +	if (ctxt->rip_relative && likely(ctxt->memopp))  		ctxt->memopp->addr.mem.ea = address_mask(ctxt,  					ctxt->memopp->addr.mem.ea + ctxt->_eip); diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index f8157a36ab09..8ca1eca5038d 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1138,21 +1138,6 @@ static void svm_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)  	mark_dirty(svm->vmcb, VMCB_INTERCEPTS);  } -static void svm_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment) -{ -	struct vcpu_svm *svm = to_svm(vcpu); - -	svm->vmcb->control.tsc_offset += adjustment; -	if (is_guest_mode(vcpu)) -		svm->nested.hsave->control.tsc_offset += adjustment; -	else -		trace_kvm_write_tsc_offset(vcpu->vcpu_id, -				     svm->vmcb->control.tsc_offset - adjustment, -				     svm->vmcb->control.tsc_offset); - -	mark_dirty(svm->vmcb, VMCB_INTERCEPTS); -} -  static void avic_init_vmcb(struct vcpu_svm *svm)  {  	struct vmcb *vmcb = svm->vmcb; @@ -3449,12 +3434,6 @@ static int cr8_write_interception(struct vcpu_svm *svm)  	return 0;  } -static u64 svm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc) -{ -	struct vmcb *vmcb = get_host_vmcb(to_svm(vcpu)); -	return vmcb->control.tsc_offset + host_tsc; -} -  static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)  {  	struct vcpu_svm *svm = to_svm(vcpu); @@ -5422,8 +5401,6 @@ static struct kvm_x86_ops svm_x86_ops __ro_after_init = {  	.has_wbinvd_exit = svm_has_wbinvd_exit,  	.write_tsc_offset = svm_write_tsc_offset, -	.adjust_tsc_offset_guest = svm_adjust_tsc_offset_guest, -	.read_l1_tsc = svm_read_l1_tsc,  	.set_tdp_cr3 = set_tdp_cr3, diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index cf1b16dbc98a..5382b82462fc 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -187,6 +187,7 @@ struct vmcs {   */  struct loaded_vmcs {  	struct vmcs *vmcs; +	struct vmcs *shadow_vmcs;  	int cpu;  	int launched;  	struct list_head loaded_vmcss_on_cpu_link; @@ -411,7 +412,6 @@ struct nested_vmx {  	 * memory during VMXOFF, VMCLEAR, VMPTRLD.  	 */  	struct vmcs12 *cached_vmcs12; -	struct vmcs *current_shadow_vmcs;  	/*  	 * Indicates if the shadow vmcs must be updated with the  	 * data hold by vmcs12 @@ -421,7 +421,6 @@ struct nested_vmx {  	/* vmcs02_list cache of VMCSs recently used to run L2 guests */  	struct list_head vmcs02_pool;  	int vmcs02_num; -	u64 vmcs01_tsc_offset;  	bool change_vmcs01_virtual_x2apic_mode;  	/* L2 must run next, and mustn't decide to exit to L1. */  	bool nested_run_pending; @@ -1419,6 +1418,8 @@ static void vmcs_clear(struct vmcs *vmcs)  static inline void loaded_vmcs_init(struct loaded_vmcs *loaded_vmcs)  {  	vmcs_clear(loaded_vmcs->vmcs); +	if (loaded_vmcs->shadow_vmcs && loaded_vmcs->launched) +		vmcs_clear(loaded_vmcs->shadow_vmcs);  	loaded_vmcs->cpu = -1;  	loaded_vmcs->launched = 0;  } @@ -2605,20 +2606,6 @@ static u64 guest_read_tsc(struct kvm_vcpu *vcpu)  }  /* - * Like guest_read_tsc, but always returns L1's notion of the timestamp - * counter, even if a nested guest (L2) is currently running. - */ -static u64 vmx_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc) -{ -	u64 tsc_offset; - -	tsc_offset = is_guest_mode(vcpu) ? -		to_vmx(vcpu)->nested.vmcs01_tsc_offset : -		vmcs_read64(TSC_OFFSET); -	return host_tsc + tsc_offset; -} - -/*   * writes 'offset' into guest's timestamp counter offset register   */  static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset) @@ -2631,7 +2618,6 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)  		 * to the newly set TSC to get L2's TSC.  		 */  		struct vmcs12 *vmcs12; -		to_vmx(vcpu)->nested.vmcs01_tsc_offset = offset;  		/* recalculate vmcs02.TSC_OFFSET: */  		vmcs12 = get_vmcs12(vcpu);  		vmcs_write64(TSC_OFFSET, offset + @@ -2644,19 +2630,6 @@ static void vmx_write_tsc_offset(struct kvm_vcpu *vcpu, u64 offset)  	}  } -static void vmx_adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, s64 adjustment) -{ -	u64 offset = vmcs_read64(TSC_OFFSET); - -	vmcs_write64(TSC_OFFSET, offset + adjustment); -	if (is_guest_mode(vcpu)) { -		/* Even when running L2, the adjustment needs to apply to L1 */ -		to_vmx(vcpu)->nested.vmcs01_tsc_offset += adjustment; -	} else -		trace_kvm_write_tsc_offset(vcpu->vcpu_id, offset, -					   offset + adjustment); -} -  static bool guest_cpuid_has_vmx(struct kvm_vcpu *vcpu)  {  	struct kvm_cpuid_entry2 *best = kvm_find_cpuid_entry(vcpu, 1, 0); @@ -3562,6 +3535,7 @@ static void free_loaded_vmcs(struct loaded_vmcs *loaded_vmcs)  	loaded_vmcs_clear(loaded_vmcs);  	free_vmcs(loaded_vmcs->vmcs);  	loaded_vmcs->vmcs = NULL; +	WARN_ON(loaded_vmcs->shadow_vmcs != NULL);  }  static void free_kvm_area(void) @@ -6696,6 +6670,7 @@ static struct loaded_vmcs *nested_get_current_vmcs02(struct vcpu_vmx *vmx)  	if (!item)  		return NULL;  	item->vmcs02.vmcs = alloc_vmcs(); +	item->vmcs02.shadow_vmcs = NULL;  	if (!item->vmcs02.vmcs) {  		kfree(item);  		return NULL; @@ -7072,7 +7047,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)  		shadow_vmcs->revision_id |= (1u << 31);  		/* init shadow vmcs */  		vmcs_clear(shadow_vmcs); -		vmx->nested.current_shadow_vmcs = shadow_vmcs; +		vmx->vmcs01.shadow_vmcs = shadow_vmcs;  	}  	INIT_LIST_HEAD(&(vmx->nested.vmcs02_pool)); @@ -7174,8 +7149,11 @@ static void free_nested(struct vcpu_vmx *vmx)  		free_page((unsigned long)vmx->nested.msr_bitmap);  		vmx->nested.msr_bitmap = NULL;  	} -	if (enable_shadow_vmcs) -		free_vmcs(vmx->nested.current_shadow_vmcs); +	if (enable_shadow_vmcs) { +		vmcs_clear(vmx->vmcs01.shadow_vmcs); +		free_vmcs(vmx->vmcs01.shadow_vmcs); +		vmx->vmcs01.shadow_vmcs = NULL; +	}  	kfree(vmx->nested.cached_vmcs12);  	/* Unpin physical memory we referred to in current vmcs02 */  	if (vmx->nested.apic_access_page) { @@ -7352,7 +7330,7 @@ static void copy_shadow_to_vmcs12(struct vcpu_vmx *vmx)  	int i;  	unsigned long field;  	u64 field_value; -	struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; +	struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;  	const unsigned long *fields = shadow_read_write_fields;  	const int num_fields = max_shadow_read_write_fields; @@ -7401,7 +7379,7 @@ static void copy_vmcs12_to_shadow(struct vcpu_vmx *vmx)  	int i, q;  	unsigned long field;  	u64 field_value = 0; -	struct vmcs *shadow_vmcs = vmx->nested.current_shadow_vmcs; +	struct vmcs *shadow_vmcs = vmx->vmcs01.shadow_vmcs;  	vmcs_load(shadow_vmcs); @@ -7591,7 +7569,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)  			vmcs_set_bits(SECONDARY_VM_EXEC_CONTROL,  				      SECONDARY_EXEC_SHADOW_VMCS);  			vmcs_write64(VMCS_LINK_POINTER, -				     __pa(vmx->nested.current_shadow_vmcs)); +				     __pa(vmx->vmcs01.shadow_vmcs));  			vmx->nested.sync_shadow_vmcs = true;  		}  	} @@ -7659,7 +7637,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)  	types = (vmx->nested.nested_vmx_ept_caps >> VMX_EPT_EXTENT_SHIFT) & 6; -	if (!(types & (1UL << type))) { +	if (type >= 32 || !(types & (1 << type))) {  		nested_vmx_failValid(vcpu,  				VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);  		skip_emulated_instruction(vcpu); @@ -7722,7 +7700,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)  	types = (vmx->nested.nested_vmx_vpid_caps >> 8) & 0x7; -	if (!(types & (1UL << type))) { +	if (type >= 32 || !(types & (1 << type))) {  		nested_vmx_failValid(vcpu,  			VMXERR_INVALID_OPERAND_TO_INVEPT_INVVPID);  		skip_emulated_instruction(vcpu); @@ -9156,6 +9134,7 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, unsigned int id)  	vmx->loaded_vmcs = &vmx->vmcs01;  	vmx->loaded_vmcs->vmcs = alloc_vmcs(); +	vmx->loaded_vmcs->shadow_vmcs = NULL;  	if (!vmx->loaded_vmcs->vmcs)  		goto free_msrs;  	if (!vmm_exclusive) @@ -10061,9 +10040,9 @@ static void prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)  	if (vmcs12->cpu_based_vm_exec_control & CPU_BASED_USE_TSC_OFFSETING)  		vmcs_write64(TSC_OFFSET, -			vmx->nested.vmcs01_tsc_offset + vmcs12->tsc_offset); +			vcpu->arch.tsc_offset + vmcs12->tsc_offset);  	else -		vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset); +		vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);  	if (kvm_has_tsc_control)  		decache_tsc_multiplier(vmx); @@ -10293,8 +10272,6 @@ static int nested_vmx_run(struct kvm_vcpu *vcpu, bool launch)  	enter_guest_mode(vcpu); -	vmx->nested.vmcs01_tsc_offset = vmcs_read64(TSC_OFFSET); -  	if (!(vmcs12->vm_entry_controls & VM_ENTRY_LOAD_DEBUG_CONTROLS))  		vmx->nested.vmcs01_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL); @@ -10818,7 +10795,7 @@ static void nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 exit_reason,  	load_vmcs12_host_state(vcpu, vmcs12);  	/* Update any VMCS fields that might have changed while L2 ran */ -	vmcs_write64(TSC_OFFSET, vmx->nested.vmcs01_tsc_offset); +	vmcs_write64(TSC_OFFSET, vcpu->arch.tsc_offset);  	if (vmx->hv_deadline_tsc == -1)  		vmcs_clear_bits(PIN_BASED_VM_EXEC_CONTROL,  				PIN_BASED_VMX_PREEMPTION_TIMER); @@ -11339,8 +11316,6 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {  	.has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,  	.write_tsc_offset = vmx_write_tsc_offset, -	.adjust_tsc_offset_guest = vmx_adjust_tsc_offset_guest, -	.read_l1_tsc = vmx_read_l1_tsc,  	.set_tdp_cr3 = vmx_set_cr3, diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e375235d81c9..3017de0431bd 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1409,7 +1409,7 @@ static u64 kvm_compute_tsc_offset(struct kvm_vcpu *vcpu, u64 target_tsc)  u64 kvm_read_l1_tsc(struct kvm_vcpu *vcpu, u64 host_tsc)  { -	return kvm_x86_ops->read_l1_tsc(vcpu, kvm_scale_tsc(vcpu, host_tsc)); +	return vcpu->arch.tsc_offset + kvm_scale_tsc(vcpu, host_tsc);  }  EXPORT_SYMBOL_GPL(kvm_read_l1_tsc); @@ -1547,7 +1547,7 @@ EXPORT_SYMBOL_GPL(kvm_write_tsc);  static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu,  					   s64 adjustment)  { -	kvm_x86_ops->adjust_tsc_offset_guest(vcpu, adjustment); +	kvm_vcpu_write_tsc_offset(vcpu, vcpu->arch.tsc_offset + adjustment);  }  static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment) @@ -1555,7 +1555,7 @@ static inline void adjust_tsc_offset_host(struct kvm_vcpu *vcpu, s64 adjustment)  	if (vcpu->arch.tsc_scaling_ratio != kvm_default_tsc_scaling_ratio)  		WARN_ON(adjustment < 0);  	adjustment = kvm_scale_tsc(vcpu, (u64) adjustment); -	kvm_x86_ops->adjust_tsc_offset_guest(vcpu, adjustment); +	adjust_tsc_offset_guest(vcpu, adjustment);  }  #ifdef CONFIG_X86_64 @@ -2262,7 +2262,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)  		/* Drop writes to this legacy MSR -- see rdmsr  		 * counterpart for further detail.  		 */ -		vcpu_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data); +		vcpu_unimpl(vcpu, "ignored wrmsr: 0x%x data 0x%llx\n", msr, data);  		break;  	case MSR_AMD64_OSVW_ID_LENGTH:  		if (!guest_cpuid_has_osvw(vcpu)) @@ -2280,11 +2280,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)  		if (kvm_pmu_is_valid_msr(vcpu, msr))  			return kvm_pmu_set_msr(vcpu, msr_info);  		if (!ignore_msrs) { -			vcpu_unimpl(vcpu, "unhandled wrmsr: 0x%x data %llx\n", +			vcpu_unimpl(vcpu, "unhandled wrmsr: 0x%x data 0x%llx\n",  				    msr, data);  			return 1;  		} else { -			vcpu_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", +			vcpu_unimpl(vcpu, "ignored wrmsr: 0x%x data 0x%llx\n",  				    msr, data);  			break;  		} @@ -7410,10 +7410,12 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)  void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)  { +	void *wbinvd_dirty_mask = vcpu->arch.wbinvd_dirty_mask; +  	kvmclock_reset(vcpu); -	free_cpumask_var(vcpu->arch.wbinvd_dirty_mask);  	kvm_x86_ops->vcpu_free(vcpu); +	free_cpumask_var(wbinvd_dirty_mask);  }  struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 2dc5c96c186a..5545a679abd8 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -376,7 +376,7 @@ static void virtblk_config_changed(struct virtio_device *vdev)  static int init_vq(struct virtio_blk *vblk)  { -	int err = 0; +	int err;  	int i;  	vq_callback_t **callbacks;  	const char **names; @@ -390,13 +390,13 @@ static int init_vq(struct virtio_blk *vblk)  	if (err)  		num_vqs = 1; -	vblk->vqs = kmalloc(sizeof(*vblk->vqs) * num_vqs, GFP_KERNEL); +	vblk->vqs = kmalloc_array(num_vqs, sizeof(*vblk->vqs), GFP_KERNEL);  	if (!vblk->vqs)  		return -ENOMEM; -	names = kmalloc(sizeof(*names) * num_vqs, GFP_KERNEL); -	callbacks = kmalloc(sizeof(*callbacks) * num_vqs, GFP_KERNEL); -	vqs = kmalloc(sizeof(*vqs) * num_vqs, GFP_KERNEL); +	names = kmalloc_array(num_vqs, sizeof(*names), GFP_KERNEL); +	callbacks = kmalloc_array(num_vqs, sizeof(*callbacks), GFP_KERNEL); +	vqs = kmalloc_array(num_vqs, sizeof(*vqs), GFP_KERNEL);  	if (!names || !callbacks || !vqs) {  		err = -ENOMEM;  		goto out; diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index d433b1db1fdd..5649234b7316 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -1539,19 +1539,29 @@ static void remove_port_data(struct port *port)  	spin_lock_irq(&port->inbuf_lock);  	/* Remove unused data this port might have received. */  	discard_port_data(port); +	spin_unlock_irq(&port->inbuf_lock);  	/* Remove buffers we queued up for the Host to send us data in. */ -	while ((buf = virtqueue_detach_unused_buf(port->in_vq))) -		free_buf(buf, true); -	spin_unlock_irq(&port->inbuf_lock); +	do { +		spin_lock_irq(&port->inbuf_lock); +		buf = virtqueue_detach_unused_buf(port->in_vq); +		spin_unlock_irq(&port->inbuf_lock); +		if (buf) +			free_buf(buf, true); +	} while (buf);  	spin_lock_irq(&port->outvq_lock);  	reclaim_consumed_buffers(port); +	spin_unlock_irq(&port->outvq_lock);  	/* Free pending buffers from the out-queue. */ -	while ((buf = virtqueue_detach_unused_buf(port->out_vq))) -		free_buf(buf, true); -	spin_unlock_irq(&port->outvq_lock); +	do { +		spin_lock_irq(&port->outvq_lock); +		buf = virtqueue_detach_unused_buf(port->out_vq); +		spin_unlock_irq(&port->outvq_lock); +		if (buf) +			free_buf(buf, true); +	} while (buf);  }  /* diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 309311b1faae..15475892af0c 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c @@ -73,13 +73,13 @@ struct rfc2734_header {  #define fwnet_get_hdr_lf(h)		(((h)->w0 & 0xc0000000) >> 30)  #define fwnet_get_hdr_ether_type(h)	(((h)->w0 & 0x0000ffff)) -#define fwnet_get_hdr_dg_size(h)	(((h)->w0 & 0x0fff0000) >> 16) +#define fwnet_get_hdr_dg_size(h)	((((h)->w0 & 0x0fff0000) >> 16) + 1)  #define fwnet_get_hdr_fg_off(h)		(((h)->w0 & 0x00000fff))  #define fwnet_get_hdr_dgl(h)		(((h)->w1 & 0xffff0000) >> 16) -#define fwnet_set_hdr_lf(lf)		((lf)  << 30) +#define fwnet_set_hdr_lf(lf)		((lf) << 30)  #define fwnet_set_hdr_ether_type(et)	(et) -#define fwnet_set_hdr_dg_size(dgs)	((dgs) << 16) +#define fwnet_set_hdr_dg_size(dgs)	(((dgs) - 1) << 16)  #define fwnet_set_hdr_fg_off(fgo)	(fgo)  #define fwnet_set_hdr_dgl(dgl)		((dgl) << 16) @@ -578,6 +578,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,  	int retval;  	u16 ether_type; +	if (len <= RFC2374_UNFRAG_HDR_SIZE) +		return 0; +  	hdr.w0 = be32_to_cpu(buf[0]);  	lf = fwnet_get_hdr_lf(&hdr);  	if (lf == RFC2374_HDR_UNFRAG) { @@ -602,7 +605,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,  		return fwnet_finish_incoming_packet(net, skb, source_node_id,  						    is_broadcast, ether_type);  	} +  	/* A datagram fragment has been received, now the fun begins. */ + +	if (len <= RFC2374_FRAG_HDR_SIZE) +		return 0; +  	hdr.w1 = ntohl(buf[1]);  	buf += 2;  	len -= RFC2374_FRAG_HDR_SIZE; @@ -614,7 +622,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len,  		fg_off = fwnet_get_hdr_fg_off(&hdr);  	}  	datagram_label = fwnet_get_hdr_dgl(&hdr); -	dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ +	dg_size = fwnet_get_hdr_dg_size(&hdr); + +	if (fg_off + len > dg_size) +		return 0;  	spin_lock_irqsave(&dev->lock, flags); @@ -722,6 +733,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r,  	fw_send_response(card, r, rcode);  } +static int gasp_source_id(__be32 *p) +{ +	return be32_to_cpu(p[0]) >> 16; +} + +static u32 gasp_specifier_id(__be32 *p) +{ +	return (be32_to_cpu(p[0]) & 0xffff) << 8 | +	       (be32_to_cpu(p[1]) & 0xff000000) >> 24; +} + +static u32 gasp_version(__be32 *p) +{ +	return be32_to_cpu(p[1]) & 0xffffff; +} +  static void fwnet_receive_broadcast(struct fw_iso_context *context,  		u32 cycle, size_t header_length, void *header, void *data)  { @@ -731,9 +758,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,  	__be32 *buf_ptr;  	int retval;  	u32 length; -	u16 source_node_id; -	u32 specifier_id; -	u32 ver;  	unsigned long offset;  	unsigned long flags; @@ -750,22 +774,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context,  	spin_unlock_irqrestore(&dev->lock, flags); -	specifier_id =    (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8 -			| (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24; -	ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; -	source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; - -	if (specifier_id == IANA_SPECIFIER_ID && -	    (ver == RFC2734_SW_VERSION +	if (length > IEEE1394_GASP_HDR_SIZE && +	    gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID && +	    (gasp_version(buf_ptr) == RFC2734_SW_VERSION  #if IS_ENABLED(CONFIG_IPV6) -	     || ver == RFC3146_SW_VERSION +	     || gasp_version(buf_ptr) == RFC3146_SW_VERSION  #endif -	    )) { -		buf_ptr += 2; -		length -= IEEE1394_GASP_HDR_SIZE; -		fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, +	    )) +		fwnet_incoming_packet(dev, buf_ptr + 2, +				      length - IEEE1394_GASP_HDR_SIZE, +				      gasp_source_id(buf_ptr),  				      context->card->generation, true); -	}  	packet.payload_length = dev->rcv_buffer_size;  	packet.interrupt = 1; diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index cd5dc27320a2..1ed6132b993c 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c @@ -293,10 +293,10 @@ static void mvebu_gpio_irq_ack(struct irq_data *d)  {  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);  	struct mvebu_gpio_chip *mvchip = gc->private; -	u32 mask = ~(1 << (d->irq - gc->irq_base)); +	u32 mask = d->mask;  	irq_gc_lock(gc); -	writel_relaxed(mask, mvebu_gpioreg_edge_cause(mvchip)); +	writel_relaxed(~mask, mvebu_gpioreg_edge_cause(mvchip));  	irq_gc_unlock(gc);  } @@ -305,7 +305,7 @@ static void mvebu_gpio_edge_irq_mask(struct irq_data *d)  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);  	struct mvebu_gpio_chip *mvchip = gc->private;  	struct irq_chip_type *ct = irq_data_get_chip_type(d); -	u32 mask = 1 << (d->irq - gc->irq_base); +	u32 mask = d->mask;  	irq_gc_lock(gc);  	ct->mask_cache_priv &= ~mask; @@ -319,8 +319,7 @@ static void mvebu_gpio_edge_irq_unmask(struct irq_data *d)  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);  	struct mvebu_gpio_chip *mvchip = gc->private;  	struct irq_chip_type *ct = irq_data_get_chip_type(d); - -	u32 mask = 1 << (d->irq - gc->irq_base); +	u32 mask = d->mask;  	irq_gc_lock(gc);  	ct->mask_cache_priv |= mask; @@ -333,8 +332,7 @@ static void mvebu_gpio_level_irq_mask(struct irq_data *d)  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);  	struct mvebu_gpio_chip *mvchip = gc->private;  	struct irq_chip_type *ct = irq_data_get_chip_type(d); - -	u32 mask = 1 << (d->irq - gc->irq_base); +	u32 mask = d->mask;  	irq_gc_lock(gc);  	ct->mask_cache_priv &= ~mask; @@ -347,8 +345,7 @@ static void mvebu_gpio_level_irq_unmask(struct irq_data *d)  	struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);  	struct mvebu_gpio_chip *mvchip = gc->private;  	struct irq_chip_type *ct = irq_data_get_chip_type(d); - -	u32 mask = 1 << (d->irq - gc->irq_base); +	u32 mask = d->mask;  	irq_gc_lock(gc);  	ct->mask_cache_priv |= mask; @@ -462,7 +459,7 @@ static void mvebu_gpio_irq_handler(struct irq_desc *desc)  	for (i = 0; i < mvchip->chip.ngpio; i++) {  		int irq; -		irq = mvchip->irqbase + i; +		irq = irq_find_mapping(mvchip->domain, i);  		if (!(cause & (1 << i)))  			continue; @@ -655,6 +652,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	struct irq_chip_type *ct;  	struct clk *clk;  	unsigned int ngpios; +	bool have_irqs;  	int soc_variant;  	int i, cpu, id;  	int err; @@ -665,6 +663,9 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	else  		soc_variant = MVEBU_GPIO_SOC_VARIANT_ORION; +	/* Some gpio controllers do not provide irq support */ +	have_irqs = of_irq_count(np) != 0; +  	mvchip = devm_kzalloc(&pdev->dev, sizeof(struct mvebu_gpio_chip),  			      GFP_KERNEL);  	if (!mvchip) @@ -697,7 +698,8 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	mvchip->chip.get = mvebu_gpio_get;  	mvchip->chip.direction_output = mvebu_gpio_direction_output;  	mvchip->chip.set = mvebu_gpio_set; -	mvchip->chip.to_irq = mvebu_gpio_to_irq; +	if (have_irqs) +		mvchip->chip.to_irq = mvebu_gpio_to_irq;  	mvchip->chip.base = id * MVEBU_MAX_GPIO_PER_BANK;  	mvchip->chip.ngpio = ngpios;  	mvchip->chip.can_sleep = false; @@ -758,34 +760,30 @@ static int mvebu_gpio_probe(struct platform_device *pdev)  	devm_gpiochip_add_data(&pdev->dev, &mvchip->chip, mvchip);  	/* Some gpio controllers do not provide irq support */ -	if (!of_irq_count(np)) +	if (!have_irqs)  		return 0; -	/* Setup the interrupt handlers. Each chip can have up to 4 -	 * interrupt handlers, with each handler dealing with 8 GPIO -	 * pins. */ -	for (i = 0; i < 4; i++) { -		int irq = platform_get_irq(pdev, i); - -		if (irq < 0) -			continue; -		irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler, -						 mvchip); -	} - -	mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); -	if (mvchip->irqbase < 0) { -		dev_err(&pdev->dev, "no irqs\n"); -		return mvchip->irqbase; +	mvchip->domain = +	    irq_domain_add_linear(np, ngpios, &irq_generic_chip_ops, NULL); +	if (!mvchip->domain) { +		dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", +			mvchip->chip.label); +		return -ENODEV;  	} -	gc = irq_alloc_generic_chip("mvebu_gpio_irq", 2, mvchip->irqbase, -				    mvchip->membase, handle_level_irq); -	if (!gc) { -		dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); -		return -ENOMEM; +	err = irq_alloc_domain_generic_chips( +	    mvchip->domain, ngpios, 2, np->name, handle_level_irq, +	    IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_LEVEL, 0, 0); +	if (err) { +		dev_err(&pdev->dev, "couldn't allocate irq chips %s (DT).\n", +			mvchip->chip.label); +		goto err_domain;  	} +	/* NOTE: The common accessors cannot be used because of the percpu +	 * access to the mask registers +	 */ +	gc = irq_get_domain_generic_chip(mvchip->domain, 0);  	gc->private = mvchip;  	ct = &gc->chip_types[0];  	ct->type = IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW; @@ -803,27 +801,23 @@ static int 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), 0, -			       IRQ_NOREQUEST, IRQ_LEVEL | IRQ_NOPROBE); +	/* Setup the interrupt handlers. Each chip can have up to 4 +	 * interrupt handlers, with each handler dealing with 8 GPIO +	 * pins. +	 */ +	for (i = 0; i < 4; i++) { +		int irq = platform_get_irq(pdev, i); -	/* Setup irq domain on top of the generic chip. */ -	mvchip->domain = irq_domain_add_simple(np, mvchip->chip.ngpio, -					       mvchip->irqbase, -					       &irq_domain_simple_ops, -					       mvchip); -	if (!mvchip->domain) { -		dev_err(&pdev->dev, "couldn't allocate irq domain %s (DT).\n", -			mvchip->chip.label); -		err = -ENODEV; -		goto err_generic_chip; +		if (irq < 0) +			continue; +		irq_set_chained_handler_and_data(irq, mvebu_gpio_irq_handler, +						 mvchip);  	}  	return 0; -err_generic_chip: -	irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, -				IRQ_LEVEL | IRQ_NOPROBE); -	kfree(gc); +err_domain: +	irq_domain_remove(mvchip->domain);  	return err;  } diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index ecad3f0e3b77..193f15d50bba 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c @@ -26,14 +26,18 @@  #include "gpiolib.h" -static int of_gpiochip_match_node(struct gpio_chip *chip, void *data) +static int of_gpiochip_match_node_and_xlate(struct gpio_chip *chip, void *data)  { -	return chip->gpiodev->dev.of_node == data; +	struct of_phandle_args *gpiospec = data; + +	return chip->gpiodev->dev.of_node == gpiospec->np && +				chip->of_xlate(chip, gpiospec, NULL) >= 0;  } -static struct gpio_chip *of_find_gpiochip_by_node(struct device_node *np) +static struct gpio_chip *of_find_gpiochip_by_xlate( +					struct of_phandle_args *gpiospec)  { -	return gpiochip_find(np, of_gpiochip_match_node); +	return gpiochip_find(gpiospec, of_gpiochip_match_node_and_xlate);  }  static struct gpio_desc *of_xlate_and_get_gpiod_flags(struct gpio_chip *chip, @@ -79,7 +83,7 @@ struct gpio_desc *of_get_named_gpiod_flags(struct device_node *np,  		return ERR_PTR(ret);  	} -	chip = of_find_gpiochip_by_node(gpiospec.np); +	chip = of_find_gpiochip_by_xlate(&gpiospec);  	if (!chip) {  		desc = ERR_PTR(-EPROBE_DEFER);  		goto out; diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 20e09b7c2de3..93ed0e00c578 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -21,6 +21,7 @@  #include <linux/uaccess.h>  #include <linux/compat.h>  #include <linux/anon_inodes.h> +#include <linux/file.h>  #include <linux/kfifo.h>  #include <linux/poll.h>  #include <linux/timekeeping.h> @@ -423,6 +424,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)  {  	struct gpiohandle_request handlereq;  	struct linehandle_state *lh; +	struct file *file;  	int fd, i, ret;  	if (copy_from_user(&handlereq, ip, sizeof(handlereq))) @@ -499,26 +501,41 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)  	i--;  	lh->numdescs = handlereq.lines; -	fd = anon_inode_getfd("gpio-linehandle", -			      &linehandle_fileops, -			      lh, -			      O_RDONLY | O_CLOEXEC); +	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);  	if (fd < 0) {  		ret = fd;  		goto out_free_descs;  	} +	file = anon_inode_getfile("gpio-linehandle", +				  &linehandle_fileops, +				  lh, +				  O_RDONLY | O_CLOEXEC); +	if (IS_ERR(file)) { +		ret = PTR_ERR(file); +		goto out_put_unused_fd; +	} +  	handlereq.fd = fd;  	if (copy_to_user(ip, &handlereq, sizeof(handlereq))) { -		ret = -EFAULT; -		goto out_free_descs; +		/* +		 * fput() will trigger the release() callback, so do not go onto +		 * the regular error cleanup path here. +		 */ +		fput(file); +		put_unused_fd(fd); +		return -EFAULT;  	} +	fd_install(fd, file); +  	dev_dbg(&gdev->dev, "registered chardev handle for %d lines\n",  		lh->numdescs);  	return 0; +out_put_unused_fd: +	put_unused_fd(fd);  out_free_descs:  	for (; i >= 0; i--)  		gpiod_free(lh->descs[i]); @@ -721,6 +738,7 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)  	struct gpioevent_request eventreq;  	struct lineevent_state *le;  	struct gpio_desc *desc; +	struct file *file;  	u32 offset;  	u32 lflags;  	u32 eflags; @@ -815,23 +833,38 @@ static int lineevent_create(struct gpio_device *gdev, void __user *ip)  	if (ret)  		goto out_free_desc; -	fd = anon_inode_getfd("gpio-event", -			      &lineevent_fileops, -			      le, -			      O_RDONLY | O_CLOEXEC); +	fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);  	if (fd < 0) {  		ret = fd;  		goto out_free_irq;  	} +	file = anon_inode_getfile("gpio-event", +				  &lineevent_fileops, +				  le, +				  O_RDONLY | O_CLOEXEC); +	if (IS_ERR(file)) { +		ret = PTR_ERR(file); +		goto out_put_unused_fd; +	} +  	eventreq.fd = fd;  	if (copy_to_user(ip, &eventreq, sizeof(eventreq))) { -		ret = -EFAULT; -		goto out_free_irq; +		/* +		 * fput() will trigger the release() callback, so do not go onto +		 * the regular error cleanup path here. +		 */ +		fput(file); +		put_unused_fd(fd); +		return -EFAULT;  	} +	fd_install(fd, file); +  	return 0; +out_put_unused_fd: +	put_unused_fd(fd);  out_free_irq:  	free_irq(le->irq, le);  out_free_desc: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index b0f6e6957536..82dc8d20e28a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -519,7 +519,8 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,  		r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true,  					   &duplicates);  		if (unlikely(r != 0)) { -			DRM_ERROR("ttm_eu_reserve_buffers failed.\n"); +			if (r != -ERESTARTSYS) +				DRM_ERROR("ttm_eu_reserve_buffers failed.\n");  			goto error_free_pages;  		} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index b4f4a9239069..7ca07e7b25c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -1959,6 +1959,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)  	/* evict remaining vram memory */  	amdgpu_bo_evict_vram(adev); +	amdgpu_atombios_scratch_regs_save(adev);  	pci_save_state(dev->pdev);  	if (suspend) {  		/* Shut down the device */ @@ -2010,6 +2011,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)  			return r;  		}  	} +	amdgpu_atombios_scratch_regs_restore(adev);  	/* post card */  	if (!amdgpu_card_posted(adev) || !resume) { @@ -2268,8 +2270,6 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)  	}  	if (need_full_reset) { -		/* save scratch */ -		amdgpu_atombios_scratch_regs_save(adev);  		r = amdgpu_suspend(adev);  retry: @@ -2279,8 +2279,9 @@ retry:  			amdgpu_display_stop_mc_access(adev, &save);  			amdgpu_wait_for_idle(adev, AMD_IP_BLOCK_TYPE_GMC);  		} - +		amdgpu_atombios_scratch_regs_save(adev);  		r = amdgpu_asic_reset(adev); +		amdgpu_atombios_scratch_regs_restore(adev);  		/* post card */  		amdgpu_atom_asic_init(adev->mode_info.atom_context); @@ -2288,8 +2289,6 @@ retry:  			dev_info(adev->dev, "GPU reset succeeded, trying to resume\n");  			r = amdgpu_resume(adev);  		} -		/* restore scratch */ -		amdgpu_atombios_scratch_regs_restore(adev);  	}  	if (!r) {  		amdgpu_irq_gpu_reset_resume_helper(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 3a2e42f4b897..77b34ec92632 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -68,6 +68,7 @@ int amdgpu_fence_slab_init(void)  void amdgpu_fence_slab_fini(void)  { +	rcu_barrier();  	kmem_cache_destroy(amdgpu_fence_slab);  }  /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c index 278708f5a744..9fa809876339 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_irq.c @@ -239,6 +239,7 @@ int amdgpu_irq_init(struct amdgpu_device *adev)  	if (r) {  		adev->irq.installed = false;  		flush_work(&adev->hotplug_work); +		cancel_work_sync(&adev->reset_work);  		return r;  	} @@ -264,6 +265,7 @@ void amdgpu_irq_fini(struct amdgpu_device *adev)  		if (adev->irq.msi_enabled)  			pci_disable_msi(adev->pdev);  		flush_work(&adev->hotplug_work); +		cancel_work_sync(&adev->reset_work);  	}  	for (i = 0; i < AMDGPU_MAX_IRQ_SRC_ID; ++i) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index c2c7fb140338..203d98b00555 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -459,10 +459,8 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file  		/* return all clocks in KHz */  		dev_info.gpu_counter_freq = amdgpu_asic_get_xclk(adev) * 10;  		if (adev->pm.dpm_enabled) { -			dev_info.max_engine_clock = -				adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk * 10; -			dev_info.max_memory_clock = -				adev->pm.dpm.dyn_state.max_clock_voltage_on_ac.mclk * 10; +			dev_info.max_engine_clock = amdgpu_dpm_get_sclk(adev, false) * 10; +			dev_info.max_memory_clock = amdgpu_dpm_get_mclk(adev, false) * 10;  		} else {  			dev_info.max_engine_clock = adev->pm.default_sclk * 10;  			dev_info.max_memory_clock = adev->pm.default_mclk * 10; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 06f24322e7c3..968c4260d7a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1758,5 +1758,6 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev)  		fence_put(adev->vm_manager.ids[i].first);  		amdgpu_sync_free(&adev->vm_manager.ids[i].active);  		fence_put(id->flushed_updates); +		fence_put(id->last_flush);  	}  } diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 1d8c375a3561..5be788b269e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -4075,7 +4075,7 @@ static int ci_enable_uvd_dpm(struct amdgpu_device *adev, bool enable)  							  pi->dpm_level_enable_mask.mclk_dpm_enable_mask);  		}  	} else { -		if (pi->last_mclk_dpm_enable_mask & 0x1) { +		if (pi->uvd_enabled) {  			pi->uvd_enabled = false;  			pi->dpm_level_enable_mask.mclk_dpm_enable_mask |= 1;  			amdgpu_ci_send_msg_to_smc_with_parameter(adev, @@ -6236,6 +6236,8 @@ static int ci_dpm_sw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; +	flush_work(&adev->pm.dpm.thermal.work); +  	mutex_lock(&adev->pm.mutex);  	amdgpu_pm_sysfs_fini(adev);  	ci_dpm_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c index 4108c686aa7c..9260caef74fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v10_0.c @@ -3151,10 +3151,6 @@ static int dce_v10_0_hw_fini(void *handle)  static int dce_v10_0_suspend(void *handle)  { -	struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -	amdgpu_atombios_scratch_regs_save(adev); -  	return dce_v10_0_hw_fini(handle);  } @@ -3165,8 +3161,6 @@ static int dce_v10_0_resume(void *handle)  	ret = dce_v10_0_hw_init(handle); -	amdgpu_atombios_scratch_regs_restore(adev); -  	/* turn on the BL */  	if (adev->mode_info.bl_encoder) {  		u8 bl_level = amdgpu_display_backlight_get_level(adev, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c index f264b8f17ad1..367739bd1927 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v11_0.c @@ -3215,10 +3215,6 @@ static int dce_v11_0_hw_fini(void *handle)  static int dce_v11_0_suspend(void *handle)  { -	struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -	amdgpu_atombios_scratch_regs_save(adev); -  	return dce_v11_0_hw_fini(handle);  } @@ -3229,8 +3225,6 @@ static int dce_v11_0_resume(void *handle)  	ret = dce_v11_0_hw_init(handle); -	amdgpu_atombios_scratch_regs_restore(adev); -  	/* turn on the BL */  	if (adev->mode_info.bl_encoder) {  		u8 bl_level = amdgpu_display_backlight_get_level(adev, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c index b948d6cb1399..15f9fc0514b2 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v6_0.c @@ -2482,10 +2482,6 @@ static int dce_v6_0_hw_fini(void *handle)  static int dce_v6_0_suspend(void *handle)  { -	struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -	amdgpu_atombios_scratch_regs_save(adev); -  	return dce_v6_0_hw_fini(handle);  } @@ -2496,8 +2492,6 @@ static int dce_v6_0_resume(void *handle)  	ret = dce_v6_0_hw_init(handle); -	amdgpu_atombios_scratch_regs_restore(adev); -  	/* turn on the BL */  	if (adev->mode_info.bl_encoder) {  		u8 bl_level = amdgpu_display_backlight_get_level(adev, diff --git a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c index 5966166ec94c..8c4d808db0f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_v8_0.c @@ -3033,10 +3033,6 @@ static int dce_v8_0_hw_fini(void *handle)  static int dce_v8_0_suspend(void *handle)  { -	struct amdgpu_device *adev = (struct amdgpu_device *)handle; - -	amdgpu_atombios_scratch_regs_save(adev); -  	return dce_v8_0_hw_fini(handle);  } @@ -3047,8 +3043,6 @@ static int dce_v8_0_resume(void *handle)  	ret = dce_v8_0_hw_init(handle); -	amdgpu_atombios_scratch_regs_restore(adev); -  	/* turn on the BL */  	if (adev->mode_info.bl_encoder) {  		u8 bl_level = amdgpu_display_backlight_get_level(adev, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index ee6a48a09214..bb97182dc749 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -640,7 +640,6 @@ static const u32 stoney_mgcg_cgcg_init[] =  	mmCP_MEM_SLP_CNTL, 0xffffffff, 0x00020201,  	mmRLC_MEM_SLP_CNTL, 0xffffffff, 0x00020201,  	mmCGTS_SM_CTRL_REG, 0xffffffff, 0x96940200, -	mmATC_MISC_CG, 0xffffffff, 0x000c0200,  };  static void gfx_v8_0_set_ring_funcs(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index c22ef140a542..a16b2201d52c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -100,6 +100,7 @@ static const u32 cz_mgcg_cgcg_init[] =  static const u32 stoney_mgcg_cgcg_init[] =  { +	mmATC_MISC_CG, 0xffffffff, 0x000c0200,  	mmMC_MEM_POWER_LS, 0xffffffff, 0x00000104  }; diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index f8618a3881a8..71d2856222fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -3063,6 +3063,8 @@ static int kv_dpm_sw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; +	flush_work(&adev->pm.dpm.thermal.work); +  	mutex_lock(&adev->pm.mutex);  	amdgpu_pm_sysfs_fini(adev);  	kv_dpm_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 3de7bca5854b..d6f85b1a0b93 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -3477,6 +3477,49 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,  	int i;  	struct si_dpm_quirk *p = si_dpm_quirk_list; +	/* limit all SI kickers */ +	if (adev->asic_type == CHIP_PITCAIRN) { +		if ((adev->pdev->revision == 0x81) || +		    (adev->pdev->device == 0x6810) || +		    (adev->pdev->device == 0x6811) || +		    (adev->pdev->device == 0x6816) || +		    (adev->pdev->device == 0x6817) || +		    (adev->pdev->device == 0x6806)) +			max_mclk = 120000; +	} else if (adev->asic_type == CHIP_VERDE) { +		if ((adev->pdev->revision == 0x81) || +		    (adev->pdev->revision == 0x83) || +		    (adev->pdev->revision == 0x87) || +		    (adev->pdev->device == 0x6820) || +		    (adev->pdev->device == 0x6821) || +		    (adev->pdev->device == 0x6822) || +		    (adev->pdev->device == 0x6823) || +		    (adev->pdev->device == 0x682A) || +		    (adev->pdev->device == 0x682B)) { +			max_sclk = 75000; +			max_mclk = 80000; +		} +	} else if (adev->asic_type == CHIP_OLAND) { +		if ((adev->pdev->revision == 0xC7) || +		    (adev->pdev->revision == 0x80) || +		    (adev->pdev->revision == 0x81) || +		    (adev->pdev->revision == 0x83) || +		    (adev->pdev->device == 0x6604) || +		    (adev->pdev->device == 0x6605)) { +			max_sclk = 75000; +			max_mclk = 80000; +		} +	} else if (adev->asic_type == CHIP_HAINAN) { +		if ((adev->pdev->revision == 0x81) || +		    (adev->pdev->revision == 0x83) || +		    (adev->pdev->revision == 0xC3) || +		    (adev->pdev->device == 0x6664) || +		    (adev->pdev->device == 0x6665) || +		    (adev->pdev->device == 0x6667)) { +			max_sclk = 75000; +			max_mclk = 80000; +		} +	}  	/* Apply dpm quirks */  	while (p && p->chip_device != 0) {  		if (adev->pdev->vendor == p->chip_vendor && @@ -3489,22 +3532,6 @@ static void si_apply_state_adjust_rules(struct amdgpu_device *adev,  		}  		++p;  	} -	/* limit mclk on all R7 370 parts for stability */ -	if (adev->pdev->device == 0x6811 && -	    adev->pdev->revision == 0x81) -		max_mclk = 120000; -	/* limit sclk/mclk on Jet parts for stability */ -	if (adev->pdev->device == 0x6665 && -	    adev->pdev->revision == 0xc3) { -		max_sclk = 75000; -		max_mclk = 80000; -	} -	/* Limit clocks for some HD8600 parts */ -	if (adev->pdev->device == 0x6660 && -	    adev->pdev->revision == 0x83) { -		max_sclk = 75000; -		max_mclk = 80000; -	}  	if (rps->vce_active) {  		rps->evclk = adev->pm.dpm.vce_states[adev->pm.dpm.vce_level].evclk; @@ -7777,6 +7804,8 @@ static int si_dpm_sw_fini(void *handle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)handle; +	flush_work(&adev->pm.dpm.thermal.work); +  	mutex_lock(&adev->pm.mutex);  	amdgpu_pm_sysfs_fini(adev);  	si_dpm_fini(adev); diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 8533269ec160..6feed726e299 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -52,6 +52,8 @@  #define VCE_V3_0_STACK_SIZE	(64 * 1024)  #define VCE_V3_0_DATA_SIZE	((16 * 1024 * AMDGPU_MAX_VCE_HANDLES) + (52 * 1024)) +#define FW_52_8_3	((52 << 24) | (8 << 16) | (3 << 8)) +  static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);  static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);  static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev); @@ -382,6 +384,10 @@ static int vce_v3_0_sw_init(void *handle)  	if (r)  		return r; +	/* 52.8.3 required for 3 ring support */ +	if (adev->vce.fw_version < FW_52_8_3) +		adev->vce.num_rings = 2; +  	r = amdgpu_vce_resume(adev);  	if (r)  		return r; diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index c0d9aad7126f..7c13090df7c0 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1651,7 +1651,7 @@ static int vi_common_early_init(void *handle)  			AMD_CG_SUPPORT_SDMA_MGCG |  			AMD_CG_SUPPORT_SDMA_LS |  			AMD_CG_SUPPORT_VCE_MGCG; -		adev->pg_flags |= AMD_PG_SUPPORT_GFX_PG | +		adev->pg_flags = AMD_PG_SUPPORT_GFX_PG |  			AMD_PG_SUPPORT_GFX_SMG |  			AMD_PG_SUPPORT_GFX_PIPELINE |  			AMD_PG_SUPPORT_UVD | diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 1167205057b3..2ba7937d2545 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -716,7 +716,7 @@ int phm_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type,  			*voltage = 1150;  	} else {  		ret = atomctrl_get_voltage_evv_on_sclk_ai(hwmgr, voltage_type, sclk, id, &vol); -		*voltage = (uint16_t)vol/100; +		*voltage = (uint16_t)(vol/100);  	}  	return ret;  } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c index 1126bd4f74dc..0894527d932f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c @@ -1320,7 +1320,8 @@ int atomctrl_get_voltage_evv_on_sclk_ai(struct pp_hwmgr *hwmgr, uint8_t voltage_  	if (0 != result)  		return result; -	*voltage = le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *)(&get_voltage_info_param_space))->ulVoltageLevel); +	*voltage = le32_to_cpu(((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_3 *) +				(&get_voltage_info_param_space))->ulVoltageLevel);  	return result;  } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c index 7de701d8a450..4477c55a58e3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/process_pptables_v1_0.c @@ -1201,12 +1201,15 @@ static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr,  static int ppt_get_num_of_vce_state_table_entries_v1_0(struct pp_hwmgr *hwmgr)  {  	const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); -	const ATOM_Tonga_VCE_State_Table *vce_state_table = -				(ATOM_Tonga_VCE_State_Table *)(((unsigned long)pp_table) + le16_to_cpu(pp_table->usVCEStateTableOffset)); +	const ATOM_Tonga_VCE_State_Table *vce_state_table; -	if (vce_state_table == NULL) + +	if (pp_table == NULL)  		return 0; +	vce_state_table = (void *)pp_table + +			le16_to_cpu(pp_table->usVCEStateTableOffset); +  	return vce_state_table->ucNumEntries;  } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 609996c84ad5..75854021f403 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -1168,8 +1168,8 @@ int smu7_enable_dpm_tasks(struct pp_hwmgr *hwmgr)  	tmp_result = (!smum_is_dpm_running(hwmgr)) ? 0 : -1;  	PP_ASSERT_WITH_CODE(tmp_result == 0, -			"DPM is already running right now, no need to enable DPM!", -			return 0); +			"DPM is already running", +			);  	if (smu7_voltage_control(hwmgr)) {  		tmp_result = smu7_enable_voltage_control(hwmgr); @@ -2127,15 +2127,18 @@ static int smu7_patch_acp_vddc(struct pp_hwmgr *hwmgr,  }  static int smu7_patch_limits_vddc(struct pp_hwmgr *hwmgr, -				     struct phm_clock_and_voltage_limits *tab) +				  struct phm_clock_and_voltage_limits *tab)  { +	uint32_t vddc, vddci;  	struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);  	if (tab) { -		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, (uint32_t *)&tab->vddc, -							&data->vddc_leakage); -		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, (uint32_t *)&tab->vddci, -							&data->vddci_leakage); +		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddc, +						   &data->vddc_leakage); +		tab->vddc = vddc; +		smu7_patch_ppt_v0_with_vdd_leakage(hwmgr, &vddci, +						   &data->vddci_leakage); +		tab->vddci = vddci;  	}  	return 0; diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 963a24d46a93..910b8d5b21c5 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -645,6 +645,7 @@ void amd_sched_fini(struct amd_gpu_scheduler *sched)  {  	if (sched->thread)  		kthread_stop(sched->thread); +	rcu_barrier();  	if (atomic_dec_and_test(&sched_fence_slab_ref))  		kmem_cache_destroy(sched_fence_slab);  } diff --git a/drivers/gpu/drm/amd/scheduler/sched_fence.c b/drivers/gpu/drm/amd/scheduler/sched_fence.c index 6b63beaf7574..3653b5a40494 100644 --- a/drivers/gpu/drm/amd/scheduler/sched_fence.c +++ b/drivers/gpu/drm/amd/scheduler/sched_fence.c @@ -103,7 +103,7 @@ static void amd_sched_fence_free(struct rcu_head *rcu)  }  /** - * amd_sched_fence_release - callback that fence can be freed + * amd_sched_fence_release_scheduled - callback that fence can be freed   *   * @fence: fence   * @@ -118,7 +118,7 @@ static void amd_sched_fence_release_scheduled(struct fence *f)  }  /** - * amd_sched_fence_release_scheduled - drop extra reference + * amd_sched_fence_release_finished - drop extra reference   *   * @f: fence   * diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 23739609427d..e6862a744210 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -420,18 +420,21 @@ drm_atomic_replace_property_blob_from_id(struct drm_crtc *crtc,  					 ssize_t expected_size,  					 bool *replaced)  { -	struct drm_device *dev = crtc->dev;  	struct drm_property_blob *new_blob = NULL;  	if (blob_id != 0) { -		new_blob = drm_property_lookup_blob(dev, blob_id); +		new_blob = drm_property_lookup_blob(crtc->dev, blob_id);  		if (new_blob == NULL)  			return -EINVAL; -		if (expected_size > 0 && expected_size != new_blob->length) + +		if (expected_size > 0 && expected_size != new_blob->length) { +			drm_property_unreference_blob(new_blob);  			return -EINVAL; +		}  	}  	drm_atomic_replace_property_blob(blob, new_blob, replaced); +	drm_property_unreference_blob(new_blob);  	return 0;  } diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index c3f83476f996..21f992605541 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -594,10 +594,6 @@ drm_atomic_helper_check_planes(struct drm_device *dev,  	struct drm_plane_state *plane_state;  	int i, ret = 0; -	ret = drm_atomic_normalize_zpos(dev, state); -	if (ret) -		return ret; -  	for_each_plane_in_state(state, plane, plane_state, i) {  		const struct drm_plane_helper_funcs *funcs; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 04e457117980..aa644487749c 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -914,6 +914,7 @@ static void drm_dp_destroy_port(struct kref *kref)  		/* no need to clean up vcpi  		 * as if we have no connector we never setup a vcpi */  		drm_dp_port_teardown_pdt(port, port->pdt); +		port->pdt = DP_PEER_DEVICE_NONE;  	}  	kfree(port);  } @@ -1159,7 +1160,9 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb,  			drm_dp_put_port(port);  			goto out;  		} -		if (port->port_num >= DP_MST_LOGICAL_PORT_0) { +		if ((port->pdt == DP_PEER_DEVICE_DP_LEGACY_CONV || +		     port->pdt == DP_PEER_DEVICE_SST_SINK) && +		    port->port_num >= DP_MST_LOGICAL_PORT_0) {  			port->cached_edid = drm_get_edid(port->connector, &port->aux.ddc);  			drm_mode_connector_set_tile_property(port->connector);  		} @@ -2919,6 +2922,7 @@ static void drm_dp_destroy_connector_work(struct work_struct *work)  		mgr->cbs->destroy_connector(mgr, port->connector);  		drm_dp_port_teardown_pdt(port, port->pdt); +		port->pdt = DP_PEER_DEVICE_NONE;  		if (!port->input && port->vcpi.vcpi > 0) {  			drm_dp_mst_reset_vcpi_slots(mgr, port); diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 03414bde1f15..6c75e62c0b22 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -131,7 +131,12 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)  	return 0;  fail:  	for (i = 0; i < fb_helper->connector_count; i++) { -		kfree(fb_helper->connector_info[i]); +		struct drm_fb_helper_connector *fb_helper_connector = +			fb_helper->connector_info[i]; + +		drm_connector_unreference(fb_helper_connector->connector); + +		kfree(fb_helper_connector);  		fb_helper->connector_info[i] = NULL;  	}  	fb_helper->connector_count = 0; @@ -603,6 +608,24 @@ int drm_fb_helper_blank(int blank, struct fb_info *info)  }  EXPORT_SYMBOL(drm_fb_helper_blank); +static void drm_fb_helper_modeset_release(struct drm_fb_helper *helper, +					  struct drm_mode_set *modeset) +{ +	int i; + +	for (i = 0; i < modeset->num_connectors; i++) { +		drm_connector_unreference(modeset->connectors[i]); +		modeset->connectors[i] = NULL; +	} +	modeset->num_connectors = 0; + +	drm_mode_destroy(helper->dev, modeset->mode); +	modeset->mode = NULL; + +	/* FIXME should hold a ref? */ +	modeset->fb = NULL; +} +  static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)  {  	int i; @@ -612,10 +635,12 @@ static void drm_fb_helper_crtc_free(struct drm_fb_helper *helper)  		kfree(helper->connector_info[i]);  	}  	kfree(helper->connector_info); +  	for (i = 0; i < helper->crtc_count; i++) { -		kfree(helper->crtc_info[i].mode_set.connectors); -		if (helper->crtc_info[i].mode_set.mode) -			drm_mode_destroy(helper->dev, helper->crtc_info[i].mode_set.mode); +		struct drm_mode_set *modeset = &helper->crtc_info[i].mode_set; + +		drm_fb_helper_modeset_release(helper, modeset); +		kfree(modeset->connectors);  	}  	kfree(helper->crtc_info);  } @@ -644,7 +669,9 @@ static void drm_fb_helper_dirty_work(struct work_struct *work)  	clip->x2 = clip->y2 = 0;  	spin_unlock_irqrestore(&helper->dirty_lock, flags); -	helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1); +	/* call dirty callback only when it has been really touched */ +	if (clip_copy.x1 < clip_copy.x2 && clip_copy.y1 < clip_copy.y2) +		helper->fb->funcs->dirty(helper->fb, NULL, 0, 0, &clip_copy, 1);  }  /** @@ -2088,7 +2115,6 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)  	struct drm_fb_helper_crtc **crtcs;  	struct drm_display_mode **modes;  	struct drm_fb_offset *offsets; -	struct drm_mode_set *modeset;  	bool *enabled;  	int width, height;  	int i; @@ -2136,45 +2162,35 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)  	/* need to set the modesets up here for use later */  	/* fill out the connector<->crtc mappings into the modesets */ -	for (i = 0; i < fb_helper->crtc_count; i++) { -		modeset = &fb_helper->crtc_info[i].mode_set; -		modeset->num_connectors = 0; -		modeset->fb = NULL; -	} +	for (i = 0; i < fb_helper->crtc_count; i++) +		drm_fb_helper_modeset_release(fb_helper, +					      &fb_helper->crtc_info[i].mode_set);  	for (i = 0; i < fb_helper->connector_count; i++) {  		struct drm_display_mode *mode = modes[i];  		struct drm_fb_helper_crtc *fb_crtc = crtcs[i];  		struct drm_fb_offset *offset = &offsets[i]; -		modeset = &fb_crtc->mode_set; +		struct drm_mode_set *modeset = &fb_crtc->mode_set;  		if (mode && fb_crtc) { +			struct drm_connector *connector = +				fb_helper->connector_info[i]->connector; +  			DRM_DEBUG_KMS("desired mode %s set on crtc %d (%d,%d)\n",  				      mode->name, fb_crtc->mode_set.crtc->base.id, offset->x, offset->y); +  			fb_crtc->desired_mode = mode;  			fb_crtc->x = offset->x;  			fb_crtc->y = offset->y; -			if (modeset->mode) -				drm_mode_destroy(dev, modeset->mode);  			modeset->mode = drm_mode_duplicate(dev,  							   fb_crtc->desired_mode); -			modeset->connectors[modeset->num_connectors++] = fb_helper->connector_info[i]->connector; +			drm_connector_reference(connector); +			modeset->connectors[modeset->num_connectors++] = connector;  			modeset->fb = fb_helper->fb;  			modeset->x = offset->x;  			modeset->y = offset->y;  		}  	} - -	/* Clear out any old modes if there are no more connected outputs. */ -	for (i = 0; i < fb_helper->crtc_count; i++) { -		modeset = &fb_helper->crtc_info[i].mode_set; -		if (modeset->num_connectors == 0) { -			BUG_ON(modeset->fb); -			if (modeset->mode) -				drm_mode_destroy(dev, modeset->mode); -			modeset->mode = NULL; -		} -	}  out:  	kfree(crtcs);  	kfree(modes); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index def78c8c1780..f86e7c846678 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -262,6 +262,26 @@ int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,  	return 0;  } +int exynos_atomic_check(struct drm_device *dev, +			struct drm_atomic_state *state) +{ +	int ret; + +	ret = drm_atomic_helper_check_modeset(dev, state); +	if (ret) +		return ret; + +	ret = drm_atomic_normalize_zpos(dev, state); +	if (ret) +		return ret; + +	ret = drm_atomic_helper_check_planes(dev, state); +	if (ret) +		return ret; + +	return ret; +} +  static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)  {  	struct drm_exynos_file_private *file_priv; diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index d215149e737b..80c4d5b81689 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -301,6 +301,7 @@ static inline int exynos_dpi_bind(struct drm_device *dev,  int exynos_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state,  			 bool nonblock); +int exynos_atomic_check(struct drm_device *dev, struct drm_atomic_state *state);  extern struct platform_driver fimd_driver; diff --git a/drivers/gpu/drm/exynos/exynos_drm_fb.c b/drivers/gpu/drm/exynos/exynos_drm_fb.c index 40ce841eb952..23cce0a3f5fc 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fb.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fb.c @@ -190,7 +190,7 @@ dma_addr_t exynos_drm_fb_dma_addr(struct drm_framebuffer *fb, int index)  static const struct drm_mode_config_funcs exynos_drm_mode_config_funcs = {  	.fb_create = exynos_user_fb_create,  	.output_poll_changed = exynos_drm_output_poll_changed, -	.atomic_check = drm_atomic_helper_check, +	.atomic_check = exynos_atomic_check,  	.atomic_commit = exynos_atomic_commit,  }; diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bfb2efd8d4d4..18dfdd5c1b3b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1447,8 +1447,6 @@ static int i915_drm_suspend(struct drm_device *dev)  	dev_priv->suspend_count++; -	intel_display_set_init_power(dev_priv, false); -  	intel_csr_ucode_suspend(dev_priv);  out: @@ -1466,6 +1464,8 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation)  	disable_rpm_wakeref_asserts(dev_priv); +	intel_display_set_init_power(dev_priv, false); +  	fw_csr = !IS_BROXTON(dev_priv) &&  		suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload;  	/* diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8b9ee4e390c0..685e9e065287 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2883,6 +2883,11 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level,  extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,  			      unsigned long arg);  #endif +extern const struct dev_pm_ops i915_pm_ops; + +extern int i915_driver_load(struct pci_dev *pdev, +			    const struct pci_device_id *ent); +extern void i915_driver_unload(struct drm_device *dev);  extern int intel_gpu_reset(struct drm_i915_private *dev_priv, u32 engine_mask);  extern bool intel_has_gpu_reset(struct drm_i915_private *dev_priv);  extern void i915_reset(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 947e82c2b175..23960de81b57 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3550,8 +3550,6 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj,  	vma->display_alignment = max_t(u64, vma->display_alignment, alignment); -	WARN_ON(obj->pin_display > i915_vma_pin_count(vma)); -  	i915_gem_object_flush_cpu_write_domain(obj);  	old_write_domain = obj->base.write_domain; @@ -3588,7 +3586,6 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma)  		list_move_tail(&vma->vm_link, &vma->vm->inactive_list);  	i915_vma_unpin(vma); -	WARN_ON(vma->obj->pin_display > i915_vma_pin_count(vma));  }  /** @@ -3745,7 +3742,12 @@ void __i915_vma_set_map_and_fenceable(struct i915_vma *vma)  	mappable = (vma->node.start + fence_size <=  		    dev_priv->ggtt.mappable_end); -	if (mappable && fenceable) +	/* +	 * Explicitly disable for rotated VMA since the display does not +	 * need the fence and the VMA is not accessible to other users. +	 */ +	if (mappable && fenceable && +	    vma->ggtt_view.type != I915_GGTT_VIEW_ROTATED)  		vma->flags |= I915_VMA_CAN_FENCE;  	else  		vma->flags &= ~I915_VMA_CAN_FENCE; diff --git a/drivers/gpu/drm/i915/i915_gem_fence.c b/drivers/gpu/drm/i915/i915_gem_fence.c index 8df1fa7234e8..2c7ba0ee127c 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence.c +++ b/drivers/gpu/drm/i915/i915_gem_fence.c @@ -290,6 +290,8 @@ i915_vma_put_fence(struct i915_vma *vma)  {  	struct drm_i915_fence_reg *fence = vma->fence; +	assert_rpm_wakelock_held(to_i915(vma->vm->dev)); +  	if (!fence)  		return 0; @@ -341,6 +343,8 @@ i915_vma_get_fence(struct i915_vma *vma)  	struct drm_i915_fence_reg *fence;  	struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; +	assert_rpm_wakelock_held(to_i915(vma->vm->dev)); +  	/* Just update our place in the LRU if our fence is getting reused. */  	if (vma->fence) {  		fence = vma->fence; @@ -371,6 +375,12 @@ void i915_gem_restore_fences(struct drm_device *dev)  	struct drm_i915_private *dev_priv = to_i915(dev);  	int i; +	/* Note that this may be called outside of struct_mutex, by +	 * runtime suspend/resume. The barrier we require is enforced by +	 * rpm itself - all access to fences/GTT are only within an rpm +	 * wakeref, and to acquire that wakeref you must pass through here. +	 */ +  	for (i = 0; i < dev_priv->num_fence_regs; i++) {  		struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i];  		struct i915_vma *vma = reg->vma; @@ -379,10 +389,17 @@ void i915_gem_restore_fences(struct drm_device *dev)  		 * Commit delayed tiling changes if we have an object still  		 * attached to the fence, otherwise just clear the fence.  		 */ -		if (vma && !i915_gem_object_is_tiled(vma->obj)) +		if (vma && !i915_gem_object_is_tiled(vma->obj)) { +			GEM_BUG_ON(!reg->dirty); +			GEM_BUG_ON(vma->obj->fault_mappable); + +			list_move(®->link, &dev_priv->mm.fence_list); +			vma->fence = NULL;  			vma = NULL; +		} -		fence_update(reg, vma); +		fence_write(reg, vma); +		reg->vma = vma;  	}  } diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 687c768833b3..31e6edd08dd0 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -431,9 +431,6 @@ static const struct pci_device_id pciidlist[] = {  };  MODULE_DEVICE_TABLE(pci, pciidlist); -extern int i915_driver_load(struct pci_dev *pdev, -			    const struct pci_device_id *ent); -  static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  {  	struct intel_device_info *intel_info = @@ -463,8 +460,6 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  	return i915_driver_load(pdev, ent);  } -extern void i915_driver_unload(struct drm_device *dev); -  static void i915_pci_remove(struct pci_dev *pdev)  {  	struct drm_device *dev = pci_get_drvdata(pdev); @@ -473,8 +468,6 @@ static void i915_pci_remove(struct pci_dev *pdev)  	drm_dev_unref(dev);  } -extern const struct dev_pm_ops i915_pm_ops; -  static struct pci_driver i915_pci_driver = {  	.name = DRIVER_NAME,  	.id_table = pciidlist, diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index c6e69e4cfa83..1f8af87c6294 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1031,6 +1031,77 @@ static u8 translate_iboost(u8 val)  	return mapping[val];  } +static void sanitize_ddc_pin(struct drm_i915_private *dev_priv, +			     enum port port) +{ +	const struct ddi_vbt_port_info *info = +		&dev_priv->vbt.ddi_port_info[port]; +	enum port p; + +	if (!info->alternate_ddc_pin) +		return; + +	for_each_port_masked(p, (1 << port) - 1) { +		struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p]; + +		if (info->alternate_ddc_pin != i->alternate_ddc_pin) +			continue; + +		DRM_DEBUG_KMS("port %c trying to use the same DDC pin (0x%x) as port %c, " +			      "disabling port %c DVI/HDMI support\n", +			      port_name(p), i->alternate_ddc_pin, +			      port_name(port), port_name(p)); + +		/* +		 * If we have multiple ports supposedly sharing the +		 * pin, then dvi/hdmi couldn't exist on the shared +		 * port. Otherwise they share the same ddc bin and +		 * system couldn't communicate with them separately. +		 * +		 * Due to parsing the ports in alphabetical order, +		 * a higher port will always clobber a lower one. +		 */ +		i->supports_dvi = false; +		i->supports_hdmi = false; +		i->alternate_ddc_pin = 0; +	} +} + +static void sanitize_aux_ch(struct drm_i915_private *dev_priv, +			    enum port port) +{ +	const struct ddi_vbt_port_info *info = +		&dev_priv->vbt.ddi_port_info[port]; +	enum port p; + +	if (!info->alternate_aux_channel) +		return; + +	for_each_port_masked(p, (1 << port) - 1) { +		struct ddi_vbt_port_info *i = &dev_priv->vbt.ddi_port_info[p]; + +		if (info->alternate_aux_channel != i->alternate_aux_channel) +			continue; + +		DRM_DEBUG_KMS("port %c trying to use the same AUX CH (0x%x) as port %c, " +			      "disabling port %c DP support\n", +			      port_name(p), i->alternate_aux_channel, +			      port_name(port), port_name(p)); + +		/* +		 * If we have multiple ports supposedlt sharing the +		 * aux channel, then DP couldn't exist on the shared +		 * port. Otherwise they share the same aux channel +		 * and system couldn't communicate with them separately. +		 * +		 * Due to parsing the ports in alphabetical order, +		 * a higher port will always clobber a lower one. +		 */ +		i->supports_dp = false; +		i->alternate_aux_channel = 0; +	} +} +  static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,  			   const struct bdb_header *bdb)  { @@ -1105,54 +1176,15 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port,  		DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port));  	if (is_dvi) { -		if (port == PORT_E) { -			info->alternate_ddc_pin = ddc_pin; -			/* if DDIE share ddc pin with other port, then -			 * dvi/hdmi couldn't exist on the shared port. -			 * Otherwise they share the same ddc bin and system -			 * couldn't communicate with them seperately. */ -			if (ddc_pin == DDC_PIN_B) { -				dev_priv->vbt.ddi_port_info[PORT_B].supports_dvi = 0; -				dev_priv->vbt.ddi_port_info[PORT_B].supports_hdmi = 0; -			} else if (ddc_pin == DDC_PIN_C) { -				dev_priv->vbt.ddi_port_info[PORT_C].supports_dvi = 0; -				dev_priv->vbt.ddi_port_info[PORT_C].supports_hdmi = 0; -			} else if (ddc_pin == DDC_PIN_D) { -				dev_priv->vbt.ddi_port_info[PORT_D].supports_dvi = 0; -				dev_priv->vbt.ddi_port_info[PORT_D].supports_hdmi = 0; -			} -		} else if (ddc_pin == DDC_PIN_B && port != PORT_B) -			DRM_DEBUG_KMS("Unexpected DDC pin for port B\n"); -		else if (ddc_pin == DDC_PIN_C && port != PORT_C) -			DRM_DEBUG_KMS("Unexpected DDC pin for port C\n"); -		else if (ddc_pin == DDC_PIN_D && port != PORT_D) -			DRM_DEBUG_KMS("Unexpected DDC pin for port D\n"); +		info->alternate_ddc_pin = ddc_pin; + +		sanitize_ddc_pin(dev_priv, port);  	}  	if (is_dp) { -		if (port == PORT_E) { -			info->alternate_aux_channel = aux_channel; -			/* if DDIE share aux channel with other port, then -			 * DP couldn't exist on the shared port. Otherwise -			 * they share the same aux channel and system -			 * couldn't communicate with them seperately. */ -			if (aux_channel == DP_AUX_A) -				dev_priv->vbt.ddi_port_info[PORT_A].supports_dp = 0; -			else if (aux_channel == DP_AUX_B) -				dev_priv->vbt.ddi_port_info[PORT_B].supports_dp = 0; -			else if (aux_channel == DP_AUX_C) -				dev_priv->vbt.ddi_port_info[PORT_C].supports_dp = 0; -			else if (aux_channel == DP_AUX_D) -				dev_priv->vbt.ddi_port_info[PORT_D].supports_dp = 0; -		} -		else if (aux_channel == DP_AUX_A && port != PORT_A) -			DRM_DEBUG_KMS("Unexpected AUX channel for port A\n"); -		else if (aux_channel == DP_AUX_B && port != PORT_B) -			DRM_DEBUG_KMS("Unexpected AUX channel for port B\n"); -		else if (aux_channel == DP_AUX_C && port != PORT_C) -			DRM_DEBUG_KMS("Unexpected AUX channel for port C\n"); -		else if (aux_channel == DP_AUX_D && port != PORT_D) -			DRM_DEBUG_KMS("Unexpected AUX channel for port D\n"); +		info->alternate_aux_channel = aux_channel; + +		sanitize_aux_ch(dev_priv, port);  	}  	if (bdb->version >= 158) { diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 73b6858600ac..1b20e160bc1f 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -192,7 +192,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)  	struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu;  	const int s_max = 3, ss_max = 3, eu_max = 8;  	int s, ss; -	u32 fuse2, eu_disable[s_max]; +	u32 fuse2, eu_disable[3]; /* s_max */  	fuse2 = I915_READ(GEN8_FUSE2);  	sseu->slice_mask = (fuse2 & GEN8_F2_S_ENA_MASK) >> GEN8_F2_S_ENA_SHIFT; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fbcfed63a76e..0ad1879bfd9d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2978,7 +2978,8 @@ int skl_check_plane_surface(struct intel_plane_state *plane_state)  	/* Rotate src coordinates to match rotated GTT view */  	if (intel_rotation_90_or_270(rotation))  		drm_rect_rotate(&plane_state->base.src, -				fb->width, fb->height, DRM_ROTATE_270); +				fb->width << 16, fb->height << 16, +				DRM_ROTATE_270);  	/*  	 * Handle the AUX surface first since @@ -14310,7 +14311,7 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)  	for_each_plane_in_state(state, plane, plane_state, i) {  		struct intel_plane_state *intel_plane_state = -			to_intel_plane_state(plane_state); +			to_intel_plane_state(plane->state);  		if (!intel_plane_state->wait_req)  			continue; diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 14a3cf0b7213..3581b5a7f716 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -1108,6 +1108,44 @@ intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)  	return ret;  } +static enum port intel_aux_port(struct drm_i915_private *dev_priv, +				enum port port) +{ +	const struct ddi_vbt_port_info *info = +		&dev_priv->vbt.ddi_port_info[port]; +	enum port aux_port; + +	if (!info->alternate_aux_channel) { +		DRM_DEBUG_KMS("using AUX %c for port %c (platform default)\n", +			      port_name(port), port_name(port)); +		return port; +	} + +	switch (info->alternate_aux_channel) { +	case DP_AUX_A: +		aux_port = PORT_A; +		break; +	case DP_AUX_B: +		aux_port = PORT_B; +		break; +	case DP_AUX_C: +		aux_port = PORT_C; +		break; +	case DP_AUX_D: +		aux_port = PORT_D; +		break; +	default: +		MISSING_CASE(info->alternate_aux_channel); +		aux_port = PORT_A; +		break; +	} + +	DRM_DEBUG_KMS("using AUX %c for port %c (VBT)\n", +		      port_name(aux_port), port_name(port)); + +	return aux_port; +} +  static i915_reg_t g4x_aux_ctl_reg(struct drm_i915_private *dev_priv,  				       enum port port)  { @@ -1168,36 +1206,9 @@ static i915_reg_t ilk_aux_data_reg(struct drm_i915_private *dev_priv,  	}  } -/* - * On SKL we don't have Aux for port E so we rely - * on VBT to set a proper alternate aux channel. - */ -static enum port skl_porte_aux_port(struct drm_i915_private *dev_priv) -{ -	const struct ddi_vbt_port_info *info = -		&dev_priv->vbt.ddi_port_info[PORT_E]; - -	switch (info->alternate_aux_channel) { -	case DP_AUX_A: -		return PORT_A; -	case DP_AUX_B: -		return PORT_B; -	case DP_AUX_C: -		return PORT_C; -	case DP_AUX_D: -		return PORT_D; -	default: -		MISSING_CASE(info->alternate_aux_channel); -		return PORT_A; -	} -} -  static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,  				       enum port port)  { -	if (port == PORT_E) -		port = skl_porte_aux_port(dev_priv); -  	switch (port) {  	case PORT_A:  	case PORT_B: @@ -1213,9 +1224,6 @@ static i915_reg_t skl_aux_ctl_reg(struct drm_i915_private *dev_priv,  static i915_reg_t skl_aux_data_reg(struct drm_i915_private *dev_priv,  					enum port port, int index)  { -	if (port == PORT_E) -		port = skl_porte_aux_port(dev_priv); -  	switch (port) {  	case PORT_A:  	case PORT_B: @@ -1253,7 +1261,8 @@ static i915_reg_t intel_aux_data_reg(struct drm_i915_private *dev_priv,  static void intel_aux_reg_init(struct intel_dp *intel_dp)  {  	struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); -	enum port port = dp_to_dig_port(intel_dp)->port; +	enum port port = intel_aux_port(dev_priv, +					dp_to_dig_port(intel_dp)->port);  	int i;  	intel_dp->aux_ch_ctl_reg = intel_aux_ctl_reg(dev_priv, port); @@ -3551,8 +3560,8 @@ intel_edp_init_dpcd(struct intel_dp *intel_dp)  	/* Read the eDP Display control capabilities registers */  	if ((intel_dp->dpcd[DP_EDP_CONFIGURATION_CAP] & DP_DPCD_DISPLAY_CONTROL_CAPABLE) &&  	    drm_dp_dpcd_read(&intel_dp->aux, DP_EDP_DPCD_REV, -			     intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd) == -			     sizeof(intel_dp->edp_dpcd))) +			     intel_dp->edp_dpcd, sizeof(intel_dp->edp_dpcd)) == +			     sizeof(intel_dp->edp_dpcd))  		DRM_DEBUG_KMS("EDP DPCD : %*ph\n", (int) sizeof(intel_dp->edp_dpcd),  			      intel_dp->edp_dpcd); diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index faa67624e1ed..c43dd9abce79 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -104,8 +104,10 @@ static int intel_fbc_calculate_cfb_size(struct drm_i915_private *dev_priv,  	int lines;  	intel_fbc_get_plane_source_size(cache, NULL, &lines); -	if (INTEL_INFO(dev_priv)->gen >= 7) +	if (INTEL_GEN(dev_priv) == 7)  		lines = min(lines, 2048); +	else if (INTEL_GEN(dev_priv) >= 8) +		lines = min(lines, 2560);  	/* Hardware needs the full buffer stride, not just the active area. */  	return lines * cache->fb.stride; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index a2f751cd187a..db24f898853c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3362,13 +3362,15 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,  	int num_active;  	int id, i; +	/* Clear the partitioning for disabled planes. */ +	memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); +	memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe])); +  	if (WARN_ON(!state))  		return 0;  	if (!cstate->base.active) {  		ddb->pipe[pipe].start = ddb->pipe[pipe].end = 0; -		memset(ddb->plane[pipe], 0, sizeof(ddb->plane[pipe])); -		memset(ddb->y_plane[pipe], 0, sizeof(ddb->y_plane[pipe]));  		return 0;  	} @@ -3468,12 +3470,6 @@ skl_allocate_pipe_ddb(struct intel_crtc_state *cstate,  	return 0;  } -static uint32_t skl_pipe_pixel_rate(const struct intel_crtc_state *config) -{ -	/* TODO: Take into account the scalers once we support them */ -	return config->base.adjusted_mode.crtc_clock; -} -  /*   * The max latency should be 257 (max the punit can code is 255 and we add 2us   * for the read latency) and cpp should always be <= 8, so that @@ -3524,7 +3520,7 @@ static uint32_t skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cst  	 * Adjusted plane pixel rate is just the pipe's adjusted pixel rate  	 * with additional adjustments for plane-specific scaling.  	 */ -	adjusted_pixel_rate = skl_pipe_pixel_rate(cstate); +	adjusted_pixel_rate = ilk_pipe_pixel_rate(cstate);  	downscale_amount = skl_plane_downscale_amount(pstate);  	pixel_rate = adjusted_pixel_rate * downscale_amount >> 16; @@ -3736,11 +3732,11 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate)  	if (!cstate->base.active)  		return 0; -	if (WARN_ON(skl_pipe_pixel_rate(cstate) == 0)) +	if (WARN_ON(ilk_pipe_pixel_rate(cstate) == 0))  		return 0;  	return DIV_ROUND_UP(8 * cstate->base.adjusted_mode.crtc_htotal * 1000, -			    skl_pipe_pixel_rate(cstate)); +			    ilk_pipe_pixel_rate(cstate));  }  static void skl_compute_transition_wm(struct intel_crtc_state *cstate, @@ -4050,6 +4046,12 @@ skl_compute_ddb(struct drm_atomic_state *state)  		intel_state->wm_results.dirty_pipes = ~0;  	} +	/* +	 * We're not recomputing for the pipes not included in the commit, so +	 * make sure we start with the current state. +	 */ +	memcpy(ddb, &dev_priv->wm.skl_hw.ddb, sizeof(*ddb)); +  	for_each_intel_crtc_mask(dev, intel_crtc, realloc_pipes) {  		struct intel_crtc_state *cstate; diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 98df09c2b388..9672b579f950 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -357,8 +357,8 @@ static int imx_drm_bind(struct device *dev)  	int ret;  	drm = drm_dev_alloc(&imx_drm_driver, dev); -	if (!drm) -		return -ENOMEM; +	if (IS_ERR(drm)) +		return PTR_ERR(drm);  	imxdrm = devm_kzalloc(dev, sizeof(*imxdrm), GFP_KERNEL);  	if (!imxdrm) { @@ -436,9 +436,11 @@ static int imx_drm_bind(struct device *dev)  err_fbhelper:  	drm_kms_helper_poll_fini(drm); +#if IS_ENABLED(CONFIG_DRM_FBDEV_EMULATION)  	if (imxdrm->fbhelper)  		drm_fbdev_cma_fini(imxdrm->fbhelper);  err_unbind: +#endif  	component_unbind_all(drm->dev, drm);  err_vblank:  	drm_vblank_cleanup(drm); diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index ce22d0a0ddc8..d5864ed4d772 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -103,11 +103,11 @@ drm_plane_state_to_vbo(struct drm_plane_state *state)  	       (state->src_x >> 16) / 2 - eba;  } -static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane, -				      struct drm_plane_state *old_state) +static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane)  {  	struct drm_plane *plane = &ipu_plane->base;  	struct drm_plane_state *state = plane->state; +	struct drm_crtc_state *crtc_state = state->crtc->state;  	struct drm_framebuffer *fb = state->fb;  	unsigned long eba, ubo, vbo;  	int active; @@ -117,7 +117,7 @@ static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,  	switch (fb->pixel_format) {  	case DRM_FORMAT_YUV420:  	case DRM_FORMAT_YVU420: -		if (old_state->fb) +		if (!drm_atomic_crtc_needs_modeset(crtc_state))  			break;  		/* @@ -149,7 +149,7 @@ static void ipu_plane_atomic_set_base(struct ipu_plane *ipu_plane,  		break;  	} -	if (old_state->fb) { +	if (!drm_atomic_crtc_needs_modeset(crtc_state)) {  		active = ipu_idmac_get_current_buffer(ipu_plane->ipu_ch);  		ipu_cpmem_set_buffer(ipu_plane->ipu_ch, !active, eba);  		ipu_idmac_select_buffer(ipu_plane->ipu_ch, !active); @@ -259,6 +259,7 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,  	struct drm_framebuffer *fb = state->fb;  	struct drm_framebuffer *old_fb = old_state->fb;  	unsigned long eba, ubo, vbo, old_ubo, old_vbo; +	int hsub, vsub;  	/* Ok to disable */  	if (!fb) @@ -355,7 +356,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,  		if ((ubo > 0xfffff8) || (vbo > 0xfffff8))  			return -EINVAL; -		if (old_fb) { +		if (old_fb && +		    (old_fb->pixel_format == DRM_FORMAT_YUV420 || +		     old_fb->pixel_format == DRM_FORMAT_YVU420)) {  			old_ubo = drm_plane_state_to_ubo(old_state);  			old_vbo = drm_plane_state_to_vbo(old_state);  			if (ubo != old_ubo || vbo != old_vbo) @@ -370,6 +373,16 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,  		if (old_fb && old_fb->pitches[1] != fb->pitches[1])  			crtc_state->mode_changed = true; + +		/* +		 * The x/y offsets must be even in case of horizontal/vertical +		 * chroma subsampling. +		 */ +		hsub = drm_format_horz_chroma_subsampling(fb->pixel_format); +		vsub = drm_format_vert_chroma_subsampling(fb->pixel_format); +		if (((state->src_x >> 16) & (hsub - 1)) || +		    ((state->src_y >> 16) & (vsub - 1))) +			return -EINVAL;  	}  	return 0; @@ -392,7 +405,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,  		struct drm_crtc_state *crtc_state = state->crtc->state;  		if (!drm_atomic_crtc_needs_modeset(crtc_state)) { -			ipu_plane_atomic_set_base(ipu_plane, old_state); +			ipu_plane_atomic_set_base(ipu_plane);  			return;  		}  	} @@ -424,6 +437,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,  			ipu_dp_set_global_alpha(ipu_plane->dp, false, 0, false);  			break;  		default: +			ipu_dp_set_global_alpha(ipu_plane->dp, true, 0, true);  			break;  		}  	} @@ -437,7 +451,7 @@ static void ipu_plane_atomic_update(struct drm_plane *plane,  	ipu_cpmem_set_high_priority(ipu_plane->ipu_ch);  	ipu_idmac_set_double_buffer(ipu_plane->ipu_ch, 1);  	ipu_cpmem_set_stride(ipu_plane->ipu_ch, state->fb->pitches[0]); -	ipu_plane_atomic_set_base(ipu_plane, old_state); +	ipu_plane_atomic_set_base(ipu_plane);  	ipu_plane_enable(ipu_plane);  } diff --git a/drivers/gpu/drm/nouveau/nouveau_acpi.c b/drivers/gpu/drm/nouveau/nouveau_acpi.c index dc57b628e074..193573d191e5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_acpi.c +++ b/drivers/gpu/drm/nouveau/nouveau_acpi.c @@ -240,7 +240,8 @@ static bool nouveau_pr3_present(struct pci_dev *pdev)  	if (!parent_adev)  		return false; -	return acpi_has_method(parent_adev->handle, "_PR3"); +	return parent_adev->power.flags.power_resources && +		acpi_has_method(parent_adev->handle, "_PR3");  }  static void nouveau_dsm_pci_probe(struct pci_dev *pdev, acpi_handle *dhandle_out, diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 103fc8650197..a0d4a0522fdc 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -1396,9 +1396,7 @@ static void cayman_pcie_gart_fini(struct radeon_device *rdev)  void cayman_cp_int_cntl_setup(struct radeon_device *rdev,  			      int ring, u32 cp_int_cntl)  { -	u32 srbm_gfx_cntl = RREG32(SRBM_GFX_CNTL) & ~3; - -	WREG32(SRBM_GFX_CNTL, srbm_gfx_cntl | (ring & 3)); +	WREG32(SRBM_GFX_CNTL, RINGID(ring));  	WREG32(CP_INT_CNTL, cp_int_cntl);  } diff --git a/drivers/gpu/drm/radeon/radeon_dp_auxch.c b/drivers/gpu/drm/radeon/radeon_dp_auxch.c index 2d465648856a..474a8a1886f7 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_auxch.c +++ b/drivers/gpu/drm/radeon/radeon_dp_auxch.c @@ -105,7 +105,7 @@ radeon_dp_aux_transfer_native(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg  	tmp &= AUX_HPD_SEL(0x7);  	tmp |= AUX_HPD_SEL(chan->rec.hpd); -	tmp |= AUX_EN | AUX_LS_READ_EN | AUX_HPD_DISCON(0x1); +	tmp |= AUX_EN | AUX_LS_READ_EN;  	WREG32(AUX_CONTROL + aux_offset[instance], tmp); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index 89bdf20344ae..c49934527a87 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2999,6 +2999,49 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,  	int i;  	struct si_dpm_quirk *p = si_dpm_quirk_list; +	/* limit all SI kickers */ +	if (rdev->family == CHIP_PITCAIRN) { +		if ((rdev->pdev->revision == 0x81) || +		    (rdev->pdev->device == 0x6810) || +		    (rdev->pdev->device == 0x6811) || +		    (rdev->pdev->device == 0x6816) || +		    (rdev->pdev->device == 0x6817) || +		    (rdev->pdev->device == 0x6806)) +			max_mclk = 120000; +	} else if (rdev->family == CHIP_VERDE) { +		if ((rdev->pdev->revision == 0x81) || +		    (rdev->pdev->revision == 0x83) || +		    (rdev->pdev->revision == 0x87) || +		    (rdev->pdev->device == 0x6820) || +		    (rdev->pdev->device == 0x6821) || +		    (rdev->pdev->device == 0x6822) || +		    (rdev->pdev->device == 0x6823) || +		    (rdev->pdev->device == 0x682A) || +		    (rdev->pdev->device == 0x682B)) { +			max_sclk = 75000; +			max_mclk = 80000; +		} +	} else if (rdev->family == CHIP_OLAND) { +		if ((rdev->pdev->revision == 0xC7) || +		    (rdev->pdev->revision == 0x80) || +		    (rdev->pdev->revision == 0x81) || +		    (rdev->pdev->revision == 0x83) || +		    (rdev->pdev->device == 0x6604) || +		    (rdev->pdev->device == 0x6605)) { +			max_sclk = 75000; +			max_mclk = 80000; +		} +	} else if (rdev->family == CHIP_HAINAN) { +		if ((rdev->pdev->revision == 0x81) || +		    (rdev->pdev->revision == 0x83) || +		    (rdev->pdev->revision == 0xC3) || +		    (rdev->pdev->device == 0x6664) || +		    (rdev->pdev->device == 0x6665) || +		    (rdev->pdev->device == 0x6667)) { +			max_sclk = 75000; +			max_mclk = 80000; +		} +	}  	/* Apply dpm quirks */  	while (p && p->chip_device != 0) {  		if (rdev->pdev->vendor == p->chip_vendor && @@ -3011,16 +3054,6 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev,  		}  		++p;  	} -	/* limit mclk on all R7 370 parts for stability */ -	if (rdev->pdev->device == 0x6811 && -	    rdev->pdev->revision == 0x81) -		max_mclk = 120000; -	/* limit sclk/mclk on Jet parts for stability */ -	if (rdev->pdev->device == 0x6665 && -	    rdev->pdev->revision == 0xc3) { -		max_sclk = 75000; -		max_mclk = 80000; -	}  	if (rps->vce_active) {  		rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index bd9c3bb9252c..392c7e6de042 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -231,8 +231,16 @@ static int rcar_du_atomic_check(struct drm_device *dev,  	struct rcar_du_device *rcdu = dev->dev_private;  	int ret; -	ret = drm_atomic_helper_check(dev, state); -	if (ret < 0) +	ret = drm_atomic_helper_check_modeset(dev, state); +	if (ret) +		return ret; + +	ret = drm_atomic_normalize_zpos(dev, state); +	if (ret) +		return ret; + +	ret = drm_atomic_helper_check_planes(dev, state); +	if (ret)  		return ret;  	if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index 2784919a7366..9df308565f6c 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -195,6 +195,26 @@ static void sti_atomic_work(struct work_struct *work)  	sti_atomic_complete(private, private->commit.state);  } +static int sti_atomic_check(struct drm_device *dev, +			    struct drm_atomic_state *state) +{ +	int ret; + +	ret = drm_atomic_helper_check_modeset(dev, state); +	if (ret) +		return ret; + +	ret = drm_atomic_normalize_zpos(dev, state); +	if (ret) +		return ret; + +	ret = drm_atomic_helper_check_planes(dev, state); +	if (ret) +		return ret; + +	return ret; +} +  static int sti_atomic_commit(struct drm_device *drm,  			     struct drm_atomic_state *state, bool nonblock)  { @@ -248,7 +268,7 @@ static void sti_output_poll_changed(struct drm_device *ddev)  static const struct drm_mode_config_funcs sti_mode_config_funcs = {  	.fb_create = drm_fb_cma_create,  	.output_poll_changed = sti_output_poll_changed, -	.atomic_check = drm_atomic_helper_check, +	.atomic_check = sti_atomic_check,  	.atomic_commit = sti_atomic_commit,  }; diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 7cf3678623c3..58048709c34e 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -338,8 +338,7 @@ static void vgdev_atomic_commit_tail(struct drm_atomic_state *state)  	drm_atomic_helper_commit_modeset_disables(dev, state);  	drm_atomic_helper_commit_modeset_enables(dev, state); -	drm_atomic_helper_commit_planes(dev, state, -					DRM_PLANE_COMMIT_ACTIVE_ONLY); +	drm_atomic_helper_commit_planes(dev, state, 0);  	drm_atomic_helper_commit_hw_done(state); diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c index 2ba7d437a2af..805b6fa7b5f4 100644 --- a/drivers/gpu/ipu-v3/ipu-image-convert.c +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c @@ -1617,7 +1617,7 @@ ipu_image_convert(struct ipu_soc *ipu, enum ipu_ic_task ic_task,  	ctx = ipu_image_convert_prepare(ipu, ic_task, in, out, rot_mode,  					complete, complete_context);  	if (IS_ERR(ctx)) -		return ERR_PTR(PTR_ERR(ctx)); +		return ERR_CAST(ctx);  	run = kzalloc(sizeof(*run), GFP_KERNEL);  	if (!run) { diff --git a/drivers/input/mouse/focaltech.c b/drivers/input/mouse/focaltech.c index 54eceb30ede5..a7d39689bbfb 100644 --- a/drivers/input/mouse/focaltech.c +++ b/drivers/input/mouse/focaltech.c @@ -43,7 +43,7 @@ int focaltech_detect(struct psmouse *psmouse, bool set_properties)  	if (set_properties) {  		psmouse->vendor = "FocalTech"; -		psmouse->name = "FocalTech Touchpad"; +		psmouse->name = "Touchpad";  	}  	return 0; @@ -146,8 +146,8 @@ static void focaltech_report_state(struct psmouse *psmouse)  	}  	input_mt_report_pointer_emulation(dev, true); -	input_report_key(psmouse->dev, BTN_LEFT, state->pressed); -	input_sync(psmouse->dev); +	input_report_key(dev, BTN_LEFT, state->pressed); +	input_sync(dev);  }  static void focaltech_process_touch_packet(struct psmouse *psmouse, diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index f4bfb4b2d50a..073246c7d163 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -877,6 +877,13 @@ static const struct dmi_system_id __initconst i8042_dmi_kbdreset_table[] = {  			DMI_MATCH(DMI_PRODUCT_NAME, "P34"),  		},  	}, +	{ +		/* Schenker XMG C504 - Elantech touchpad */ +		.matches = { +			DMI_MATCH(DMI_SYS_VENDOR, "XMG"), +			DMI_MATCH(DMI_PRODUCT_NAME, "C504"), +		}, +	},  	{ }  }; diff --git a/drivers/md/md.c b/drivers/md/md.c index eac84d8ff724..2089d46b0eb8 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3887,10 +3887,10 @@ array_state_show(struct mddev *mddev, char *page)  			st = read_auto;  			break;  		case 0: -			if (mddev->in_sync) -				st = clean; -			else if (test_bit(MD_CHANGE_PENDING, &mddev->flags)) +			if (test_bit(MD_CHANGE_PENDING, &mddev->flags))  				st = write_pending; +			else if (mddev->in_sync) +				st = clean;  			else if (mddev->safemode)  				st = active_idle;  			else @@ -8144,14 +8144,14 @@ void md_do_sync(struct md_thread *thread)  	if (!test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&  	    !test_bit(MD_RECOVERY_INTR, &mddev->recovery) && -	    mddev->curr_resync > 2) { +	    mddev->curr_resync > 3) {  		mddev->curr_resync_completed = mddev->curr_resync;  		sysfs_notify(&mddev->kobj, NULL, "sync_completed");  	}  	mddev->pers->sync_request(mddev, max_sectors, &skipped);  	if (!test_bit(MD_RECOVERY_CHECK, &mddev->recovery) && -	    mddev->curr_resync > 2) { +	    mddev->curr_resync > 3) {  		if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) {  			if (test_bit(MD_RECOVERY_INTR, &mddev->recovery)) {  				if (mddev->curr_resync >= mddev->recovery_cp) { diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 1961d827dbd1..29e2df5cd77b 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -403,11 +403,14 @@ static void raid1_end_write_request(struct bio *bio)  	struct bio *to_put = NULL;  	int mirror = find_bio_disk(r1_bio, bio);  	struct md_rdev *rdev = conf->mirrors[mirror].rdev; +	bool discard_error; + +	discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;  	/*  	 * 'one mirror IO has finished' event handler:  	 */ -	if (bio->bi_error) { +	if (bio->bi_error && !discard_error) {  		set_bit(WriteErrorSeen,	&rdev->flags);  		if (!test_and_set_bit(WantReplacement, &rdev->flags))  			set_bit(MD_RECOVERY_NEEDED, & @@ -444,7 +447,7 @@ static void raid1_end_write_request(struct bio *bio)  		/* Maybe we can clear some bad blocks. */  		if (is_badblock(rdev, r1_bio->sector, r1_bio->sectors, -				&first_bad, &bad_sectors)) { +				&first_bad, &bad_sectors) && !discard_error) {  			r1_bio->bios[mirror] = IO_MADE_GOOD;  			set_bit(R1BIO_MadeGood, &r1_bio->state);  		} @@ -2294,17 +2297,23 @@ static void handle_read_error(struct r1conf *conf, struct r1bio *r1_bio)  	 * This is all done synchronously while the array is  	 * frozen  	 */ + +	bio = r1_bio->bios[r1_bio->read_disk]; +	bdevname(bio->bi_bdev, b); +	bio_put(bio); +	r1_bio->bios[r1_bio->read_disk] = NULL; +  	if (mddev->ro == 0) {  		freeze_array(conf, 1);  		fix_read_error(conf, r1_bio->read_disk,  			       r1_bio->sector, r1_bio->sectors);  		unfreeze_array(conf); -	} else -		md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev); +	} else { +		r1_bio->bios[r1_bio->read_disk] = IO_BLOCKED; +	} +  	rdev_dec_pending(conf->mirrors[r1_bio->read_disk].rdev, conf->mddev); -	bio = r1_bio->bios[r1_bio->read_disk]; -	bdevname(bio->bi_bdev, b);  read_more:  	disk = read_balance(conf, r1_bio, &max_sectors);  	if (disk == -1) { @@ -2315,11 +2324,6 @@ read_more:  	} else {  		const unsigned long do_sync  			= r1_bio->master_bio->bi_opf & REQ_SYNC; -		if (bio) { -			r1_bio->bios[r1_bio->read_disk] = -				mddev->ro ? IO_BLOCKED : NULL; -			bio_put(bio); -		}  		r1_bio->read_disk = disk;  		bio = bio_clone_mddev(r1_bio->master_bio, GFP_NOIO, mddev);  		bio_trim(bio, r1_bio->sector - bio->bi_iter.bi_sector, diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index be1a9fca3b2d..39fddda2fef2 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -447,6 +447,9 @@ static void raid10_end_write_request(struct bio *bio)  	struct r10conf *conf = r10_bio->mddev->private;  	int slot, repl;  	struct md_rdev *rdev = NULL; +	bool discard_error; + +	discard_error = bio->bi_error && bio_op(bio) == REQ_OP_DISCARD;  	dev = find_bio_disk(conf, r10_bio, bio, &slot, &repl); @@ -460,7 +463,7 @@ static void raid10_end_write_request(struct bio *bio)  	/*  	 * this branch is our 'one mirror IO has finished' event handler:  	 */ -	if (bio->bi_error) { +	if (bio->bi_error && !discard_error) {  		if (repl)  			/* Never record new bad blocks to replacement,  			 * just fail it. @@ -503,7 +506,7 @@ static void raid10_end_write_request(struct bio *bio)  		if (is_badblock(rdev,  				r10_bio->devs[slot].addr,  				r10_bio->sectors, -				&first_bad, &bad_sectors)) { +				&first_bad, &bad_sectors) && !discard_error) {  			bio_put(bio);  			if (repl)  				r10_bio->devs[slot].repl_bio = IO_MADE_GOOD; diff --git a/drivers/md/raid5-cache.c b/drivers/md/raid5-cache.c index 1b1ab4a1d132..a227a9f3ee65 100644 --- a/drivers/md/raid5-cache.c +++ b/drivers/md/raid5-cache.c @@ -1087,7 +1087,7 @@ static int r5l_recovery_log(struct r5l_log *log)  	 * 1's seq + 10 and let superblock points to meta2. The same recovery will  	 * not think meta 3 is a valid meta, because its seq doesn't match  	 */ -	if (ctx.seq > log->last_cp_seq + 1) { +	if (ctx.seq > log->last_cp_seq) {  		int ret;  		ret = r5l_log_write_empty_meta_block(log, ctx.pos, ctx.seq + 10); @@ -1096,6 +1096,8 @@ static int r5l_recovery_log(struct r5l_log *log)  		log->seq = ctx.seq + 11;  		log->log_start = r5l_ring_add(log, ctx.pos, BLOCK_SECTORS);  		r5l_write_super(log, ctx.pos); +		log->last_checkpoint = ctx.pos; +		log->next_checkpoint = ctx.pos;  	} else {  		log->log_start = ctx.pos;  		log->seq = ctx.seq; @@ -1154,6 +1156,7 @@ create:  	if (create_super) {  		log->last_cp_seq = prandom_u32();  		cp = 0; +		r5l_log_write_empty_meta_block(log, cp, log->last_cp_seq);  		/*  		 * Make sure super points to correct address. Log might have  		 * data very soon. If super hasn't correct log tail address, @@ -1168,6 +1171,7 @@ create:  	if (log->max_free_space > RECLAIM_MAX_FREE_SPACE)  		log->max_free_space = RECLAIM_MAX_FREE_SPACE;  	log->last_checkpoint = cp; +	log->next_checkpoint = cp;  	__free_page(page); diff --git a/drivers/media/usb/b2c2/flexcop-usb.c b/drivers/media/usb/b2c2/flexcop-usb.c index d4bdba60b0f7..52bc42da8a4c 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.c +++ b/drivers/media/usb/b2c2/flexcop-usb.c @@ -73,23 +73,34 @@ static int flexcop_usb_readwrite_dw(struct flexcop_device *fc, u16 wRegOffsPCI,  	u8 request_type = (read ? USB_DIR_IN : USB_DIR_OUT) | USB_TYPE_VENDOR;  	u8 wAddress = B2C2_FLEX_PCIOFFSET_TO_INTERNALADDR(wRegOffsPCI) |  		(read ? 0x80 : 0); +	int ret; + +	mutex_lock(&fc_usb->data_mutex); +	if (!read) +		memcpy(fc_usb->data, val, sizeof(*val)); -	int len = usb_control_msg(fc_usb->udev, +	ret = usb_control_msg(fc_usb->udev,  			read ? B2C2_USB_CTRL_PIPE_IN : B2C2_USB_CTRL_PIPE_OUT,  			request,  			request_type, /* 0xc0 read or 0x40 write */  			wAddress,  			0, -			val, +			fc_usb->data,  			sizeof(u32),  			B2C2_WAIT_FOR_OPERATION_RDW * HZ); -	if (len != sizeof(u32)) { +	if (ret != sizeof(u32)) {  		err("error while %s dword from %d (%d).", read ? "reading" :  				"writing", wAddress, wRegOffsPCI); -		return -EIO; +		if (ret >= 0) +			ret = -EIO;  	} -	return 0; + +	if (read && ret >= 0) +		memcpy(val, fc_usb->data, sizeof(*val)); +	mutex_unlock(&fc_usb->data_mutex); + +	return ret;  }  /*   * DKT 010817 - add support for V8 memory read/write and flash update @@ -100,9 +111,14 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,  {  	u8 request_type = USB_TYPE_VENDOR;  	u16 wIndex; -	int nWaitTime, pipe, len; +	int nWaitTime, pipe, ret;  	wIndex = page << 8; +	if (buflen > sizeof(fc_usb->data)) { +		err("Buffer size bigger than max URB control message\n"); +		return -EIO; +	} +  	switch (req) {  	case B2C2_USB_READ_V8_MEM:  		nWaitTime = B2C2_WAIT_FOR_OPERATION_V8READ; @@ -127,17 +143,32 @@ static int flexcop_usb_v8_memory_req(struct flexcop_usb *fc_usb,  	deb_v8("v8mem: %02x %02x %04x %04x, len: %d\n", request_type, req,  			wAddress, wIndex, buflen); -	len = usb_control_msg(fc_usb->udev, pipe, +	mutex_lock(&fc_usb->data_mutex); + +	if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) +		memcpy(fc_usb->data, pbBuffer, buflen); + +	ret = usb_control_msg(fc_usb->udev, pipe,  			req,  			request_type,  			wAddress,  			wIndex, -			pbBuffer, +			fc_usb->data,  			buflen,  			nWaitTime * HZ); +	if (ret != buflen) +		ret = -EIO; + +	if (ret >= 0) { +		ret = 0; +		if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) +			memcpy(pbBuffer, fc_usb->data, buflen); +	} -	debug_dump(pbBuffer, len, deb_v8); -	return len == buflen ? 0 : -EIO; +	mutex_unlock(&fc_usb->data_mutex); + +	debug_dump(pbBuffer, ret, deb_v8); +	return ret;  }  #define bytes_left_to_read_on_page(paddr,buflen) \ @@ -196,29 +227,6 @@ static int flexcop_usb_get_mac_addr(struct flexcop_device *fc, int extended)  		fc->dvb_adapter.proposed_mac, 6);  } -#if 0 -static int flexcop_usb_utility_req(struct flexcop_usb *fc_usb, int set, -		flexcop_usb_utility_function_t func, u8 extra, u16 wIndex, -		u16 buflen, u8 *pvBuffer) -{ -	u16 wValue; -	u8 request_type = (set ? USB_DIR_OUT : USB_DIR_IN) | USB_TYPE_VENDOR; -	int nWaitTime = 2, -	    pipe = set ? B2C2_USB_CTRL_PIPE_OUT : B2C2_USB_CTRL_PIPE_IN, len; -	wValue = (func << 8) | extra; - -	len = usb_control_msg(fc_usb->udev,pipe, -			B2C2_USB_UTILITY, -			request_type, -			wValue, -			wIndex, -			pvBuffer, -			buflen, -			nWaitTime * HZ); -	return len == buflen ? 0 : -EIO; -} -#endif -  /* usb i2c stuff */  static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,  		flexcop_usb_request_t req, flexcop_usb_i2c_function_t func, @@ -226,9 +234,14 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,  {  	struct flexcop_usb *fc_usb = i2c->fc->bus_specific;  	u16 wValue, wIndex; -	int nWaitTime,pipe,len; +	int nWaitTime, pipe, ret;  	u8 request_type = USB_TYPE_VENDOR; +	if (buflen > sizeof(fc_usb->data)) { +		err("Buffer size bigger than max URB control message\n"); +		return -EIO; +	} +  	switch (func) {  	case USB_FUNC_I2C_WRITE:  	case USB_FUNC_I2C_MULTIWRITE: @@ -257,15 +270,32 @@ static int flexcop_usb_i2c_req(struct flexcop_i2c_adapter *i2c,  			wValue & 0xff, wValue >> 8,  			wIndex & 0xff, wIndex >> 8); -	len = usb_control_msg(fc_usb->udev,pipe, +	mutex_lock(&fc_usb->data_mutex); + +	if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) +		memcpy(fc_usb->data, buf, buflen); + +	ret = usb_control_msg(fc_usb->udev, pipe,  			req,  			request_type,  			wValue,  			wIndex, -			buf, +			fc_usb->data,  			buflen,  			nWaitTime * HZ); -	return len == buflen ? 0 : -EREMOTEIO; + +	if (ret != buflen) +		ret = -EIO; + +	if (ret >= 0) { +		ret = 0; +		if ((request_type & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) +			memcpy(buf, fc_usb->data, buflen); +	} + +	mutex_unlock(&fc_usb->data_mutex); + +	return 0;  }  /* actual bus specific access functions, @@ -516,6 +546,7 @@ static int flexcop_usb_probe(struct usb_interface *intf,  	/* general flexcop init */  	fc_usb = fc->bus_specific;  	fc_usb->fc_dev = fc; +	mutex_init(&fc_usb->data_mutex);  	fc->read_ibi_reg  = flexcop_usb_read_ibi_reg;  	fc->write_ibi_reg = flexcop_usb_write_ibi_reg; diff --git a/drivers/media/usb/b2c2/flexcop-usb.h b/drivers/media/usb/b2c2/flexcop-usb.h index 92529a9c4475..25ad43166e78 100644 --- a/drivers/media/usb/b2c2/flexcop-usb.h +++ b/drivers/media/usb/b2c2/flexcop-usb.h @@ -29,6 +29,10 @@ struct flexcop_usb {  	u8 tmp_buffer[1023+190];  	int tmp_buffer_length; + +	/* for URB control messages */ +	u8 data[80]; +	struct mutex data_mutex;  };  #if 0 diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 13620cdf0599..e9100a235831 100644 --- a/drivers/media/usb/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c @@ -545,18 +545,30 @@ static void free_sbufs(struct camera_data *cam)  static int write_packet(struct usb_device *udev,  			u8 request, u8 * registers, u16 start, size_t size)  { +	unsigned char *buf; +	int ret; +  	if (!registers || size <= 0)  		return -EINVAL; -	return usb_control_msg(udev, +	buf = kmalloc(size, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	memcpy(buf, registers, size); + +	ret = usb_control_msg(udev,  			       usb_sndctrlpipe(udev, 0),  			       request,  			       USB_TYPE_VENDOR | USB_RECIP_DEVICE,  			       start,	/* value */  			       0,	/* index */ -			       registers,	/* buffer */ +			       buf,	/* buffer */  			       size,  			       HZ); + +	kfree(buf); +	return ret;  }  /**************************************************************************** @@ -567,18 +579,32 @@ static int write_packet(struct usb_device *udev,  static int read_packet(struct usb_device *udev,  		       u8 request, u8 * registers, u16 start, size_t size)  { +	unsigned char *buf; +	int ret; +  	if (!registers || size <= 0)  		return -EINVAL; -	return usb_control_msg(udev, +	buf = kmalloc(size, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	ret = usb_control_msg(udev,  			       usb_rcvctrlpipe(udev, 0),  			       request,  			       USB_DIR_IN|USB_TYPE_VENDOR|USB_RECIP_DEVICE,  			       start,	/* value */  			       0,	/* index */ -			       registers,	/* buffer */ +			       buf,	/* buffer */  			       size,  			       HZ); + +	if (ret >= 0) +		memcpy(registers, buf, size); + +	kfree(buf); + +	return ret;  }  /****************************************************************************** diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c index efa782ed6e2d..b257780fb380 100644 --- a/drivers/media/usb/dvb-usb/af9005.c +++ b/drivers/media/usb/dvb-usb/af9005.c @@ -52,17 +52,16 @@ u8 regmask[8] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };  struct af9005_device_state {  	u8 sequence;  	int led_state; +	unsigned char data[256]; +	struct mutex data_mutex;  };  static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,  			      int readwrite, int type, u8 * values, int len)  {  	struct af9005_device_state *st = d->priv; -	u8 obuf[16] = { 0 }; -	u8 ibuf[17] = { 0 }; -	u8 command; -	int i; -	int ret; +	u8 command, seq; +	int i, ret;  	if (len < 1) {  		err("generic read/write, less than 1 byte. Makes no sense."); @@ -73,16 +72,17 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,  		return -EINVAL;  	} -	obuf[0] = 14;		/* rest of buffer length low */ -	obuf[1] = 0;		/* rest of buffer length high */ +	mutex_lock(&st->data_mutex); +	st->data[0] = 14;		/* rest of buffer length low */ +	st->data[1] = 0;		/* rest of buffer length high */ -	obuf[2] = AF9005_REGISTER_RW;	/* register operation */ -	obuf[3] = 12;		/* rest of buffer length */ +	st->data[2] = AF9005_REGISTER_RW;	/* register operation */ +	st->data[3] = 12;		/* rest of buffer length */ -	obuf[4] = st->sequence++;	/* sequence number */ +	st->data[4] = seq = st->sequence++;	/* sequence number */ -	obuf[5] = (u8) (reg >> 8);	/* register address */ -	obuf[6] = (u8) (reg & 0xff); +	st->data[5] = (u8) (reg >> 8);	/* register address */ +	st->data[6] = (u8) (reg & 0xff);  	if (type == AF9005_OFDM_REG) {  		command = AF9005_CMD_OFDM_REG; @@ -96,51 +96,52 @@ static int af9005_generic_read_write(struct dvb_usb_device *d, u16 reg,  	command |= readwrite;  	if (readwrite == AF9005_CMD_WRITE)  		for (i = 0; i < len; i++) -			obuf[8 + i] = values[i]; +			st->data[8 + i] = values[i];  	else if (type == AF9005_TUNER_REG)  		/* read command for tuner, the first byte contains the i2c address */ -		obuf[8] = values[0]; -	obuf[7] = command; +		st->data[8] = values[0]; +	st->data[7] = command; -	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 17, 0); +	ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 17, 0);  	if (ret) -		return ret; +		goto ret;  	/* sanity check */ -	if (ibuf[2] != AF9005_REGISTER_RW_ACK) { +	if (st->data[2] != AF9005_REGISTER_RW_ACK) {  		err("generic read/write, wrong reply code."); -		return -EIO; +		ret = -EIO; +		goto ret;  	} -	if (ibuf[3] != 0x0d) { +	if (st->data[3] != 0x0d) {  		err("generic read/write, wrong length in reply."); -		return -EIO; +		ret = -EIO; +		goto ret;  	} -	if (ibuf[4] != obuf[4]) { +	if (st->data[4] != seq) {  		err("generic read/write, wrong sequence in reply."); -		return -EIO; +		ret = -EIO; +		goto ret;  	}  	/* -	   Windows driver doesn't check these fields, in fact sometimes -	   the register in the reply is different that what has been sent - -	   if (ibuf[5] != obuf[5] || ibuf[6] != obuf[6]) { -	   err("generic read/write, wrong register in reply."); -	   return -EIO; -	   } -	   if (ibuf[7] != command) { -	   err("generic read/write wrong command in reply."); -	   return -EIO; -	   } +	 * In thesis, both input and output buffers should have +	 * identical values for st->data[5] to st->data[8]. +	 * However, windows driver doesn't check these fields, in fact +	 * sometimes the register in the reply is different that what +	 * has been sent  	 */ -	if (ibuf[16] != 0x01) { +	if (st->data[16] != 0x01) {  		err("generic read/write wrong status code in reply."); -		return -EIO; +		ret = -EIO; +		goto ret;  	} +  	if (readwrite == AF9005_CMD_READ)  		for (i = 0; i < len; i++) -			values[i] = ibuf[8 + i]; +			values[i] = st->data[8 + i]; -	return 0; +ret: +	mutex_unlock(&st->data_mutex); +	return ret;  } @@ -464,8 +465,7 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,  	struct af9005_device_state *st = d->priv;  	int ret, i, packet_len; -	u8 buf[64]; -	u8 ibuf[64]; +	u8 seq;  	if (wlen < 0) {  		err("send command, wlen less than 0 bytes. Makes no sense."); @@ -480,94 +480,97 @@ int af9005_send_command(struct dvb_usb_device *d, u8 command, u8 * wbuf,  		return -EINVAL;  	}  	packet_len = wlen + 5; -	buf[0] = (u8) (packet_len & 0xff); -	buf[1] = (u8) ((packet_len & 0xff00) >> 8); - -	buf[2] = 0x26;		/* packet type */ -	buf[3] = wlen + 3; -	buf[4] = st->sequence++; -	buf[5] = command; -	buf[6] = wlen; + +	mutex_lock(&st->data_mutex); + +	st->data[0] = (u8) (packet_len & 0xff); +	st->data[1] = (u8) ((packet_len & 0xff00) >> 8); + +	st->data[2] = 0x26;		/* packet type */ +	st->data[3] = wlen + 3; +	st->data[4] = seq = st->sequence++; +	st->data[5] = command; +	st->data[6] = wlen;  	for (i = 0; i < wlen; i++) -		buf[7 + i] = wbuf[i]; -	ret = dvb_usb_generic_rw(d, buf, wlen + 7, ibuf, rlen + 7, 0); -	if (ret) -		return ret; -	if (ibuf[2] != 0x27) { +		st->data[7 + i] = wbuf[i]; +	ret = dvb_usb_generic_rw(d, st->data, wlen + 7, st->data, rlen + 7, 0); +	if (st->data[2] != 0x27) {  		err("send command, wrong reply code."); -		return -EIO; -	} -	if (ibuf[4] != buf[4]) { +		ret = -EIO; +	} else if (st->data[4] != seq) {  		err("send command, wrong sequence in reply."); -		return -EIO; -	} -	if (ibuf[5] != 0x01) { +		ret = -EIO; +	} else if (st->data[5] != 0x01) {  		err("send command, wrong status code in reply."); -		return -EIO; -	} -	if (ibuf[6] != rlen) { +		ret = -EIO; +	} else if (st->data[6] != rlen) {  		err("send command, invalid data length in reply."); -		return -EIO; +		ret = -EIO;  	} -	for (i = 0; i < rlen; i++) -		rbuf[i] = ibuf[i + 7]; -	return 0; +	if (!ret) { +		for (i = 0; i < rlen; i++) +			rbuf[i] = st->data[i + 7]; +	} + +	mutex_unlock(&st->data_mutex); +	return ret;  }  int af9005_read_eeprom(struct dvb_usb_device *d, u8 address, u8 * values,  		       int len)  {  	struct af9005_device_state *st = d->priv; -	u8 obuf[16], ibuf[14]; +	u8 seq;  	int ret, i; -	memset(obuf, 0, sizeof(obuf)); -	memset(ibuf, 0, sizeof(ibuf)); +	mutex_lock(&st->data_mutex); -	obuf[0] = 14;		/* length of rest of packet low */ -	obuf[1] = 0;		/* length of rest of packer high */ +	memset(st->data, 0, sizeof(st->data)); -	obuf[2] = 0x2a;		/* read/write eeprom */ +	st->data[0] = 14;		/* length of rest of packet low */ +	st->data[1] = 0;		/* length of rest of packer high */ -	obuf[3] = 12;		/* size */ +	st->data[2] = 0x2a;		/* read/write eeprom */ -	obuf[4] = st->sequence++; +	st->data[3] = 12;		/* size */ -	obuf[5] = 0;		/* read */ +	st->data[4] = seq = st->sequence++; -	obuf[6] = len; -	obuf[7] = address; -	ret = dvb_usb_generic_rw(d, obuf, 16, ibuf, 14, 0); -	if (ret) -		return ret; -	if (ibuf[2] != 0x2b) { +	st->data[5] = 0;		/* read */ + +	st->data[6] = len; +	st->data[7] = address; +	ret = dvb_usb_generic_rw(d, st->data, 16, st->data, 14, 0); +	if (st->data[2] != 0x2b) {  		err("Read eeprom, invalid reply code"); -		return -EIO; -	} -	if (ibuf[3] != 10) { +		ret = -EIO; +	} else if (st->data[3] != 10) {  		err("Read eeprom, invalid reply length"); -		return -EIO; -	} -	if (ibuf[4] != obuf[4]) { +		ret = -EIO; +	} else if (st->data[4] != seq) {  		err("Read eeprom, wrong sequence in reply "); -		return -EIO; -	} -	if (ibuf[5] != 1) { +		ret = -EIO; +	} else if (st->data[5] != 1) {  		err("Read eeprom, wrong status in reply "); -		return -EIO; +		ret = -EIO;  	} -	for (i = 0; i < len; i++) { -		values[i] = ibuf[6 + i]; + +	if (!ret) { +		for (i = 0; i < len; i++) +			values[i] = st->data[6 + i];  	} -	return 0; +	mutex_unlock(&st->data_mutex); + +	return ret;  } -static int af9005_boot_packet(struct usb_device *udev, int type, u8 * reply) +static int af9005_boot_packet(struct usb_device *udev, int type, u8 *reply, +			      u8 *buf, int size)  { -	u8 buf[FW_BULKOUT_SIZE + 2];  	u16 checksum;  	int act_len, i, ret; -	memset(buf, 0, sizeof(buf)); + +	memset(buf, 0, size);  	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff);  	buf[1] = (u8) ((FW_BULKOUT_SIZE >> 8) & 0xff);  	switch (type) { @@ -720,15 +723,21 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa  {  	int i, packets, ret, act_len; -	u8 buf[FW_BULKOUT_SIZE + 2]; +	u8 *buf;  	u8 reply; -	ret = af9005_boot_packet(udev, FW_CONFIG, &reply); +	buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf, +				 FW_BULKOUT_SIZE + 2);  	if (ret) -		return ret; +		goto err;  	if (reply != 0x01) {  		err("before downloading firmware, FW_CONFIG expected 0x01, received 0x%x", reply); -		return -EIO; +		ret = -EIO; +		goto err;  	}  	packets = fw->size / FW_BULKOUT_SIZE;  	buf[0] = (u8) (FW_BULKOUT_SIZE & 0xff); @@ -743,28 +752,35 @@ static int af9005_download_firmware(struct usb_device *udev, const struct firmwa  				   buf, FW_BULKOUT_SIZE + 2, &act_len, 1000);  		if (ret) {  			err("firmware download failed at packet %d with code %d", i, ret); -			return ret; +			goto err;  		}  	} -	ret = af9005_boot_packet(udev, FW_CONFIRM, &reply); +	ret = af9005_boot_packet(udev, FW_CONFIRM, &reply, +				 buf, FW_BULKOUT_SIZE + 2);  	if (ret) -		return ret; +		goto err;  	if (reply != (u8) (packets & 0xff)) {  		err("after downloading firmware, FW_CONFIRM expected 0x%x, received 0x%x", packets & 0xff, reply); -		return -EIO; +		ret = -EIO; +		goto err;  	} -	ret = af9005_boot_packet(udev, FW_BOOT, &reply); +	ret = af9005_boot_packet(udev, FW_BOOT, &reply, buf, +				 FW_BULKOUT_SIZE + 2);  	if (ret) -		return ret; -	ret = af9005_boot_packet(udev, FW_CONFIG, &reply); +		goto err; +	ret = af9005_boot_packet(udev, FW_CONFIG, &reply, buf, +				 FW_BULKOUT_SIZE + 2);  	if (ret) -		return ret; +		goto err;  	if (reply != 0x02) {  		err("after downloading firmware, FW_CONFIG expected 0x02, received 0x%x", reply); -		return -EIO; +		ret = -EIO; +		goto err;  	} -	return 0; +err: +	kfree(buf); +	return ret;  } @@ -823,53 +839,59 @@ static int af9005_rc_query(struct dvb_usb_device *d, u32 * event, int *state)  {  	struct af9005_device_state *st = d->priv;  	int ret, len; - -	u8 obuf[5]; -	u8 ibuf[256]; +	u8 seq;  	*state = REMOTE_NO_KEY_PRESSED;  	if (rc_decode == NULL) {  		/* it shouldn't never come here */  		return 0;  	} + +	mutex_lock(&st->data_mutex); +  	/* deb_info("rc_query\n"); */ -	obuf[0] = 3;		/* rest of packet length low */ -	obuf[1] = 0;		/* rest of packet lentgh high */ -	obuf[2] = 0x40;		/* read remote */ -	obuf[3] = 1;		/* rest of packet length */ -	obuf[4] = st->sequence++;	/* sequence number */ -	ret = dvb_usb_generic_rw(d, obuf, 5, ibuf, 256, 0); +	st->data[0] = 3;		/* rest of packet length low */ +	st->data[1] = 0;		/* rest of packet lentgh high */ +	st->data[2] = 0x40;		/* read remote */ +	st->data[3] = 1;		/* rest of packet length */ +	st->data[4] = seq = st->sequence++;	/* sequence number */ +	ret = dvb_usb_generic_rw(d, st->data, 5, st->data, 256, 0);  	if (ret) {  		err("rc query failed"); -		return ret; +		goto ret;  	} -	if (ibuf[2] != 0x41) { +	if (st->data[2] != 0x41) {  		err("rc query bad header."); -		return -EIO; -	} -	if (ibuf[4] != obuf[4]) { +		ret = -EIO; +		goto ret; +	} else if (st->data[4] != seq) {  		err("rc query bad sequence."); -		return -EIO; +		ret = -EIO; +		goto ret;  	} -	len = ibuf[5]; +	len = st->data[5];  	if (len > 246) {  		err("rc query invalid length"); -		return -EIO; +		ret = -EIO; +		goto ret;  	}  	if (len > 0) {  		deb_rc("rc data (%d) ", len); -		debug_dump((ibuf + 6), len, deb_rc); -		ret = rc_decode(d, &ibuf[6], len, event, state); +		debug_dump((st->data + 6), len, deb_rc); +		ret = rc_decode(d, &st->data[6], len, event, state);  		if (ret) {  			err("rc_decode failed"); -			return ret; +			goto ret;  		} else {  			deb_rc("rc_decode state %x event %x\n", *state, *event);  			if (*state == REMOTE_KEY_REPEAT)  				*event = d->last_event;  		}  	} -	return 0; + +ret: +	mutex_unlock(&st->data_mutex); +	return ret;  }  static int af9005_power_ctrl(struct dvb_usb_device *d, int onoff) @@ -953,10 +975,16 @@ static int af9005_identify_state(struct usb_device *udev,  				 int *cold)  {  	int ret; -	u8 reply; -	ret = af9005_boot_packet(udev, FW_CONFIG, &reply); +	u8 reply, *buf; + +	buf = kmalloc(FW_BULKOUT_SIZE + 2, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	ret = af9005_boot_packet(udev, FW_CONFIG, &reply, +				 buf, FW_BULKOUT_SIZE + 2);  	if (ret) -		return ret; +		goto err;  	deb_info("result of FW_CONFIG in identify state %d\n", reply);  	if (reply == 0x01)  		*cold = 1; @@ -965,7 +993,10 @@ static int af9005_identify_state(struct usb_device *udev,  	else  		return -EIO;  	deb_info("Identify state cold = %d\n", *cold); -	return 0; + +err: +	kfree(buf); +	return ret;  }  static struct dvb_usb_device_properties af9005_properties; @@ -973,8 +1004,20 @@ static struct dvb_usb_device_properties af9005_properties;  static int af9005_usb_probe(struct usb_interface *intf,  			    const struct usb_device_id *id)  { -	return dvb_usb_device_init(intf, &af9005_properties, -				   THIS_MODULE, NULL, adapter_nr); +	struct dvb_usb_device *d; +	struct af9005_device_state *st; +	int ret; + +	ret = dvb_usb_device_init(intf, &af9005_properties, +				  THIS_MODULE, &d, adapter_nr); + +	if (ret < 0) +		return ret; + +	st = d->priv; +	mutex_init(&st->data_mutex); + +	return 0;  }  enum af9005_usb_table_entry { diff --git a/drivers/media/usb/dvb-usb/cinergyT2-core.c b/drivers/media/usb/dvb-usb/cinergyT2-core.c index 9fd1527494eb..8ac825413d5a 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-core.c @@ -41,6 +41,8 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);  struct cinergyt2_state {  	u8 rc_counter; +	unsigned char data[64]; +	struct mutex data_mutex;  };  /* We are missing a release hook with usb_device data */ @@ -50,38 +52,57 @@ static struct dvb_usb_device_properties cinergyt2_properties;  static int cinergyt2_streaming_ctrl(struct dvb_usb_adapter *adap, int enable)  { -	char buf[] = { CINERGYT2_EP1_CONTROL_STREAM_TRANSFER, enable ? 1 : 0 }; -	char result[64]; -	return dvb_usb_generic_rw(adap->dev, buf, sizeof(buf), result, -				sizeof(result), 0); +	struct dvb_usb_device *d = adap->dev; +	struct cinergyt2_state *st = d->priv; +	int ret; + +	mutex_lock(&st->data_mutex); +	st->data[0] = CINERGYT2_EP1_CONTROL_STREAM_TRANSFER; +	st->data[1] = enable ? 1 : 0; + +	ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 64, 0); +	mutex_unlock(&st->data_mutex); + +	return ret;  }  static int cinergyt2_power_ctrl(struct dvb_usb_device *d, int enable)  { -	char buf[] = { CINERGYT2_EP1_SLEEP_MODE, enable ? 0 : 1 }; -	char state[3]; -	return dvb_usb_generic_rw(d, buf, sizeof(buf), state, sizeof(state), 0); +	struct cinergyt2_state *st = d->priv; +	int ret; + +	mutex_lock(&st->data_mutex); +	st->data[0] = CINERGYT2_EP1_SLEEP_MODE; +	st->data[1] = enable ? 0 : 1; + +	ret = dvb_usb_generic_rw(d, st->data, 2, st->data, 3, 0); +	mutex_unlock(&st->data_mutex); + +	return ret;  }  static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap)  { -	char query[] = { CINERGYT2_EP1_GET_FIRMWARE_VERSION }; -	char state[3]; +	struct dvb_usb_device *d = adap->dev; +	struct cinergyt2_state *st = d->priv;  	int ret;  	adap->fe_adap[0].fe = cinergyt2_fe_attach(adap->dev); -	ret = dvb_usb_generic_rw(adap->dev, query, sizeof(query), state, -				sizeof(state), 0); +	mutex_lock(&st->data_mutex); +	st->data[0] = CINERGYT2_EP1_GET_FIRMWARE_VERSION; + +	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0);  	if (ret < 0) {  		deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep "  			"state info\n");  	} +	mutex_unlock(&st->data_mutex);  	/* Copy this pointer as we are gonna need it in the release phase */  	cinergyt2_usb_device = adap->dev; -	return 0; +	return ret;  }  static struct rc_map_table rc_map_cinergyt2_table[] = { @@ -141,13 +162,18 @@ static int repeatable_keys[] = {  static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)  {  	struct cinergyt2_state *st = d->priv; -	u8 key[5] = {0, 0, 0, 0, 0}, cmd = CINERGYT2_EP1_GET_RC_EVENTS; -	int i; +	int i, ret;  	*state = REMOTE_NO_KEY_PRESSED; -	dvb_usb_generic_rw(d, &cmd, 1, key, sizeof(key), 0); -	if (key[4] == 0xff) { +	mutex_lock(&st->data_mutex); +	st->data[0] = CINERGYT2_EP1_GET_RC_EVENTS; + +	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0); +	if (ret < 0) +		goto ret; + +	if (st->data[4] == 0xff) {  		/* key repeat */  		st->rc_counter++;  		if (st->rc_counter > RC_REPEAT_DELAY) { @@ -157,31 +183,45 @@ static int cinergyt2_rc_query(struct dvb_usb_device *d, u32 *event, int *state)  					*event = d->last_event;  					deb_rc("repeat key, event %x\n",  						   *event); -					return 0; +					goto ret;  				}  			}  			deb_rc("repeated key (non repeatable)\n");  		} -		return 0; +		goto ret;  	}  	/* hack to pass checksum on the custom field */ -	key[2] = ~key[1]; -	dvb_usb_nec_rc_key_to_event(d, key, event, state); -	if (key[0] != 0) { +	st->data[2] = ~st->data[1]; +	dvb_usb_nec_rc_key_to_event(d, st->data, event, state); +	if (st->data[0] != 0) {  		if (*event != d->last_event)  			st->rc_counter = 0; -		deb_rc("key: %*ph\n", 5, key); +		deb_rc("key: %*ph\n", 5, st->data);  	} -	return 0; + +ret: +	mutex_unlock(&st->data_mutex); +	return ret;  }  static int cinergyt2_usb_probe(struct usb_interface *intf,  				const struct usb_device_id *id)  { -	return dvb_usb_device_init(intf, &cinergyt2_properties, -					THIS_MODULE, NULL, adapter_nr); +	struct dvb_usb_device *d; +	struct cinergyt2_state *st; +	int ret; + +	ret = dvb_usb_device_init(intf, &cinergyt2_properties, +				  THIS_MODULE, &d, adapter_nr); +	if (ret < 0) +		return ret; + +	st = d->priv; +	mutex_init(&st->data_mutex); + +	return 0;  } diff --git a/drivers/media/usb/dvb-usb/cinergyT2-fe.c b/drivers/media/usb/dvb-usb/cinergyT2-fe.c index b3ec743a7a2e..2d29b4174dba 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-fe.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-fe.c @@ -139,32 +139,42 @@ static uint16_t compute_tps(struct dtv_frontend_properties *op)  struct cinergyt2_fe_state {  	struct dvb_frontend fe;  	struct dvb_usb_device *d; + +	unsigned char data[64]; +	struct mutex data_mutex; + +	struct dvbt_get_status_msg status;  };  static int cinergyt2_fe_read_status(struct dvb_frontend *fe,  				    enum fe_status *status)  {  	struct cinergyt2_fe_state *state = fe->demodulator_priv; -	struct dvbt_get_status_msg result; -	u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS };  	int ret; -	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&result, -			sizeof(result), 0); +	mutex_lock(&state->data_mutex); +	state->data[0] = CINERGYT2_EP1_GET_TUNER_STATUS; + +	ret = dvb_usb_generic_rw(state->d, state->data, 1, +				 state->data, sizeof(state->status), 0); +	if (!ret) +		memcpy(&state->status, state->data, sizeof(state->status)); +	mutex_unlock(&state->data_mutex); +  	if (ret < 0)  		return ret;  	*status = 0; -	if (0xffff - le16_to_cpu(result.gain) > 30) +	if (0xffff - le16_to_cpu(state->status.gain) > 30)  		*status |= FE_HAS_SIGNAL; -	if (result.lock_bits & (1 << 6)) +	if (state->status.lock_bits & (1 << 6))  		*status |= FE_HAS_LOCK; -	if (result.lock_bits & (1 << 5)) +	if (state->status.lock_bits & (1 << 5))  		*status |= FE_HAS_SYNC; -	if (result.lock_bits & (1 << 4)) +	if (state->status.lock_bits & (1 << 4))  		*status |= FE_HAS_CARRIER; -	if (result.lock_bits & (1 << 1)) +	if (state->status.lock_bits & (1 << 1))  		*status |= FE_HAS_VITERBI;  	if ((*status & (FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC)) != @@ -177,34 +187,16 @@ static int cinergyt2_fe_read_status(struct dvb_frontend *fe,  static int cinergyt2_fe_read_ber(struct dvb_frontend *fe, u32 *ber)  {  	struct cinergyt2_fe_state *state = fe->demodulator_priv; -	struct dvbt_get_status_msg status; -	char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; -	int ret; - -	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, -				sizeof(status), 0); -	if (ret < 0) -		return ret; -	*ber = le32_to_cpu(status.viterbi_error_rate); +	*ber = le32_to_cpu(state->status.viterbi_error_rate);  	return 0;  }  static int cinergyt2_fe_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)  {  	struct cinergyt2_fe_state *state = fe->demodulator_priv; -	struct dvbt_get_status_msg status; -	u8 cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; -	int ret; -	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (u8 *)&status, -				sizeof(status), 0); -	if (ret < 0) { -		err("cinergyt2_fe_read_unc_blocks() Failed! (Error=%d)\n", -			ret); -		return ret; -	} -	*unc = le32_to_cpu(status.uncorrected_block_count); +	*unc = le32_to_cpu(state->status.uncorrected_block_count);  	return 0;  } @@ -212,35 +204,16 @@ static int cinergyt2_fe_read_signal_strength(struct dvb_frontend *fe,  						u16 *strength)  {  	struct cinergyt2_fe_state *state = fe->demodulator_priv; -	struct dvbt_get_status_msg status; -	char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; -	int ret; -	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, -				sizeof(status), 0); -	if (ret < 0) { -		err("cinergyt2_fe_read_signal_strength() Failed!" -			" (Error=%d)\n", ret); -		return ret; -	} -	*strength = (0xffff - le16_to_cpu(status.gain)); +	*strength = (0xffff - le16_to_cpu(state->status.gain));  	return 0;  }  static int cinergyt2_fe_read_snr(struct dvb_frontend *fe, u16 *snr)  {  	struct cinergyt2_fe_state *state = fe->demodulator_priv; -	struct dvbt_get_status_msg status; -	char cmd[] = { CINERGYT2_EP1_GET_TUNER_STATUS }; -	int ret; -	ret = dvb_usb_generic_rw(state->d, cmd, sizeof(cmd), (char *)&status, -				sizeof(status), 0); -	if (ret < 0) { -		err("cinergyt2_fe_read_snr() Failed! (Error=%d)\n", ret); -		return ret; -	} -	*snr = (status.snr << 8) | status.snr; +	*snr = (state->status.snr << 8) | state->status.snr;  	return 0;  } @@ -266,34 +239,36 @@ static int cinergyt2_fe_set_frontend(struct dvb_frontend *fe)  {  	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;  	struct cinergyt2_fe_state *state = fe->demodulator_priv; -	struct dvbt_set_parameters_msg param; -	char result[2]; +	struct dvbt_set_parameters_msg *param;  	int err; -	param.cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; -	param.tps = cpu_to_le16(compute_tps(fep)); -	param.freq = cpu_to_le32(fep->frequency / 1000); -	param.flags = 0; +	mutex_lock(&state->data_mutex); + +	param = (void *)state->data; +	param->cmd = CINERGYT2_EP1_SET_TUNER_PARAMETERS; +	param->tps = cpu_to_le16(compute_tps(fep)); +	param->freq = cpu_to_le32(fep->frequency / 1000); +	param->flags = 0;  	switch (fep->bandwidth_hz) {  	default:  	case 8000000: -		param.bandwidth = 8; +		param->bandwidth = 8;  		break;  	case 7000000: -		param.bandwidth = 7; +		param->bandwidth = 7;  		break;  	case 6000000: -		param.bandwidth = 6; +		param->bandwidth = 6;  		break;  	} -	err = dvb_usb_generic_rw(state->d, -			(char *)¶m, sizeof(param), -			result, sizeof(result), 0); +	err = dvb_usb_generic_rw(state->d, state->data, sizeof(*param), +				 state->data, 2, 0);  	if (err < 0)  		err("cinergyt2_fe_set_frontend() Failed! err=%d\n", err); +	mutex_unlock(&state->data_mutex);  	return (err < 0) ? err : 0;  } @@ -315,6 +290,7 @@ struct dvb_frontend *cinergyt2_fe_attach(struct dvb_usb_device *d)  	s->d = d;  	memcpy(&s->fe.ops, &cinergyt2_fe_ops, sizeof(struct dvb_frontend_ops));  	s->fe.demodulator_priv = s; +	mutex_init(&s->data_mutex);  	return &s->fe;  } diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 907ac01ae297..39772812269d 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -45,9 +45,6 @@  #include "si2168.h"  #include "si2157.h" -/* Max transfer size done by I2C transfer functions */ -#define MAX_XFER_SIZE  80 -  /* debug */  static int dvb_usb_cxusb_debug;  module_param_named(debug, dvb_usb_cxusb_debug, int, 0644); @@ -61,23 +58,27 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);  static int cxusb_ctrl_msg(struct dvb_usb_device *d,  			  u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)  { -	int wo = (rbuf == NULL || rlen == 0); /* write-only */ -	u8 sndbuf[MAX_XFER_SIZE]; +	struct cxusb_state *st = d->priv; +	int ret, wo; -	if (1 + wlen > sizeof(sndbuf)) { -		warn("i2c wr: len=%d is too big!\n", -		     wlen); +	if (1 + wlen > MAX_XFER_SIZE) { +		warn("i2c wr: len=%d is too big!\n", wlen);  		return -EOPNOTSUPP;  	} -	memset(sndbuf, 0, 1+wlen); +	wo = (rbuf == NULL || rlen == 0); /* write-only */ -	sndbuf[0] = cmd; -	memcpy(&sndbuf[1], wbuf, wlen); +	mutex_lock(&st->data_mutex); +	st->data[0] = cmd; +	memcpy(&st->data[1], wbuf, wlen);  	if (wo) -		return dvb_usb_generic_write(d, sndbuf, 1+wlen); +		ret = dvb_usb_generic_write(d, st->data, 1 + wlen);  	else -		return dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0); +		ret = dvb_usb_generic_rw(d, st->data, 1 + wlen, +					 rbuf, rlen, 0); + +	mutex_unlock(&st->data_mutex); +	return ret;  }  /* GPIO */ @@ -1460,36 +1461,43 @@ static struct dvb_usb_device_properties cxusb_mygica_t230_properties;  static int cxusb_probe(struct usb_interface *intf,  		       const struct usb_device_id *id)  { +	struct dvb_usb_device *d; +	struct cxusb_state *st; +  	if (0 == dvb_usb_device_init(intf, &cxusb_medion_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgh064f_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dee1601_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_lgz201_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dtt7579_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_dualdig4_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_bluebird_nano2_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf,  				&cxusb_bluebird_nano2_needsfirmware_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_aver_a868r_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf,  				     &cxusb_bluebird_dualdig4_rev2_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_d680_dmb_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties, -				     THIS_MODULE, NULL, adapter_nr) || -	    0) +				     THIS_MODULE, &d, adapter_nr) || +	    0) { +		st = d->priv; +		mutex_init(&st->data_mutex); +  		return 0; +	}  	return -EINVAL;  } diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h index 527ff7905e15..9f3ee0e47d5c 100644 --- a/drivers/media/usb/dvb-usb/cxusb.h +++ b/drivers/media/usb/dvb-usb/cxusb.h @@ -28,10 +28,16 @@  #define CMD_ANALOG        0x50  #define CMD_DIGITAL       0x51 +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE  80 +  struct cxusb_state {  	u8 gpio_write_state[3];  	struct i2c_client *i2c_client_demod;  	struct i2c_client *i2c_client_tuner; + +	unsigned char data[MAX_XFER_SIZE]; +	struct mutex data_mutex;  };  #endif diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index f3196658fb70..92d5408684ac 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -213,7 +213,7 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,  						 usb_rcvctrlpipe(d->udev, 0),  						 REQUEST_NEW_I2C_READ,  						 USB_TYPE_VENDOR | USB_DIR_IN, -						 value, index, msg[i].buf, +						 value, index, st->buf,  						 msg[i].len,  						 USB_CTRL_GET_TIMEOUT);  			if (result < 0) { @@ -221,6 +221,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,  				break;  			} +			if (msg[i].len > sizeof(st->buf)) { +				deb_info("buffer too small to fit %d bytes\n", +					 msg[i].len); +				return -EIO; +			} + +			memcpy(msg[i].buf, st->buf, msg[i].len); +  			deb_data("<<< ");  			debug_dump(msg[i].buf, msg[i].len, deb_data); @@ -238,6 +246,13 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg,  			/* I2C ctrl + FE bus; */  			st->buf[3] = ((gen_mode << 6) & 0xC0) |  				 ((bus_mode << 4) & 0x30); + +			if (msg[i].len > sizeof(st->buf) - 4) { +				deb_info("i2c message to big: %d\n", +					 msg[i].len); +				return -EIO; +			} +  			/* The Actual i2c payload */  			memcpy(&st->buf[4], msg[i].buf, msg[i].len); @@ -283,6 +298,11 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,  		/* fill in the address */  		st->buf[1] = msg[i].addr << 1;  		/* fill the buffer */ +		if (msg[i].len > sizeof(st->buf) - 2) { +			deb_info("i2c xfer to big: %d\n", +				msg[i].len); +			return -EIO; +		}  		memcpy(&st->buf[2], msg[i].buf, msg[i].len);  		/* write/read request */ @@ -292,13 +312,20 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap,  			/* special thing in the current firmware: when length is zero the read-failed */  			len = dib0700_ctrl_rd(d, st->buf, msg[i].len + 2, -					msg[i+1].buf, msg[i+1].len); +					      st->buf, msg[i + 1].len);  			if (len <= 0) {  				deb_info("I2C read failed on address 0x%02x\n",  						msg[i].addr);  				break;  			} +			if (msg[i + 1].len > sizeof(st->buf)) { +				deb_info("i2c xfer buffer to small for %d\n", +					msg[i].len); +				return -EIO; +			} +			memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len); +  			msg[i+1].len = len;  			i++; diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c index 0857b56e652c..ef1b8ee75c57 100644 --- a/drivers/media/usb/dvb-usb/dib0700_devices.c +++ b/drivers/media/usb/dvb-usb/dib0700_devices.c @@ -508,8 +508,6 @@ static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)  #define DEFAULT_RC_INTERVAL 50 -static u8 rc_request[] = { REQUEST_POLL_RC, 0 }; -  /*   * This function is used only when firmware is < 1.20 version. Newer   * firmwares use bulk mode, with functions implemented at dib0700_core, @@ -517,7 +515,6 @@ static u8 rc_request[] = { REQUEST_POLL_RC, 0 };   */  static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)  { -	u8 key[4];  	enum rc_type protocol;  	u32 scancode;  	u8 toggle; @@ -532,39 +529,43 @@ static int dib0700_rc_query_old_firmware(struct dvb_usb_device *d)  		return 0;  	} -	i = dib0700_ctrl_rd(d, rc_request, 2, key, 4); +	st->buf[0] = REQUEST_POLL_RC; +	st->buf[1] = 0; + +	i = dib0700_ctrl_rd(d, st->buf, 2, st->buf, 4);  	if (i <= 0) {  		err("RC Query Failed"); -		return -1; +		return -EIO;  	}  	/* losing half of KEY_0 events from Philipps rc5 remotes.. */ -	if (key[0] == 0 && key[1] == 0 && key[2] == 0 && key[3] == 0) +	if (st->buf[0] == 0 && st->buf[1] == 0 +	    && st->buf[2] == 0 && st->buf[3] == 0)  		return 0; -	/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)key[3-2],(int)key[3-3],(int)key[3-1],(int)key[3]);  */ +	/* info("%d: %2X %2X %2X %2X",dvb_usb_dib0700_ir_proto,(int)st->buf[3 - 2],(int)st->buf[3 - 3],(int)st->buf[3 - 1],(int)st->buf[3]);  */  	dib0700_rc_setup(d, NULL); /* reset ir sensor data to prevent false events */  	switch (d->props.rc.core.protocol) {  	case RC_BIT_NEC:  		/* NEC protocol sends repeat code as 0 0 0 FF */ -		if ((key[3-2] == 0x00) && (key[3-3] == 0x00) && -		    (key[3] == 0xff)) { +		if ((st->buf[3 - 2] == 0x00) && (st->buf[3 - 3] == 0x00) && +		    (st->buf[3] == 0xff)) {  			rc_repeat(d->rc_dev);  			return 0;  		}  		protocol = RC_TYPE_NEC; -		scancode = RC_SCANCODE_NEC(key[3-2], key[3-3]); +		scancode = RC_SCANCODE_NEC(st->buf[3 - 2], st->buf[3 - 3]);  		toggle = 0;  		break;  	default:  		/* RC-5 protocol changes toggle bit on new keypress */  		protocol = RC_TYPE_RC5; -		scancode = RC_SCANCODE_RC5(key[3-2], key[3-3]); -		toggle = key[3-1]; +		scancode = RC_SCANCODE_RC5(st->buf[3 - 2], st->buf[3 - 3]); +		toggle = st->buf[3 - 1];  		break;  	} diff --git a/drivers/media/usb/dvb-usb/dibusb-common.c b/drivers/media/usb/dvb-usb/dibusb-common.c index 18ed3bfbb5e2..de3ee2547479 100644 --- a/drivers/media/usb/dvb-usb/dibusb-common.c +++ b/drivers/media/usb/dvb-usb/dibusb-common.c @@ -62,72 +62,117 @@ EXPORT_SYMBOL(dibusb_pid_filter_ctrl);  int dibusb_power_ctrl(struct dvb_usb_device *d, int onoff)  { -	u8 b[3]; +	u8 *b;  	int ret; + +	b = kmalloc(3, GFP_KERNEL); +	if (!b) +		return -ENOMEM; +  	b[0] = DIBUSB_REQ_SET_IOCTL;  	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE;  	b[2] = onoff ? DIBUSB_IOCTL_POWER_WAKEUP : DIBUSB_IOCTL_POWER_SLEEP; -	ret = dvb_usb_generic_write(d,b,3); + +	ret = dvb_usb_generic_write(d, b, 3); + +	kfree(b); +  	msleep(10); +  	return ret;  }  EXPORT_SYMBOL(dibusb_power_ctrl);  int dibusb2_0_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)  { -	u8 b[3] = { 0 };  	int ret; +	u8 *b; + +	b = kmalloc(3, GFP_KERNEL); +	if (!b) +		return -ENOMEM;  	if ((ret = dibusb_streaming_ctrl(adap,onoff)) < 0) -		return ret; +		goto ret;  	if (onoff) {  		b[0] = DIBUSB_REQ_SET_STREAMING_MODE;  		b[1] = 0x00; -		if ((ret = dvb_usb_generic_write(adap->dev,b,2)) < 0) -			return ret; +		ret = dvb_usb_generic_write(adap->dev, b, 2); +		if (ret  < 0) +			goto ret;  	}  	b[0] = DIBUSB_REQ_SET_IOCTL;  	b[1] = onoff ? DIBUSB_IOCTL_CMD_ENABLE_STREAM : DIBUSB_IOCTL_CMD_DISABLE_STREAM; -	return dvb_usb_generic_write(adap->dev,b,3); +	ret = dvb_usb_generic_write(adap->dev, b, 3); + +ret: +	kfree(b); +	return ret;  }  EXPORT_SYMBOL(dibusb2_0_streaming_ctrl);  int dibusb2_0_power_ctrl(struct dvb_usb_device *d, int onoff)  { -	if (onoff) { -		u8 b[3] = { DIBUSB_REQ_SET_IOCTL, DIBUSB_IOCTL_CMD_POWER_MODE, DIBUSB_IOCTL_POWER_WAKEUP }; -		return dvb_usb_generic_write(d,b,3); -	} else +	u8 *b; +	int ret; + +	if (!onoff)  		return 0; + +	b = kmalloc(3, GFP_KERNEL); +	if (!b) +		return -ENOMEM; + +	b[0] = DIBUSB_REQ_SET_IOCTL; +	b[1] = DIBUSB_IOCTL_CMD_POWER_MODE; +	b[2] = DIBUSB_IOCTL_POWER_WAKEUP; + +	ret = dvb_usb_generic_write(d, b, 3); + +	kfree(b); + +	return ret;  }  EXPORT_SYMBOL(dibusb2_0_power_ctrl);  static int dibusb_i2c_msg(struct dvb_usb_device *d, u8 addr,  			  u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)  { -	u8 sndbuf[MAX_XFER_SIZE]; /* lead(1) devaddr,direction(1) addr(2) data(wlen) (len(2) (when reading)) */ +	u8 *sndbuf; +	int ret, wo, len; +  	/* write only ? */ -	int wo = (rbuf == NULL || rlen == 0), -		len = 2 + wlen + (wo ? 0 : 2); +	wo = (rbuf == NULL || rlen == 0); + +	len = 2 + wlen + (wo ? 0 : 2); + +	sndbuf = kmalloc(MAX_XFER_SIZE, GFP_KERNEL); +	if (!sndbuf) +		return -ENOMEM; -	if (4 + wlen > sizeof(sndbuf)) { +	if (4 + wlen > MAX_XFER_SIZE) {  		warn("i2c wr: len=%d is too big!\n", wlen); -		return -EOPNOTSUPP; +		ret = -EOPNOTSUPP; +		goto ret;  	}  	sndbuf[0] = wo ? DIBUSB_REQ_I2C_WRITE : DIBUSB_REQ_I2C_READ;  	sndbuf[1] = (addr << 1) | (wo ? 0 : 1); -	memcpy(&sndbuf[2],wbuf,wlen); +	memcpy(&sndbuf[2], wbuf, wlen);  	if (!wo) { -		sndbuf[wlen+2] = (rlen >> 8) & 0xff; -		sndbuf[wlen+3] = rlen & 0xff; +		sndbuf[wlen + 2] = (rlen >> 8) & 0xff; +		sndbuf[wlen + 3] = rlen & 0xff;  	} -	return dvb_usb_generic_rw(d,sndbuf,len,rbuf,rlen,0); +	ret = dvb_usb_generic_rw(d, sndbuf, len, rbuf, rlen, 0); + +ret: +	kfree(sndbuf); +	return ret;  }  /* @@ -319,11 +364,27 @@ EXPORT_SYMBOL(rc_map_dibusb_table);  int dibusb_rc_query(struct dvb_usb_device *d, u32 *event, int *state)  { -	u8 key[5],cmd = DIBUSB_REQ_POLL_REMOTE; -	dvb_usb_generic_rw(d,&cmd,1,key,5,0); -	dvb_usb_nec_rc_key_to_event(d,key,event,state); -	if (key[0] != 0) -		deb_info("key: %*ph\n", 5, key); -	return 0; +	u8 *buf; +	int ret; + +	buf = kmalloc(5, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	buf[0] = DIBUSB_REQ_POLL_REMOTE; + +	ret = dvb_usb_generic_rw(d, buf, 1, buf, 5, 0); +	if (ret < 0) +		goto ret; + +	dvb_usb_nec_rc_key_to_event(d, buf, event, state); + +	if (buf[0] != 0) +		deb_info("key: %*ph\n", 5, buf); + +	kfree(buf); + +ret: +	return ret;  }  EXPORT_SYMBOL(dibusb_rc_query); diff --git a/drivers/media/usb/dvb-usb/dibusb.h b/drivers/media/usb/dvb-usb/dibusb.h index 3f82163d8ab8..697be2a17ade 100644 --- a/drivers/media/usb/dvb-usb/dibusb.h +++ b/drivers/media/usb/dvb-usb/dibusb.h @@ -96,6 +96,9 @@  #define DIBUSB_IOCTL_CMD_ENABLE_STREAM	0x01  #define DIBUSB_IOCTL_CMD_DISABLE_STREAM	0x02 +/* Max transfer size done by I2C transfer functions */ +#define MAX_XFER_SIZE  64 +  struct dibusb_state {  	struct dib_fe_xfer_ops ops;  	int mt2060_present; diff --git a/drivers/media/usb/dvb-usb/digitv.c b/drivers/media/usb/dvb-usb/digitv.c index 63134335c994..4284f6984dc1 100644 --- a/drivers/media/usb/dvb-usb/digitv.c +++ b/drivers/media/usb/dvb-usb/digitv.c @@ -28,22 +28,26 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);  static int digitv_ctrl_msg(struct dvb_usb_device *d,  		u8 cmd, u8 vv, u8 *wbuf, int wlen, u8 *rbuf, int rlen)  { -	int wo = (rbuf == NULL || rlen == 0); /* write-only */ -	u8 sndbuf[7],rcvbuf[7]; -	memset(sndbuf,0,7); memset(rcvbuf,0,7); +	struct digitv_state *st = d->priv; +	int ret, wo; -	sndbuf[0] = cmd; -	sndbuf[1] = vv; -	sndbuf[2] = wo ? wlen : rlen; +	wo = (rbuf == NULL || rlen == 0); /* write-only */ + +	memset(st->sndbuf, 0, 7); +	memset(st->rcvbuf, 0, 7); + +	st->sndbuf[0] = cmd; +	st->sndbuf[1] = vv; +	st->sndbuf[2] = wo ? wlen : rlen;  	if (wo) { -		memcpy(&sndbuf[3],wbuf,wlen); -		dvb_usb_generic_write(d,sndbuf,7); +		memcpy(&st->sndbuf[3], wbuf, wlen); +		ret = dvb_usb_generic_write(d, st->sndbuf, 7);  	} else { -		dvb_usb_generic_rw(d,sndbuf,7,rcvbuf,7,10); -		memcpy(rbuf,&rcvbuf[3],rlen); +		ret = dvb_usb_generic_rw(d, st->sndbuf, 7, st->rcvbuf, 7, 10); +		memcpy(rbuf, &st->rcvbuf[3], rlen);  	} -	return 0; +	return ret;  }  /* I2C */ diff --git a/drivers/media/usb/dvb-usb/digitv.h b/drivers/media/usb/dvb-usb/digitv.h index 908c09f4966b..581e09c25491 100644 --- a/drivers/media/usb/dvb-usb/digitv.h +++ b/drivers/media/usb/dvb-usb/digitv.h @@ -5,7 +5,10 @@  #include "dvb-usb.h"  struct digitv_state { -    int is_nxt6000; +	int is_nxt6000; + +	unsigned char sndbuf[7]; +	unsigned char rcvbuf[7];  };  /* protocol (from usblogging and the SDK: diff --git a/drivers/media/usb/dvb-usb/dtt200u-fe.c b/drivers/media/usb/dvb-usb/dtt200u-fe.c index c09332bd99cb..f5c042baa254 100644 --- a/drivers/media/usb/dvb-usb/dtt200u-fe.c +++ b/drivers/media/usb/dvb-usb/dtt200u-fe.c @@ -18,17 +18,28 @@ struct dtt200u_fe_state {  	struct dtv_frontend_properties fep;  	struct dvb_frontend frontend; + +	unsigned char data[80]; +	struct mutex data_mutex;  };  static int dtt200u_fe_read_status(struct dvb_frontend *fe,  				  enum fe_status *stat)  {  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	u8 st = GET_TUNE_STATUS, b[3]; +	int ret; + +	mutex_lock(&state->data_mutex); +	state->data[0] = GET_TUNE_STATUS; -	dvb_usb_generic_rw(state->d,&st,1,b,3,0); +	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0); +	if (ret < 0) { +		*stat = 0; +		mutex_unlock(&state->data_mutex); +		return ret; +	} -	switch (b[0]) { +	switch (state->data[0]) {  		case 0x01:  			*stat = FE_HAS_SIGNAL | FE_HAS_CARRIER |  				FE_HAS_VITERBI | FE_HAS_SYNC | FE_HAS_LOCK; @@ -41,51 +52,86 @@ static int dtt200u_fe_read_status(struct dvb_frontend *fe,  			*stat = 0;  			break;  	} +	mutex_unlock(&state->data_mutex);  	return 0;  }  static int dtt200u_fe_read_ber(struct dvb_frontend* fe, u32 *ber)  {  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	u8 bw = GET_VIT_ERR_CNT,b[3]; -	dvb_usb_generic_rw(state->d,&bw,1,b,3,0); -	*ber = (b[0] << 16) | (b[1] << 8) | b[2]; -	return 0; +	int ret; + +	mutex_lock(&state->data_mutex); +	state->data[0] = GET_VIT_ERR_CNT; + +	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 3, 0); +	if (ret >= 0) +		*ber = (state->data[0] << 16) | (state->data[1] << 8) | state->data[2]; + +	mutex_unlock(&state->data_mutex); +	return ret;  }  static int dtt200u_fe_read_unc_blocks(struct dvb_frontend* fe, u32 *unc)  {  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	u8 bw = GET_RS_UNCOR_BLK_CNT,b[2]; +	int ret; -	dvb_usb_generic_rw(state->d,&bw,1,b,2,0); -	*unc = (b[0] << 8) | b[1]; -	return 0; +	mutex_lock(&state->data_mutex); +	state->data[0] = GET_RS_UNCOR_BLK_CNT; + +	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 2, 0); +	if (ret >= 0) +		*unc = (state->data[0] << 8) | state->data[1]; + +	mutex_unlock(&state->data_mutex); +	return ret;  }  static int dtt200u_fe_read_signal_strength(struct dvb_frontend* fe, u16 *strength)  {  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	u8 bw = GET_AGC, b; -	dvb_usb_generic_rw(state->d,&bw,1,&b,1,0); -	*strength = (b << 8) | b; -	return 0; +	int ret; + +	mutex_lock(&state->data_mutex); +	state->data[0] = GET_AGC; + +	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0); +	if (ret >= 0) +		*strength = (state->data[0] << 8) | state->data[0]; + +	mutex_unlock(&state->data_mutex); +	return ret;  }  static int dtt200u_fe_read_snr(struct dvb_frontend* fe, u16 *snr)  {  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	u8 bw = GET_SNR,br; -	dvb_usb_generic_rw(state->d,&bw,1,&br,1,0); -	*snr = ~((br << 8) | br); -	return 0; +	int ret; + +	mutex_lock(&state->data_mutex); +	state->data[0] = GET_SNR; + +	ret = dvb_usb_generic_rw(state->d, state->data, 1, state->data, 1, 0); +	if (ret >= 0) +		*snr = ~((state->data[0] << 8) | state->data[0]); + +	mutex_unlock(&state->data_mutex); +	return ret;  }  static int dtt200u_fe_init(struct dvb_frontend* fe)  {  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	u8 b = SET_INIT; -	return dvb_usb_generic_write(state->d,&b,1); +	int ret; + +	mutex_lock(&state->data_mutex); +	state->data[0] = SET_INIT; + +	ret = dvb_usb_generic_write(state->d, state->data, 1); +	mutex_unlock(&state->data_mutex); + +	return ret;  }  static int dtt200u_fe_sleep(struct dvb_frontend* fe) @@ -105,39 +151,40 @@ static int dtt200u_fe_set_frontend(struct dvb_frontend *fe)  {  	struct dtv_frontend_properties *fep = &fe->dtv_property_cache;  	struct dtt200u_fe_state *state = fe->demodulator_priv; -	int i; -	enum fe_status st; +	int ret;  	u16 freq = fep->frequency / 250000; -	u8 bwbuf[2] = { SET_BANDWIDTH, 0 },freqbuf[3] = { SET_RF_FREQ, 0, 0 }; +	mutex_lock(&state->data_mutex); +	state->data[0] = SET_BANDWIDTH;  	switch (fep->bandwidth_hz) {  	case 8000000: -		bwbuf[1] = 8; +		state->data[1] = 8;  		break;  	case 7000000: -		bwbuf[1] = 7; +		state->data[1] = 7;  		break;  	case 6000000: -		bwbuf[1] = 6; +		state->data[1] = 6;  		break;  	default: -		return -EINVAL; +		ret = -EINVAL; +		goto ret;  	} -	dvb_usb_generic_write(state->d,bwbuf,2); +	ret = dvb_usb_generic_write(state->d, state->data, 2); +	if (ret < 0) +		goto ret; -	freqbuf[1] = freq & 0xff; -	freqbuf[2] = (freq >> 8) & 0xff; -	dvb_usb_generic_write(state->d,freqbuf,3); +	state->data[0] = SET_RF_FREQ; +	state->data[1] = freq & 0xff; +	state->data[2] = (freq >> 8) & 0xff; +	ret = dvb_usb_generic_write(state->d, state->data, 3); +	if (ret < 0) +		goto ret; -	for (i = 0; i < 30; i++) { -		msleep(20); -		dtt200u_fe_read_status(fe, &st); -		if (st & FE_TIMEDOUT) -			continue; -	} - -	return 0; +ret: +	mutex_unlock(&state->data_mutex); +	return ret;  }  static int dtt200u_fe_get_frontend(struct dvb_frontend* fe, @@ -169,6 +216,7 @@ struct dvb_frontend* dtt200u_fe_attach(struct dvb_usb_device *d)  	deb_info("attaching frontend dtt200u\n");  	state->d = d; +	mutex_init(&state->data_mutex);  	memcpy(&state->frontend.ops,&dtt200u_fe_ops,sizeof(struct dvb_frontend_ops));  	state->frontend.demodulator_priv = state; diff --git a/drivers/media/usb/dvb-usb/dtt200u.c b/drivers/media/usb/dvb-usb/dtt200u.c index d2a01b50af0d..f88572c7ae7c 100644 --- a/drivers/media/usb/dvb-usb/dtt200u.c +++ b/drivers/media/usb/dvb-usb/dtt200u.c @@ -20,75 +20,114 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2 (or-able))." DVB_USB  DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +struct dtt200u_state { +	unsigned char data[80]; +	struct mutex data_mutex; +}; +  static int dtt200u_power_ctrl(struct dvb_usb_device *d, int onoff)  { -	u8 b = SET_INIT; +	struct dtt200u_state *st = d->priv; +	int ret = 0; + +	mutex_lock(&st->data_mutex); + +	st->data[0] = SET_INIT;  	if (onoff) -		dvb_usb_generic_write(d,&b,2); +		ret = dvb_usb_generic_write(d, st->data, 2); -	return 0; +	mutex_unlock(&st->data_mutex); +	return ret;  }  static int dtt200u_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)  { -	u8 b_streaming[2] = { SET_STREAMING, onoff }; -	u8 b_rst_pid = RESET_PID_FILTER; +	struct dtt200u_state *st = adap->dev->priv; +	int ret; -	dvb_usb_generic_write(adap->dev, b_streaming, 2); +	mutex_lock(&st->data_mutex); +	st->data[0] = SET_STREAMING; +	st->data[1] = onoff; -	if (onoff == 0) -		dvb_usb_generic_write(adap->dev, &b_rst_pid, 1); -	return 0; +	ret = dvb_usb_generic_write(adap->dev, st->data, 2); +	if (ret < 0) +		goto ret; + +	if (onoff) +		goto ret; + +	st->data[0] = RESET_PID_FILTER; +	ret = dvb_usb_generic_write(adap->dev, st->data, 1); + +ret: +	mutex_unlock(&st->data_mutex); + +	return ret;  }  static int dtt200u_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid, int onoff)  { -	u8 b_pid[4]; +	struct dtt200u_state *st = adap->dev->priv; +	int ret; +  	pid = onoff ? pid : 0; -	b_pid[0] = SET_PID_FILTER; -	b_pid[1] = index; -	b_pid[2] = pid & 0xff; -	b_pid[3] = (pid >> 8) & 0x1f; +	mutex_lock(&st->data_mutex); +	st->data[0] = SET_PID_FILTER; +	st->data[1] = index; +	st->data[2] = pid & 0xff; +	st->data[3] = (pid >> 8) & 0x1f; -	return dvb_usb_generic_write(adap->dev, b_pid, 4); +	ret = dvb_usb_generic_write(adap->dev, st->data, 4); +	mutex_unlock(&st->data_mutex); + +	return ret;  }  static int dtt200u_rc_query(struct dvb_usb_device *d)  { -	u8 key[5],cmd = GET_RC_CODE; +	struct dtt200u_state *st = d->priv;  	u32 scancode; +	int ret; + +	mutex_lock(&st->data_mutex); +	st->data[0] = GET_RC_CODE; + +	ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 5, 0); +	if (ret < 0) +		goto ret; -	dvb_usb_generic_rw(d,&cmd,1,key,5,0); -	if (key[0] == 1) { +	if (st->data[0] == 1) {  		enum rc_type proto = RC_TYPE_NEC; -		scancode = key[1]; -		if ((u8) ~key[1] != key[2]) { +		scancode = st->data[1]; +		if ((u8) ~st->data[1] != st->data[2]) {  			/* Extended NEC */  			scancode = scancode << 8; -			scancode |= key[2]; +			scancode |= st->data[2];  			proto = RC_TYPE_NECX;  		}  		scancode = scancode << 8; -		scancode |= key[3]; +		scancode |= st->data[3];  		/* Check command checksum is ok */ -		if ((u8) ~key[3] == key[4]) +		if ((u8) ~st->data[3] == st->data[4])  			rc_keydown(d->rc_dev, proto, scancode, 0);  		else  			rc_keyup(d->rc_dev); -	} else if (key[0] == 2) { +	} else if (st->data[0] == 2) {  		rc_repeat(d->rc_dev);  	} else {  		rc_keyup(d->rc_dev);  	} -	if (key[0] != 0) -		deb_info("key: %*ph\n", 5, key); +	if (st->data[0] != 0) +		deb_info("st->data: %*ph\n", 5, st->data); -	return 0; +ret: +	mutex_unlock(&st->data_mutex); +	return ret;  }  static int dtt200u_frontend_attach(struct dvb_usb_adapter *adap) @@ -106,17 +145,24 @@ static struct dvb_usb_device_properties wt220u_miglia_properties;  static int dtt200u_usb_probe(struct usb_interface *intf,  		const struct usb_device_id *id)  { +	struct dvb_usb_device *d; +	struct dtt200u_state *st; +  	if (0 == dvb_usb_device_init(intf, &dtt200u_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &wt220u_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &wt220u_fc_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &wt220u_zl0353_properties, -				     THIS_MODULE, NULL, adapter_nr) || +				     THIS_MODULE, &d, adapter_nr) ||  	    0 == dvb_usb_device_init(intf, &wt220u_miglia_properties, -				     THIS_MODULE, NULL, adapter_nr)) +				     THIS_MODULE, &d, adapter_nr)) { +		st = d->priv; +		mutex_init(&st->data_mutex); +  		return 0; +	}  	return -ENODEV;  } @@ -140,6 +186,8 @@ static struct dvb_usb_device_properties dtt200u_properties = {  	.usb_ctrl = CYPRESS_FX2,  	.firmware = "dvb-usb-dtt200u-01.fw", +	.size_of_priv     = sizeof(struct dtt200u_state), +  	.num_adapters = 1,  	.adapter = {  		{ @@ -190,6 +238,8 @@ static struct dvb_usb_device_properties wt220u_properties = {  	.usb_ctrl = CYPRESS_FX2,  	.firmware = "dvb-usb-wt220u-02.fw", +	.size_of_priv     = sizeof(struct dtt200u_state), +  	.num_adapters = 1,  	.adapter = {  		{ @@ -240,6 +290,8 @@ static struct dvb_usb_device_properties wt220u_fc_properties = {  	.usb_ctrl = CYPRESS_FX2,  	.firmware = "dvb-usb-wt220u-fc03.fw", +	.size_of_priv     = sizeof(struct dtt200u_state), +  	.num_adapters = 1,  	.adapter = {  		{ @@ -290,6 +342,8 @@ static struct dvb_usb_device_properties wt220u_zl0353_properties = {  	.usb_ctrl = CYPRESS_FX2,  	.firmware = "dvb-usb-wt220u-zl0353-01.fw", +	.size_of_priv     = sizeof(struct dtt200u_state), +  	.num_adapters = 1,  	.adapter = {  		{ @@ -340,6 +394,8 @@ static struct dvb_usb_device_properties wt220u_miglia_properties = {  	.usb_ctrl = CYPRESS_FX2,  	.firmware = "dvb-usb-wt220u-miglia-01.fw", +	.size_of_priv     = sizeof(struct dtt200u_state), +  	.num_adapters = 1,  	.generic_bulk_ctrl_endpoint = 0x01, diff --git a/drivers/media/usb/dvb-usb/dtv5100.c b/drivers/media/usb/dvb-usb/dtv5100.c index 3d11df41cac0..c60fb54f445f 100644 --- a/drivers/media/usb/dvb-usb/dtv5100.c +++ b/drivers/media/usb/dvb-usb/dtv5100.c @@ -31,9 +31,14 @@ module_param_named(debug, dvb_usb_dtv5100_debug, int, 0644);  MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);  DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +struct dtv5100_state { +	unsigned char data[80]; +}; +  static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,  			   u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)  { +	struct dtv5100_state *st = d->priv;  	u8 request;  	u8 type;  	u16 value; @@ -60,9 +65,10 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,  	}  	index = (addr << 8) + wbuf[0]; +	memcpy(st->data, rbuf, rlen);  	msleep(1); /* avoid I2C errors */  	return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, -			       type, value, index, rbuf, rlen, +			       type, value, index, st->data, rlen,  			       DTV5100_USB_TIMEOUT);  } @@ -176,7 +182,7 @@ static struct dvb_usb_device_properties dtv5100_properties = {  	.caps = DVB_USB_IS_AN_I2C_ADAPTER,  	.usb_ctrl = DEVICE_SPECIFIC, -	.size_of_priv = 0, +	.size_of_priv = sizeof(struct dtv5100_state),  	.num_adapters = 1,  	.adapter = {{ diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 5fb0c650926e..2c720cb2fb00 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -852,7 +852,7 @@ static int su3000_power_ctrl(struct dvb_usb_device *d, int i)  	if (i && !state->initialized) {  		state->initialized = 1;  		/* reset board */ -		dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0); +		return dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);  	}  	return 0; diff --git a/drivers/media/usb/dvb-usb/gp8psk.c b/drivers/media/usb/dvb-usb/gp8psk.c index 5d0384dd45b5..adfd76491451 100644 --- a/drivers/media/usb/dvb-usb/gp8psk.c +++ b/drivers/media/usb/dvb-usb/gp8psk.c @@ -24,6 +24,10 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))." DV  DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); +struct gp8psk_state { +	unsigned char data[80]; +}; +  static int gp8psk_get_fw_version(struct dvb_usb_device *d, u8 *fw_vers)  {  	return (gp8psk_usb_in_op(d, GET_FW_VERS, 0, 0, fw_vers, 6)); @@ -53,17 +57,22 @@ static void gp8psk_info(struct dvb_usb_device *d)  int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8 *b, int blen)  { +	struct gp8psk_state *st = d->priv;  	int ret = 0,try = 0; +	if (blen > sizeof(st->data)) +		return -EIO; +  	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))  		return ret;  	while (ret >= 0 && ret != blen && try < 3) { +		memcpy(st->data, b, blen);  		ret = usb_control_msg(d->udev,  			usb_rcvctrlpipe(d->udev,0),  			req,  			USB_TYPE_VENDOR | USB_DIR_IN, -			value,index,b,blen, +			value, index, st->data, blen,  			2000);  		deb_info("reading number %d (ret: %d)\n",try,ret);  		try++; @@ -86,19 +95,24 @@ int gp8psk_usb_in_op(struct dvb_usb_device *d, u8 req, u16 value, u16 index, u8  int gp8psk_usb_out_op(struct dvb_usb_device *d, u8 req, u16 value,  			     u16 index, u8 *b, int blen)  { +	struct gp8psk_state *st = d->priv;  	int ret;  	deb_xfer("out: req. %x, val: %x, ind: %x, buffer: ",req,value,index);  	debug_dump(b,blen,deb_xfer); +	if (blen > sizeof(st->data)) +		return -EIO; +  	if ((ret = mutex_lock_interruptible(&d->usb_mutex)))  		return ret; +	memcpy(st->data, b, blen);  	if (usb_control_msg(d->udev,  			usb_sndctrlpipe(d->udev,0),  			req,  			USB_TYPE_VENDOR | USB_DIR_OUT, -			value,index,b,blen, +			value, index, st->data, blen,  			2000) != blen) {  		warn("usb out operation failed.");  		ret = -EIO; @@ -143,6 +157,11 @@ static int gp8psk_load_bcm4500fw(struct dvb_usb_device *d)  			err("failed to load bcm4500 firmware.");  			goto out_free;  		} +		if (buflen > 64) { +			err("firmare chunk size bigger than 64 bytes."); +			goto out_free; +		} +  		memcpy(buf, ptr, buflen);  		if (dvb_usb_generic_write(d, buf, buflen)) {  			err("failed to load bcm4500 firmware."); @@ -265,6 +284,8 @@ static struct dvb_usb_device_properties gp8psk_properties = {  	.usb_ctrl = CYPRESS_FX2,  	.firmware = "dvb-usb-gp8psk-01.fw", +	.size_of_priv = sizeof(struct gp8psk_state), +  	.num_adapters = 1,  	.adapter = {  		{ diff --git a/drivers/media/usb/dvb-usb/nova-t-usb2.c b/drivers/media/usb/dvb-usb/nova-t-usb2.c index fc7569e2728d..1babd3341910 100644 --- a/drivers/media/usb/dvb-usb/nova-t-usb2.c +++ b/drivers/media/usb/dvb-usb/nova-t-usb2.c @@ -74,22 +74,31 @@ static struct rc_map_table rc_map_haupp_table[] = {   */  static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)  { -	u8 key[5],cmd[2] = { DIBUSB_REQ_POLL_REMOTE, 0x35 }, data,toggle,custom; +	u8 *buf, data, toggle, custom;  	u16 raw; -	int i; +	int i, ret;  	struct dibusb_device_state *st = d->priv; -	dvb_usb_generic_rw(d,cmd,2,key,5,0); +	buf = kmalloc(5, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	buf[0] = DIBUSB_REQ_POLL_REMOTE; +	buf[1] = 0x35; +	ret = dvb_usb_generic_rw(d, buf, 2, buf, 5, 0); +	if (ret < 0) +		goto ret;  	*state = REMOTE_NO_KEY_PRESSED; -	switch (key[0]) { +	switch (buf[0]) {  		case DIBUSB_RC_HAUPPAUGE_KEY_PRESSED: -			raw = ((key[1] << 8) | key[2]) >> 3; +			raw = ((buf[1] << 8) | buf[2]) >> 3;  			toggle = !!(raw & 0x800);  			data = raw & 0x3f;  			custom = (raw >> 6) & 0x1f; -			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n",key[1],key[2],key[3],custom,data,toggle); +			deb_rc("raw key code 0x%02x, 0x%02x, 0x%02x to c: %02x d: %02x toggle: %d\n", +			       buf[1], buf[2], buf[3], custom, data, toggle);  			for (i = 0; i < ARRAY_SIZE(rc_map_haupp_table); i++) {  				if (rc5_data(&rc_map_haupp_table[i]) == data && @@ -117,7 +126,9 @@ static int nova_t_rc_query(struct dvb_usb_device *d, u32 *event, int *state)  			break;  	} -	return 0; +ret: +	kfree(buf); +	return ret;  }  static int nova_t_read_mac_address (struct dvb_usb_device *d, u8 mac[6]) diff --git a/drivers/media/usb/dvb-usb/pctv452e.c b/drivers/media/usb/dvb-usb/pctv452e.c index c05de1b088a4..07fa08be9e99 100644 --- a/drivers/media/usb/dvb-usb/pctv452e.c +++ b/drivers/media/usb/dvb-usb/pctv452e.c @@ -97,48 +97,53 @@ struct pctv452e_state {  	u8 c;	   /* transaction counter, wraps around...  */  	u8 initialized; /* set to 1 if 0x15 has been sent */  	u16 last_rc_key; + +	unsigned char data[80];  };  static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,  			 unsigned int write_len, unsigned int read_len)  {  	struct pctv452e_state *state = (struct pctv452e_state *)d->priv; -	u8 buf[64];  	u8 id;  	unsigned int rlen;  	int ret; -	BUG_ON(NULL == data && 0 != (write_len | read_len)); -	BUG_ON(write_len > 64 - 4); -	BUG_ON(read_len > 64 - 4); +	if (!data || (write_len > 64 - 4) || (read_len > 64 - 4)) { +		err("%s: transfer data invalid", __func__); +		return -EIO; +	} +	mutex_lock(&state->ca_mutex);  	id = state->c++; -	buf[0] = SYNC_BYTE_OUT; -	buf[1] = id; -	buf[2] = cmd; -	buf[3] = write_len; +	state->data[0] = SYNC_BYTE_OUT; +	state->data[1] = id; +	state->data[2] = cmd; +	state->data[3] = write_len; -	memcpy(buf + 4, data, write_len); +	memcpy(state->data + 4, data, write_len);  	rlen = (read_len > 0) ? 64 : 0; -	ret = dvb_usb_generic_rw(d, buf, 4 + write_len, -				  buf, rlen, /* delay_ms */ 0); +	ret = dvb_usb_generic_rw(d, state->data, 4 + write_len, +				  state->data, rlen, /* delay_ms */ 0);  	if (0 != ret)  		goto failed;  	ret = -EIO; -	if (SYNC_BYTE_IN != buf[0] || id != buf[1]) +	if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])  		goto failed; -	memcpy(data, buf + 4, read_len); +	memcpy(data, state->data + 4, read_len); +	mutex_unlock(&state->ca_mutex);  	return 0;  failed:  	err("CI error %d; %02X %02X %02X -> %*ph.", -	     ret, SYNC_BYTE_OUT, id, cmd, 3, buf); +	     ret, SYNC_BYTE_OUT, id, cmd, 3, state->data); +	mutex_unlock(&state->ca_mutex);  	return ret;  } @@ -405,52 +410,53 @@ static int pctv452e_i2c_msg(struct dvb_usb_device *d, u8 addr,  				u8 *rcv_buf, u8 rcv_len)  {  	struct pctv452e_state *state = (struct pctv452e_state *)d->priv; -	u8 buf[64];  	u8 id;  	int ret; +	mutex_lock(&state->ca_mutex);  	id = state->c++;  	ret = -EINVAL;  	if (snd_len > 64 - 7 || rcv_len > 64 - 7)  		goto failed; -	buf[0] = SYNC_BYTE_OUT; -	buf[1] = id; -	buf[2] = PCTV_CMD_I2C; -	buf[3] = snd_len + 3; -	buf[4] = addr << 1; -	buf[5] = snd_len; -	buf[6] = rcv_len; +	state->data[0] = SYNC_BYTE_OUT; +	state->data[1] = id; +	state->data[2] = PCTV_CMD_I2C; +	state->data[3] = snd_len + 3; +	state->data[4] = addr << 1; +	state->data[5] = snd_len; +	state->data[6] = rcv_len; -	memcpy(buf + 7, snd_buf, snd_len); +	memcpy(state->data + 7, snd_buf, snd_len); -	ret = dvb_usb_generic_rw(d, buf, 7 + snd_len, -				  buf, /* rcv_len */ 64, +	ret = dvb_usb_generic_rw(d, state->data, 7 + snd_len, +				  state->data, /* rcv_len */ 64,  				  /* delay_ms */ 0);  	if (ret < 0)  		goto failed;  	/* TT USB protocol error. */  	ret = -EIO; -	if (SYNC_BYTE_IN != buf[0] || id != buf[1]) +	if (SYNC_BYTE_IN != state->data[0] || id != state->data[1])  		goto failed;  	/* I2C device didn't respond as expected. */  	ret = -EREMOTEIO; -	if (buf[5] < snd_len || buf[6] < rcv_len) +	if (state->data[5] < snd_len || state->data[6] < rcv_len)  		goto failed; -	memcpy(rcv_buf, buf + 7, rcv_len); +	memcpy(rcv_buf, state->data + 7, rcv_len); +	mutex_unlock(&state->ca_mutex);  	return rcv_len;  failed: -	err("I2C error %d; %02X %02X  %02X %02X %02X -> " -	     "%02X %02X  %02X %02X %02X.", +	err("I2C error %d; %02X %02X  %02X %02X %02X -> %*ph",  	     ret, SYNC_BYTE_OUT, id, addr << 1, snd_len, rcv_len, -	     buf[0], buf[1], buf[4], buf[5], buf[6]); +	     7, state->data); +	mutex_unlock(&state->ca_mutex);  	return ret;  } @@ -499,8 +505,7 @@ static u32 pctv452e_i2c_func(struct i2c_adapter *adapter)  static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)  {  	struct pctv452e_state *state = (struct pctv452e_state *)d->priv; -	u8 b0[] = { 0xaa, 0, PCTV_CMD_RESET, 1, 0 }; -	u8 rx[PCTV_ANSWER_LEN]; +	u8 *rx;  	int ret;  	info("%s: %d\n", __func__, i); @@ -511,6 +516,11 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)  	if (state->initialized)  		return 0; +	rx = kmalloc(PCTV_ANSWER_LEN, GFP_KERNEL); +	if (!rx) +		return -ENOMEM; + +	mutex_lock(&state->ca_mutex);  	/* hmm where shoud this should go? */  	ret = usb_set_interface(d->udev, 0, ISOC_INTERFACE_ALTERNATIVE);  	if (ret != 0) @@ -518,65 +528,75 @@ static int pctv452e_power_ctrl(struct dvb_usb_device *d, int i)  			__func__, ret);  	/* this is a one-time initialization, dont know where to put */ -	b0[1] = state->c++; +	state->data[0] = 0xaa; +	state->data[1] = state->c++; +	state->data[2] = PCTV_CMD_RESET; +	state->data[3] = 1; +	state->data[4] = 0;  	/* reset board */ -	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); +	ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);  	if (ret) -		return ret; +		goto ret; -	b0[1] = state->c++; -	b0[4] = 1; +	state->data[1] = state->c++; +	state->data[4] = 1;  	/* reset board (again?) */ -	ret = dvb_usb_generic_rw(d, b0, sizeof(b0), rx, PCTV_ANSWER_LEN, 0); +	ret = dvb_usb_generic_rw(d, state->data, 5, rx, PCTV_ANSWER_LEN, 0);  	if (ret) -		return ret; +		goto ret;  	state->initialized = 1; -	return 0; +ret: +	mutex_unlock(&state->ca_mutex); +	kfree(rx); +	return ret;  }  static int pctv452e_rc_query(struct dvb_usb_device *d)  {  	struct pctv452e_state *state = (struct pctv452e_state *)d->priv; -	u8 b[CMD_BUFFER_SIZE]; -	u8 rx[PCTV_ANSWER_LEN];  	int ret, i; -	u8 id = state->c++; +	u8 id; + +	mutex_lock(&state->ca_mutex); +	id = state->c++;  	/* prepare command header  */ -	b[0] = SYNC_BYTE_OUT; -	b[1] = id; -	b[2] = PCTV_CMD_IR; -	b[3] = 0; +	state->data[0] = SYNC_BYTE_OUT; +	state->data[1] = id; +	state->data[2] = PCTV_CMD_IR; +	state->data[3] = 0;  	/* send ir request */ -	ret = dvb_usb_generic_rw(d, b, 4, rx, PCTV_ANSWER_LEN, 0); +	ret = dvb_usb_generic_rw(d, state->data, 4, +				 state->data, PCTV_ANSWER_LEN, 0);  	if (ret != 0) -		return ret; +		goto ret;  	if (debug > 3) { -		info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx); -		for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++) -			info(" %02x", rx[i+3]); +		info("%s: read: %2d: %*ph: ", __func__, ret, 3, state->data); +		for (i = 0; (i < state->data[3]) && ((i + 3) < PCTV_ANSWER_LEN); i++) +			info(" %02x", state->data[i + 3]);  		info("\n");  	} -	if ((rx[3] == 9) &&  (rx[12] & 0x01)) { +	if ((state->data[3] == 9) &&  (state->data[12] & 0x01)) {  		/* got a "press" event */ -		state->last_rc_key = RC_SCANCODE_RC5(rx[7], rx[6]); +		state->last_rc_key = RC_SCANCODE_RC5(state->data[7], state->data[6]);  		if (debug > 2)  			info("%s: cmd=0x%02x sys=0x%02x\n", -				__func__, rx[6], rx[7]); +				__func__, state->data[6], state->data[7]);  		rc_keydown(d->rc_dev, RC_TYPE_RC5, state->last_rc_key, 0);  	} else if (state->last_rc_key) {  		rc_keyup(d->rc_dev);  		state->last_rc_key = 0;  	} - -	return 0; +ret: +	mutex_unlock(&state->ca_mutex); +	return ret;  }  static int pctv452e_read_mac_address(struct dvb_usb_device *d, u8 mac[6]) diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c index d9f3262bf071..4706628a3ed5 100644 --- a/drivers/media/usb/dvb-usb/technisat-usb2.c +++ b/drivers/media/usb/dvb-usb/technisat-usb2.c @@ -89,9 +89,13 @@ struct technisat_usb2_state {  static int technisat_usb2_i2c_access(struct usb_device *udev,  		u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)  { -	u8 b[64]; +	u8 *b;  	int ret, actual_length; +	b = kmalloc(64, GFP_KERNEL); +	if (!b) +		return -ENOMEM; +  	deb_i2c("i2c-access: %02x, tx: ", device_addr);  	debug_dump(tx, txlen, deb_i2c);  	deb_i2c(" "); @@ -123,7 +127,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,  	if (ret < 0) {  		err("i2c-error: out failed %02x = %d", device_addr, ret); -		return -ENODEV; +		goto err;  	}  	ret = usb_bulk_msg(udev, @@ -131,7 +135,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,  			b, 64, &actual_length, 1000);  	if (ret < 0) {  		err("i2c-error: in failed %02x = %d", device_addr, ret); -		return -ENODEV; +		goto err;  	}  	if (b[0] != I2C_STATUS_OK) { @@ -140,7 +144,7 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,  		if (!(b[0] == I2C_STATUS_NAK &&  				device_addr == 0x60  				/* && device_is_technisat_usb2 */)) -			return -ENODEV; +			goto err;  	}  	deb_i2c("status: %d, ", b[0]); @@ -154,7 +158,9 @@ static int technisat_usb2_i2c_access(struct usb_device *udev,  	deb_i2c("\n"); -	return 0; +err: +	kfree(b); +	return ret;  }  static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c index c3a0e87066eb..f7bb78c1873c 100644 --- a/drivers/media/usb/s2255/s2255drv.c +++ b/drivers/media/usb/s2255/s2255drv.c @@ -1901,19 +1901,30 @@ static long s2255_vendor_req(struct s2255_dev *dev, unsigned char Request,  			     s32 TransferBufferLength, int bOut)  {  	int r; +	unsigned char *buf; + +	buf = kmalloc(TransferBufferLength, GFP_KERNEL); +	if (!buf) +		return -ENOMEM; +  	if (!bOut) {  		r = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),  				    Request,  				    USB_TYPE_VENDOR | USB_RECIP_DEVICE |  				    USB_DIR_IN, -				    Value, Index, TransferBuffer, +				    Value, Index, buf,  				    TransferBufferLength, HZ * 5); + +		if (r >= 0) +			memcpy(TransferBuffer, buf, TransferBufferLength);  	} else { +		memcpy(buf, TransferBuffer, TransferBufferLength);  		r = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),  				    Request, USB_TYPE_VENDOR | USB_RECIP_DEVICE, -				    Value, Index, TransferBuffer, +				    Value, Index, buf,  				    TransferBufferLength, HZ * 5);  	} +	kfree(buf);  	return r;  } diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index db200c9d796d..22a9aae16291 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -147,20 +147,26 @@ int stk_camera_write_reg(struct stk_camera *dev, u16 index, u8 value)  int stk_camera_read_reg(struct stk_camera *dev, u16 index, int *value)  {  	struct usb_device *udev = dev->udev; +	unsigned char *buf;  	int ret; +	buf = kmalloc(sizeof(u8), GFP_KERNEL); +	if (!buf) +		return -ENOMEM; +  	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),  			0x00,  			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,  			0x00,  			index, -			(u8 *) value, +			buf,  			sizeof(u8),  			500); -	if (ret < 0) -		return ret; -	else -		return 0; +	if (ret >= 0) +		memcpy(value, buf, sizeof(u8)); + +	kfree(buf); +	return ret;  }  static int stk_start_stream(struct stk_camera *dev) diff --git a/drivers/mmc/host/dw_mmc-pltfm.c b/drivers/mmc/host/dw_mmc-pltfm.c index c0bb0c793e84..dbbc4303bdd0 100644 --- a/drivers/mmc/host/dw_mmc-pltfm.c +++ b/drivers/mmc/host/dw_mmc-pltfm.c @@ -46,12 +46,13 @@ int dw_mci_pltfm_register(struct platform_device *pdev,  	host->pdata = pdev->dev.platform_data;  	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	/* Get registers' physical base address */ -	host->phy_regs = regs->start;  	host->regs = devm_ioremap_resource(&pdev->dev, regs);  	if (IS_ERR(host->regs))  		return PTR_ERR(host->regs); +	/* Get registers' physical base address */ +	host->phy_regs = regs->start; +  	platform_set_drvdata(pdev, host);  	return dw_mci_probe(host);  } diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c index 8ef44a2a2fd9..90ed2e12d345 100644 --- a/drivers/mmc/host/sdhci-msm.c +++ b/drivers/mmc/host/sdhci-msm.c @@ -647,6 +647,7 @@ static int sdhci_msm_probe(struct platform_device *pdev)  	if (msm_host->pwr_irq < 0) {  		dev_err(&pdev->dev, "Get pwr_irq failed (%d)\n",  			msm_host->pwr_irq); +		ret = msm_host->pwr_irq;  		goto clk_disable;  	} diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c index 0f68a99fc4ad..141bd70a49c2 100644 --- a/drivers/mtd/nand/gpmi-nand/gpmi-lib.c +++ b/drivers/mtd/nand/gpmi-nand/gpmi-lib.c @@ -161,7 +161,7 @@ int gpmi_init(struct gpmi_nand_data *this)  	ret = gpmi_enable_clk(this);  	if (ret) -		goto err_out; +		return ret;  	ret = gpmi_reset_block(r->gpmi_regs, false);  	if (ret)  		goto err_out; @@ -197,6 +197,7 @@ int gpmi_init(struct gpmi_nand_data *this)  	gpmi_disable_clk(this);  	return 0;  err_out: +	gpmi_disable_clk(this);  	return ret;  } @@ -270,7 +271,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)  	ret = gpmi_enable_clk(this);  	if (ret) -		goto err_out; +		return ret;  	/*  	* Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this @@ -308,6 +309,7 @@ int bch_set_geometry(struct gpmi_nand_data *this)  	gpmi_disable_clk(this);  	return 0;  err_out: +	gpmi_disable_clk(this);  	return ret;  } diff --git a/drivers/mtd/nand/mtk_ecc.c b/drivers/mtd/nand/mtk_ecc.c index d54f666417e1..dbf256217b3e 100644 --- a/drivers/mtd/nand/mtk_ecc.c +++ b/drivers/mtd/nand/mtk_ecc.c @@ -86,6 +86,8 @@ struct mtk_ecc {  	struct completion done;  	struct mutex lock;  	u32 sectors; + +	u8 eccdata[112];  };  static inline void mtk_ecc_wait_idle(struct mtk_ecc *ecc, @@ -366,9 +368,8 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,  		   u8 *data, u32 bytes)  {  	dma_addr_t addr; -	u8 *p; -	u32 len, i, val; -	int ret = 0; +	u32 len; +	int ret;  	addr = dma_map_single(ecc->dev, data, bytes, DMA_TO_DEVICE);  	ret = dma_mapping_error(ecc->dev, addr); @@ -393,14 +394,12 @@ int mtk_ecc_encode(struct mtk_ecc *ecc, struct mtk_ecc_config *config,  	/* Program ECC bytes to OOB: per sector oob = FDM + ECC + SPARE */  	len = (config->strength * ECC_PARITY_BITS + 7) >> 3; -	p = data + bytes; -	/* write the parity bytes generated by the ECC back to the OOB region */ -	for (i = 0; i < len; i++) { -		if ((i % 4) == 0) -			val = readl(ecc->regs + ECC_ENCPAR(i / 4)); -		p[i] = (val >> ((i % 4) * 8)) & 0xff; -	} +	/* write the parity bytes generated by the ECC back to temp buffer */ +	__ioread32_copy(ecc->eccdata, ecc->regs + ECC_ENCPAR(0), round_up(len, 4)); + +	/* copy into possibly unaligned OOB region with actual length */ +	memcpy(data + bytes, ecc->eccdata, len);  timeout:  	dma_unmap_single(ecc->dev, addr, bytes, DMA_TO_DEVICE); diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index e5718e5ecf92..3bde96a3f7bf 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1095,10 +1095,11 @@ static void nand_release_data_interface(struct nand_chip *chip)  /**   * nand_reset - Reset and initialize a NAND device   * @chip: The NAND chip + * @chipnr: Internal die id   *   * Returns 0 for success or negative error code otherwise   */ -int nand_reset(struct nand_chip *chip) +int nand_reset(struct nand_chip *chip, int chipnr)  {  	struct mtd_info *mtd = nand_to_mtd(chip);  	int ret; @@ -1107,9 +1108,17 @@ int nand_reset(struct nand_chip *chip)  	if (ret)  		return ret; +	/* +	 * The CS line has to be released before we can apply the new NAND +	 * interface settings, hence this weird ->select_chip() dance. +	 */ +	chip->select_chip(mtd, chipnr);  	chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1); +	chip->select_chip(mtd, -1); +	chip->select_chip(mtd, chipnr);  	ret = nand_setup_data_interface(chip); +	chip->select_chip(mtd, -1);  	if (ret)  		return ret; @@ -1185,8 +1194,6 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)  	/* Shift to get chip number */  	chipnr = ofs >> chip->chip_shift; -	chip->select_chip(mtd, chipnr); -  	/*  	 * Reset the chip.  	 * If we want to check the WP through READ STATUS and check the bit 7 @@ -1194,7 +1201,9 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)  	 * some operation can also clear the bit 7 of status register  	 * eg. erase/program a locked block  	 */ -	nand_reset(chip); +	nand_reset(chip, chipnr); + +	chip->select_chip(mtd, chipnr);  	/* Check, if it is write protected */  	if (nand_check_wp(mtd)) { @@ -1244,8 +1253,6 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)  	/* Shift to get chip number */  	chipnr = ofs >> chip->chip_shift; -	chip->select_chip(mtd, chipnr); -  	/*  	 * Reset the chip.  	 * If we want to check the WP through READ STATUS and check the bit 7 @@ -1253,7 +1260,9 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)  	 * some operation can also clear the bit 7 of status register  	 * eg. erase/program a locked block  	 */ -	nand_reset(chip); +	nand_reset(chip, chipnr); + +	chip->select_chip(mtd, chipnr);  	/* Check, if it is write protected */  	if (nand_check_wp(mtd)) { @@ -2940,10 +2949,6 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,  	}  	chipnr = (int)(to >> chip->chip_shift); -	chip->select_chip(mtd, chipnr); - -	/* Shift to get page */ -	page = (int)(to >> chip->page_shift);  	/*  	 * Reset the chip. Some chips (like the Toshiba TC5832DC found in one @@ -2951,7 +2956,12 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,  	 * if we don't do this. I have no clue why, but I seem to have 'fixed'  	 * it in the doc2000 driver in August 1999.  dwmw2.  	 */ -	nand_reset(chip); +	nand_reset(chip, chipnr); + +	chip->select_chip(mtd, chipnr); + +	/* Shift to get page */ +	page = (int)(to >> chip->page_shift);  	/* Check, if it is write protected */  	if (nand_check_wp(mtd)) { @@ -3984,14 +3994,14 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,  	int i, maf_idx;  	u8 id_data[8]; -	/* Select the device */ -	chip->select_chip(mtd, 0); -  	/*  	 * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)  	 * after power-up.  	 */ -	nand_reset(chip); +	nand_reset(chip, 0); + +	/* Select the device */ +	chip->select_chip(mtd, 0);  	/* Send the command for reading device ID */  	chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); @@ -4329,17 +4339,31 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,  		return PTR_ERR(type);  	} +	/* Initialize the ->data_interface field. */  	ret = nand_init_data_interface(chip);  	if (ret)  		return ret; +	/* +	 * Setup the data interface correctly on the chip and controller side. +	 * This explicit call to nand_setup_data_interface() is only required +	 * for the first die, because nand_reset() has been called before +	 * ->data_interface and ->default_onfi_timing_mode were set. +	 * For the other dies, nand_reset() will automatically switch to the +	 * best mode for us. +	 */ +	ret = nand_setup_data_interface(chip); +	if (ret) +		return ret; +  	chip->select_chip(mtd, -1);  	/* Check for a chip array */  	for (i = 1; i < maxchips; i++) { -		chip->select_chip(mtd, i);  		/* See comment in nand_get_flash_type for reset */ -		nand_reset(chip); +		nand_reset(chip, i); + +		chip->select_chip(mtd, i);  		/* Send the command for reading device ID */  		chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);  		/* Read manufacturer and device IDs */ diff --git a/drivers/pci/host/pcie-designware.c b/drivers/pci/host/pcie-designware.c index 035f50c03281..bed19994c1e9 100644 --- a/drivers/pci/host/pcie-designware.c +++ b/drivers/pci/host/pcie-designware.c @@ -637,8 +637,6 @@ int dw_pcie_host_init(struct pcie_port *pp)  		}  	} -	pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp); -  	if (pp->ops->host_init)  		pp->ops->host_init(pp); @@ -809,6 +807,11 @@ void dw_pcie_setup_rc(struct pcie_port *pp)  {  	u32 val; +	/* get iATU unroll support */ +	pp->iatu_unroll_enabled = dw_pcie_iatu_unroll_enabled(pp); +	dev_dbg(pp->dev, "iATU unroll: %s\n", +		pp->iatu_unroll_enabled ? "enabled" : "disabled"); +  	/* set the number of lanes */  	val = dw_pcie_readl_rc(pp, PCIE_PORT_LINK_CONTROL);  	val &= ~PORT_LINK_MODE_MASK; diff --git a/drivers/pci/host/pcie-qcom.c b/drivers/pci/host/pcie-qcom.c index ef0a84c7a588..35936409b2d4 100644 --- a/drivers/pci/host/pcie-qcom.c +++ b/drivers/pci/host/pcie-qcom.c @@ -533,11 +533,11 @@ static int qcom_pcie_probe(struct platform_device *pdev)  	if (IS_ERR(pcie->phy))  		return PTR_ERR(pcie->phy); +	pp->dev = dev;  	ret = pcie->ops->get_resources(pcie);  	if (ret)  		return ret; -	pp->dev = dev;  	pp->root_bus_nr = -1;  	pp->ops = &qcom_pcie_dw_ops; diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 3d53d636b17b..f0cfb0451757 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -2636,18 +2636,9 @@ static int arcmsr_queue_command_lck(struct scsi_cmnd *cmd,  	struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata;  	struct CommandControlBlock *ccb;  	int target = cmd->device->id; -	int lun = cmd->device->lun; -	uint8_t scsicmd = cmd->cmnd[0];  	cmd->scsi_done = done;  	cmd->host_scribble = NULL;  	cmd->result = 0; -	if ((scsicmd == SYNCHRONIZE_CACHE) ||(scsicmd == SEND_DIAGNOSTIC)){ -		if(acb->devstate[target][lun] == ARECA_RAID_GONE) { -    			cmd->result = (DID_NO_CONNECT << 16); -		} -		cmd->scsi_done(cmd); -		return 0; -	}  	if (target == 16) {  		/* virtual device for iop message transfer */  		arcmsr_handle_virtual_command(acb, cmd); diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index 9ff57dee72d7..d8b1fbd4c8aa 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -1700,16 +1700,13 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)  		goto out_done;  	} -	switch (scmd->cmnd[0]) { -	case SYNCHRONIZE_CACHE: -		/* -		 * FW takes care of flush cache on its own -		 * No need to send it down -		 */ +	/* +	 * FW takes care of flush cache on its own for Virtual Disk. +	 * No need to send it down for VD. For JBOD send SYNCHRONIZE_CACHE to FW. +	 */ +	if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd)) {  		scmd->result = DID_OK << 16;  		goto out_done; -	default: -		break;  	}  	return instance->instancet->build_and_issue_cmd(instance, scmd); diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index c905709707f0..cf04a364fd8b 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -5134,6 +5134,7 @@ static void __exit scsi_debug_exit(void)  	bus_unregister(&pseudo_lld_bus);  	root_device_unregister(pseudo_primary); +	vfree(map_storep);  	vfree(dif_storep);  	vfree(fake_storep);  	kfree(sdebug_q_arr); diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c index ea15cc638097..4d9bd02ede47 100644 --- a/drivers/staging/media/bcm2048/radio-bcm2048.c +++ b/drivers/staging/media/bcm2048/radio-bcm2048.c @@ -482,6 +482,8 @@ static int bcm2048_set_rds_no_lock(struct bcm2048_device *bdev, u8 rds_on)  					   flags);  		memset(&bdev->rds_info, 0, sizeof(bdev->rds_info));  	} +	if (err) +		return err;  	return bcm2048_send_command(bdev, BCM2048_I2C_FM_RDS_SYSTEM,  				    bdev->cache_fm_rds_system); diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index d624a527777f..031bc08d000d 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -829,8 +829,9 @@ static long vfio_pci_ioctl(void *device_data,  	} else if (cmd == VFIO_DEVICE_SET_IRQS) {  		struct vfio_irq_set hdr; +		size_t size;  		u8 *data = NULL; -		int ret = 0; +		int max, ret = 0;  		minsz = offsetofend(struct vfio_irq_set, count); @@ -838,23 +839,31 @@ static long vfio_pci_ioctl(void *device_data,  			return -EFAULT;  		if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS || +		    hdr.count >= (U32_MAX - hdr.start) ||  		    hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |  				  VFIO_IRQ_SET_ACTION_TYPE_MASK))  			return -EINVAL; -		if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { -			size_t size; -			int max = vfio_pci_get_irq_count(vdev, hdr.index); +		max = vfio_pci_get_irq_count(vdev, hdr.index); +		if (hdr.start >= max || hdr.start + hdr.count > max) +			return -EINVAL; -			if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) -				size = sizeof(uint8_t); -			else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) -				size = sizeof(int32_t); -			else -				return -EINVAL; +		switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) { +		case VFIO_IRQ_SET_DATA_NONE: +			size = 0; +			break; +		case VFIO_IRQ_SET_DATA_BOOL: +			size = sizeof(uint8_t); +			break; +		case VFIO_IRQ_SET_DATA_EVENTFD: +			size = sizeof(int32_t); +			break; +		default: +			return -EINVAL; +		} -			if (hdr.argsz - minsz < hdr.count * size || -			    hdr.start >= max || hdr.start + hdr.count > max) +		if (size) { +			if (hdr.argsz - minsz < hdr.count * size)  				return -EINVAL;  			data = memdup_user((void __user *)(arg + minsz), diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index c2e60893cd09..1c46045b0e7f 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -256,7 +256,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix)  	if (!is_irq_none(vdev))  		return -EINVAL; -	vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); +	vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL);  	if (!vdev->ctx)  		return -ENOMEM; diff --git a/drivers/virtio/config.c b/drivers/virtio/config.c deleted file mode 100644 index f70bcd2ff98f..000000000000 --- a/drivers/virtio/config.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Configuration space parsing helpers for virtio. - * - * The configuration is [type][len][... len bytes ...] fields. - * - * Copyright 2007 Rusty Russell, IBM Corporation. - * GPL v2 or later. - */ -#include <linux/err.h> -#include <linux/virtio.h> -#include <linux/virtio_config.h> -#include <linux/bug.h> - diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 4e7003db12c4..181793f07852 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -577,6 +577,8 @@ static int virtballoon_probe(struct virtio_device *vdev)  	virtio_device_ready(vdev); +	if (towards_target(vb)) +		virtballoon_changed(vdev);  	return 0;  out_del_vqs: diff --git a/drivers/virtio/virtio_pci_legacy.c b/drivers/virtio/virtio_pci_legacy.c index 8c4e61783441..6d9e5173d5fa 100644 --- a/drivers/virtio/virtio_pci_legacy.c +++ b/drivers/virtio/virtio_pci_legacy.c @@ -212,10 +212,18 @@ int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev)  		return -ENODEV;  	} -	rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(64)); -	if (rc) -		rc = dma_set_mask_and_coherent(&pci_dev->dev, -						DMA_BIT_MASK(32)); +	rc = dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(64)); +	if (rc) { +		rc = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32)); +	} else { +		/* +		 * The virtio ring base address is expressed as a 32-bit PFN, +		 * with a page size of 1 << VIRTIO_PCI_QUEUE_ADDR_SHIFT. +		 */ +		dma_set_coherent_mask(&pci_dev->dev, +				DMA_BIT_MASK(32 + VIRTIO_PCI_QUEUE_ADDR_SHIFT)); +	} +  	if (rc)  		dev_warn(&pci_dev->dev, "Failed to enable 64-bit or 32-bit DMA.  Trying to continue, but this might not work.\n"); diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c index ed9c9eeedfe5..489bfc61cf30 100644 --- a/drivers/virtio/virtio_ring.c +++ b/drivers/virtio/virtio_ring.c @@ -167,7 +167,7 @@ static bool vring_use_dma_api(struct virtio_device *vdev)   * making all of the arch DMA ops work on the vring device itself   * is a mess.  For now, we use the parent device for DMA ops.   */ -static struct device *vring_dma_dev(const struct vring_virtqueue *vq) +static inline struct device *vring_dma_dev(const struct vring_virtqueue *vq)  {  	return vq->vq.vdev->dev.parent;  } @@ -732,7 +732,8 @@ void virtqueue_disable_cb(struct virtqueue *_vq)  	if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) {  		vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; -		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); +		if (!vq->event) +			vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);  	}  } @@ -764,7 +765,8 @@ unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq)  	 * entry. Always do both to keep code simple. */  	if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {  		vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; -		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); +		if (!vq->event) +			vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);  	}  	vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx);  	END_USE(vq); @@ -832,10 +834,11 @@ bool virtqueue_enable_cb_delayed(struct virtqueue *_vq)  	 * more to do. */  	/* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to  	 * either clear the flags bit or point the event index at the next -	 * entry. Always do both to keep code simple. */ +	 * entry. Always update the event index to keep code simple. */  	if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) {  		vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; -		vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); +		if (!vq->event) +			vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow);  	}  	/* TODO: tune this threshold */  	bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; @@ -953,7 +956,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,  	/* No callback?  Tell other side not to bother us. */  	if (!callback) {  		vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; -		vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); +		if (!vq->event) +			vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow);  	}  	/* Put everything in free lists. */ diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 210c94ac8818..4607af38c72e 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -2647,7 +2647,10 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,  		btrfs_free_delayed_extent_op(extent_op);  		if (ret) { +			spin_lock(&delayed_refs->lock);  			locked_ref->processing = 0; +			delayed_refs->num_heads_ready++; +			spin_unlock(&delayed_refs->lock);  			btrfs_delayed_ref_unlock(locked_ref);  			btrfs_put_delayed_ref(ref);  			btrfs_debug(fs_info, "run_one_delayed_ref returned %d", diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 66a755150056..8ed05d95584a 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -5569,7 +5569,7 @@ void le_bitmap_set(u8 *map, unsigned int start, int len)  		*p |= mask_to_set;  		len -= bits_to_set;  		bits_to_set = BITS_PER_BYTE; -		mask_to_set = ~(u8)0; +		mask_to_set = ~0;  		p++;  	}  	if (len) { @@ -5589,7 +5589,7 @@ void le_bitmap_clear(u8 *map, unsigned int start, int len)  		*p &= ~mask_to_clear;  		len -= bits_to_clear;  		bits_to_clear = BITS_PER_BYTE; -		mask_to_clear = ~(u8)0; +		mask_to_clear = ~0;  		p++;  	}  	if (len) { @@ -5679,7 +5679,7 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start,  		kaddr[offset] |= mask_to_set;  		len -= bits_to_set;  		bits_to_set = BITS_PER_BYTE; -		mask_to_set = ~(u8)0; +		mask_to_set = ~0;  		if (++offset >= PAGE_SIZE && len > 0) {  			offset = 0;  			page = eb->pages[++i]; @@ -5721,7 +5721,7 @@ void extent_buffer_bitmap_clear(struct extent_buffer *eb, unsigned long start,  		kaddr[offset] &= ~mask_to_clear;  		len -= bits_to_clear;  		bits_to_clear = BITS_PER_BYTE; -		mask_to_clear = ~(u8)0; +		mask_to_clear = ~0;  		if (++offset >= PAGE_SIZE && len > 0) {  			offset = 0;  			page = eb->pages[++i]; diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 2b790bda7998..8e3a5a266917 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -4605,8 +4605,8 @@ delete:  			BUG_ON(ret);  			if (btrfs_should_throttle_delayed_refs(trans, root))  				btrfs_async_run_delayed_refs(root, -							     trans->transid, -					trans->delayed_ref_updates * 2, 0); +					trans->delayed_ref_updates * 2, +					trans->transid, 0);  			if (be_nice) {  				if (truncate_space_check(trans, root,  							 extent_num_bytes)) { @@ -8931,9 +8931,14 @@ again:  	 *    So even we call qgroup_free_data(), it won't decrease reserved  	 *    space.  	 * 2) Not written to disk -	 *    This means the reserved space should be freed here. +	 *    This means the reserved space should be freed here. However, +	 *    if a truncate invalidates the page (by clearing PageDirty) +	 *    and the page is accounted for while allocating extent +	 *    in btrfs_check_data_free_space() we let delayed_ref to +	 *    free the entire extent.  	 */ -	btrfs_qgroup_free_data(inode, page_start, PAGE_SIZE); +	if (PageDirty(page)) +		btrfs_qgroup_free_data(inode, page_start, PAGE_SIZE);  	if (!inode_evicting) {  		clear_extent_bit(tree, page_start, page_end,  				 EXTENT_LOCKED | EXTENT_DIRTY | diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 18e1aa0f85f5..7acbd2cf6192 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3814,6 +3814,11 @@ process_slot:  		}  		btrfs_release_path(path);  		key.offset = next_key_min_offset; + +		if (fatal_signal_pending(current)) { +			ret = -EINTR; +			goto out; +		}  	}  	ret = 0; diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 0ec8ffa37ab0..c4af0cdb783d 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -2728,7 +2728,14 @@ static int do_relocation(struct btrfs_trans_handle *trans,  		bytenr = btrfs_node_blockptr(upper->eb, slot);  		if (lowest) { -			BUG_ON(bytenr != node->bytenr); +			if (bytenr != node->bytenr) { +				btrfs_err(root->fs_info, +		"lowest leaf/node mismatch: bytenr %llu node->bytenr %llu slot %d upper %llu", +					  bytenr, node->bytenr, slot, +					  upper->eb->start); +				err = -EIO; +				goto next; +			}  		} else {  			if (node->eb->start == bytenr)  				goto next; diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index b10d557f9c9e..ee36efd5aece 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -84,6 +84,8 @@ struct nfsd_net {  	struct list_head client_lru;  	struct list_head close_lru;  	struct list_head del_recall_lru; + +	/* protected by blocked_locks_lock */  	struct list_head blocked_locks_lru;  	struct delayed_work laundromat_work; @@ -91,6 +93,9 @@ struct nfsd_net {  	/* client_lock protects the client lru list and session hash table */  	spinlock_t client_lock; +	/* protects blocked_locks_lru */ +	spinlock_t blocked_locks_lock; +  	struct file *rec_file;  	bool in_grace;  	const struct nfsd4_client_tracking_ops *client_tracking_ops; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9752beb78659..4b4beaaa4eaa 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -217,7 +217,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh,  {  	struct nfsd4_blocked_lock *cur, *found = NULL; -	spin_lock(&nn->client_lock); +	spin_lock(&nn->blocked_locks_lock);  	list_for_each_entry(cur, &lo->lo_blocked, nbl_list) {  		if (fh_match(fh, &cur->nbl_fh)) {  			list_del_init(&cur->nbl_list); @@ -226,7 +226,7 @@ find_blocked_lock(struct nfs4_lockowner *lo, struct knfsd_fh *fh,  			break;  		}  	} -	spin_unlock(&nn->client_lock); +	spin_unlock(&nn->blocked_locks_lock);  	if (found)  		posix_unblock_lock(&found->nbl_lock);  	return found; @@ -1227,9 +1227,7 @@ static void put_ol_stateid_locked(struct nfs4_ol_stateid *stp,  static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp)  { -	struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); - -	lockdep_assert_held(&oo->oo_owner.so_client->cl_lock); +	lockdep_assert_held(&stp->st_stid.sc_client->cl_lock);  	list_del_init(&stp->st_locks);  	nfs4_unhash_stid(&stp->st_stid); @@ -1238,12 +1236,12 @@ static bool unhash_lock_stateid(struct nfs4_ol_stateid *stp)  static void release_lock_stateid(struct nfs4_ol_stateid *stp)  { -	struct nfs4_openowner *oo = openowner(stp->st_openstp->st_stateowner); +	struct nfs4_client *clp = stp->st_stid.sc_client;  	bool unhashed; -	spin_lock(&oo->oo_owner.so_client->cl_lock); +	spin_lock(&clp->cl_lock);  	unhashed = unhash_lock_stateid(stp); -	spin_unlock(&oo->oo_owner.so_client->cl_lock); +	spin_unlock(&clp->cl_lock);  	if (unhashed)  		nfs4_put_stid(&stp->st_stid);  } @@ -4665,7 +4663,7 @@ nfs4_laundromat(struct nfsd_net *nn)  	 * indefinitely once the lock does become free.  	 */  	BUG_ON(!list_empty(&reaplist)); -	spin_lock(&nn->client_lock); +	spin_lock(&nn->blocked_locks_lock);  	while (!list_empty(&nn->blocked_locks_lru)) {  		nbl = list_first_entry(&nn->blocked_locks_lru,  					struct nfsd4_blocked_lock, nbl_lru); @@ -4678,7 +4676,7 @@ nfs4_laundromat(struct nfsd_net *nn)  		list_move(&nbl->nbl_lru, &reaplist);  		list_del_init(&nbl->nbl_list);  	} -	spin_unlock(&nn->client_lock); +	spin_unlock(&nn->blocked_locks_lock);  	while (!list_empty(&reaplist)) {  		nbl = list_first_entry(&nn->blocked_locks_lru, @@ -5439,13 +5437,13 @@ nfsd4_lm_notify(struct file_lock *fl)  	bool queue = false;  	/* An empty list means that something else is going to be using it */ -	spin_lock(&nn->client_lock); +	spin_lock(&nn->blocked_locks_lock);  	if (!list_empty(&nbl->nbl_list)) {  		list_del_init(&nbl->nbl_list);  		list_del_init(&nbl->nbl_lru);  		queue = true;  	} -	spin_unlock(&nn->client_lock); +	spin_unlock(&nn->blocked_locks_lock);  	if (queue)  		nfsd4_run_cb(&nbl->nbl_cb); @@ -5868,10 +5866,10 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,  	if (fl_flags & FL_SLEEP) {  		nbl->nbl_time = jiffies; -		spin_lock(&nn->client_lock); +		spin_lock(&nn->blocked_locks_lock);  		list_add_tail(&nbl->nbl_list, &lock_sop->lo_blocked);  		list_add_tail(&nbl->nbl_lru, &nn->blocked_locks_lru); -		spin_unlock(&nn->client_lock); +		spin_unlock(&nn->blocked_locks_lock);  	}  	err = vfs_lock_file(filp, F_SETLK, file_lock, conflock); @@ -5900,10 +5898,10 @@ out:  	if (nbl) {  		/* dequeue it if we queued it before */  		if (fl_flags & FL_SLEEP) { -			spin_lock(&nn->client_lock); +			spin_lock(&nn->blocked_locks_lock);  			list_del_init(&nbl->nbl_list);  			list_del_init(&nbl->nbl_lru); -			spin_unlock(&nn->client_lock); +			spin_unlock(&nn->blocked_locks_lock);  		}  		free_blocked_lock(nbl);  	} @@ -6943,9 +6941,11 @@ static int nfs4_state_create_net(struct net *net)  	INIT_LIST_HEAD(&nn->client_lru);  	INIT_LIST_HEAD(&nn->close_lru);  	INIT_LIST_HEAD(&nn->del_recall_lru); -	INIT_LIST_HEAD(&nn->blocked_locks_lru);  	spin_lock_init(&nn->client_lock); +	spin_lock_init(&nn->blocked_locks_lock); +	INIT_LIST_HEAD(&nn->blocked_locks_lru); +  	INIT_DELAYED_WORK(&nn->laundromat_work, laundromat_main);  	get_net(net); @@ -7063,14 +7063,14 @@ nfs4_state_shutdown_net(struct net *net)  	}  	BUG_ON(!list_empty(&reaplist)); -	spin_lock(&nn->client_lock); +	spin_lock(&nn->blocked_locks_lock);  	while (!list_empty(&nn->blocked_locks_lru)) {  		nbl = list_first_entry(&nn->blocked_locks_lru,  					struct nfsd4_blocked_lock, nbl_lru);  		list_move(&nbl->nbl_lru, &reaplist);  		list_del_init(&nbl->nbl_list);  	} -	spin_unlock(&nn->client_lock); +	spin_unlock(&nn->blocked_locks_lock);  	while (!list_empty(&reaplist)) {  		nbl = list_first_entry(&nn->blocked_locks_lru, diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index aeb60f791418..36795eed40b0 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c @@ -178,6 +178,8 @@ static int ovl_copy_up_data(struct path *old, struct path *new, loff_t len)  		len -= bytes;  	} +	if (!error) +		error = vfs_fsync(new_file, 0);  	fput(new_file);  out_fput:  	fput(old_file); diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c index c58f01babf30..7fb53d055537 100644 --- a/fs/overlayfs/inode.c +++ b/fs/overlayfs/inode.c @@ -270,9 +270,6 @@ struct posix_acl *ovl_get_acl(struct inode *inode, int type)  	if (!IS_ENABLED(CONFIG_FS_POSIX_ACL) || !IS_POSIXACL(realinode))  		return NULL; -	if (!realinode->i_op->get_acl) -		return NULL; -  	old_cred = ovl_override_creds(inode->i_sb);  	acl = get_acl(realinode, type);  	revert_creds(old_cred); diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index bcf3965be819..edd46a0e951d 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1037,6 +1037,21 @@ ovl_posix_acl_xattr_set(const struct xattr_handler *handler,  	posix_acl_release(acl); +	/* +	 * Check if sgid bit needs to be cleared (actual setacl operation will +	 * be done with mounter's capabilities and so that won't do it for us). +	 */ +	if (unlikely(inode->i_mode & S_ISGID) && +	    handler->flags == ACL_TYPE_ACCESS && +	    !in_group_p(inode->i_gid) && +	    !capable_wrt_inode_uidgid(inode, CAP_FSETID)) { +		struct iattr iattr = { .ia_valid = ATTR_KILL_SGID }; + +		err = ovl_setattr(dentry, &iattr); +		if (err) +			return err; +	} +  	err = ovl_xattr_set(dentry, handler->name, value, size, flags);  	if (!err)  		ovl_copyattr(ovl_inode_real(inode, NULL), inode); diff --git a/include/drm/drm_plane.h b/include/drm/drm_plane.h index 43cf193e54d6..8b4dc62470ff 100644 --- a/include/drm/drm_plane.h +++ b/include/drm/drm_plane.h @@ -47,8 +47,14 @@ struct drm_crtc;   * @src_h: height of visible portion of plane (in 16.16)   * @rotation: rotation of the plane   * @zpos: priority of the given plane on crtc (optional) + *	Note that multiple active planes on the same crtc can have an identical + *	zpos value. The rule to solving the conflict is to compare the plane + *	object IDs; the plane with a higher ID must be stacked on top of a + *	plane with a lower ID.   * @normalized_zpos: normalized value of zpos: unique, range from 0 to N-1 - *	where N is the number of active planes for given crtc + *	where N is the number of active planes for given crtc. Note that + *	the driver must call drm_atomic_normalize_zpos() to update this before + *	it can be trusted.   * @src: clipped source coordinates of the plane (in 16.16)   * @dst: clipped destination coordinates of the plane   * @visible: visibility of the plane diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index c5d3d5024fc8..d8905a229f34 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -1184,7 +1184,7 @@ int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,  			   int page);  /* Reset and initialize a NAND device */ -int nand_reset(struct nand_chip *chip); +int nand_reset(struct nand_chip *chip, int chipnr);  /* Free resources held by the NAND device */  void nand_cleanup(struct nand_chip *chip); diff --git a/kernel/fork.c b/kernel/fork.c index 623259fc794d..997ac1d584f7 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -315,6 +315,9 @@ static void account_kernel_stack(struct task_struct *tsk, int account)  static void release_task_stack(struct task_struct *tsk)  { +	if (WARN_ON(tsk->state != TASK_DEAD)) +		return;  /* Better to leak the stack than to free prematurely */ +  	account_kernel_stack(tsk, -1);  	arch_release_thread_stack(tsk->stack);  	free_thread_stack(tsk); @@ -1862,6 +1865,7 @@ bad_fork_cleanup_count:  	atomic_dec(&p->cred->user->processes);  	exit_creds(p);  bad_fork_free: +	p->state = TASK_DEAD;  	put_task_stack(p);  	free_task(p);  fork_out: diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 8fd42aa7c4bd..072d791dce2d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -92,7 +92,7 @@ int _node_numa_mem_[MAX_NUMNODES];  #endif  #ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY -volatile u64 latent_entropy __latent_entropy; +volatile unsigned long latent_entropy __latent_entropy;  EXPORT_SYMBOL(latent_entropy);  #endif diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index d8bd97a5a7c9..3dfd769dc5b5 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c @@ -1616,7 +1616,7 @@ gss_validate(struct rpc_task *task, __be32 *p)  {  	struct rpc_cred *cred = task->tk_rqstp->rq_cred;  	struct gss_cl_ctx *ctx = gss_cred_get_ctx(cred); -	__be32		seq; +	__be32		*seq = NULL;  	struct kvec	iov;  	struct xdr_buf	verf_buf;  	struct xdr_netobj mic; @@ -1631,9 +1631,12 @@ gss_validate(struct rpc_task *task, __be32 *p)  		goto out_bad;  	if (flav != RPC_AUTH_GSS)  		goto out_bad; -	seq = htonl(task->tk_rqstp->rq_seqno); -	iov.iov_base = &seq; -	iov.iov_len = sizeof(seq); +	seq = kmalloc(4, GFP_NOFS); +	if (!seq) +		goto out_bad; +	*seq = htonl(task->tk_rqstp->rq_seqno); +	iov.iov_base = seq; +	iov.iov_len = 4;  	xdr_buf_from_iov(&iov, &verf_buf);  	mic.data = (u8 *)p;  	mic.len = len; @@ -1653,11 +1656,13 @@ gss_validate(struct rpc_task *task, __be32 *p)  	gss_put_ctx(ctx);  	dprintk("RPC: %5u %s: gss_verify_mic succeeded.\n",  			task->tk_pid, __func__); +	kfree(seq);  	return p + XDR_QUADLEN(len);  out_bad:  	gss_put_ctx(ctx);  	dprintk("RPC: %5u %s failed ret %ld.\n", task->tk_pid, __func__,  		PTR_ERR(ret)); +	kfree(seq);  	return ret;  } diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 244245bcbbd2..90115ceefd49 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c @@ -166,8 +166,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,  		       unsigned int usage, struct xdr_netobj *cksumout)  {  	struct scatterlist              sg[1]; -	int err; -	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; +	int err = -1; +	u8 *checksumdata;  	u8 rc4salt[4];  	struct crypto_ahash *md5;  	struct crypto_ahash *hmac_md5; @@ -187,23 +187,22 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,  		return GSS_S_FAILURE;  	} +	checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); +	if (!checksumdata) +		return GSS_S_FAILURE; +  	md5 = crypto_alloc_ahash("md5", 0, CRYPTO_ALG_ASYNC);  	if (IS_ERR(md5)) -		return GSS_S_FAILURE; +		goto out_free_cksum;  	hmac_md5 = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0,  				      CRYPTO_ALG_ASYNC); -	if (IS_ERR(hmac_md5)) { -		crypto_free_ahash(md5); -		return GSS_S_FAILURE; -	} +	if (IS_ERR(hmac_md5)) +		goto out_free_md5;  	req = ahash_request_alloc(md5, GFP_KERNEL); -	if (!req) { -		crypto_free_ahash(hmac_md5); -		crypto_free_ahash(md5); -		return GSS_S_FAILURE; -	} +	if (!req) +		goto out_free_hmac_md5;  	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); @@ -232,11 +231,8 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,  	ahash_request_free(req);  	req = ahash_request_alloc(hmac_md5, GFP_KERNEL); -	if (!req) { -		crypto_free_ahash(hmac_md5); -		crypto_free_ahash(md5); -		return GSS_S_FAILURE; -	} +	if (!req) +		goto out_free_hmac_md5;  	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); @@ -258,8 +254,12 @@ make_checksum_hmac_md5(struct krb5_ctx *kctx, char *header, int hdrlen,  	cksumout->len = kctx->gk5e->cksumlength;  out:  	ahash_request_free(req); -	crypto_free_ahash(md5); +out_free_hmac_md5:  	crypto_free_ahash(hmac_md5); +out_free_md5: +	crypto_free_ahash(md5); +out_free_cksum: +	kfree(checksumdata);  	return err ? GSS_S_FAILURE : 0;  } @@ -276,8 +276,8 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,  	struct crypto_ahash *tfm;  	struct ahash_request *req;  	struct scatterlist              sg[1]; -	int err; -	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; +	int err = -1; +	u8 *checksumdata;  	unsigned int checksumlen;  	if (kctx->gk5e->ctype == CKSUMTYPE_HMAC_MD5_ARCFOUR) @@ -291,15 +291,17 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,  		return GSS_S_FAILURE;  	} +	checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); +	if (checksumdata == NULL) +		return GSS_S_FAILURE; +  	tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);  	if (IS_ERR(tfm)) -		return GSS_S_FAILURE; +		goto out_free_cksum;  	req = ahash_request_alloc(tfm, GFP_KERNEL); -	if (!req) { -		crypto_free_ahash(tfm); -		return GSS_S_FAILURE; -	} +	if (!req) +		goto out_free_ahash;  	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); @@ -349,7 +351,10 @@ make_checksum(struct krb5_ctx *kctx, char *header, int hdrlen,  	cksumout->len = kctx->gk5e->cksumlength;  out:  	ahash_request_free(req); +out_free_ahash:  	crypto_free_ahash(tfm); +out_free_cksum: +	kfree(checksumdata);  	return err ? GSS_S_FAILURE : 0;  } @@ -368,8 +373,8 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,  	struct crypto_ahash *tfm;  	struct ahash_request *req;  	struct scatterlist sg[1]; -	int err; -	u8 checksumdata[GSS_KRB5_MAX_CKSUM_LEN]; +	int err = -1; +	u8 *checksumdata;  	unsigned int checksumlen;  	if (kctx->gk5e->keyed_cksum == 0) { @@ -383,16 +388,18 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,  		return GSS_S_FAILURE;  	} +	checksumdata = kmalloc(GSS_KRB5_MAX_CKSUM_LEN, GFP_NOFS); +	if (!checksumdata) +		return GSS_S_FAILURE; +  	tfm = crypto_alloc_ahash(kctx->gk5e->cksum_name, 0, CRYPTO_ALG_ASYNC);  	if (IS_ERR(tfm)) -		return GSS_S_FAILURE; +		goto out_free_cksum;  	checksumlen = crypto_ahash_digestsize(tfm);  	req = ahash_request_alloc(tfm, GFP_KERNEL); -	if (!req) { -		crypto_free_ahash(tfm); -		return GSS_S_FAILURE; -	} +	if (!req) +		goto out_free_ahash;  	ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP, NULL, NULL); @@ -433,7 +440,10 @@ make_checksum_v2(struct krb5_ctx *kctx, char *header, int hdrlen,  	}  out:  	ahash_request_free(req); +out_free_ahash:  	crypto_free_ahash(tfm); +out_free_cksum: +	kfree(checksumdata);  	return err ? GSS_S_FAILURE : 0;  } @@ -666,14 +676,17 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf,  	u32 ret;  	struct scatterlist sg[1];  	SKCIPHER_REQUEST_ON_STACK(req, cipher); -	u8 data[GSS_KRB5_MAX_BLOCKSIZE * 2]; +	u8 *data;  	struct page **save_pages;  	u32 len = buf->len - offset; -	if (len > ARRAY_SIZE(data)) { +	if (len > GSS_KRB5_MAX_BLOCKSIZE * 2) {  		WARN_ON(0);  		return -ENOMEM;  	} +	data = kmalloc(GSS_KRB5_MAX_BLOCKSIZE * 2, GFP_NOFS); +	if (!data) +		return -ENOMEM;  	/*  	 * For encryption, we want to read from the cleartext @@ -708,6 +721,7 @@ gss_krb5_cts_crypt(struct crypto_skcipher *cipher, struct xdr_buf *buf,  	ret = write_bytes_to_xdr_buf(buf, offset, data, len);  out: +	kfree(data);  	return ret;  } diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index d67f7e1bc82d..45662d7f0943 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -718,30 +718,37 @@ gss_write_null_verf(struct svc_rqst *rqstp)  static int  gss_write_verf(struct svc_rqst *rqstp, struct gss_ctx *ctx_id, u32 seq)  { -	__be32			xdr_seq; +	__be32			*xdr_seq;  	u32			maj_stat;  	struct xdr_buf		verf_data;  	struct xdr_netobj	mic;  	__be32			*p;  	struct kvec		iov; +	int err = -1;  	svc_putnl(rqstp->rq_res.head, RPC_AUTH_GSS); -	xdr_seq = htonl(seq); +	xdr_seq = kmalloc(4, GFP_KERNEL); +	if (!xdr_seq) +		return -1; +	*xdr_seq = htonl(seq); -	iov.iov_base = &xdr_seq; -	iov.iov_len = sizeof(xdr_seq); +	iov.iov_base = xdr_seq; +	iov.iov_len = 4;  	xdr_buf_from_iov(&iov, &verf_data);  	p = rqstp->rq_res.head->iov_base + rqstp->rq_res.head->iov_len;  	mic.data = (u8 *)(p + 1);  	maj_stat = gss_get_mic(ctx_id, &verf_data, &mic);  	if (maj_stat != GSS_S_COMPLETE) -		return -1; +		goto out;  	*p++ = htonl(mic.len);  	memset((u8 *)p + mic.len, 0, round_up_to_quad(mic.len) - mic.len);  	p += XDR_QUADLEN(mic.len);  	if (!xdr_ressize_check(rqstp, p)) -		return -1; -	return 0; +		goto out; +	err = 0; +out: +	kfree(xdr_seq); +	return err;  }  struct gss_domain { diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index 2d8545c34095..20027f8de129 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c @@ -177,18 +177,26 @@ xprt_rdma_bc_allocate(struct rpc_task *task)  		return -EINVAL;  	} +	/* svc_rdma_sendto releases this page */  	page = alloc_page(RPCRDMA_DEF_GFP);  	if (!page)  		return -ENOMEM; -  	rqst->rq_buffer = page_address(page); + +	rqst->rq_rbuffer = kmalloc(rqst->rq_rcvsize, RPCRDMA_DEF_GFP); +	if (!rqst->rq_rbuffer) { +		put_page(page); +		return -ENOMEM; +	}  	return 0;  }  static void  xprt_rdma_bc_free(struct rpc_task *task)  { -	/* No-op: ctxt and page have already been freed. */ +	struct rpc_rqst *rqst = task->tk_rqstp; + +	kfree(rqst->rq_rbuffer);  }  static int diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 0137af1c0916..e01c825bc683 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -2563,6 +2563,7 @@ static int bc_malloc(struct rpc_task *task)  	buf->len = PAGE_SIZE;  	rqst->rq_buffer = buf->data; +	rqst->rq_rbuffer = (char *)rqst->rq_buffer + rqst->rq_callsize;  	return 0;  } diff --git a/scripts/gcc-plugins/cyc_complexity_plugin.c b/scripts/gcc-plugins/cyc_complexity_plugin.c index 34df974c6ba3..8af7db06122d 100644 --- a/scripts/gcc-plugins/cyc_complexity_plugin.c +++ b/scripts/gcc-plugins/cyc_complexity_plugin.c @@ -20,7 +20,7 @@  #include "gcc-common.h" -int plugin_is_GPL_compatible; +__visible int plugin_is_GPL_compatible;  static struct plugin_info cyc_complexity_plugin_info = {  	.version	= "20160225", @@ -49,7 +49,7 @@ static unsigned int cyc_complexity_execute(void)  #include "gcc-generate-gimple-pass.h" -int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) +__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)  {  	const char * const plugin_name = plugin_info->base_name;  	struct register_pass_info cyc_complexity_pass_info; diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index 172850bcd0d9..950fd2e64bb7 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -130,6 +130,7 @@ extern void dump_gimple_stmt(pretty_printer *, gimple, int, int);  #endif  #define __unused __attribute__((__unused__)) +#define __visible __attribute__((visibility("default")))  #define DECL_NAME_POINTER(node) IDENTIFIER_POINTER(DECL_NAME(node))  #define DECL_NAME_LENGTH(node) IDENTIFIER_LENGTH(DECL_NAME(node)) diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c index ff1939b804ae..8160f1c1b56e 100644 --- a/scripts/gcc-plugins/latent_entropy_plugin.c +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -77,7 +77,7 @@  #include "gcc-common.h" -int plugin_is_GPL_compatible; +__visible int plugin_is_GPL_compatible;  static GTY(()) tree latent_entropy_decl; @@ -340,7 +340,7 @@ static enum tree_code get_op(tree *rhs)  		break;  	}  	if (rhs) -		*rhs = build_int_cstu(unsigned_intDI_type_node, random_const); +		*rhs = build_int_cstu(long_unsigned_type_node, random_const);  	return op;  } @@ -372,7 +372,7 @@ static void __perturb_latent_entropy(gimple_stmt_iterator *gsi,  	enum tree_code op;  	/* 1. create temporary copy of latent_entropy */ -	temp = create_var(unsigned_intDI_type_node, "tmp_latent_entropy"); +	temp = create_var(long_unsigned_type_node, "temp_latent_entropy");  	/* 2. read... */  	add_referenced_var(latent_entropy_decl); @@ -459,13 +459,13 @@ static void init_local_entropy(basic_block bb, tree local_entropy)  	gsi_insert_before(&gsi, call, GSI_NEW_STMT);  	update_stmt(call); -	udi_frame_addr = fold_convert(unsigned_intDI_type_node, frame_addr); +	udi_frame_addr = fold_convert(long_unsigned_type_node, frame_addr);  	assign = gimple_build_assign(local_entropy, udi_frame_addr);  	gsi_insert_after(&gsi, assign, GSI_NEW_STMT);  	update_stmt(assign);  	/* 3. create temporary copy of latent_entropy */ -	tmp = create_var(unsigned_intDI_type_node, "tmp_latent_entropy"); +	tmp = create_var(long_unsigned_type_node, "temp_latent_entropy");  	/* 4. read the global entropy variable into local entropy */  	add_referenced_var(latent_entropy_decl); @@ -480,7 +480,7 @@ static void init_local_entropy(basic_block bb, tree local_entropy)  	update_stmt(assign);  	rand_cst = get_random_const(); -	rand_const = build_int_cstu(unsigned_intDI_type_node, rand_cst); +	rand_const = build_int_cstu(long_unsigned_type_node, rand_cst);  	op = get_op(NULL);  	assign = create_assign(op, local_entropy, local_entropy, rand_const);  	gsi_insert_after(&gsi, assign, GSI_NEW_STMT); @@ -529,7 +529,7 @@ static unsigned int latent_entropy_execute(void)  	}  	/* 1. create the local entropy variable */ -	local_entropy = create_var(unsigned_intDI_type_node, "local_entropy"); +	local_entropy = create_var(long_unsigned_type_node, "local_entropy");  	/* 2. initialize the local entropy variable */  	init_local_entropy(bb, local_entropy); @@ -561,10 +561,9 @@ static void latent_entropy_start_unit(void *gcc_data __unused,  	if (in_lto_p)  		return; -	/* extern volatile u64 latent_entropy */ -	gcc_assert(TYPE_PRECISION(long_long_unsigned_type_node) == 64); -	quals = TYPE_QUALS(long_long_unsigned_type_node) | TYPE_QUAL_VOLATILE; -	type = build_qualified_type(long_long_unsigned_type_node, quals); +	/* extern volatile unsigned long latent_entropy */ +	quals = TYPE_QUALS(long_unsigned_type_node) | TYPE_QUAL_VOLATILE; +	type = build_qualified_type(long_unsigned_type_node, quals);  	id = get_identifier("latent_entropy");  	latent_entropy_decl = build_decl(UNKNOWN_LOCATION, VAR_DECL, id, type); @@ -584,8 +583,8 @@ static void latent_entropy_start_unit(void *gcc_data __unused,  	| TODO_update_ssa  #include "gcc-generate-gimple-pass.h" -int plugin_init(struct plugin_name_args *plugin_info, -		struct plugin_gcc_version *version) +__visible int plugin_init(struct plugin_name_args *plugin_info, +			  struct plugin_gcc_version *version)  {  	bool enabled = true;  	const char * const plugin_name = plugin_info->base_name; diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c index aedd6113cb73..7ea0b3f50739 100644 --- a/scripts/gcc-plugins/sancov_plugin.c +++ b/scripts/gcc-plugins/sancov_plugin.c @@ -21,7 +21,7 @@  #include "gcc-common.h" -int plugin_is_GPL_compatible; +__visible int plugin_is_GPL_compatible;  tree sancov_fndecl; @@ -86,7 +86,7 @@ static void sancov_start_unit(void __unused *gcc_data, void __unused *user_data)  #endif  } -int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version) +__visible int plugin_init(struct plugin_name_args *plugin_info, struct plugin_gcc_version *version)  {  	int i;  	struct register_pass_info sancov_plugin_pass_info; diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile index 877a8a4721b6..c012edbdb13b 100644 --- a/tools/virtio/ringtest/Makefile +++ b/tools/virtio/ringtest/Makefile @@ -3,8 +3,8 @@ all:  all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring  CFLAGS += -Wall -CFLAGS += -pthread -O2 -ggdb -LDFLAGS += -pthread -O2 -ggdb +CFLAGS += -pthread -O2 -ggdb -flto -fwhole-program +LDFLAGS += -pthread -O2 -ggdb -flto -fwhole-program  main.o: main.c main.h  ring.o: ring.c main.h diff --git a/tools/virtio/ringtest/main.c b/tools/virtio/ringtest/main.c index 147abb452a6c..f31353fac541 100644 --- a/tools/virtio/ringtest/main.c +++ b/tools/virtio/ringtest/main.c @@ -96,7 +96,13 @@ void set_affinity(const char *arg)  	assert(!ret);  } -static void run_guest(void) +void poll_used(void) +{ +	while (used_empty()) +		busy_wait(); +} + +static void __attribute__((__flatten__)) run_guest(void)  {  	int completed_before;  	int completed = 0; @@ -141,7 +147,7 @@ static void run_guest(void)  		assert(completed <= bufs);  		assert(started <= bufs);  		if (do_sleep) { -			if (enable_call()) +			if (used_empty() && enable_call())  				wait_for_call();  		} else {  			poll_used(); @@ -149,7 +155,13 @@ static void run_guest(void)  	}  } -static void run_host(void) +void poll_avail(void) +{ +	while (avail_empty()) +		busy_wait(); +} + +static void __attribute__((__flatten__)) run_host(void)  {  	int completed_before;  	int completed = 0; @@ -160,7 +172,7 @@ static void run_host(void)  	for (;;) {  		if (do_sleep) { -			if (enable_kick()) +			if (avail_empty() && enable_kick())  				wait_for_kick();  		} else {  			poll_avail(); diff --git a/tools/virtio/ringtest/main.h b/tools/virtio/ringtest/main.h index 16917acb0ade..34e63cc4c572 100644 --- a/tools/virtio/ringtest/main.h +++ b/tools/virtio/ringtest/main.h @@ -56,15 +56,15 @@ void alloc_ring(void);  int add_inbuf(unsigned, void *, void *);  void *get_buf(unsigned *, void **);  void disable_call(); +bool used_empty();  bool enable_call();  void kick_available(); -void poll_used();  /* host side */  void disable_kick(); +bool avail_empty();  bool enable_kick();  bool use_buf(unsigned *, void **);  void call_used(); -void poll_avail();  /* implemented by main */  extern bool do_sleep; diff --git a/tools/virtio/ringtest/noring.c b/tools/virtio/ringtest/noring.c index eda2f4824130..b8d1c1daac7c 100644 --- a/tools/virtio/ringtest/noring.c +++ b/tools/virtio/ringtest/noring.c @@ -24,8 +24,9 @@ void *get_buf(unsigned *lenp, void **bufp)  	return "Buffer";  } -void poll_used(void) +bool used_empty()  { +	return false;  }  void disable_call() @@ -54,8 +55,9 @@ bool enable_kick()  	assert(0);  } -void poll_avail(void) +bool avail_empty()  { +	return false;  }  bool use_buf(unsigned *lenp, void **bufp) diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c index bd2ad1d3b7a9..635b07b4fdd3 100644 --- a/tools/virtio/ringtest/ptr_ring.c +++ b/tools/virtio/ringtest/ptr_ring.c @@ -133,18 +133,9 @@ void *get_buf(unsigned *lenp, void **bufp)  	return datap;  } -void poll_used(void) +bool used_empty()  { -	void *b; - -	do { -		if (tailcnt == headcnt || __ptr_ring_full(&array)) { -			b = NULL; -			barrier(); -		} else { -			b = "Buffer\n"; -		} -	} while (!b); +	return (tailcnt == headcnt || __ptr_ring_full(&array));  }  void disable_call() @@ -173,14 +164,9 @@ bool enable_kick()  	assert(0);  } -void poll_avail(void) +bool avail_empty()  { -	void *b; - -	do { -		barrier(); -		b = __ptr_ring_peek(&array); -	} while (!b); +	return !__ptr_ring_peek(&array);  }  bool use_buf(unsigned *lenp, void **bufp) diff --git a/tools/virtio/ringtest/ring.c b/tools/virtio/ringtest/ring.c index c25c8d248b6b..747c5dd47be8 100644 --- a/tools/virtio/ringtest/ring.c +++ b/tools/virtio/ringtest/ring.c @@ -163,12 +163,11 @@ void *get_buf(unsigned *lenp, void **bufp)  	return datap;  } -void poll_used(void) +bool used_empty()  {  	unsigned head = (ring_size - 1) & guest.last_used_idx; -	while (ring[head].flags & DESC_HW) -		busy_wait(); +	return (ring[head].flags & DESC_HW);  }  void disable_call() @@ -180,13 +179,11 @@ void disable_call()  bool enable_call()  { -	unsigned head = (ring_size - 1) & guest.last_used_idx; -  	event->call_index = guest.last_used_idx;  	/* Flush call index write */  	/* Barrier D (for pairing) */  	smp_mb(); -	return ring[head].flags & DESC_HW; +	return used_empty();  }  void kick_available(void) @@ -213,20 +210,17 @@ void disable_kick()  bool enable_kick()  { -	unsigned head = (ring_size - 1) & host.used_idx; -  	event->kick_index = host.used_idx;  	/* Barrier C (for pairing) */  	smp_mb(); -	return !(ring[head].flags & DESC_HW); +	return avail_empty();  } -void poll_avail(void) +bool avail_empty()  {  	unsigned head = (ring_size - 1) & host.used_idx; -	while (!(ring[head].flags & DESC_HW)) -		busy_wait(); +	return !(ring[head].flags & DESC_HW);  }  bool use_buf(unsigned *lenp, void **bufp) diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c index 761866212aac..bbc3043b2fb1 100644 --- a/tools/virtio/ringtest/virtio_ring_0_9.c +++ b/tools/virtio/ringtest/virtio_ring_0_9.c @@ -194,24 +194,16 @@ void *get_buf(unsigned *lenp, void **bufp)  	return datap;  } -void poll_used(void) +bool used_empty()  { +	unsigned short last_used_idx = guest.last_used_idx;  #ifdef RING_POLL -	unsigned head = (ring_size - 1) & guest.last_used_idx; +	unsigned short head = last_used_idx & (ring_size - 1); +	unsigned index = ring.used->ring[head].id; -	for (;;) { -		unsigned index = ring.used->ring[head].id; - -		if ((index ^ guest.last_used_idx ^ 0x8000) & ~(ring_size - 1)) -			busy_wait(); -		else -			break; -	} +	return (index ^ last_used_idx ^ 0x8000) & ~(ring_size - 1);  #else -	unsigned head = guest.last_used_idx; - -	while (ring.used->idx == head) -		busy_wait(); +	return ring.used->idx == last_used_idx;  #endif  } @@ -224,22 +216,11 @@ void disable_call()  bool enable_call()  { -	unsigned short last_used_idx; - -	vring_used_event(&ring) = (last_used_idx = guest.last_used_idx); +	vring_used_event(&ring) = guest.last_used_idx;  	/* Flush call index write */  	/* Barrier D (for pairing) */  	smp_mb(); -#ifdef RING_POLL -	{ -		unsigned short head = last_used_idx & (ring_size - 1); -		unsigned index = ring.used->ring[head].id; - -		return (index ^ last_used_idx ^ 0x8000) & ~(ring_size - 1); -	} -#else -	return ring.used->idx == last_used_idx; -#endif +	return used_empty();  }  void kick_available(void) @@ -266,36 +247,21 @@ void disable_kick()  bool enable_kick()  { -	unsigned head = host.used_idx; - -	vring_avail_event(&ring) = head; +	vring_avail_event(&ring) = host.used_idx;  	/* Barrier C (for pairing) */  	smp_mb(); -#ifdef RING_POLL -	{ -		unsigned index = ring.avail->ring[head & (ring_size - 1)]; - -		return (index ^ head ^ 0x8000) & ~(ring_size - 1); -	} -#else -	return head == ring.avail->idx; -#endif +	return avail_empty();  } -void poll_avail(void) +bool avail_empty()  {  	unsigned head = host.used_idx;  #ifdef RING_POLL -	for (;;) { -		unsigned index = ring.avail->ring[head & (ring_size - 1)]; -		if ((index ^ head ^ 0x8000) & ~(ring_size - 1)) -			busy_wait(); -		else -			break; -	} +	unsigned index = ring.avail->ring[head & (ring_size - 1)]; + +	return ((index ^ head ^ 0x8000) & ~(ring_size - 1));  #else -	while (ring.avail->idx == head) -		busy_wait(); +	return head == ring.avail->idx;  #endif  } diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c index f397e9b20370..a29786dd9522 100644 --- a/virt/kvm/eventfd.c +++ b/virt/kvm/eventfd.c @@ -42,6 +42,7 @@  #ifdef CONFIG_HAVE_KVM_IRQFD +static struct workqueue_struct *irqfd_cleanup_wq;  static void  irqfd_inject(struct work_struct *work) @@ -167,7 +168,7 @@ irqfd_deactivate(struct kvm_kernel_irqfd *irqfd)  	list_del_init(&irqfd->list); -	schedule_work(&irqfd->shutdown); +	queue_work(irqfd_cleanup_wq, &irqfd->shutdown);  }  int __attribute__((weak)) kvm_arch_set_irq_inatomic( @@ -554,7 +555,7 @@ kvm_irqfd_deassign(struct kvm *kvm, struct kvm_irqfd *args)  	 * so that we guarantee there will not be any more interrupts on this  	 * gsi once this deassign function returns.  	 */ -	flush_work(&irqfd->shutdown); +	flush_workqueue(irqfd_cleanup_wq);  	return 0;  } @@ -591,7 +592,7 @@ kvm_irqfd_release(struct kvm *kvm)  	 * Block until we know all outstanding shutdown jobs have completed  	 * since we do not take a kvm* reference.  	 */ -	flush_work(&irqfd->shutdown); +	flush_workqueue(irqfd_cleanup_wq);  } @@ -621,8 +622,23 @@ void kvm_irq_routing_update(struct kvm *kvm)  	spin_unlock_irq(&kvm->irqfds.lock);  } +/* + * create a host-wide workqueue for issuing deferred shutdown requests + * aggregated from all vm* instances. We need our own isolated + * queue to ease flushing work items when a VM exits. + */ +int kvm_irqfd_init(void) +{ +	irqfd_cleanup_wq = alloc_workqueue("kvm-irqfd-cleanup", 0, 0); +	if (!irqfd_cleanup_wq) +		return -ENOMEM; + +	return 0; +} +  void kvm_irqfd_exit(void)  { +	destroy_workqueue(irqfd_cleanup_wq);  }  #endif diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2907b7b78654..5c360347a1e9 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -3844,7 +3844,12 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,  	 * kvm_arch_init makes sure there's at most one caller  	 * for architectures that support multiple implementations,  	 * like intel and amd on x86. +	 * kvm_arch_init must be called before kvm_irqfd_init to avoid creating +	 * conflicts in case kvm is already setup for another implementation.  	 */ +	r = kvm_irqfd_init(); +	if (r) +		goto out_irqfd;  	if (!zalloc_cpumask_var(&cpus_hardware_enabled, GFP_KERNEL)) {  		r = -ENOMEM; @@ -3926,6 +3931,7 @@ out_free_0a:  	free_cpumask_var(cpus_hardware_enabled);  out_free_0:  	kvm_irqfd_exit(); +out_irqfd:  	kvm_arch_exit();  out_fail:  	return r;  | 

