From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E932B32B99E; Sun, 17 May 2026 15:39:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779032384; cv=none; b=oeS7vscEh3a+TdJO7KjeVCnYiu8C0pNApe7pmS7NijFwlCPevM0P+1n66MR6fuuu6WkD2Ma9R7a6zEHHIrOQrfM5qwOihoQkmtEdcuZhctriKunMtgWHqu1Riea+s88alRKuIaoU08SFo1kfHQ22iZYtgjcC9L1ECO/WbXEE1qw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779032384; c=relaxed/simple; bh=E1fDLRtZKVYSkyUXN4V0+5h/yGpPvWXVZmqFRpedIes=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KXgiuxlb1jE0a/UxHcHRgtJ3Qjn7+wEcKAm+kB0Qa+SeZqqUNq7h4ZITrjalHR52Qn1hE/FC4XYSqhSnSOX1jQ1ktn8QdUs/AadCTQR2sLz/03Ti0QOQ1aIrgHg5oOcayqgx0rdnNfsGKlNNGaeiJM8QMseAQ5vQkI0xZ78UQ80= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b=VcLqOA0q; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.b="VcLqOA0q" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A0FCC2BCB0; Sun, 17 May 2026 15:39:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=linuxfoundation.org; s=korg; t=1779032383; bh=E1fDLRtZKVYSkyUXN4V0+5h/yGpPvWXVZmqFRpedIes=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VcLqOA0qVnS1rqKcGCb0RSweIxJtffCp1PiIwwRVpT73n0uOp1FLVVbblc5FJm71f 0IyWaKYigPsjKlpWvcHegaPpp2GcSOKxf0uiVFLwUNS4j4RSPgQPm6F39SnRzPd1c0 AnqhL8uRUpeD/D5QLxCLB2O+ITzudUdzej7u3y4o= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, akpm@linux-foundation.org, torvalds@linux-foundation.org, stable@vger.kernel.org Cc: lwn@lwn.net, jslaby@suse.cz, Greg Kroah-Hartman Subject: Re: Linux 6.18.32 Date: Sun, 17 May 2026 17:39:38 +0200 Message-ID: <2026051737-last-video-bca1@gregkh> X-Mailer: git-send-email 2.54.0 In-Reply-To: <2026051737-armored-feminist-9bea@gregkh> References: <2026051737-armored-feminist-9bea@gregkh> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit diff --git a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml index 96b6c8938768..d0bce8bfb1b1 100644 --- a/Documentation/devicetree/bindings/media/rockchip,vdec.yaml +++ b/Documentation/devicetree/bindings/media/rockchip,vdec.yaml @@ -27,16 +27,20 @@ properties: reg: minItems: 1 - items: - - description: The function configuration registers base - - description: The link table configuration registers base - - description: The cache configuration registers base + maxItems: 3 reg-names: - items: - - const: function - - const: link - - const: cache + oneOf: + - items: + - const: link + - const: function + - const: cache + - items: + - const: function + - const: link + - const: cache + deprecated: true + description: Use link,function,cache block order instead. interrupts: maxItems: 1 @@ -122,6 +126,8 @@ allOf: minItems: 5 reset-names: minItems: 5 + required: + - reg-names else: properties: reg: diff --git a/Makefile b/Makefile index 89c614db5240..d1fcec7cf956 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 6 PATCHLEVEL = 18 -SUBLEVEL = 31 +SUBLEVEL = 32 EXTRAVERSION = NAME = Baby Opossum Posse diff --git a/arch/arm64/boot/dts/broadcom/bcm2712-d-rpi-5-b.dts b/arch/arm64/boot/dts/broadcom/bcm2712-d-rpi-5-b.dts index 7de24d60bcd1..127be0fc27c2 100644 --- a/arch/arm64/boot/dts/broadcom/bcm2712-d-rpi-5-b.dts +++ b/arch/arm64/boot/dts/broadcom/bcm2712-d-rpi-5-b.dts @@ -35,3 +35,17 @@ &gio_aon { "PMIC_SCL", // AON_SGPIO_04 "PMIC_SDA"; // AON_SGPIO_05 }; + +&pinctrl { + compatible = "brcm,bcm2712d0-pinctrl"; + reg = <0x7d504100 0x20>; +}; + +&pinctrl_aon { + compatible = "brcm,bcm2712d0-aon-pinctrl"; + reg = <0x7d510700 0x1c>; +}; + +&uart10 { + interrupts = ; +}; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi index eec2cd6c6d32..7f6e39e27ce5 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-cex7.dtsi @@ -162,6 +162,8 @@ rtc@51 { }; &fspi { + pinctrl-names = "default"; + pinctrl-0 = <&fspi_data74_pins>, <&fspi_data30_pins>, <&fspi_dqs_sck_cs10_pins>; status = "okay"; flash@0 { @@ -177,6 +179,11 @@ flash@0 { }; }; +&pinmux_i2crv { + pinctrl-names = "default"; + pinctrl-0 = <&gpio0_14_12_pins>; +}; + &usb0 { status = "okay"; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi index af6258b2fe82..580ee9b3026e 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a-clearfog-itx.dtsi @@ -89,6 +89,8 @@ &emdio2 { }; &esdhc0 { + pinctrl-names = "default"; + pinctrl-0 = <&esdhc0_cd_wp_pins>, <&esdhc0_cmd_data30_clk_vsel_pins>; sd-uhs-sdr104; sd-uhs-sdr50; sd-uhs-sdr25; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi index c9541403bcd8..bc1d34f1cd54 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2160a.dtsi @@ -1717,6 +1717,10 @@ i2c1_scl_gpio: i2c1-scl-gpio-pins { pinctrl-single,bits = <0x0 0x1 0x7>; }; + esdhc0_cd_wp_pins: iic2-sdhc-pins { + pinctrl-single,bits = <0x0 0x6 0x7>; + }; + i2c2_scl: i2c2-scl-pins { pinctrl-single,bits = <0x0 0 (0x7 << 3)>; }; @@ -1749,6 +1753,26 @@ i2c5_scl_gpio: i2c5-scl-gpio-pins { pinctrl-single,bits = <0x0 (0x1 << 12) (0x7 << 12)>; }; + fspi_data74_pins: xspi1-data74-pins { + pinctrl-single,bits = <0x0 0x0 (0x7 << 15)>; + }; + + fspi_data30_pins: xspi1-data30-pins { + pinctrl-single,bits = <0x0 0x0 (0x7 << 18)>; + }; + + fspi_dqs_sck_cs10_pins: xspi1-base-pins { + pinctrl-single,bits = <0x0 0x0 (0x7 << 21)>; + }; + + esdhc0_cmd_data30_clk_vsel_pins: sdhc1-base-sdhc-vsel-pins { + pinctrl-single,bits = <0x0 0x0 (0x7 << 24)>; + }; + + gpio0_14_12_pins: sdhc1-dir-gpio-pins { + pinctrl-single,bits = <0x0 (0x1 << 27) (0x7 << 27)>; + }; + i2c6_scl: i2c6-scl-pins { pinctrl-single,bits = <0x4 0x2 0x7>; }; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts index eafef8718a0f..8920326a0673 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts +++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-clearfog.dts @@ -223,6 +223,8 @@ ethernet_phy8: ethernet-phy@15 { }; &esdhc0 { + pinctrl-names = "default"; + pinctrl-0 = <&esdhc0_cd_wp_pins>, <&esdhc0_cmd_data30_clk_vsel_pins>; sd-uhs-sdr104; sd-uhs-sdr50; sd-uhs-sdr25; diff --git a/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi b/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi index e914291e63a1..e1344942eaae 100644 --- a/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi +++ b/arch/arm64/boot/dts/freescale/fsl-lx2162a-sr-som.dtsi @@ -30,6 +30,8 @@ &esdhc1 { }; &fspi { + pinctrl-names = "default"; + pinctrl-0 = <&fspi_data74_pins>, <&fspi_data30_pins>, <&fspi_dqs_sck_cs10_pins>; status = "okay"; flash@0 { @@ -80,3 +82,8 @@ rtc@6f { reg = <0x6f>; }; }; + +&pinmux_i2crv { + pinctrl-names = "default"; + pinctrl-0 = <&gpio0_14_12_pins>; +}; diff --git a/arch/arm64/boot/dts/qcom/lemans.dtsi b/arch/arm64/boot/dts/qcom/lemans.dtsi index c2d2200d845b..530dc1e832b7 100644 --- a/arch/arm64/boot/dts/qcom/lemans.dtsi +++ b/arch/arm64/boot/dts/qcom/lemans.dtsi @@ -1563,7 +1563,7 @@ i2c20: i2c@898000 { reg = <0x0 0x898000 0x0 0x4000>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>; clock-names = "se"; pinctrl-0 = <&qup_i2c20_default>; @@ -1590,7 +1590,7 @@ spi20: spi@898000 { reg = <0x0 0x898000 0x0 0x4000>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>; clock-names = "se"; pinctrl-0 = <&qup_spi20_default>; @@ -1615,7 +1615,7 @@ &config_noc SLAVE_QUP_2 QCOM_ICC_TAG_ALWAYS>, uart20: serial@898000 { compatible = "qcom,geni-uart"; reg = <0x0 0x00898000 0x0 0x4000>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP2_S6_CLK>; clock-names = "se"; pinctrl-0 = <&qup_uart20_default>; @@ -2561,7 +2561,7 @@ i2c13: i2c@a98000 { reg = <0x0 0xa98000 0x0 0x4000>; #address-cells = <1>; #size-cells = <0>; - interrupts = ; + interrupts = ; clocks = <&gcc GCC_QUPV3_WRAP1_S6_CLK>; clock-names = "se"; pinctrl-0 = <&qup_i2c13_default>; diff --git a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts index af591fe6ae4f..b41d8dd159ad 100644 --- a/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts +++ b/arch/arm64/boot/dts/ti/k3-am62a7-sk.dts @@ -394,7 +394,7 @@ AM62AX_IOPAD(0x01d4, PIN_INPUT, 7) /* (C15) UART0_RTSn.GPIO1_23 */ vddshv_sdio_pins_default: vddshv-sdio-default-pins { pinctrl-single,pins = < - AM62AX_IOPAD(0x07c, PIN_OUTPUT, 7) /* (M19) GPMC0_CLK.GPIO0_31 */ + AM62AX_IOPAD(0x07c, PIN_OUTPUT, 7) /* (N22) GPMC0_CLK.GPIO0_31 */ >; }; diff --git a/arch/loongarch/Kbuild b/arch/loongarch/Kbuild index beb8499dd8ed..1c7a0dbe5e72 100644 --- a/arch/loongarch/Kbuild +++ b/arch/loongarch/Kbuild @@ -3,7 +3,7 @@ obj-y += mm/ obj-y += net/ obj-y += vdso/ -obj-$(CONFIG_KVM) += kvm/ +obj-$(subst m,y,$(CONFIG_KVM)) += kvm/ # for cleaning subdir- += boot diff --git a/arch/loongarch/include/asm/asm-prototypes.h b/arch/loongarch/include/asm/asm-prototypes.h index 704066b4f736..de0c17f3f49c 100644 --- a/arch/loongarch/include/asm/asm-prototypes.h +++ b/arch/loongarch/include/asm/asm-prototypes.h @@ -20,3 +20,23 @@ asmlinkage void noinstr __no_stack_protector ret_from_kernel_thread(struct task_ struct pt_regs *regs, int (*fn)(void *), void *fn_arg); + +struct kvm_run; +struct kvm_vcpu; +struct loongarch_fpu; + +void kvm_exc_entry(void); +int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu); + +void kvm_save_fpu(struct loongarch_fpu *fpu); +void kvm_restore_fpu(struct loongarch_fpu *fpu); + +#ifdef CONFIG_CPU_HAS_LSX +void kvm_save_lsx(struct loongarch_fpu *fpu); +void kvm_restore_lsx(struct loongarch_fpu *fpu); +#endif + +#ifdef CONFIG_CPU_HAS_LASX +void kvm_save_lasx(struct loongarch_fpu *fpu); +void kvm_restore_lasx(struct loongarch_fpu *fpu); +#endif diff --git a/arch/loongarch/include/asm/kvm_host.h b/arch/loongarch/include/asm/kvm_host.h index 0cecbd038bb3..377d7fb04bda 100644 --- a/arch/loongarch/include/asm/kvm_host.h +++ b/arch/loongarch/include/asm/kvm_host.h @@ -85,7 +85,6 @@ struct kvm_context { struct kvm_world_switch { int (*exc_entry)(void); int (*enter_guest)(struct kvm_run *run, struct kvm_vcpu *vcpu); - unsigned long page_order; }; #define MAX_PGTABLE_LEVELS 4 @@ -339,8 +338,6 @@ void kvm_exc_entry(void); int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu); extern unsigned long vpid_mask; -extern const unsigned long kvm_exception_size; -extern const unsigned long kvm_enter_guest_size; extern struct kvm_world_switch *kvm_loongarch_ops; #define SW_GCSR (1 << 0) diff --git a/arch/loongarch/kvm/Makefile b/arch/loongarch/kvm/Makefile index cb41d9265662..f32a170c1838 100644 --- a/arch/loongarch/kvm/Makefile +++ b/arch/loongarch/kvm/Makefile @@ -7,11 +7,12 @@ include $(srctree)/virt/kvm/Makefile.kvm obj-$(CONFIG_KVM) += kvm.o +obj-y += switch.o + kvm-y += exit.o kvm-y += interrupt.o kvm-y += main.o kvm-y += mmu.o -kvm-y += switch.o kvm-y += timer.o kvm-y += tlb.o kvm-y += vcpu.o diff --git a/arch/loongarch/kvm/main.c b/arch/loongarch/kvm/main.c index 80ea63d465b8..67d234540ed4 100644 --- a/arch/loongarch/kvm/main.c +++ b/arch/loongarch/kvm/main.c @@ -340,8 +340,7 @@ void kvm_arch_disable_virtualization_cpu(void) static int kvm_loongarch_env_init(void) { - int cpu, order, ret; - void *addr; + int cpu, ret; struct kvm_context *context; vmcs = alloc_percpu(struct kvm_context); @@ -357,30 +356,8 @@ static int kvm_loongarch_env_init(void) return -ENOMEM; } - /* - * PGD register is shared between root kernel and kvm hypervisor. - * So world switch entry should be in DMW area rather than TLB area - * to avoid page fault reenter. - * - * In future if hardware pagetable walking is supported, we won't - * need to copy world switch code to DMW area. - */ - order = get_order(kvm_exception_size + kvm_enter_guest_size); - addr = (void *)__get_free_pages(GFP_KERNEL, order); - if (!addr) { - free_percpu(vmcs); - vmcs = NULL; - kfree(kvm_loongarch_ops); - kvm_loongarch_ops = NULL; - return -ENOMEM; - } - - memcpy(addr, kvm_exc_entry, kvm_exception_size); - memcpy(addr + kvm_exception_size, kvm_enter_guest, kvm_enter_guest_size); - flush_icache_range((unsigned long)addr, (unsigned long)addr + kvm_exception_size + kvm_enter_guest_size); - kvm_loongarch_ops->exc_entry = addr; - kvm_loongarch_ops->enter_guest = addr + kvm_exception_size; - kvm_loongarch_ops->page_order = order; + kvm_loongarch_ops->exc_entry = (void *)kvm_exc_entry; + kvm_loongarch_ops->enter_guest = (void *)kvm_enter_guest; vpid_mask = read_csr_gstat(); vpid_mask = (vpid_mask & CSR_GSTAT_GIDBIT) >> CSR_GSTAT_GIDBIT_SHIFT; @@ -414,16 +391,10 @@ static int kvm_loongarch_env_init(void) static void kvm_loongarch_env_exit(void) { - unsigned long addr; - if (vmcs) free_percpu(vmcs); if (kvm_loongarch_ops) { - if (kvm_loongarch_ops->exc_entry) { - addr = (unsigned long)kvm_loongarch_ops->exc_entry; - free_pages(addr, kvm_loongarch_ops->page_order); - } kfree(kvm_loongarch_ops); } diff --git a/arch/loongarch/kvm/switch.S b/arch/loongarch/kvm/switch.S index 9eaad5dbed91..281daf0b7810 100644 --- a/arch/loongarch/kvm/switch.S +++ b/arch/loongarch/kvm/switch.S @@ -4,9 +4,11 @@ */ #include +#include #include #include #include +#include #include #include @@ -100,8 +102,13 @@ * - is still in guest mode, such as pgd table/vmid registers etc, * - will fix with hw page walk enabled in future * load kvm_vcpu from reserved CSR KVM_VCPU_KS, and save a2 to KVM_TEMP_KS + * + * PGD register is shared between root kernel and kvm hypervisor. + * So world switch entry should be in DMW area rather than TLB area + * to avoid page fault re-enter. */ .text + .p2align PAGE_SHIFT .cfi_sections .debug_frame SYM_CODE_START(kvm_exc_entry) UNWIND_HINT_END_OF_STACK @@ -190,8 +197,8 @@ ret_to_host: kvm_restore_host_gpr a2 jr ra -SYM_INNER_LABEL(kvm_exc_entry_end, SYM_L_LOCAL) SYM_CODE_END(kvm_exc_entry) +EXPORT_SYMBOL_GPL(kvm_exc_entry) /* * int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu) @@ -215,8 +222,8 @@ SYM_FUNC_START(kvm_enter_guest) /* Save kvm_vcpu to kscratch */ csrwr a1, KVM_VCPU_KS kvm_switch_to_guest -SYM_INNER_LABEL(kvm_enter_guest_end, SYM_L_LOCAL) SYM_FUNC_END(kvm_enter_guest) +EXPORT_SYMBOL_GPL(kvm_enter_guest) SYM_FUNC_START(kvm_save_fpu) fpu_save_csr a0 t1 @@ -224,6 +231,7 @@ SYM_FUNC_START(kvm_save_fpu) fpu_save_cc a0 t1 t2 jr ra SYM_FUNC_END(kvm_save_fpu) +EXPORT_SYMBOL_GPL(kvm_save_fpu) SYM_FUNC_START(kvm_restore_fpu) fpu_restore_double a0 t1 @@ -231,6 +239,7 @@ SYM_FUNC_START(kvm_restore_fpu) fpu_restore_cc a0 t1 t2 jr ra SYM_FUNC_END(kvm_restore_fpu) +EXPORT_SYMBOL_GPL(kvm_restore_fpu) #ifdef CONFIG_CPU_HAS_LSX SYM_FUNC_START(kvm_save_lsx) @@ -239,6 +248,7 @@ SYM_FUNC_START(kvm_save_lsx) lsx_save_data a0 t1 jr ra SYM_FUNC_END(kvm_save_lsx) +EXPORT_SYMBOL_GPL(kvm_save_lsx) SYM_FUNC_START(kvm_restore_lsx) lsx_restore_data a0 t1 @@ -246,6 +256,7 @@ SYM_FUNC_START(kvm_restore_lsx) fpu_restore_csr a0 t1 t2 jr ra SYM_FUNC_END(kvm_restore_lsx) +EXPORT_SYMBOL_GPL(kvm_restore_lsx) #endif #ifdef CONFIG_CPU_HAS_LASX @@ -255,6 +266,7 @@ SYM_FUNC_START(kvm_save_lasx) lasx_save_data a0 t1 jr ra SYM_FUNC_END(kvm_save_lasx) +EXPORT_SYMBOL_GPL(kvm_save_lasx) SYM_FUNC_START(kvm_restore_lasx) lasx_restore_data a0 t1 @@ -262,10 +274,8 @@ SYM_FUNC_START(kvm_restore_lasx) fpu_restore_csr a0 t1 t2 jr ra SYM_FUNC_END(kvm_restore_lasx) +EXPORT_SYMBOL_GPL(kvm_restore_lasx) #endif - .section ".rodata" -SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry) -SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest) #ifdef CONFIG_CPU_HAS_LBT STACK_FRAME_NON_STANDARD kvm_restore_fpu diff --git a/arch/powerpc/platforms/pseries/papr-hvpipe.c b/arch/powerpc/platforms/pseries/papr-hvpipe.c index 431f6a3da4c5..a238db095b4e 100644 --- a/arch/powerpc/platforms/pseries/papr-hvpipe.c +++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c @@ -449,13 +449,14 @@ static int papr_hvpipe_handle_release(struct inode *inode, struct file *file) { struct hvpipe_source_info *src_info; + unsigned long flags; /* * Hold the lock, remove source from src_list, reset the * hvpipe status and release the lock to prevent any race * with message event IRQ. */ - spin_lock(&hvpipe_src_list_lock); + spin_lock_irqsave(&hvpipe_src_list_lock, flags); src_info = file->private_data; list_del(&src_info->list); file->private_data = NULL; @@ -466,10 +467,10 @@ static int papr_hvpipe_handle_release(struct inode *inode, */ if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) { src_info->hvpipe_status = 0; - spin_unlock(&hvpipe_src_list_lock); + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); hvpipe_rtas_recv_msg(NULL, 0); } else - spin_unlock(&hvpipe_src_list_lock); + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); kfree(src_info); return 0; @@ -484,24 +485,22 @@ static const struct file_operations papr_hvpipe_handle_ops = { static int papr_hvpipe_dev_create_handle(u32 srcID) { - struct hvpipe_source_info *src_info; - struct file *file; - long err; - int fd; + struct hvpipe_source_info *src_info __free(kfree) = NULL; + unsigned long flags; - spin_lock(&hvpipe_src_list_lock); + spin_lock_irqsave(&hvpipe_src_list_lock, flags); /* * Do not allow more than one process communicates with * each source. */ src_info = hvpipe_find_source(srcID); if (src_info) { - spin_unlock(&hvpipe_src_list_lock); + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); pr_err("pid(%d) is already using the source(%d)\n", src_info->tsk->pid, srcID); return -EALREADY; } - spin_unlock(&hvpipe_src_list_lock); + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); src_info = kzalloc(sizeof(*src_info), GFP_KERNEL_ACCOUNT); if (!src_info) @@ -511,44 +510,26 @@ static int papr_hvpipe_dev_create_handle(u32 srcID) src_info->tsk = current; init_waitqueue_head(&src_info->recv_wqh); - fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC); - if (fd < 0) { - err = fd; - goto free_buf; - } + FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC, + anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops, + (void *)src_info, O_RDWR)); + if (fdf.err) + return fdf.err; - file = anon_inode_getfile("[papr-hvpipe]", - &papr_hvpipe_handle_ops, (void *)src_info, - O_RDWR); - if (IS_ERR(file)) { - err = PTR_ERR(file); - goto free_fd; - } - - spin_lock(&hvpipe_src_list_lock); + retain_and_null_ptr(src_info); + spin_lock_irqsave(&hvpipe_src_list_lock, flags); /* * If two processes are executing ioctl() for the same * source ID concurrently, prevent the second process to * acquire FD. */ if (hvpipe_find_source(srcID)) { - spin_unlock(&hvpipe_src_list_lock); - err = -EALREADY; - goto free_file; + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + return -EALREADY; } list_add(&src_info->list, &hvpipe_src_list); - spin_unlock(&hvpipe_src_list_lock); - - fd_install(fd, file); - return fd; - -free_file: - fput(file); -free_fd: - put_unused_fd(fd); -free_buf: - kfree(src_info); - return err; + spin_unlock_irqrestore(&hvpipe_src_list_lock, flags); + return fd_publish(fdf); } /* diff --git a/block/blk-zoned.c b/block/blk-zoned.c index e98bd9ad0232..59b7a1d14af5 100644 --- a/block/blk-zoned.c +++ b/block/blk-zoned.c @@ -83,17 +83,17 @@ static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk) * being executed or the zone write plug bio list is not empty. * - BLK_ZONE_WPLUG_NEED_WP_UPDATE: Indicates that we lost track of a zone * write pointer offset and need to update it. - * - BLK_ZONE_WPLUG_UNHASHED: Indicates that the zone write plug was removed - * from the disk hash table and that the initial reference to the zone - * write plug set when the plug was first added to the hash table has been - * dropped. This flag is set when a zone is reset, finished or become full, - * to prevent new references to the zone write plug to be taken for - * newly incoming BIOs. A zone write plug flagged with this flag will be - * freed once all remaining references from BIOs or functions are dropped. + * - BLK_ZONE_WPLUG_DEAD: Indicates that the zone write plug will be + * removed from the disk hash table of zone write plugs when the last + * reference on the zone write plug is dropped. If set, this flag also + * indicates that the initial extra reference on the zone write plug was + * dropped, meaning that the reference count indicates the current number of + * active users (code context or BIOs and requests in flight). This flag is + * set when a zone is reset, finished or becomes full. */ #define BLK_ZONE_WPLUG_PLUGGED (1U << 0) #define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1) -#define BLK_ZONE_WPLUG_UNHASHED (1U << 2) +#define BLK_ZONE_WPLUG_DEAD (1U << 2) /** * blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX. @@ -467,67 +467,42 @@ static void disk_free_zone_wplug_rcu(struct rcu_head *rcu_head) mempool_free(zwplug, zwplug->disk->zone_wplugs_pool); } -static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug) +static void disk_free_zone_wplug(struct blk_zone_wplug *zwplug) { - if (refcount_dec_and_test(&zwplug->ref)) { - WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list)); - WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED); - WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)); - - call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu); - } -} - -static inline bool disk_should_remove_zone_wplug(struct gendisk *disk, - struct blk_zone_wplug *zwplug) -{ - lockdep_assert_held(&zwplug->lock); - - /* If the zone write plug was already removed, we are done. */ - if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) - return false; + struct gendisk *disk = zwplug->disk; + unsigned long flags; - /* If the zone write plug is still plugged, it cannot be removed. */ - if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED) - return false; + WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)); + WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED); + WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list)); - /* - * Completions of BIOs with blk_zone_write_plug_bio_endio() may - * happen after handling a request completion with - * blk_zone_write_plug_finish_request() (e.g. with split BIOs - * that are chained). In such case, disk_zone_wplug_unplug_bio() - * should not attempt to remove the zone write plug until all BIO - * completions are seen. Check by looking at the zone write plug - * reference count, which is 2 when the plug is unused (one reference - * taken when the plug was allocated and another reference taken by the - * caller context). - */ - if (refcount_read(&zwplug->ref) > 2) - return false; + spin_lock_irqsave(&disk->zone_wplugs_lock, flags); + hlist_del_init_rcu(&zwplug->node); + atomic_dec(&disk->nr_zone_wplugs); + spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); - /* We can remove zone write plugs for zones that are empty or full. */ - return !zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug); + call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu); } -static void disk_remove_zone_wplug(struct gendisk *disk, - struct blk_zone_wplug *zwplug) +static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug) { - unsigned long flags; + if (refcount_dec_and_test(&zwplug->ref)) + disk_free_zone_wplug(zwplug); +} - /* If the zone write plug was already removed, we have nothing to do. */ - if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) - return; +/* + * Flag the zone write plug as dead and drop the initial reference we got when + * the zone write plug was added to the hash table. The zone write plug will be + * unhashed when its last reference is dropped. + */ +static void disk_mark_zone_wplug_dead(struct blk_zone_wplug *zwplug) +{ + lockdep_assert_held(&zwplug->lock); - /* - * Mark the zone write plug as unhashed and drop the extra reference we - * took when the plug was inserted in the hash table. - */ - zwplug->flags |= BLK_ZONE_WPLUG_UNHASHED; - spin_lock_irqsave(&disk->zone_wplugs_lock, flags); - hlist_del_init_rcu(&zwplug->node); - atomic_dec(&disk->nr_zone_wplugs); - spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags); - disk_put_zone_wplug(zwplug); + if (!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)) { + zwplug->flags |= BLK_ZONE_WPLUG_DEAD; + disk_put_zone_wplug(zwplug); + } } static void blk_zone_wplug_bio_work(struct work_struct *work); @@ -547,18 +522,7 @@ static struct blk_zone_wplug *disk_get_and_lock_zone_wplug(struct gendisk *disk, again: zwplug = disk_get_zone_wplug(disk, sector); if (zwplug) { - /* - * Check that a BIO completion or a zone reset or finish - * operation has not already removed the zone write plug from - * the hash table and dropped its reference count. In such case, - * we need to get a new plug so start over from the beginning. - */ spin_lock_irqsave(&zwplug->lock, *flags); - if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) { - spin_unlock_irqrestore(&zwplug->lock, *flags); - disk_put_zone_wplug(zwplug); - goto again; - } return zwplug; } @@ -645,14 +609,8 @@ static void disk_zone_wplug_set_wp_offset(struct gendisk *disk, zwplug->flags &= ~BLK_ZONE_WPLUG_NEED_WP_UPDATE; zwplug->wp_offset = wp_offset; disk_zone_wplug_abort(zwplug); - - /* - * The zone write plug now has no BIO plugged: remove it from the - * hash table so that it cannot be seen. The plug will be freed - * when the last reference is dropped. - */ - if (disk_should_remove_zone_wplug(disk, zwplug)) - disk_remove_zone_wplug(disk, zwplug); + if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug)) + disk_mark_zone_wplug_dead(zwplug); } static unsigned int blk_zone_wp_offset(struct blk_zone *zone) @@ -1068,6 +1026,19 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs) return true; } + /* + * If we got a zone write plug marked as dead, then the user is issuing + * writes to a full zone, or without synchronizing with zone reset or + * zone finish operations. In such case, fail the BIO to signal this + * invalid usage. + */ + if (zwplug->flags & BLK_ZONE_WPLUG_DEAD) { + spin_unlock_irqrestore(&zwplug->lock, flags); + disk_put_zone_wplug(zwplug); + bio_io_error(bio); + return true; + } + /* Indicate that this BIO is being handled using zone write plugging. */ bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING); @@ -1136,7 +1107,7 @@ static void blk_zone_wplug_handle_native_zone_append(struct bio *bio) disk->disk_name, zwplug->zone_no); disk_zone_wplug_abort(zwplug); } - disk_remove_zone_wplug(disk, zwplug); + disk_mark_zone_wplug_dead(zwplug); spin_unlock_irqrestore(&zwplug->lock, flags); disk_put_zone_wplug(zwplug); @@ -1239,14 +1210,8 @@ static void disk_zone_wplug_unplug_bio(struct gendisk *disk, } zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED; - - /* - * If the zone is full (it was fully written or finished, or empty - * (it was reset), remove its zone write plug from the hash table. - */ - if (disk_should_remove_zone_wplug(disk, zwplug)) - disk_remove_zone_wplug(disk, zwplug); - + if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug)) + disk_mark_zone_wplug_dead(zwplug); spin_unlock_irqrestore(&zwplug->lock, flags); } @@ -1457,9 +1422,9 @@ static void disk_destroy_zone_wplugs_hash_table(struct gendisk *disk) while (!hlist_empty(&disk->zone_wplugs_hash[i])) { zwplug = hlist_entry(disk->zone_wplugs_hash[i].first, struct blk_zone_wplug, node); - refcount_inc(&zwplug->ref); - disk_remove_zone_wplug(disk, zwplug); - disk_put_zone_wplug(zwplug); + spin_lock_irq(&zwplug->lock); + disk_mark_zone_wplug_dead(zwplug); + spin_unlock_irq(&zwplug->lock); } } diff --git a/drivers/edac/versalnet_edac.c b/drivers/edac/versalnet_edac.c index f90723bc93d5..4053ee2e0bee 100644 --- a/drivers/edac/versalnet_edac.c +++ b/drivers/edac/versalnet_edac.c @@ -765,9 +765,9 @@ static int init_versalnet(struct mc_priv *priv, struct platform_device *pdev) u32 num_chans, rank, dwidth, config; struct edac_mc_layer layers[2]; struct mem_ctl_info *mci; + char name[32]; struct device *dev; enum dev_type dt; - char *name; int rc, i; for (i = 0; i < NUM_CONTROLLERS; i++) { @@ -814,7 +814,6 @@ static int init_versalnet(struct mc_priv *priv, struct platform_device *pdev) dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev->release = versal_edac_release; - name = kmalloc(32, GFP_KERNEL); sprintf(name, "versal-net-ddrmc5-edac-%d", i); dev->init_name = name; rc = device_register(dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index d3f541d3108c..0ab85d0a6a43 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1717,7 +1717,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( alloc_domain = AMDGPU_GEM_DOMAIN_GTT; alloc_flags = 0; } else { - alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE; + alloc_flags = AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE | + AMDGPU_GEM_CREATE_VRAM_CLEARED; alloc_flags |= (flags & KFD_IOC_ALLOC_MEM_FLAGS_PUBLIC) ? AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED : 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index 83f3b94ed975..3392bd930c91 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -262,12 +262,19 @@ void amdgpu_gart_table_ram_free(struct amdgpu_device *adev) */ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev) { + int r; + if (adev->gart.bo != NULL) return 0; - return amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE, - AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo, - NULL, (void *)&adev->gart.ptr); + r = amdgpu_bo_create_kernel(adev, adev->gart.table_size, PAGE_SIZE, + AMDGPU_GEM_DOMAIN_VRAM, &adev->gart.bo, + NULL, (void *)&adev->gart.ptr); + if (r) + return r; + + memset_io(adev->gart.ptr, adev->gart.gart_pte_flags, adev->gart.table_size); + return 0; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c index 1e3b8a506d1b..b8613888c5c3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c @@ -737,6 +737,12 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid, return 0; if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) { + + if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid) { + r = 0; + goto error_unlock_reset; + } + if (adev->gmc.flush_tlb_needs_extra_type_2) adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid, 2, all_hub, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 4b46e3c26ff3..0098b1eadfc8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -547,15 +547,18 @@ void amdgpu_debugfs_ring_init(struct amdgpu_device *adev, int amdgpu_ring_init_mqd(struct amdgpu_ring *ring); -static inline u32 amdgpu_ib_get_value(struct amdgpu_ib *ib, int idx) +static inline u32 amdgpu_ib_get_value(struct amdgpu_ib *ib, uint32_t idx) { - return ib->ptr[idx]; + if (idx < ib->length_dw) + return ib->ptr[idx]; + return 0; } -static inline void amdgpu_ib_set_value(struct amdgpu_ib *ib, int idx, +static inline void amdgpu_ib_set_value(struct amdgpu_ib *ib, uint32_t idx, uint32_t value) { - ib->ptr[idx] = value; + if (idx < ib->length_dw) + ib->ptr[idx] = value; } int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index ce318f5de047..3b9a9010ed35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -656,6 +656,9 @@ static int amdgpu_vce_cs_reloc(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib, uint64_t addr; int r; + if (lo >= ib->length_dw || hi >= ib->length_dw) + return -EINVAL; + if (index == 0xffffffff) index = 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 69080e373489..0d7c48927f39 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1066,9 +1066,10 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params, } /* Prepare a TLB flush fence to be attached to PTs */ - if (!params->unlocked && - /* SI doesn't support pasid or KIQ/MES */ - params->adev->family > AMDGPU_FAMILY_SI) { + /* The check for need_tlb_fence should be dropped once we + * sort out the issues with KIQ/MES TLB invalidation timeouts. + */ + if (!params->unlocked && vm->need_tlb_fence) { amdgpu_vm_tlb_fence_create(params->adev, vm, fence); /* Makes sure no PD/PT is freed before the flush */ @@ -2586,6 +2587,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, ttm_lru_bulk_move_init(&vm->lru_bulk_move); vm->is_compute_context = false; + vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev); vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode & AMDGPU_VM_USE_CPU_FOR_GFX); @@ -2723,6 +2725,7 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) dma_fence_put(vm->last_update); vm->last_update = dma_fence_get_stub(); vm->is_compute_context = true; + vm->need_tlb_fence = true; unreserve_bo: amdgpu_bo_unreserve(vm->root.bo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 70fec516a290..076d9a3a5e62 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -439,6 +439,8 @@ struct amdgpu_vm { struct ttm_lru_bulk_move lru_bulk_move; /* Flag to indicate if VM is used for compute */ bool is_compute_context; + /* Flag to indicate if VM needs a TLB fence (KFD or KGD) */ + bool need_tlb_fence; /* Memory partition number, -1 means any partition */ int8_t mem_id; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c index 22e2e5b47341..f078db3fef79 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c @@ -21,6 +21,8 @@ */ #include "amdgpu_vm.h" +#include "amdgpu.h" +#include "amdgpu_reset.h" #include "amdgpu_object.h" #include "amdgpu_trace.h" @@ -108,11 +110,19 @@ static int amdgpu_vm_cpu_update(struct amdgpu_vm_update_params *p, static int amdgpu_vm_cpu_commit(struct amdgpu_vm_update_params *p, struct dma_fence **fence) { + struct amdgpu_device *adev = p->adev; + if (p->needs_flush) atomic64_inc(&p->vm->tlb_seq); mb(); - amdgpu_device_flush_hdp(p->adev, NULL); + /* A reset flushed the HDP anyway, so that here can be skipped when a reset is ongoing */ + if (!down_read_trylock(&adev->reset_domain->sem)) + return 0; + + amdgpu_device_flush_hdp(adev, NULL); + up_read(&adev->reset_domain->sem); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c index 1dd9fd486eec..feb56b6b31c9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c @@ -64,6 +64,11 @@ #define regPC_CONFIG_CNTL_1 0x194d #define regPC_CONFIG_CNTL_1_BASE_IDX 1 +#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0 0x0030 +#define regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0_BASE_IDX 1 +#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0 0x0031 +#define regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0_BASE_IDX 1 + #define regCP_GFX_MQD_CONTROL_DEFAULT 0x00000100 #define regCP_GFX_HQD_VMID_DEFAULT 0x00000000 #define regCP_GFX_HQD_QUEUE_PRIORITY_DEFAULT 0x00000000 @@ -5174,11 +5179,27 @@ static uint64_t gfx_v11_0_get_gpu_clock_counter(struct amdgpu_device *adev) amdgpu_gfx_off_ctrl(adev, true); } else { preempt_disable(); - clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER); - clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER); - clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_UPPER); - if (clock_counter_hi_pre != clock_counter_hi_after) - clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, regGOLDEN_TSC_COUNT_LOWER); + if (amdgpu_ip_version(adev, SMUIO_HWIP, 0) < IP_VERSION(15, 0, 0)) { + clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_UPPER); + clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_LOWER); + clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_UPPER); + if (clock_counter_hi_pre != clock_counter_hi_after) + clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_LOWER); + } else { + clock_counter_hi_pre = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0); + clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0); + clock_counter_hi_after = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_UPPER_smu_15_0_0); + if (clock_counter_hi_pre != clock_counter_hi_after) + clock_counter_lo = (uint64_t)RREG32_SOC15(SMUIO, 0, + regGOLDEN_TSC_COUNT_LOWER_smu_15_0_0); + } preempt_enable(); } clock = clock_counter_lo | (clock_counter_hi_after << 32ULL); diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 7d0a2d239b78..f589457f6018 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -5640,9 +5640,6 @@ static void gfx_v9_0_ring_emit_fence_kiq(struct amdgpu_ring *ring, u64 addr, { struct amdgpu_device *adev = ring->adev; - /* we only allocate 32bit for each seq wb address */ - BUG_ON(flags & AMDGPU_FENCE_FLAG_64BIT); - /* write fence seq to the "addr" */ amdgpu_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3)); amdgpu_ring_write(ring, (WRITE_DATA_ENGINE_SEL(0) | diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index f38004e6064e..4d0dc58c9045 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -890,7 +890,7 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se /* write the fence */ amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE)); /* zero in first two bits */ - BUG_ON(addr & 0x3); + WARN_ON(addr & 0x3); amdgpu_ring_write(ring, lower_32_bits(addr)); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, lower_32_bits(seq)); @@ -900,7 +900,7 @@ static void sdma_v4_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se addr += 4; amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE)); /* zero in first two bits */ - BUG_ON(addr & 0x3); + WARN_ON(addr & 0x3); amdgpu_ring_write(ring, lower_32_bits(addr)); amdgpu_ring_write(ring, upper_32_bits(addr)); amdgpu_ring_write(ring, upper_32_bits(seq)); diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index d9cf8f0feeb3..8b226edfbea3 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -1908,7 +1908,7 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, { struct ttm_operation_ctx ctx = { false, false }; struct amdgpu_bo_va_mapping *map; - uint32_t *msg, num_buffers; + uint32_t *msg, num_buffers, len_dw; struct amdgpu_bo *bo; uint64_t start, end; unsigned int i; @@ -1929,6 +1929,11 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, return -EINVAL; } + if (end - addr < 16) { + DRM_ERROR("VCN messages must be at least 4 DWORDs!\n"); + return -EINVAL; + } + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); @@ -1945,8 +1950,8 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, msg = ptr + addr - start; - /* Check length */ if (msg[1] > end - addr) { + DRM_ERROR("VCN message header does not fit in BO!\n"); r = -EINVAL; goto out; } @@ -1954,9 +1959,19 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, if (msg[3] != RDECODE_MSG_CREATE) goto out; + len_dw = msg[1] / 4; num_buffers = msg[2]; + + /* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */ + if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) { + DRM_ERROR("VCN message has too many buffers!\n"); + r = -EINVAL; + goto out; + } + for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { uint32_t offset, size, *create; + uint64_t buf_end; if (msg[0] != RDECODE_MESSAGE_CREATE) continue; @@ -1964,14 +1979,16 @@ static int vcn_v3_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, offset = msg[1]; size = msg[2]; - if (offset + size > end) { + if (size < 4 || check_add_overflow(offset, size, &buf_end) || + buf_end > end - addr) { + DRM_ERROR("VCN message buffer exceeds BO bounds!\n"); r = -EINVAL; goto out; } create = ptr + addr + offset - start; - /* H246, HEVC and VP9 can run on any instance */ + /* H264, HEVC and VP9 can run on any instance */ if (create[0] == 0x7 || create[0] == 0x10 || create[0] == 0x11) continue; diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c index 3ae666522d57..64bda0e944a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c @@ -1825,7 +1825,7 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, { struct ttm_operation_ctx ctx = { false, false }; struct amdgpu_bo_va_mapping *map; - uint32_t *msg, num_buffers; + uint32_t *msg, num_buffers, len_dw; struct amdgpu_bo *bo; uint64_t start, end; unsigned int i; @@ -1846,6 +1846,11 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, return -EINVAL; } + if (end - addr < 16) { + DRM_ERROR("VCN messages must be at least 4 DWORDs!\n"); + return -EINVAL; + } + bo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; amdgpu_bo_placement_from_domain(bo, bo->allowed_domains); r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); @@ -1862,8 +1867,8 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, msg = ptr + addr - start; - /* Check length */ if (msg[1] > end - addr) { + DRM_ERROR("VCN message header does not fit in BO!\n"); r = -EINVAL; goto out; } @@ -1871,9 +1876,19 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, if (msg[3] != RDECODE_MSG_CREATE) goto out; + len_dw = msg[1] / 4; num_buffers = msg[2]; + + /* Verify that all indices fit within the claimed length. Each index is 4 DWORDs */ + if (num_buffers > len_dw || 6 + num_buffers * 4 > len_dw) { + DRM_ERROR("VCN message has too many buffers!\n"); + r = -EINVAL; + goto out; + } + for (i = 0, msg = &msg[6]; i < num_buffers; ++i, msg += 4) { uint32_t offset, size, *create; + uint64_t buf_end; if (msg[0] != RDECODE_MESSAGE_CREATE) continue; @@ -1881,7 +1896,9 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, offset = msg[1]; size = msg[2]; - if (offset + size > end) { + if (size < 4 || check_add_overflow(offset, size, &buf_end) || + buf_end > end - addr) { + DRM_ERROR("VCN message buffer exceeds BO bounds!\n"); r = -EINVAL; goto out; } @@ -1912,9 +1929,10 @@ static int vcn_v4_0_dec_msg(struct amdgpu_cs_parser *p, struct amdgpu_job *job, static int vcn_v4_0_enc_find_ib_param(struct amdgpu_ib *ib, uint32_t id, int start) { int i; + uint32_t len; - for (i = start; i < ib->length_dw && ib->ptr[i] >= 8; i += ib->ptr[i] / 4) { - if (ib->ptr[i + 1] == id) + for (i = start; (len = amdgpu_ib_get_value(ib, i)) >= 8; i += len / 4) { + if (amdgpu_ib_get_value(ib, i + 1) == id) return i; } return -1; @@ -1925,8 +1943,6 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, struct amdgpu_ib *ib) { struct amdgpu_ring *ring = amdgpu_job_ring(job); - struct amdgpu_vcn_decode_buffer *decode_buffer; - uint64_t addr; uint32_t val; int idx = 0, sidx; @@ -1937,20 +1953,22 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p, while ((idx = vcn_v4_0_enc_find_ib_param(ib, RADEON_VCN_ENGINE_INFO, idx)) >= 0) { val = amdgpu_ib_get_value(ib, idx + 2); /* RADEON_VCN_ENGINE_TYPE */ if (val == RADEON_VCN_ENGINE_TYPE_DECODE) { - decode_buffer = (struct amdgpu_vcn_decode_buffer *)&ib->ptr[idx + 6]; + uint32_t valid_buf_flag = amdgpu_ib_get_value(ib, idx + 6); + uint64_t msg_buffer_addr; - if (!(decode_buffer->valid_buf_flag & 0x1)) + if (!(valid_buf_flag & 0x1)) return 0; - addr = ((u64)decode_buffer->msg_buffer_address_hi) << 32 | - decode_buffer->msg_buffer_address_lo; - return vcn_v4_0_dec_msg(p, job, addr); + msg_buffer_addr = ((u64)amdgpu_ib_get_value(ib, idx + 7)) << 32 | + amdgpu_ib_get_value(ib, idx + 8); + return vcn_v4_0_dec_msg(p, job, msg_buffer_addr); } else if (val == RADEON_VCN_ENGINE_TYPE_ENCODE) { sidx = vcn_v4_0_enc_find_ib_param(ib, RENCODE_IB_PARAM_SESSION_INIT, idx); - if (sidx >= 0 && ib->ptr[sidx + 2] == RENCODE_ENCODE_STANDARD_AV1) + if (sidx >= 0 && + amdgpu_ib_get_value(ib, sidx + 2) == RENCODE_ENCODE_STANDARD_AV1) return vcn_v4_0_limit_sched(p, job); } - idx += ib->ptr[idx] / 4; + idx += amdgpu_ib_get_value(ib, idx) / 4; } return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 0f0719528bcc..0fcf150b9ffa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -763,6 +764,9 @@ static int kfd_ioctl_get_process_apertures_new(struct file *filp, goto out_unlock; } + if (args->num_of_nodes > kfd_topology_get_num_devices()) + return -EINVAL; + /* Fill in process-aperture information for all available * nodes, but not more than args->num_of_nodes as that is * the amount of memory allocated by user @@ -1337,7 +1341,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); if (WARN_ON_ONCE(!peer_pdd)) continue; - kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); + kfd_flush_tlb(peer_pdd); } kfree(devices_arr); @@ -1432,7 +1436,7 @@ static int kfd_ioctl_unmap_memory_from_gpu(struct file *filep, if (WARN_ON_ONCE(!peer_pdd)) continue; if (flush_tlb) - kfd_flush_tlb(peer_pdd, TLB_FLUSH_HEAVYWEIGHT); + kfd_flush_tlb(peer_pdd); /* Remove dma mapping after tlb flush to avoid IO_PAGE_FAULT */ err = amdgpu_amdkfd_gpuvm_dmaunmap_mem(mem, peer_pdd->drm_priv); @@ -1673,6 +1677,16 @@ static int kfd_ioctl_smi_events(struct file *filep, return kfd_smi_event_open(pdd->dev, &args->anon_fd); } +static int kfd_ioctl_svm_validate(void *kdata, unsigned int usize) +{ + struct kfd_ioctl_svm_args *args = kdata; + size_t expected = struct_size(args, attrs, args->nattr); + + if (expected == SIZE_MAX || usize < expected) + return -EINVAL; + return 0; +} + #if IS_ENABLED(CONFIG_HSA_AMD_SVM) static int kfd_ioctl_set_xnack_mode(struct file *filep, @@ -3119,7 +3133,11 @@ static int kfd_ioctl_set_debug_trap(struct file *filep, struct kfd_process *p, v #define AMDKFD_IOCTL_DEF(ioctl, _func, _flags) \ [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ - .cmd_drv = 0, .name = #ioctl} + .validate = NULL, .cmd_drv = 0, .name = #ioctl} + +#define AMDKFD_IOCTL_DEF_V(ioctl, _func, _validate, _flags) \ + [_IOC_NR(ioctl)] = {.cmd = ioctl, .func = _func, .flags = _flags, \ + .validate = _validate, .cmd_drv = 0, .name = #ioctl} /** Ioctl table */ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { @@ -3216,7 +3234,8 @@ static const struct amdkfd_ioctl_desc amdkfd_ioctls[] = { AMDKFD_IOCTL_DEF(AMDKFD_IOC_SMI_EVENTS, kfd_ioctl_smi_events, 0), - AMDKFD_IOCTL_DEF(AMDKFD_IOC_SVM, kfd_ioctl_svm, 0), + AMDKFD_IOCTL_DEF_V(AMDKFD_IOC_SVM, kfd_ioctl_svm, + kfd_ioctl_svm_validate, 0), AMDKFD_IOCTL_DEF(AMDKFD_IOC_SET_XNACK_MODE, kfd_ioctl_set_xnack_mode, 0), @@ -3338,6 +3357,12 @@ static long kfd_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) memset(kdata, 0, usize); } + if (ioctl->validate) { + retcode = ioctl->validate(kdata, usize); + if (retcode) + goto err_i1; + } + retcode = func(filep, process, kdata); if (cmd & IOC_OUT) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 58c5acf50a22..51a47a91e21e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -569,7 +569,7 @@ static int allocate_vmid(struct device_queue_manager *dqm, qpd->vmid, qpd->page_table_base); /* invalidate the VM context after pasid and vmid mapping is set up */ - kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY); + kfd_flush_tlb(qpd_to_pdd(qpd)); if (dqm->dev->kfd2kgd->set_scratch_backing_va) dqm->dev->kfd2kgd->set_scratch_backing_va(dqm->dev->adev, @@ -607,7 +607,7 @@ static void deallocate_vmid(struct device_queue_manager *dqm, if (flush_texture_cache_nocpsch(q->device, qpd)) dev_err(dev, "Failed to flush TC\n"); - kfd_flush_tlb(qpd_to_pdd(qpd), TLB_FLUSH_LEGACY); + kfd_flush_tlb(qpd_to_pdd(qpd)); /* Release the vmid mapping */ set_pasid_vmid_mapping(dqm, 0, qpd->vmid); @@ -1282,7 +1282,7 @@ static int restore_process_queues_nocpsch(struct device_queue_manager *dqm, dqm->dev->adev, qpd->vmid, qpd->page_table_base); - kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY); + kfd_flush_tlb(pdd); } /* Take a safe reference to the mm_struct, which may otherwise diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 4f4eb0791138..24e85440473a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1036,10 +1036,13 @@ extern struct srcu_struct kfd_processes_srcu; typedef int amdkfd_ioctl_t(struct file *filep, struct kfd_process *p, void *data); +typedef int amdkfd_ioctl_validate_t(void *kdata, unsigned int usize); + struct amdkfd_ioctl_desc { unsigned int cmd; int flags; amdkfd_ioctl_t *func; + amdkfd_ioctl_validate_t *validate; unsigned int cmd_drv; const char *name; }; @@ -1175,6 +1178,7 @@ static inline struct kfd_node *kfd_node_by_irq_ids(struct amdgpu_device *adev, return NULL; } int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_node **kdev); +uint32_t kfd_topology_get_num_devices(void); int kfd_numa_node_to_apic_id(int numa_node_id); /* Interrupts */ @@ -1529,13 +1533,13 @@ void kfd_signal_reset_event(struct kfd_node *dev); void kfd_signal_poison_consumed_event(struct kfd_node *dev, u32 pasid); -static inline void kfd_flush_tlb(struct kfd_process_device *pdd, - enum TLB_FLUSH_TYPE type) +static inline void kfd_flush_tlb(struct kfd_process_device *pdd) { struct amdgpu_device *adev = pdd->dev->adev; struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); - amdgpu_vm_flush_compute_tlb(adev, vm, type, pdd->dev->xcc_mask); + amdgpu_vm_flush_compute_tlb(adev, vm, TLB_FLUSH_HEAVYWEIGHT, + pdd->dev->xcc_mask); } static inline bool kfd_flush_tlb_after_unmap(struct kfd_dev *dev) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 6daa70ace261..a24b3c00f9f0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1391,7 +1391,7 @@ svm_range_unmap_from_gpus(struct svm_range *prange, unsigned long start, if (r) break; } - kfd_flush_tlb(pdd, TLB_FLUSH_HEAVYWEIGHT); + kfd_flush_tlb(pdd); } return r; @@ -1525,7 +1525,7 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset, } } - kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY); + kfd_flush_tlb(pdd); } return r; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c index 3eb32d58a120..02b1860cde7d 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_topology.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_topology.c @@ -2295,6 +2295,17 @@ int kfd_topology_remove_device(struct kfd_node *gpu) return res; } +uint32_t kfd_topology_get_num_devices(void) +{ + uint32_t num_devices; + + down_read(&topology_lock); + num_devices = sys_props.num_devices; + up_read(&topology_lock); + + return num_devices; +} + /* kfd_topology_enum_kfd_devices - Enumerate through all devices in KFD * topology. If GPU device is found @idx, then valid kfd_dev pointer is * returned through @kdev diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index bc5dedf5f60c..a614bfe50630 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -4954,7 +4954,7 @@ void resource_build_bit_depth_reduction_params(struct dc_stream_state *stream, option = DITHER_OPTION_SPATIAL8; break; case COLOR_DEPTH_101010: - option = DITHER_OPTION_TRUN10; + option = DITHER_OPTION_SPATIAL10; break; default: option = DITHER_OPTION_DISABLE; diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c index ad1fd3150d03..0cb7eaaba384 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/ci_smumgr.c @@ -1326,12 +1326,13 @@ static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr) dev_id = adev->pdev->device; - if ((dpm_table->mclk_table.count >= 2) - && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) { - smu_data->smc_state_table.MemoryLevel[1].MinVddci = - smu_data->smc_state_table.MemoryLevel[0].MinVddci; - smu_data->smc_state_table.MemoryLevel[1].MinMvdd = - smu_data->smc_state_table.MemoryLevel[0].MinMvdd; + if ((dpm_table->mclk_table.count >= 2) && + ((dev_id == 0x67B0) || (dev_id == 0x67B1)) && + (adev->pdev->revision == 0)) { + smu_data->smc_state_table.MemoryLevel[1].MinVddc = + smu_data->smc_state_table.MemoryLevel[0].MinVddc; + smu_data->smc_state_table.MemoryLevel[1].MinVddcPhases = + smu_data->smc_state_table.MemoryLevel[0].MinVddcPhases; } smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c index 470a901926f3..3924429e1120 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c @@ -2442,6 +2442,7 @@ static int smu_v14_0_2_od_restore_table_single(struct smu_context *smu, long inp } od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + od_table->OverDriveTable.FeatureCtrlMask &= ~BIT(PP_OD_FEATURE_FAN_LEGACY_BIT); break; case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE: od_table->OverDriveTable.FanZeroRpmEnable = @@ -2470,7 +2471,8 @@ static int smu_v14_0_2_od_restore_table_single(struct smu_context *smu, long inp od_table->OverDriveTable.FanMinimumPwm = boot_overdrive_table->OverDriveTable.FanMinimumPwm; od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; - od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_LEGACY_BIT); + od_table->OverDriveTable.FeatureCtrlMask &= ~BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; default: dev_info(adev->dev, "Invalid table index: %ld\n", input); @@ -2640,6 +2642,7 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FanLinearPwmPoints[input[0]] = input[2]; od_table->OverDriveTable.FanMode = FAN_MODE_MANUAL_LINEAR; od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + od_table->OverDriveTable.FeatureCtrlMask &= ~BIT(PP_OD_FEATURE_FAN_LEGACY_BIT); break; case PP_OD_EDIT_ACOUSTIC_LIMIT: @@ -2709,7 +2712,7 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, break; case PP_OD_EDIT_FAN_MINIMUM_PWM: - if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_CURVE_BIT)) { + if (!smu_v14_0_2_is_od_feature_supported(smu, PP_OD_FEATURE_FAN_LEGACY_BIT)) { dev_warn(adev->dev, "Fan curve setting not supported!\n"); return -ENOTSUPP; } @@ -2727,7 +2730,8 @@ static int smu_v14_0_2_od_edit_dpm_table(struct smu_context *smu, od_table->OverDriveTable.FanMinimumPwm = input[0]; od_table->OverDriveTable.FanMode = FAN_MODE_AUTO; - od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_CURVE_BIT); + od_table->OverDriveTable.FeatureCtrlMask |= BIT(PP_OD_FEATURE_FAN_LEGACY_BIT); + od_table->OverDriveTable.FeatureCtrlMask &= ~BIT(PP_OD_FEATURE_FAN_CURVE_BIT); break; case PP_OD_EDIT_FAN_ZERO_RPM_ENABLE: diff --git a/drivers/gpu/drm/bridge/tda998x_drv.c b/drivers/gpu/drm/bridge/tda998x_drv.c index e636459d9185..f90b08869267 100644 --- a/drivers/gpu/drm/bridge/tda998x_drv.c +++ b/drivers/gpu/drm/bridge/tda998x_drv.c @@ -1697,7 +1697,7 @@ static const struct drm_bridge_funcs tda998x_bridge_funcs = { static int tda998x_get_audio_ports(struct tda998x_priv *priv, struct device_node *np) { - const u32 *port_data; + const __be32 *port_data; u32 size; int i; diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index 11e7141c1524..6d0d27aca518 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -969,7 +969,7 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_gem_change_handle *args = data; - struct drm_gem_object *obj; + struct drm_gem_object *obj, *idrobj; int handle, ret; if (!drm_core_check_feature(dev, DRIVER_GEM)) @@ -992,8 +992,29 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, mutex_lock(&file_priv->prime.lock); spin_lock(&file_priv->table_lock); + + /* When create_tail allocs an obj idr, it needs to first alloc as NULL, + * then later replace with the correct object. This is not necessary + * here, because the only operations that could race are drm_prime + * bookkeeping, and we hold the prime lock. + */ ret = idr_alloc(&file_priv->object_idr, obj, handle, handle + 1, GFP_NOWAIT); + + if (ret < 0) { + spin_unlock(&file_priv->table_lock); + goto out_unlock; + } + + idrobj = idr_replace(&file_priv->object_idr, NULL, handle); + if (idrobj != obj) { + idr_replace(&file_priv->object_idr, idrobj, handle); + idr_remove(&file_priv->object_idr, args->new_handle); + spin_unlock(&file_priv->table_lock); + ret = -ENOENT; + goto out_unlock; + } + spin_unlock(&file_priv->table_lock); if (ret < 0) @@ -1005,6 +1026,8 @@ int drm_gem_change_handle_ioctl(struct drm_device *dev, void *data, if (ret < 0) { spin_lock(&file_priv->table_lock); idr_remove(&file_priv->object_idr, handle); + idrobj = idr_replace(&file_priv->object_idr, obj, handle); + WARN_ON(idrobj != NULL); spin_unlock(&file_priv->table_lock); goto out_unlock; } diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 4bc89d33df59..daa5471365c4 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -171,8 +171,8 @@ int drm_gem_fb_init_with_funcs(struct drm_device *dev, } for (i = 0; i < info->num_planes; i++) { - unsigned int width = mode_cmd->width / (i ? info->hsub : 1); - unsigned int height = mode_cmd->height / (i ? info->vsub : 1); + unsigned int width = drm_format_info_plane_width(info, mode_cmd->width, i); + unsigned int height = drm_format_info_plane_height(info, mode_cmd->height, i); unsigned int min_size; objs[i] = drm_gem_object_lookup(file, mode_cmd->handles[i]); diff --git a/drivers/gpu/drm/drm_gpusvm.c b/drivers/gpu/drm/drm_gpusvm.c index cb906765897e..853ca57800d3 100644 --- a/drivers/gpu/drm/drm_gpusvm.c +++ b/drivers/gpu/drm/drm_gpusvm.c @@ -1443,6 +1443,7 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, return 0; err_unmap: + svm_pages->flags.has_dma_mapping = true; __drm_gpusvm_unmap_pages(gpusvm, svm_pages, num_dma_mapped); drm_gpusvm_notifier_unlock(gpusvm); err_free: diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c index 29a8366513fa..e68c954ec3e6 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_mic.c +++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c @@ -423,7 +423,9 @@ static int exynos_mic_probe(struct platform_device *pdev) mic->bridge.of_node = dev->of_node; - drm_bridge_add(&mic->bridge); + ret = devm_drm_bridge_add(dev, &mic->bridge); + if (ret) + goto err; pm_runtime_enable(dev); @@ -443,12 +445,8 @@ static int exynos_mic_probe(struct platform_device *pdev) static void exynos_mic_remove(struct platform_device *pdev) { - struct exynos_mic *mic = platform_get_drvdata(pdev); - component_del(&pdev->dev, &exynos_mic_component_ops); pm_runtime_disable(&pdev->dev); - - drm_bridge_remove(&mic->bridge); } static const struct of_device_id exynos_mic_of_match[] = { diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 504f6228bf35..1da20065ea77 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -2840,7 +2840,7 @@ int intel_psr2_sel_fetch_update(struct intel_atomic_state *state, return ret; do { - bool cursor_in_su_area; + bool cursor_in_su_area = false; /* * Adjust su area to cover cursor fully as necessary diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c index d5f2ee41c03f..68cd30b0bd1b 100644 --- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c +++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c @@ -110,8 +110,7 @@ imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, output_fmt = imxpd->bus_format ? : MEDIA_BUS_FMT_RGB888_1X24; /* Now make sure the requested output format is supported. */ - if ((imxpd->bus_format && imxpd->bus_format != output_fmt) || - !imx_pd_format_supported(output_fmt)) { + if (!imx_pd_format_supported(output_fmt)) { *num_input_fmts = 0; return NULL; } @@ -121,7 +120,17 @@ imx_pd_bridge_atomic_get_input_bus_fmts(struct drm_bridge *bridge, if (!input_fmts) return NULL; - input_fmts[0] = output_fmt; + /* + * Prefer bus format set via legacy "interface-pix-fmt" DT property + * over panel bus format. This is necessary to retain support for + * DTs which configure the IPUv3 parallel output as 24bit, but + * connect 18bit DPI panels to it with hardware swizzling. + */ + if (imxpd->bus_format && imxpd->bus_format != output_fmt) + input_fmts[0] = imxpd->bus_format; + else + input_fmts[0] = output_fmt; + return input_fmts; } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 46fd58646d32..93a491a103e0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -80,7 +80,7 @@ static int msm_hdmi_config_avi_infoframe(struct hdmi *hdmi, for (i = 0; i < ARRAY_SIZE(buf); i++) hdmi_write(hdmi, REG_HDMI_AVI_INFO(i), buf[i]); - val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); val |= HDMI_INFOFRAME_CTRL0_AVI_SEND | HDMI_INFOFRAME_CTRL0_AVI_CONT; hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, val); @@ -116,7 +116,7 @@ static int msm_hdmi_config_audio_infoframe(struct hdmi *hdmi, buffer[9] << 16 | buffer[10] << 24); - val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL1); + val = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0); val |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT | HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE | diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 7e977fec4100..94b32973cd6a 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -536,6 +536,11 @@ static int msm_ioctl_gem_info_get_metadata(struct drm_gem_object *obj, len = msm_obj->metadata_size; buf = kmemdup(msm_obj->metadata, len, GFP_KERNEL); + if (!buf) { + msm_gem_unlock(obj); + return -ENOMEM; + } + msm_gem_unlock(obj); if (*metadata_size < len) { @@ -548,7 +553,7 @@ static int msm_ioctl_gem_info_get_metadata(struct drm_gem_object *obj, kfree(buf); - return 0; + return ret; } static int msm_ioctl_gem_info(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index dd0605fe1243..a4377ee84c72 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -548,32 +548,30 @@ static void recover_worker(struct kthread_work *work) msm_update_fence(ring->fctx, fence); } - if (msm_gpu_active(gpu)) { - /* retire completed submits, plus the one that hung: */ - retire_submits(gpu); + /* retire completed submits, plus the one that hung: */ + retire_submits(gpu); - gpu->funcs->recover(gpu); + gpu->funcs->recover(gpu); - /* - * Replay all remaining submits starting with highest priority - * ring - */ - for (i = 0; i < gpu->nr_rings; i++) { - struct msm_ringbuffer *ring = gpu->rb[i]; - unsigned long flags; + /* + * Replay all remaining submits starting with highest priority + * ring + */ + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + unsigned long flags; - spin_lock_irqsave(&ring->submit_lock, flags); - list_for_each_entry(submit, &ring->submits, node) { - /* - * If the submit uses an unusable vm make sure - * we don't actually run it - */ - if (to_msm_vm(submit->vm)->unusable) - submit->nr_cmds = 0; - gpu->funcs->submit(gpu, submit); - } - spin_unlock_irqrestore(&ring->submit_lock, flags); + spin_lock_irqsave(&ring->submit_lock, flags); + list_for_each_entry(submit, &ring->submits, node) { + /* + * If the submit uses an unusable vm make sure + * we don't actually run it + */ + if (to_msm_vm(submit->vm)->unusable) + submit->nr_cmds = 0; + gpu->funcs->submit(gpu, submit); } + spin_unlock_irqrestore(&ring->submit_lock, flags); } pm_runtime_put(&gpu->pdev->dev); diff --git a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c index d5fe105bdbdd..658ce64c71eb 100644 --- a/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c +++ b/drivers/gpu/drm/panel/panel-boe-tv101wum-nl6.c @@ -1324,6 +1324,8 @@ static int boe_panel_disable(struct drm_panel *panel) mipi_dsi_dcs_set_display_off_multi(&ctx); mipi_dsi_dcs_enter_sleep_mode_multi(&ctx); + boe->dsi->mode_flags |= MIPI_DSI_MODE_LPM; + mipi_dsi_msleep(&ctx, 150); return ctx.accum_err; diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c index 4c432d207634..ebbd649c67dc 100644 --- a/drivers/gpu/drm/panel/panel-himax-hx83102.c +++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c @@ -850,6 +850,8 @@ static int hx83102_disable(struct drm_panel *panel) mipi_dsi_dcs_set_display_off_multi(&dsi_ctx); mipi_dsi_dcs_enter_sleep_mode_multi(&dsi_ctx); + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + mipi_dsi_msleep(&dsi_ctx, 150); return dsi_ctx.accum_err; diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index ba8db1d07c07..b47b91272b24 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -2461,7 +2461,8 @@ static void ci_register_patching_mc_arb(struct radeon_device *rdev, if (patch && ((rdev->pdev->device == 0x67B0) || - (rdev->pdev->device == 0x67B1))) { + (rdev->pdev->device == 0x67B1)) && + (rdev->pdev->revision == 0)) { if ((memory_clock > 100000) && (memory_clock <= 125000)) { tmp2 = (((0x31 * engine_clock) / 125000) - 1) & 0xff; *dram_timimg2 &= ~0x00ff0000; @@ -3304,7 +3305,8 @@ static int ci_populate_all_memory_levels(struct radeon_device *rdev) pi->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; if ((dpm_table->mclk_table.count >= 2) && - ((rdev->pdev->device == 0x67B0) || (rdev->pdev->device == 0x67B1))) { + ((rdev->pdev->device == 0x67B0) || (rdev->pdev->device == 0x67B1)) && + (rdev->pdev->revision == 0)) { pi->smc_state_table.MemoryLevel[1].MinVddc = pi->smc_state_table.MemoryLevel[0].MinVddc; pi->smc_state_table.MemoryLevel[1].MinVddcPhases = @@ -4493,7 +4495,8 @@ static int ci_register_patching_mc_seq(struct radeon_device *rdev, if (patch && ((rdev->pdev->device == 0x67B0) || - (rdev->pdev->device == 0x67B1))) { + (rdev->pdev->device == 0x67B1)) && + (rdev->pdev->revision == 0)) { for (i = 0; i < table->last; i++) { if (table->last >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) return -EINVAL; diff --git a/drivers/gpu/drm/tiny/appletbdrm.c b/drivers/gpu/drm/tiny/appletbdrm.c index 751b05753c94..f596e9637a7b 100644 --- a/drivers/gpu/drm/tiny/appletbdrm.c +++ b/drivers/gpu/drm/tiny/appletbdrm.c @@ -353,7 +353,7 @@ static int appletbdrm_primary_plane_helper_atomic_check(struct drm_plane *plane, frames_size + sizeof(struct appletbdrm_fb_request_footer), 16); - appletbdrm_state->request = kzalloc(request_size, GFP_KERNEL); + appletbdrm_state->request = kvzalloc(request_size, GFP_KERNEL); if (!appletbdrm_state->request) return -ENOMEM; @@ -543,7 +543,7 @@ static void appletbdrm_primary_plane_destroy_state(struct drm_plane *plane, { struct appletbdrm_plane_state *appletbdrm_state = to_appletbdrm_plane_state(state); - kfree(appletbdrm_state->request); + kvfree(appletbdrm_state->request); kfree(appletbdrm_state->response); __drm_gem_destroy_shadow_plane_state(&appletbdrm_state->base); diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index bc58991a6f14..b4c23dbcf3e3 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -285,13 +285,12 @@ static struct urb *udl_get_urb_locked(struct udl_device *udl, long timeout) return unode->urb; } -#define GET_URB_TIMEOUT HZ struct urb *udl_get_urb(struct udl_device *udl) { struct urb *urb; spin_lock_irq(&udl->urbs.lock); - urb = udl_get_urb_locked(udl, GET_URB_TIMEOUT); + urb = udl_get_urb_locked(udl, HZ * 2); spin_unlock_irq(&udl->urbs.lock); return urb; } diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 231e829bd709..1ca073a4ecb2 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -342,8 +343,10 @@ static void udl_crtc_helper_atomic_enable(struct drm_crtc *crtc, struct drm_atom return; urb = udl_get_urb(udl); - if (!urb) + if (!urb) { + drm_err_ratelimited(dev, "get urb failed when enabling crtc\n"); goto out; + } buf = (char *)urb->transfer_buffer; buf = udl_vidreg_lock(buf); diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c index a270aef7c498..0dabe8535139 100644 --- a/drivers/gpu/drm/xe/xe_bo.c +++ b/drivers/gpu/drm/xe/xe_bo.c @@ -2112,8 +2112,10 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo, } /* XE_BO_FLAG_GGTTx requires XE_BO_FLAG_GGTT also be set */ - if ((flags & XE_BO_FLAG_GGTT_ALL) && !(flags & XE_BO_FLAG_GGTT)) + if ((flags & XE_BO_FLAG_GGTT_ALL) && !(flags & XE_BO_FLAG_GGTT)) { + xe_bo_free(bo); return ERR_PTR(-EINVAL); + } if (flags & (XE_BO_FLAG_VRAM_MASK | XE_BO_FLAG_STOLEN) && !(flags & XE_BO_FLAG_IGNORE_MIN_PAGE_SIZE) && @@ -2132,8 +2134,10 @@ struct xe_bo *xe_bo_init_locked(struct xe_device *xe, struct xe_bo *bo, alignment = SZ_4K >> PAGE_SHIFT; } - if (type == ttm_bo_type_device && aligned_size != size) + if (type == ttm_bo_type_device && aligned_size != size) { + xe_bo_free(bo); return ERR_PTR(-EINVAL); + } if (!bo) { bo = xe_bo_alloc(); diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c index 2650c5abb365..4cef02ff1451 100644 --- a/drivers/gpu/drm/xe/xe_dma_buf.c +++ b/drivers/gpu/drm/xe/xe_dma_buf.c @@ -227,6 +227,13 @@ struct dma_buf *xe_gem_prime_export(struct drm_gem_object *obj, int flags) return buf; } +/* + * Takes ownership of @storage: on success it is transferred to the returned + * drm_gem_object; on failure it is freed before returning the error. + * This matches the contract of xe_bo_init_locked() which frees @storage on + * its error paths, so callers need not (and must not) free @storage after + * this call. + */ static struct drm_gem_object * xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage, struct dma_buf *dma_buf) @@ -240,8 +247,10 @@ xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage, int ret = 0; dummy_obj = drm_gpuvm_resv_object_alloc(&xe->drm); - if (!dummy_obj) + if (!dummy_obj) { + xe_bo_free(storage); return ERR_PTR(-ENOMEM); + } dummy_obj->resv = resv; xe_validation_guard(&ctx, &xe->val, &exec, (struct xe_val_flags) {}, ret) { @@ -250,6 +259,7 @@ xe_dma_buf_init_obj(struct drm_device *dev, struct xe_bo *storage, if (ret) break; + /* xe_bo_init_locked() frees storage on error */ bo = xe_bo_init_locked(xe, storage, NULL, resv, NULL, dma_buf->size, 0, /* Will require 1way or 2way for vm_bind */ ttm_bo_type_sg, XE_BO_FLAG_SYSTEM, &exec); @@ -337,12 +347,15 @@ struct drm_gem_object *xe_gem_prime_import(struct drm_device *dev, goto out_err; } - /* Errors here will take care of freeing the bo. */ + /* + * xe_dma_buf_init_obj() takes ownership of bo on both success + * and failure, so we must not touch bo after this call. + */ obj = xe_dma_buf_init_obj(dev, bo, dma_buf); - if (IS_ERR(obj)) + if (IS_ERR(obj)) { + dma_buf_detach(dma_buf, attach); return obj; - - + } get_dma_buf(dma_buf); obj->import_attach = attach; return obj; diff --git a/drivers/gpu/drm/xe/xe_vm_madvise.c b/drivers/gpu/drm/xe/xe_vm_madvise.c index 9dc801f65712..da306013a013 100644 --- a/drivers/gpu/drm/xe/xe_vm_madvise.c +++ b/drivers/gpu/drm/xe/xe_vm_madvise.c @@ -299,6 +299,45 @@ static bool madvise_args_are_sane(struct xe_device *xe, const struct drm_xe_madv return true; } +static bool check_pat_args_are_sane(struct xe_device *xe, + struct xe_vmas_in_madvise_range *madvise_range, + u16 pat_index) +{ + u16 coh_mode = xe_pat_index_get_coh_mode(xe, pat_index); + int i; + + /* + * Using coh_none with CPU cached buffers is not allowed on iGPU. + * On iGPU the GPU shares the LLC with the CPU, so with coh_none + * the GPU bypasses CPU caches and reads directly from DRAM, + * potentially seeing stale sensitive data from previously freed + * pages. On dGPU this restriction does not apply, because the + * platform does not provide a non-coherent system memory access + * path that would violate the DMA coherency contract. + */ + if (coh_mode != XE_COH_NONE || IS_DGFX(xe)) + return true; + + for (i = 0; i < madvise_range->num_vmas; i++) { + struct xe_vma *vma = madvise_range->vmas[i]; + struct xe_bo *bo = xe_vma_bo(vma); + + if (bo) { + /* BO with WB caching + COH_NONE is not allowed */ + if (XE_IOCTL_DBG(xe, bo->cpu_caching == DRM_XE_GEM_CPU_CACHING_WB)) + return false; + /* Imported dma-buf without caching info, assume cached */ + if (XE_IOCTL_DBG(xe, !bo->cpu_caching)) + return false; + } else if (XE_IOCTL_DBG(xe, xe_vma_is_cpu_addr_mirror(vma) || + xe_vma_is_userptr(vma))) + /* System memory (userptr/SVM) is always CPU cached */ + return false; + } + + return true; +} + static bool check_bo_args_are_sane(struct xe_vm *vm, struct xe_vma **vmas, int num_vmas, u32 atomic_val) { @@ -384,6 +423,14 @@ int xe_vm_madvise_ioctl(struct drm_device *dev, void *data, struct drm_file *fil if (err || !madvise_range.num_vmas) goto unlock_vm; + if (args->type == DRM_XE_MEM_RANGE_ATTR_PAT) { + if (!check_pat_args_are_sane(xe, &madvise_range, + args->pat_index.val)) { + err = -EINVAL; + goto free_vmas; + } + } + if (madvise_range.has_bo_vmas) { if (args->type == DRM_XE_MEM_RANGE_ATTR_ATOMIC) { if (!check_bo_args_are_sane(vm, madvise_range.vmas, diff --git a/drivers/hid/hid-appletb-kbd.c b/drivers/hid/hid-appletb-kbd.c index 0b10cff465e1..c96423a531f6 100644 --- a/drivers/hid/hid-appletb-kbd.c +++ b/drivers/hid/hid-appletb-kbd.c @@ -17,7 +17,7 @@ #include #include #include -#include +#include #include #include "hid-ids.h" @@ -62,7 +62,8 @@ struct appletb_kbd { struct input_handle kbd_handle; struct input_handle tpd_handle; struct backlight_device *backlight_dev; - struct timer_list inactivity_timer; + struct delayed_work inactivity_work; + struct work_struct restore_brightness_work; bool has_dimmed; bool has_turned_off; u8 saved_mode; @@ -164,16 +165,18 @@ static int appletb_tb_key_to_slot(unsigned int code) } } -static void appletb_inactivity_timer(struct timer_list *t) +static void appletb_inactivity_work(struct work_struct *work) { - struct appletb_kbd *kbd = timer_container_of(kbd, t, inactivity_timer); + struct appletb_kbd *kbd = container_of(to_delayed_work(work), + struct appletb_kbd, + inactivity_work); if (kbd->backlight_dev && appletb_tb_autodim) { if (!kbd->has_dimmed) { backlight_device_set_brightness(kbd->backlight_dev, 1); kbd->has_dimmed = true; - mod_timer(&kbd->inactivity_timer, - jiffies + secs_to_jiffies(appletb_tb_idle_timeout)); + mod_delayed_work(system_wq, &kbd->inactivity_work, + secs_to_jiffies(appletb_tb_idle_timeout)); } else if (!kbd->has_turned_off) { backlight_device_set_brightness(kbd->backlight_dev, 0); kbd->has_turned_off = true; @@ -181,16 +184,25 @@ static void appletb_inactivity_timer(struct timer_list *t) } } +static void appletb_restore_brightness_work(struct work_struct *work) +{ + struct appletb_kbd *kbd = container_of(work, struct appletb_kbd, + restore_brightness_work); + + if (kbd->backlight_dev) + backlight_device_set_brightness(kbd->backlight_dev, 2); +} + static void reset_inactivity_timer(struct appletb_kbd *kbd) { if (kbd->backlight_dev && appletb_tb_autodim) { if (kbd->has_dimmed || kbd->has_turned_off) { - backlight_device_set_brightness(kbd->backlight_dev, 2); kbd->has_dimmed = false; kbd->has_turned_off = false; + schedule_work(&kbd->restore_brightness_work); } - mod_timer(&kbd->inactivity_timer, - jiffies + secs_to_jiffies(appletb_tb_dim_timeout)); + mod_delayed_work(system_wq, &kbd->inactivity_work, + secs_to_jiffies(appletb_tb_dim_timeout)); } } @@ -408,9 +420,11 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id dev_err_probe(dev, -ENODEV, "Failed to get backlight device\n"); } else { backlight_device_set_brightness(kbd->backlight_dev, 2); - timer_setup(&kbd->inactivity_timer, appletb_inactivity_timer, 0); - mod_timer(&kbd->inactivity_timer, - jiffies + secs_to_jiffies(appletb_tb_dim_timeout)); + INIT_DELAYED_WORK(&kbd->inactivity_work, appletb_inactivity_work); + INIT_WORK(&kbd->restore_brightness_work, + appletb_restore_brightness_work); + mod_delayed_work(system_wq, &kbd->inactivity_work, + secs_to_jiffies(appletb_tb_dim_timeout)); } kbd->inp_handler.event = appletb_kbd_inp_event; @@ -440,13 +454,14 @@ static int appletb_kbd_probe(struct hid_device *hdev, const struct hid_device_id unregister_handler: input_unregister_handler(&kbd->inp_handler); close_hw: - if (kbd->backlight_dev) { - put_device(&kbd->backlight_dev->dev); - timer_delete_sync(&kbd->inactivity_timer); - } hid_hw_close(hdev); stop_hw: hid_hw_stop(hdev); + if (kbd->backlight_dev) { + cancel_delayed_work_sync(&kbd->inactivity_work); + cancel_work_sync(&kbd->restore_brightness_work); + put_device(&kbd->backlight_dev->dev); + } return ret; } @@ -457,13 +472,14 @@ static void appletb_kbd_remove(struct hid_device *hdev) appletb_kbd_set_mode(kbd, APPLETB_KBD_MODE_OFF); input_unregister_handler(&kbd->inp_handler); + hid_hw_close(hdev); + hid_hw_stop(hdev); + if (kbd->backlight_dev) { + cancel_delayed_work_sync(&kbd->inactivity_work); + cancel_work_sync(&kbd->restore_brightness_work); put_device(&kbd->backlight_dev->dev); - timer_delete_sync(&kbd->inactivity_timer); } - - hid_hw_close(hdev); - hid_hw_stop(hdev); } #ifdef CONFIG_PM diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index 2ec6d4445e84..12fad45ac106 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2378,7 +2378,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * (struct dualshock4_input_report_usb *)data; ds4_report = &usb->common; - num_touch_reports = usb->num_touch_reports; + num_touch_reports = min_t(u8, usb->num_touch_reports, + ARRAY_SIZE(usb->touch_reports)); touch_reports = usb->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT && size == DS4_INPUT_REPORT_BT_SIZE) { @@ -2392,7 +2393,8 @@ static int dualshock4_parse_report(struct ps_device *ps_dev, struct hid_report * } ds4_report = &bt->common; - num_touch_reports = bt->num_touch_reports; + num_touch_reports = min_t(u8, bt->num_touch_reports, + ARRAY_SIZE(bt->touch_reports)); touch_reports = bt->touch_reports; } else if (hdev->bus == BUS_BLUETOOTH && report->id == DS4_INPUT_REPORT_BT_MINIMAL && diff --git a/drivers/hid/usbhid/hid-pidff.c b/drivers/hid/usbhid/hid-pidff.c index 56d6af39ba81..c06b1913f5ba 100644 --- a/drivers/hid/usbhid/hid-pidff.c +++ b/drivers/hid/usbhid/hid-pidff.c @@ -11,6 +11,7 @@ #include "hid-pidff.h" #include #include +#include #include #include #include @@ -325,8 +326,10 @@ static s32 pidff_clamp(s32 i, struct hid_field *field) */ static int pidff_rescale(int i, int max, struct hid_field *field) { - return i * (field->logical_maximum - field->logical_minimum) / max + - field->logical_minimum; + /* 64 bits needed for big values during rescale */ + s64 result = field->logical_maximum - field->logical_minimum; + + return div_s64(result * i, max) + field->logical_minimum; } /* diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c index b3bf2173c14e..7c30731cb9a5 100644 --- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c +++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c @@ -345,6 +345,7 @@ static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma) return err; } + vm_flags_set(vma, VM_DONTEXPAND | VM_DONTDUMP); /* * Use common vm_area operations to track buffer refcount. */ diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c index d90f1b0b2051..f4e963cdb7f2 100644 --- a/drivers/media/dvb-frontends/dib8000.c +++ b/drivers/media/dvb-frontends/dib8000.c @@ -2695,7 +2695,7 @@ static void dib8000_viterbi_state(struct dib8000_state *state, u8 onoff) static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) { - s16 unit_khz_dds_val; + s32 unit_khz_dds_val; u32 abs_offset_khz = abs(offset_khz); u32 dds = state->cfg.pll->ifreq & 0x1ffffff; u8 invert = !!(state->cfg.pll->ifreq & (1 << 25)); @@ -2716,7 +2716,7 @@ static void dib8000_set_dds(struct dib8000_state *state, s32 offset_khz) dds = (1<<26) - dds; } else { ratio = 2; - unit_khz_dds_val = (u16) (67108864 / state->cfg.pll->internal); + unit_khz_dds_val = 67108864 / state->cfg.pll->internal; if (offset_khz < 0) unit_khz_dds_val *= -1; diff --git a/drivers/media/i2c/imx283.c b/drivers/media/i2c/imx283.c index 8ab63ad8f385..1be6164c2d15 100644 --- a/drivers/media/i2c/imx283.c +++ b/drivers/media/i2c/imx283.c @@ -129,7 +129,8 @@ /* Master Mode Operation Control */ #define IMX283_REG_XMSTA CCI_REG8(0x3105) -#define IMX283_XMSTA BIT(0) +#define IMX283_XMSTA_START 0 +#define IMX283_XMSTA_STOP BIT(0) #define IMX283_REG_SYNCDRV CCI_REG8(0x3107) #define IMX283_SYNCDRV_XHS_XVS (0xa0 | 0x02) @@ -1023,8 +1024,6 @@ static int imx283_standby_cancel(struct imx283 *imx283) usleep_range(19000, 20000); cci_write(imx283->cci, IMX283_REG_CLAMP, IMX283_CLPSQRST, &ret); - cci_write(imx283->cci, IMX283_REG_XMSTA, 0, &ret); - cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret); return ret; } @@ -1117,6 +1116,10 @@ static int imx283_start_streaming(struct imx283 *imx283, /* Apply customized values from controls (HMAX/VMAX/SHR) */ ret = __v4l2_ctrl_handler_setup(imx283->sd.ctrl_handler); + /* Start master mode */ + cci_write(imx283->cci, IMX283_REG_XMSTA, IMX283_XMSTA_START, &ret); + cci_write(imx283->cci, IMX283_REG_SYNCDRV, IMX283_SYNCDRV_XHS_XVS, &ret); + return ret; } @@ -1153,12 +1156,14 @@ static int imx283_disable_streams(struct v4l2_subdev *sd, u64 streams_mask) { struct imx283 *imx283 = to_imx283(sd); - int ret; + int ret = 0; if (pad != IMAGE_PAD) return -EINVAL; - ret = cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STBLOGIC, NULL); + cci_write(imx283->cci, IMX283_REG_XMSTA, IMX283_XMSTA_STOP, &ret); + cci_write(imx283->cci, IMX283_REG_STANDBY, IMX283_STANDBY, &ret); + if (ret) dev_err(imx283->dev, "Failed to stop stream\n"); diff --git a/drivers/media/i2c/imx412.c b/drivers/media/i2c/imx412.c index 7bbd639a9ddf..5656b581a717 100644 --- a/drivers/media/i2c/imx412.c +++ b/drivers/media/i2c/imx412.c @@ -925,7 +925,7 @@ static int imx412_parse_hw_config(struct imx412 *imx412) /* Request optional reset pin */ imx412->reset_gpio = devm_gpiod_get_optional(imx412->dev, "reset", - GPIOD_OUT_LOW); + GPIOD_OUT_HIGH); if (IS_ERR(imx412->reset_gpio)) { dev_err(imx412->dev, "failed to get reset gpio %ld\n", PTR_ERR(imx412->reset_gpio)); diff --git a/drivers/media/i2c/ov08d10.c b/drivers/media/i2c/ov08d10.c index 43ec2a1f2fcf..5e1b8b58b3d6 100644 --- a/drivers/media/i2c/ov08d10.c +++ b/drivers/media/i2c/ov08d10.c @@ -217,7 +217,7 @@ static const struct ov08d10_reg lane_2_mode_3280x2460[] = { {0x9a, 0x30}, {0xa8, 0x02}, {0xfd, 0x02}, - {0xa1, 0x01}, + {0xa1, 0x00}, {0xa2, 0x09}, {0xa3, 0x9c}, {0xa5, 0x00}, @@ -335,7 +335,7 @@ static const struct ov08d10_reg lane_2_mode_3264x2448[] = { {0x9a, 0x30}, {0xa8, 0x02}, {0xfd, 0x02}, - {0xa1, 0x09}, + {0xa1, 0x08}, {0xa2, 0x09}, {0xa3, 0x90}, {0xa5, 0x08}, @@ -467,7 +467,7 @@ static const struct ov08d10_reg lane_2_mode_1632x1224[] = { {0xaa, 0xd0}, {0xab, 0x06}, {0xac, 0x68}, - {0xa1, 0x09}, + {0xa1, 0x04}, {0xa2, 0x04}, {0xa3, 0xc8}, {0xa5, 0x04}, @@ -613,8 +613,8 @@ static const struct ov08d10_lane_cfg lane_cfg_2 = { static u32 ov08d10_get_format_code(struct ov08d10 *ov08d10) { static const u32 codes[2][2] = { - { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10}, - { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10}, + { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10 }, + { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10 }, }; return codes[ov08d10->vflip->val][ov08d10->hflip->val]; @@ -1430,6 +1430,9 @@ static int ov08d10_probe(struct i2c_client *client) goto probe_error_v4l2_ctrl_handler_free; } + pm_runtime_set_active(ov08d10->dev); + pm_runtime_enable(ov08d10->dev); + ret = v4l2_async_register_subdev_sensor(&ov08d10->sd); if (ret < 0) { dev_err(ov08d10->dev, "failed to register V4L2 subdev: %d", @@ -1437,17 +1440,13 @@ static int ov08d10_probe(struct i2c_client *client) goto probe_error_media_entity_cleanup; } - /* - * Device is already turned on by i2c-core with ACPI domain PM. - * Enable runtime PM and turn off the device. - */ - pm_runtime_set_active(ov08d10->dev); - pm_runtime_enable(ov08d10->dev); pm_runtime_idle(ov08d10->dev); return 0; probe_error_media_entity_cleanup: + pm_runtime_disable(ov08d10->dev); + pm_runtime_set_suspended(ov08d10->dev); media_entity_cleanup(&ov08d10->sd.entity); probe_error_v4l2_ctrl_handler_free: diff --git a/drivers/media/i2c/ov8856.c b/drivers/media/i2c/ov8856.c index e2998cfa0d18..dd01e1d515ff 100644 --- a/drivers/media/i2c/ov8856.c +++ b/drivers/media/i2c/ov8856.c @@ -1951,12 +1951,18 @@ static int ov8856_init_controls(struct ov8856 *ov8856) V4L2_CID_HFLIP, 0, 1, 1, 0); v4l2_ctrl_new_std(ctrl_hdlr, &ov8856_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0); - if (ctrl_hdlr->error) - return ctrl_hdlr->error; + if (ctrl_hdlr->error) { + ret = ctrl_hdlr->error; + goto err_ctrl_handler_free; + } ov8856->sd.ctrl_handler = ctrl_hdlr; return 0; + +err_ctrl_handler_free: + v4l2_ctrl_handler_free(ctrl_hdlr); + return ret; } static void ov8856_update_pad_format(struct ov8856 *ov8856, diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c index a2768f44017a..fab7783c664b 100644 --- a/drivers/media/pci/intel/ipu6/ipu6.c +++ b/drivers/media/pci/intel/ipu6/ipu6.c @@ -686,7 +686,7 @@ static int ipu6_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) out_ipu6_rpm_put: pm_runtime_put_sync(&isp->psys->auxdev.dev); out_ipu6_bus_del_devices: - if (isp->psys) { + if (!IS_ERR_OR_NULL(isp->psys)) { ipu6_cpd_free_pkg_dir(isp->psys); ipu6_buttress_unmap_fw_image(isp->psys, &isp->psys->fw_sgt); } diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c index a8a004f28ca0..ac290f546413 100644 --- a/drivers/media/pci/saa7164/saa7164-core.c +++ b/drivers/media/pci/saa7164/saa7164-core.c @@ -888,6 +888,15 @@ static int get_resources(struct saa7164_dev *dev) return -EBUSY; } +static void release_resources(struct saa7164_dev *dev) +{ + release_mem_region(pci_resource_start(dev->pci, 0), + pci_resource_len(dev->pci, 0)); + + release_mem_region(pci_resource_start(dev->pci, 2), + pci_resource_len(dev->pci, 2)); +} + static int saa7164_port_init(struct saa7164_dev *dev, int portnr) { struct saa7164_port *port = NULL; @@ -947,9 +956,9 @@ static int saa7164_dev_setup(struct saa7164_dev *dev) snprintf(dev->name, sizeof(dev->name), "saa7164[%d]", dev->nr); - mutex_lock(&devlist); - list_add_tail(&dev->devlist, &saa7164_devlist); - mutex_unlock(&devlist); + scoped_guard(mutex, &devlist) { + list_add_tail(&dev->devlist, &saa7164_devlist); + } /* board config */ dev->board = UNSET; @@ -996,11 +1005,17 @@ static int saa7164_dev_setup(struct saa7164_dev *dev) } /* PCI/e allocations */ - dev->lmmio = ioremap(pci_resource_start(dev->pci, 0), - pci_resource_len(dev->pci, 0)); + dev->lmmio = pci_ioremap_bar(dev->pci, 0); + if (!dev->lmmio) { + dev_err(&dev->pci->dev, "Failed to remap MMIO BAR 0\n"); + goto err_ioremap_bar0; + } - dev->lmmio2 = ioremap(pci_resource_start(dev->pci, 2), - pci_resource_len(dev->pci, 2)); + dev->lmmio2 = pci_ioremap_bar(dev->pci, 2); + if (!dev->lmmio2) { + dev_err(&dev->pci->dev, "Failed to remap MMIO BAR 2\n"); + goto err_ioremap_bar2; + } dev->bmmio = (u8 __iomem *)dev->lmmio; dev->bmmio2 = (u8 __iomem *)dev->lmmio2; @@ -1019,17 +1034,25 @@ static int saa7164_dev_setup(struct saa7164_dev *dev) saa7164_pci_quirks(dev); return 0; + +err_ioremap_bar2: + iounmap(dev->lmmio); +err_ioremap_bar0: + release_resources(dev); + + scoped_guard(mutex, &devlist) { + list_del(&dev->devlist); + } + saa7164_devcount--; + + return -ENODEV; } static void saa7164_dev_unregister(struct saa7164_dev *dev) { dprintk(1, "%s()\n", __func__); - release_mem_region(pci_resource_start(dev->pci, 0), - pci_resource_len(dev->pci, 0)); - - release_mem_region(pci_resource_start(dev->pci, 2), - pci_resource_len(dev->pci, 2)); + release_resources(dev); if (!atomic_dec_and_test(&dev->refcount)) return; diff --git a/drivers/media/pci/zoran/zoran_card.c b/drivers/media/pci/zoran/zoran_card.c index d81facf735d9..f707bdc1fb0f 100644 --- a/drivers/media/pci/zoran/zoran_card.c +++ b/drivers/media/pci/zoran/zoran_card.c @@ -1373,7 +1373,7 @@ static int zoran_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } if (zr->codec->type != zr->card.video_codec) { pci_err(pdev, "%s - wrong codec\n", __func__); - goto zr_unreg_videocodec; + goto zr_detach_codec; } } if (zr->card.video_vfe != 0) { diff --git a/drivers/media/platform/chips-media/wave5/wave5-vdi.c b/drivers/media/platform/chips-media/wave5/wave5-vdi.c index bb13267ced38..8f71920a8a35 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vdi.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vdi.c @@ -49,6 +49,7 @@ int wave5_vdi_init(struct device *dev) if (!PRODUCT_CODE_W_SERIES(vpu_dev->product_code)) { WARN_ONCE(1, "unsupported product code: 0x%x\n", vpu_dev->product_code); + wave5_vdi_free_dma_memory(vpu_dev, &vpu_dev->common_mem); return -EOPNOTSUPP; } diff --git a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c index cff2fa17c3f5..7a4625acc047 100644 --- a/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c +++ b/drivers/media/platform/chips-media/wave5/wave5-vpu-dec.c @@ -1265,13 +1265,17 @@ static void wave5_vpu_dec_buf_queue_dst(struct vb2_buffer *vb) if (vb2_is_streaming(vb->vb2_queue) && v4l2_m2m_dst_buf_is_last(m2m_ctx)) { unsigned int i; + unsigned long flags; for (i = 0; i < vb->num_planes; i++) vb2_set_plane_payload(vb, i, 0); vbuf->field = V4L2_FIELD_NONE; + spin_lock_irqsave(&inst->state_spinlock, flags); send_eos_event(inst); + spin_unlock_irqrestore(&inst->state_spinlock, flags); + v4l2_m2m_last_buffer_done(m2m_ctx, vbuf); } else { v4l2_m2m_buf_queue(m2m_ctx, vbuf); @@ -1415,8 +1419,13 @@ static int streamoff_output(struct vb2_queue *q) inst->codec_info->dec_info.stream_rd_ptr = new_rd_ptr; inst->codec_info->dec_info.stream_wr_ptr = new_rd_ptr; - if (v4l2_m2m_has_stopped(m2m_ctx)) + if (v4l2_m2m_has_stopped(m2m_ctx)) { + unsigned long flags; + + spin_lock_irqsave(&inst->state_spinlock, flags); send_eos_event(inst); + spin_unlock_irqrestore(&inst->state_spinlock, flags); + } /* streamoff on output cancels any draining operation */ inst->eos = false; @@ -1535,6 +1544,7 @@ static int initialize_sequence(struct vpu_instance *inst) { struct dec_initial_info initial_info; int ret = 0; + unsigned long flags; memset(&initial_info, 0, sizeof(struct dec_initial_info)); @@ -1556,7 +1566,9 @@ static int initialize_sequence(struct vpu_instance *inst) return ret; } + spin_lock_irqsave(&inst->state_spinlock, flags); handle_dynamic_resolution_change(inst); + spin_unlock_irqrestore(&inst->state_spinlock, flags); return 0; } diff --git a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c index 13682bf6e9f8..1be3a728f32f 100644 --- a/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c +++ b/drivers/media/platform/nxp/imx8-isi/imx8-isi-video.c @@ -1410,7 +1410,7 @@ int mxc_isi_video_register(struct mxc_isi_pipe *pipe, q->mem_ops = &vb2_dma_contig_memops; q->buf_struct_size = sizeof(struct mxc_isi_buffer); q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; - q->min_queued_buffers = 2; + q->min_queued_buffers = 0; q->lock = &video->lock; q->dev = pipe->isi->dev; diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 664245cf6eb0..bd059243790e 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -48,9 +48,9 @@ #define IS_CSID_690(csid) ((csid->camss->res->version == CAMSS_8775P) \ || (csid->camss->res->version == CAMSS_8300)) #define CSID_BUF_DONE_IRQ_STATUS 0x8C -#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ?\ - 1 : (IS_CSID_690(csid) ?\ - 13 : 14)) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? \ + ((IS_CSID_690(csid) ? 0 : 1)) : \ + ((IS_CSID_690(csid) ? 13 : 14))) #define CSID_BUF_DONE_IRQ_MASK 0x90 #define CSID_BUF_DONE_IRQ_CLEAR 0x94 #define CSID_BUF_DONE_IRQ_SET 0x98 diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index fc838b3d2203..c1148f6ad6b2 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -2782,12 +2782,10 @@ static const struct camss_subdev_resources csid_res_8775p[] = { /* CSID2 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, .clock_rate = { - { 0, 0, 400000000, 400000000, 0}, - { 0, 0, 400000000, 480000000, 0} + { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid_lite0" }, .interrupt = { "csid_lite0" }, @@ -2801,12 +2799,10 @@ static const struct camss_subdev_resources csid_res_8775p[] = { /* CSID3 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, .clock_rate = { - { 0, 0, 400000000, 400000000, 0}, - { 0, 0, 400000000, 480000000, 0} + { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid_lite1" }, .interrupt = { "csid_lite1" }, @@ -2820,12 +2816,10 @@ static const struct camss_subdev_resources csid_res_8775p[] = { /* CSID4 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, .clock_rate = { - { 0, 0, 400000000, 400000000, 0}, - { 0, 0, 400000000, 480000000, 0} + { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid_lite2" }, .interrupt = { "csid_lite2" }, @@ -2839,12 +2833,10 @@ static const struct camss_subdev_resources csid_res_8775p[] = { /* CSID5 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, .clock_rate = { - { 0, 0, 400000000, 400000000, 0}, - { 0, 0, 400000000, 480000000, 0} + { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid_lite3" }, .interrupt = { "csid_lite3" }, @@ -2858,12 +2850,10 @@ static const struct camss_subdev_resources csid_res_8775p[] = { /* CSID6 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", - "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, .clock_rate = { - { 0, 0, 400000000, 400000000, 0}, - { 0, 0, 400000000, 480000000, 0} + { 400000000, 480000000 }, + { 400000000, 480000000 } }, .reg = { "csid_lite4" }, .interrupt = { "csid_lite4" }, @@ -2936,15 +2926,17 @@ static const struct camss_subdev_resources vfe_res_8775p[] = { /* VFE2 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + "vfe_lite", "camnoc_axi"}, .clock_rate = { - { 0, 0, 0, 0 }, + { 0 }, + { 0 }, { 300000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, }, .reg = { "vfe_lite0" }, .interrupt = { "vfe_lite0" }, @@ -2959,15 +2951,17 @@ static const struct camss_subdev_resources vfe_res_8775p[] = { /* VFE3 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + "vfe_lite", "camnoc_axi"}, .clock_rate = { - { 0, 0, 0, 0 }, + { 0 }, + { 0 }, { 300000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, }, .reg = { "vfe_lite1" }, .interrupt = { "vfe_lite1" }, @@ -2982,15 +2976,17 @@ static const struct camss_subdev_resources vfe_res_8775p[] = { /* VFE4 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + "vfe_lite", "camnoc_axi"}, .clock_rate = { - { 0, 0, 0, 0 }, + { 0 }, + { 0 }, { 300000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, }, .reg = { "vfe_lite2" }, .interrupt = { "vfe_lite2" }, @@ -3005,15 +3001,17 @@ static const struct camss_subdev_resources vfe_res_8775p[] = { /* VFE5 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + "vfe_lite", "camnoc_axi"}, .clock_rate = { - { 0, 0, 0, 0 }, + { 0 }, + { 0 }, { 300000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, }, .reg = { "vfe_lite3" }, .interrupt = { "vfe_lite3" }, @@ -3028,15 +3026,17 @@ static const struct camss_subdev_resources vfe_res_8775p[] = { /* VFE6 (lite) */ { .regulators = {}, - .clock = { "cpas_vfe_lite", "vfe_lite_ahb", + .clock = { "cpas_ahb", "cpas_vfe_lite", "vfe_lite_ahb", "vfe_lite_csid", "vfe_lite_cphy_rx", - "vfe_lite"}, + "vfe_lite", "camnoc_axi"}, .clock_rate = { - { 0, 0, 0, 0 }, + { 0 }, + { 0 }, { 300000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 400000000, 400000000, 400000000, 400000000 }, { 480000000, 600000000, 600000000, 600000000 }, + { 400000000 }, }, .reg = { "vfe_lite4" }, .interrupt = { "vfe_lite4" }, diff --git a/drivers/media/platform/qcom/iris/Kconfig b/drivers/media/platform/qcom/iris/Kconfig index 3c803a05305a..5498f48362d1 100644 --- a/drivers/media/platform/qcom/iris/Kconfig +++ b/drivers/media/platform/qcom/iris/Kconfig @@ -3,7 +3,7 @@ config VIDEO_QCOM_IRIS depends on VIDEO_DEV depends on ARCH_QCOM || COMPILE_TEST select V4L2_MEM2MEM_DEV - select QCOM_MDT_LOADER if ARCH_QCOM + select QCOM_MDT_LOADER select QCOM_SCM select VIDEOBUF2_DMA_CONTIG help diff --git a/drivers/media/platform/qcom/iris/iris_buffer.c b/drivers/media/platform/qcom/iris/iris_buffer.c index 006ad855a8e5..11eb205f8646 100644 --- a/drivers/media/platform/qcom/iris/iris_buffer.c +++ b/drivers/media/platform/qcom/iris/iris_buffer.c @@ -571,10 +571,12 @@ static int iris_release_internal_buffers(struct iris_inst *inst, continue; if (!(buffer->attr & BUF_ATTR_QUEUED)) continue; + buffer->attr |= BUF_ATTR_PENDING_RELEASE; ret = hfi_ops->session_release_buf(inst, buffer); - if (ret) + if (ret) { + buffer->attr &= ~BUF_ATTR_PENDING_RELEASE; return ret; - buffer->attr |= BUF_ATTR_PENDING_RELEASE; + } } return 0; diff --git a/drivers/media/platform/qcom/iris/iris_hfi_queue.c b/drivers/media/platform/qcom/iris/iris_hfi_queue.c index b3ed06297953..bf6db23b53e2 100644 --- a/drivers/media/platform/qcom/iris/iris_hfi_queue.c +++ b/drivers/media/platform/qcom/iris/iris_hfi_queue.c @@ -263,7 +263,7 @@ int iris_hfi_queues_init(struct iris_core *core) GFP_KERNEL, DMA_ATTR_WRITE_COMBINE); if (!core->sfr_vaddr) { dev_err(core->dev, "sfr alloc and map failed\n"); - dma_free_attrs(core->dev, sizeof(*q_tbl_hdr), core->iface_q_table_vaddr, + dma_free_attrs(core->dev, queue_size, core->iface_q_table_vaddr, core->iface_q_table_daddr, DMA_ATTR_WRITE_COMBINE); return -ENOMEM; } diff --git a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h index 04f0b7400a1e..dfef180d32ed 100644 --- a/drivers/media/platform/qcom/iris/iris_vpu_buffer.h +++ b/drivers/media/platform/qcom/iris/iris_vpu_buffer.h @@ -61,7 +61,7 @@ struct iris_inst; #define SIZE_DOLBY_RPU_METADATA (41 * 1024) #define H264_CABAC_HDR_RATIO_HD_TOT 1 #define H264_CABAC_RES_RATIO_HD_TOT 3 -#define H265D_MAX_SLICE 1200 +#define H265D_MAX_SLICE 3600 #define SIZE_H265D_HW_PIC_T SIZE_H264D_HW_PIC_T #define H265_CABAC_HDR_RATIO_HD_TOT 2 #define H265_CABAC_RES_RATIO_HD_TOT 2 diff --git a/drivers/media/platform/qcom/venus/Kconfig b/drivers/media/platform/qcom/venus/Kconfig index ffb731ecd48c..63ee8c78dc6d 100644 --- a/drivers/media/platform/qcom/venus/Kconfig +++ b/drivers/media/platform/qcom/venus/Kconfig @@ -4,7 +4,7 @@ config VIDEO_QCOM_VENUS depends on VIDEO_DEV && QCOM_SMEM depends on (ARCH_QCOM && ARM64 && IOMMU_API) || COMPILE_TEST select OF_DYNAMIC if ARCH_QCOM - select QCOM_MDT_LOADER if ARCH_QCOM + select QCOM_MDT_LOADER select QCOM_SCM select VIDEOBUF2_DMA_CONTIG select V4L2_MEM2MEM_DEV diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c index b619d1436a41..f9af9177e02f 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-dma.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-dma.c @@ -676,8 +676,30 @@ void rvin_crop_scale_comp(struct rvin_dev *vin) if (vin->scaler) vin->scaler(vin); + /* + * VNIS_REG has four lowest bits always 0, i.e. the stride has to be + * aligned to 16 bytes. This is done in rvin_format_bytesperline(). + */ + fmt = rvin_format_from_pixel(vin, vin->format.pixelformat); stride = vin->format.bytesperline / fmt->bpp; + + /* + * RAW8 format bpp is 1, but the hardware process RAW8 format in 2 pixel + * units, so we need to divide the stride by 2. + */ + switch (vin->format.pixelformat) { + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SGBRG8: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SRGGB8: + case V4L2_PIX_FMT_GREY: + stride /= 2; + break; + default: + break; + } + rvin_write(vin, stride, VNIS_REG); } diff --git a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c index 079dbaf016c2..9d45e11898c1 100644 --- a/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c +++ b/drivers/media/platform/renesas/rcar-vin/rcar-v4l2.c @@ -155,6 +155,18 @@ static u32 rvin_format_bytesperline(struct rvin_dev *vin, case V4L2_PIX_FMT_NV16: align = 0x20; break; + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SGBRG8: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SRGGB8: + case V4L2_PIX_FMT_GREY: + /* + * RAW8 format bpp is 1, but the hardware process RAW8 format in + * 2 pixel units, and we need to align to 32 bytes. See + * rvin_crop_scale_comp(). + */ + align = 0x20; + break; default: align = 0x10; break; diff --git a/drivers/media/platform/renesas/vsp1/vsp1_drv.c b/drivers/media/platform/renesas/vsp1/vsp1_drv.c index 6c64657fc4f3..30df9b36642d 100644 --- a/drivers/media/platform/renesas/vsp1/vsp1_drv.c +++ b/drivers/media/platform/renesas/vsp1/vsp1_drv.c @@ -240,8 +240,12 @@ static void vsp1_destroy_entities(struct vsp1_device *vsp1) media_device_unregister(&vsp1->media_dev); media_device_cleanup(&vsp1->media_dev); - if (!vsp1->info->uapi) - vsp1_drm_cleanup(vsp1); + if (!vsp1->info->uapi) { + if (vsp1->info->version == VI6_IP_VERSION_MODEL_VSPX_GEN4) + vsp1_vspx_cleanup(vsp1); + else + vsp1_drm_cleanup(vsp1); + } } static int vsp1_create_entities(struct vsp1_device *vsp1) diff --git a/drivers/media/platform/ti/omap3isp/ispvideo.c b/drivers/media/platform/ti/omap3isp/ispvideo.c index eb33a776f27c..a0549e731fbf 100644 --- a/drivers/media/platform/ti/omap3isp/ispvideo.c +++ b/drivers/media/platform/ti/omap3isp/ispvideo.c @@ -1325,6 +1325,7 @@ static int isp_video_open(struct file *file) ret = vb2_queue_init(&handle->queue); if (ret < 0) { + v4l2_pipeline_pm_put(&video->video.entity); omap3isp_put(video->isp); goto done; } diff --git a/drivers/media/rc/streamzap.c b/drivers/media/rc/streamzap.c index d3b48a0dd1f4..8e9b156e4300 100644 --- a/drivers/media/rc/streamzap.c +++ b/drivers/media/rc/streamzap.c @@ -219,9 +219,8 @@ static void streamzap_callback(struct urb *urb) case -ESHUTDOWN: /* * this urb is terminated, clean up. - * sz might already be invalid at this point */ - dev_err(sz->dev, "urb terminated, status: %d\n", urb->status); + dev_dbg(sz->dev, "urb terminated, status: %d\n", urb->status); return; default: break; @@ -358,11 +357,16 @@ static int streamzap_probe(struct usb_interface *intf, usb_set_intfdata(intf, sz); - if (usb_submit_urb(sz->urb_in, GFP_ATOMIC)) + retval = usb_submit_urb(sz->urb_in, GFP_ATOMIC); + if (retval < 0) { dev_err(sz->dev, "urb submit failed\n"); + goto rc_submit_fail; + } return 0; - +rc_submit_fail: + rc_free_device(sz->rdev); + usb_set_intfdata(intf, NULL); rc_dev_fail: usb_free_urb(sz->urb_in); free_buf_in: diff --git a/drivers/media/rc/xbox_remote.c b/drivers/media/rc/xbox_remote.c index a1572381d097..0c9c855ced72 100644 --- a/drivers/media/rc/xbox_remote.c +++ b/drivers/media/rc/xbox_remote.c @@ -55,7 +55,7 @@ struct xbox_remote { struct usb_interface *interface; struct urb *irq_urb; - unsigned char inbuf[DATA_BUFSIZE] __aligned(sizeof(u16)); + u8 *inbuf; char rc_name[NAME_BUFSIZE]; char rc_phys[NAME_BUFSIZE]; @@ -218,6 +218,10 @@ static int xbox_remote_probe(struct usb_interface *interface, if (!xbox_remote || !rc_dev) goto exit_free_dev_rdev; + xbox_remote->inbuf = kzalloc(DATA_BUFSIZE, GFP_KERNEL); + if (!xbox_remote->inbuf) + goto exit_free_inbuf; + /* Allocate URB buffer */ xbox_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); if (!xbox_remote->irq_urb) @@ -262,6 +266,8 @@ static int xbox_remote_probe(struct usb_interface *interface, usb_kill_urb(xbox_remote->irq_urb); exit_free_buffers: usb_free_urb(xbox_remote->irq_urb); +exit_free_inbuf: + kfree(xbox_remote->inbuf); exit_free_dev_rdev: rc_free_device(rc_dev); kfree(xbox_remote); @@ -286,6 +292,7 @@ static void xbox_remote_disconnect(struct usb_interface *interface) usb_kill_urb(xbox_remote->irq_urb); rc_unregister_device(xbox_remote->rdev); usb_free_urb(xbox_remote->irq_urb); + kfree(xbox_remote->inbuf); kfree(xbox_remote); } diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index e838c6c1893a..085abdb116af 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -243,7 +243,7 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) int ret; queue->queue.type = type; - queue->queue.io_modes = VB2_MMAP | VB2_USERPTR; + queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF; queue->queue.drv_priv = queue; queue->queue.buf_struct_size = sizeof(struct uvc_buffer); queue->queue.mem_ops = &vb2_vmalloc_memops; @@ -256,7 +256,6 @@ int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type) queue->queue.ops = &uvc_meta_queue_qops; break; default: - queue->queue.io_modes |= VB2_DMABUF; queue->queue.ops = &uvc_queue_qops; break; } diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 31d099bd8db4..550d4b39a92a 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -362,6 +362,11 @@ static const struct key_entry hp_wmi_keymap[] = { { KE_KEY, 0x21a9, { KEY_TOUCHPAD_OFF } }, { KE_KEY, 0x121a9, { KEY_TOUCHPAD_ON } }, { KE_KEY, 0x231b, { KEY_HELP } }, + { KE_IGNORE, 0x21ab, }, /* FnLock on */ + { KE_IGNORE, 0x121ab, }, /* FnLock off */ + { KE_IGNORE, 0x30021aa, }, /* kbd backlight: level 2 -> off */ + { KE_IGNORE, 0x33221aa, }, /* kbd backlight: off -> level 1 */ + { KE_IGNORE, 0x36421aa, }, /* kbd backlight: level 1 -> level 2*/ { KE_END, 0 } }; diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c index 24cbdd833863..5bbe2bce740e 100644 --- a/drivers/regulator/act8945a-regulator.c +++ b/drivers/regulator/act8945a-regulator.c @@ -302,8 +302,9 @@ static int act8945a_pmic_probe(struct platform_device *pdev) num_regulators = ARRAY_SIZE(act8945a_regulators); } + device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); + config.dev = &pdev->dev; - config.dev->of_node = pdev->dev.parent->of_node; config.driver_data = act8945a; for (i = 0; i < num_regulators; i++) { rdev = devm_regulator_register(&pdev->dev, ®ulators[i], diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index 209beabb5c37..f4de24a281b1 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -287,8 +287,9 @@ static int bd9571mwv_regulator_probe(struct platform_device *pdev) platform_set_drvdata(pdev, bdreg); + device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); + config.dev = &pdev->dev; - config.dev->of_node = pdev->dev.parent->of_node; config.driver_data = bdreg; config.regmap = bdreg->regmap; diff --git a/drivers/regulator/bq257xx-regulator.c b/drivers/regulator/bq257xx-regulator.c index dab8f1ab4450..711dbe045383 100644 --- a/drivers/regulator/bq257xx-regulator.c +++ b/drivers/regulator/bq257xx-regulator.c @@ -142,8 +142,7 @@ static int bq257xx_regulator_probe(struct platform_device *pdev) struct device_node *np = dev->of_node; struct regulator_config cfg = {}; - pdev->dev.of_node = pdev->dev.parent->of_node; - pdev->dev.of_node_reused = true; + device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); pdata = devm_kzalloc(&pdev->dev, sizeof(struct bq257xx_reg_data), GFP_KERNEL); if (!pdata) diff --git a/drivers/regulator/max77650-regulator.c b/drivers/regulator/max77650-regulator.c index 7368f54f046d..99293bde3358 100644 --- a/drivers/regulator/max77650-regulator.c +++ b/drivers/regulator/max77650-regulator.c @@ -337,7 +337,7 @@ static int max77650_regulator_probe(struct platform_device *pdev) parent = dev->parent; if (!dev->of_node) - dev->of_node = parent->of_node; + device_set_of_node_from_dev(dev, parent); rdescs = devm_kcalloc(dev, MAX77650_REGULATOR_NUM_REGULATORS, sizeof(*rdescs), GFP_KERNEL); diff --git a/drivers/regulator/mt6357-regulator.c b/drivers/regulator/mt6357-regulator.c index 1eb69c7a6acb..09feb454ab6b 100644 --- a/drivers/regulator/mt6357-regulator.c +++ b/drivers/regulator/mt6357-regulator.c @@ -410,7 +410,7 @@ static int mt6357_regulator_probe(struct platform_device *pdev) struct regulator_dev *rdev; int i; - pdev->dev.of_node = pdev->dev.parent->of_node; + device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); for (i = 0; i < MT6357_MAX_REGULATOR; i++) { config.dev = &pdev->dev; diff --git a/drivers/regulator/rk808-regulator.c b/drivers/regulator/rk808-regulator.c index 1e8142479656..94cfb66ae656 100644 --- a/drivers/regulator/rk808-regulator.c +++ b/drivers/regulator/rk808-regulator.c @@ -1875,8 +1875,7 @@ static int rk808_regulator_probe(struct platform_device *pdev) struct regmap *regmap; int ret, i, nregulators; - pdev->dev.of_node = pdev->dev.parent->of_node; - pdev->dev.of_node_reused = true; + device_set_of_node_from_dev(&pdev->dev, pdev->dev.parent); regmap = dev_get_regmap(pdev->dev.parent, NULL); if (!regmap) diff --git a/drivers/regulator/s2dos05-regulator.c b/drivers/regulator/s2dos05-regulator.c index 1463585c4565..a1c394ddbaff 100644 --- a/drivers/regulator/s2dos05-regulator.c +++ b/drivers/regulator/s2dos05-regulator.c @@ -126,7 +126,7 @@ static int s2dos05_pmic_probe(struct platform_device *pdev) s2dos05->regmap = iodev->regmap_pmic; s2dos05->dev = dev; if (!dev->of_node) - dev->of_node = dev->parent->of_node; + device_set_of_node_from_dev(dev, dev->parent); config.dev = dev; config.driver_data = s2dos05; diff --git a/drivers/spi/spi-amlogic-spisg.c b/drivers/spi/spi-amlogic-spisg.c index 6045c89c37c8..56a6cf8471b9 100644 --- a/drivers/spi/spi-amlogic-spisg.c +++ b/drivers/spi/spi-amlogic-spisg.c @@ -801,7 +801,7 @@ static int aml_spisg_probe(struct platform_device *pdev) goto out_clk; } - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { dev_err(&pdev->dev, "spi controller registration failed\n"); goto out_clk; @@ -824,6 +824,8 @@ static void aml_spisg_remove(struct platform_device *pdev) { struct spisg_device *spisg = platform_get_drvdata(pdev); + spi_unregister_controller(spisg->controller); + if (!pm_runtime_suspended(&pdev->dev)) { pinctrl_pm_select_sleep_state(&spisg->pdev->dev); clk_disable_unprepare(spisg->core); diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c index 62a11142bd63..04eebb65cfa6 100644 --- a/drivers/spi/spi-aspeed-smc.c +++ b/drivers/spi/spi-aspeed-smc.c @@ -726,7 +726,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) return -ENOMEM; aspi = spi_controller_get_devdata(ctlr); - platform_set_drvdata(pdev, aspi); + platform_set_drvdata(pdev, ctlr); aspi->data = data; aspi->dev = dev; @@ -765,7 +765,7 @@ static int aspeed_spi_probe(struct platform_device *pdev) ctlr->num_chipselect = data->max_cs; ctlr->dev.of_node = dev->of_node; - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) dev_err(&pdev->dev, "spi_register_controller failed\n"); @@ -774,7 +774,10 @@ static int aspeed_spi_probe(struct platform_device *pdev) static void aspeed_spi_remove(struct platform_device *pdev) { - struct aspeed_spi *aspi = platform_get_drvdata(pdev); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct aspeed_spi *aspi = spi_controller_get_devdata(ctlr); + + spi_unregister_controller(ctlr); aspeed_spi_enable(aspi, false); } diff --git a/drivers/spi/spi-at91-usart.c b/drivers/spi/spi-at91-usart.c index bbe97ce89a2f..3617f538f98e 100644 --- a/drivers/spi/spi-at91-usart.c +++ b/drivers/spi/spi-at91-usart.c @@ -556,7 +556,7 @@ static int at91_usart_spi_probe(struct platform_device *pdev) spin_lock_init(&aus->lock); init_completion(&aus->xfer_completion); - ret = devm_spi_register_controller(&pdev->dev, controller); + ret = spi_register_controller(controller); if (ret) goto at91_usart_fail_register_controller; @@ -634,8 +634,14 @@ static void at91_usart_spi_remove(struct platform_device *pdev) struct spi_controller *ctlr = platform_get_drvdata(pdev); struct at91_usart_spi *aus = spi_controller_get_devdata(ctlr); + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + at91_usart_spi_release_dma(ctlr); clk_disable_unprepare(aus->clk); + + spi_controller_put(ctlr); } static const struct dev_pm_ops at91_usart_spi_pm_ops = { diff --git a/drivers/spi/spi-atmel.c b/drivers/spi/spi-atmel.c index 89977bff76d2..586e2fd357ed 100644 --- a/drivers/spi/spi-atmel.c +++ b/drivers/spi/spi-atmel.c @@ -1655,7 +1655,7 @@ static int atmel_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_free_dma; @@ -1689,8 +1689,12 @@ static void atmel_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct atmel_spi *as = spi_controller_get_devdata(host); + spi_controller_get(host); + pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ if (as->use_dma) { atmel_spi_stop_dma(host); @@ -1717,6 +1721,8 @@ static void atmel_spi_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(host); } static int atmel_spi_runtime_suspend(struct device *dev) diff --git a/drivers/spi/spi-bcm63xx.c b/drivers/spi/spi-bcm63xx.c index 2e3c62f12bef..cf7eefd39839 100644 --- a/drivers/spi/spi-bcm63xx.c +++ b/drivers/spi/spi-bcm63xx.c @@ -603,7 +603,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev) goto out_clk_disable; /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(dev, "spi register failed\n"); goto out_clk_disable; @@ -626,11 +626,17 @@ static void bcm63xx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcm63xx_spi *bs = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + /* reset spi block */ bcm_spi_writeb(bs, 0, SPI_INT_MASK); /* HW shutdown */ clk_disable_unprepare(bs->clk); + + spi_controller_put(host); } static int bcm63xx_spi_suspend(struct device *dev) diff --git a/drivers/spi/spi-bcmbca-hsspi.c b/drivers/spi/spi-bcmbca-hsspi.c index f16298b75236..f0f0e6b29668 100644 --- a/drivers/spi/spi-bcmbca-hsspi.c +++ b/drivers/spi/spi-bcmbca-hsspi.c @@ -550,7 +550,7 @@ static int bcmbca_hsspi_probe(struct platform_device *pdev) } /* register and we are done */ - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto out_sysgroup_disable; @@ -572,6 +572,8 @@ static void bcmbca_hsspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct bcmbca_hsspi *bs = spi_controller_get_devdata(host); + spi_unregister_controller(host); + /* reset the hardware and block queue progress */ __raw_writel(0, bs->regs + HSSPI_INT_MASK_REG); clk_disable_unprepare(bs->pll_clk); diff --git a/drivers/spi/spi-cadence.c b/drivers/spi/spi-cadence.c index 5ae09b21d23a..7a745c2e0892 100644 --- a/drivers/spi/spi-cadence.c +++ b/drivers/spi/spi-cadence.c @@ -662,7 +662,6 @@ static int cdns_spi_probe(struct platform_device *pdev) /* Set to default valid value */ ctlr->max_speed_hz = xspi->clk_rate / 4; xspi->speed_hz = ctlr->max_speed_hz; - pm_runtime_put_autosuspend(&pdev->dev); } else { ctlr->mode_bits |= SPI_NO_CS; ctlr->target_abort = cdns_target_abort; @@ -673,12 +672,17 @@ static int cdns_spi_probe(struct platform_device *pdev) goto clk_dis_all; } + if (!spi_controller_is_target(ctlr)) + pm_runtime_put_autosuspend(&pdev->dev); + return ret; clk_dis_all: if (!spi_controller_is_target(ctlr)) { pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); } remove_ctlr: spi_controller_put(ctlr); @@ -697,15 +701,26 @@ static void cdns_spi_remove(struct platform_device *pdev) { struct spi_controller *ctlr = platform_get_drvdata(pdev); struct cdns_spi *xspi = spi_controller_get_devdata(ctlr); + int ret = 0; - cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); + if (!spi_controller_is_target(ctlr)) + ret = pm_runtime_get_sync(&pdev->dev); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + + if (ret >= 0) + cdns_spi_write(xspi, CDNS_SPI_ER, CDNS_SPI_ER_DISABLE); if (!spi_controller_is_target(ctlr)) { pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); } - spi_unregister_controller(ctlr); + spi_controller_put(ctlr); } /** diff --git a/drivers/spi/spi-cavium-thunderx.c b/drivers/spi/spi-cavium-thunderx.c index 367ae7120bb3..81142b3f7b41 100644 --- a/drivers/spi/spi-cavium-thunderx.c +++ b/drivers/spi/spi-cavium-thunderx.c @@ -71,7 +71,7 @@ static int thunderx_spi_probe(struct pci_dev *pdev, pci_set_drvdata(pdev, host); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto error; @@ -91,8 +91,14 @@ static void thunderx_spi_remove(struct pci_dev *pdev) if (!p) return; + spi_controller_get(host); + + spi_unregister_controller(host); + /* Put everything in a known state. */ writeq(0, p->register_base + OCTEON_SPI_CFG(p)); + + spi_controller_put(host); } static const struct pci_device_id thunderx_spi_pci_id_table[] = { diff --git a/drivers/spi/spi-ch341.c b/drivers/spi/spi-ch341.c index ded093566260..3eaa8f176f63 100644 --- a/drivers/spi/spi-ch341.c +++ b/drivers/spi/spi-ch341.c @@ -152,7 +152,7 @@ static int ch341_probe(struct usb_interface *intf, if (ret) return ret; - ctrl = devm_spi_alloc_host(&udev->dev, sizeof(struct ch341_spi_dev)); + ctrl = devm_spi_alloc_host(&intf->dev, sizeof(struct ch341_spi_dev)); if (!ctrl) return -ENOMEM; @@ -163,7 +163,7 @@ static int ch341_probe(struct usb_interface *intf, ch341->read_pipe = usb_rcvbulkpipe(udev, usb_endpoint_num(in)); ch341->rx_len = usb_endpoint_maxp(in); - ch341->rx_buf = devm_kzalloc(&udev->dev, ch341->rx_len, GFP_KERNEL); + ch341->rx_buf = devm_kzalloc(&intf->dev, ch341->rx_len, GFP_KERNEL); if (!ch341->rx_buf) return -ENOMEM; @@ -171,8 +171,7 @@ static int ch341_probe(struct usb_interface *intf, if (!ch341->rx_urb) return -ENOMEM; - ch341->tx_buf = - devm_kzalloc(&udev->dev, CH341_PACKET_LENGTH, GFP_KERNEL); + ch341->tx_buf = devm_kzalloc(&intf->dev, CH341_PACKET_LENGTH, GFP_KERNEL); if (!ch341->tx_buf) { ret = -ENOMEM; goto err_free_urb; diff --git a/drivers/spi/spi-coldfire-qspi.c b/drivers/spi/spi-coldfire-qspi.c index fdf37636cb9f..b45f44de85dc 100644 --- a/drivers/spi/spi-coldfire-qspi.c +++ b/drivers/spi/spi-coldfire-qspi.c @@ -410,9 +410,9 @@ static int mcfqspi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); pm_runtime_enable(&pdev->dev); - status = devm_spi_register_controller(&pdev->dev, host); + status = spi_register_controller(host); if (status) { - dev_dbg(&pdev->dev, "devm_spi_register_controller failed\n"); + dev_dbg(&pdev->dev, "failed to register controller\n"); goto fail1; } @@ -436,11 +436,17 @@ static void mcfqspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mcfqspi *mcfqspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); /* disable the hardware (set the baud rate to 0) */ mcfqspi_wr_qmr(mcfqspi, MCFQSPI_QMR_MSTR); mcfqspi_cs_teardown(mcfqspi); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-dln2.c b/drivers/spi/spi-dln2.c index 2013bc56ded8..7260c4b96931 100644 --- a/drivers/spi/spi-dln2.c +++ b/drivers/spi/spi-dln2.c @@ -761,7 +761,7 @@ static int dln2_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "Failed to register host\n"); goto exit_register; @@ -786,10 +786,16 @@ static void dln2_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct dln2_spi *dln2 = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); if (dln2_spi_enable(dln2, false) < 0) dev_err(&pdev->dev, "Failed to disable SPI module\n"); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-fsl-espi.c b/drivers/spi/spi-fsl-espi.c index f2f1d3298e6c..cf89f36ab30b 100644 --- a/drivers/spi/spi-fsl-espi.c +++ b/drivers/spi/spi-fsl-espi.c @@ -719,7 +719,7 @@ static int fsl_espi_probe(struct device *dev, struct resource *mem, pm_runtime_enable(dev); pm_runtime_get_sync(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret < 0) goto err_pm; @@ -783,7 +783,15 @@ static int of_fsl_espi_probe(struct platform_device *ofdev) static void of_fsl_espi_remove(struct platform_device *dev) { + struct spi_controller *host = platform_get_drvdata(dev); + + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&dev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c index 481a7b28aacd..a516abbb6f67 100644 --- a/drivers/spi/spi-fsl-spi.c +++ b/drivers/spi/spi-fsl-spi.c @@ -614,7 +614,7 @@ static struct spi_controller *fsl_spi_probe(struct device *dev, mpc8xxx_spi_write_reg(®_base->mode, regval); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret < 0) goto err_probe; @@ -705,7 +705,13 @@ static void of_fsl_spi_remove(struct platform_device *ofdev) struct spi_controller *host = platform_get_drvdata(ofdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + fsl_spi_cpm_free(mpc8xxx_spi); + + spi_controller_put(host); } static struct platform_driver of_fsl_spi_driver = { @@ -751,7 +757,13 @@ static void plat_mpc8xxx_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mpc8xxx_spi *mpc8xxx_spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + fsl_spi_cpm_free(mpc8xxx_spi); + + spi_controller_put(host); } MODULE_ALIAS("platform:mpc8xxx_spi"); diff --git a/drivers/spi/spi-img-spfi.c b/drivers/spi/spi-img-spfi.c index 168ccf51f6d4..a6d15b9ca509 100644 --- a/drivers/spi/spi-img-spfi.c +++ b/drivers/spi/spi-img-spfi.c @@ -644,7 +644,7 @@ static int img_spfi_probe(struct platform_device *pdev) pm_runtime_set_active(spfi->dev); pm_runtime_enable(spfi->dev); - ret = devm_spi_register_controller(spfi->dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -670,6 +670,10 @@ static void img_spfi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct img_spfi *spfi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + if (spfi->tx_ch) dma_release_channel(spfi->tx_ch); if (spfi->rx_ch) @@ -680,6 +684,8 @@ static void img_spfi_remove(struct platform_device *pdev) clk_disable_unprepare(spfi->spfi_clk); clk_disable_unprepare(spfi->sys_clk); } + + spi_controller_put(host); } #ifdef CONFIG_PM diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index dc7ffa8cb287..ce3c7aa53f19 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1948,6 +1948,7 @@ static int spi_imx_probe(struct platform_device *pdev) out_runtime_pm_put: pm_runtime_dont_use_autosuspend(spi_imx->dev); pm_runtime_disable(spi_imx->dev); + pm_runtime_put_noidle(spi_imx->dev); pm_runtime_set_suspended(&pdev->dev); clk_disable_unprepare(spi_imx->clk_ipg); diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index 60849e07f674..97dbd58244b1 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -995,7 +995,7 @@ static int lantiq_ssc_probe(struct platform_device *pdev) "Lantiq SSC SPI controller (Rev %i, TXFS %u, RXFS %u, DMA %u)\n", revision, spi->tx_fifo_size, spi->rx_fifo_size, supports_dma); - err = devm_spi_register_controller(dev, host); + err = spi_register_controller(host); if (err) { dev_err(dev, "failed to register spi host\n"); goto err_wq_destroy; @@ -1017,6 +1017,10 @@ static void lantiq_ssc_remove(struct platform_device *pdev) { struct lantiq_ssc_spi *spi = platform_get_drvdata(pdev); + spi_controller_get(spi->host); + + spi_unregister_controller(spi->host); + lantiq_ssc_writel(spi, 0, LTQ_SPI_IRNEN); lantiq_ssc_writel(spi, 0, LTQ_SPI_CLC); rx_fifo_flush(spi); @@ -1025,6 +1029,8 @@ static void lantiq_ssc_remove(struct platform_device *pdev) destroy_workqueue(spi->wq); clk_put(spi->fpi_clk); + + spi_controller_put(spi->host); } static struct platform_driver lantiq_ssc_driver = { diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index c99fab392add..bb27a3b2bbc2 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -1082,7 +1082,7 @@ static int meson_spicc_probe(struct platform_device *pdev) } } - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "spi registration failed\n"); goto out_host; @@ -1100,8 +1100,14 @@ static void meson_spicc_remove(struct platform_device *pdev) { struct meson_spicc_device *spicc = platform_get_drvdata(pdev); + spi_controller_get(spicc->host); + + spi_unregister_controller(spicc->host); + /* Disable SPI */ writel(0, spicc->base + SPICC_CONREG); + + spi_controller_put(spicc->host); } static const struct meson_spicc_data meson_spicc_gx_data = { diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c index 6d4dde15ac54..84aade141606 100644 --- a/drivers/spi/spi-mpc52xx.c +++ b/drivers/spi/spi-mpc52xx.c @@ -501,6 +501,9 @@ static int mpc52xx_spi_probe(struct platform_device *op) err_register: dev_err(&ms->host->dev, "initialization failed\n"); + free_irq(ms->irq0, ms); + free_irq(ms->irq1, ms); + cancel_work_sync(&ms->work); err_gpio: while (i-- > 0) gpiod_put(ms->gpio_cs[i]); @@ -520,15 +523,17 @@ static void mpc52xx_spi_remove(struct platform_device *op) struct mpc52xx_spi *ms = spi_controller_get_devdata(host); int i; - cancel_work_sync(&ms->work); + spi_unregister_controller(host); + free_irq(ms->irq0, ms); free_irq(ms->irq1, ms); + cancel_work_sync(&ms->work); + for (i = 0; i < ms->gpio_cs_count; i++) gpiod_put(ms->gpio_cs[i]); kfree(ms->gpio_cs); - spi_unregister_controller(host); iounmap(ms->regs); spi_controller_put(host); } diff --git a/drivers/spi/spi-mpfs.c b/drivers/spi/spi-mpfs.c index 7e9e64d8e6c8..c41e0e55b52f 100644 --- a/drivers/spi/spi-mpfs.c +++ b/drivers/spi/spi-mpfs.c @@ -575,7 +575,7 @@ static int mpfs_spi_probe(struct platform_device *pdev) mpfs_spi_init(host, spi); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { mpfs_spi_disable_ints(spi); mpfs_spi_disable(spi); @@ -593,6 +593,8 @@ static void mpfs_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mpfs_spi *spi = spi_controller_get_devdata(host); + spi_unregister_controller(host); + mpfs_spi_disable_ints(spi); mpfs_spi_disable(spi); } diff --git a/drivers/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 90e5813cfdc3..9522d6f23788 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -1326,7 +1326,7 @@ static int mtk_spi_probe(struct platform_device *pdev) pm_runtime_enable(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) { pm_runtime_disable(dev); return dev_err_probe(dev, ret, "failed to register host\n"); @@ -1341,6 +1341,8 @@ static void mtk_spi_remove(struct platform_device *pdev) struct mtk_spi *mdata = spi_controller_get_devdata(host); int ret; + spi_unregister_controller(host); + cpu_latency_qos_remove_request(&mdata->qos_request); if (mdata->use_spimem && !completion_done(&mdata->spimem_done)) complete(&mdata->spimem_done); diff --git a/drivers/spi/spi-mtk-nor.c b/drivers/spi/spi-mtk-nor.c index 5cc4632e13d7..ba41ff42f0dd 100644 --- a/drivers/spi/spi-mtk-nor.c +++ b/drivers/spi/spi-mtk-nor.c @@ -914,7 +914,7 @@ static int mtk_nor_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); pm_runtime_get_noresume(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) goto err_probe; @@ -939,6 +939,8 @@ static void mtk_nor_remove(struct platform_device *pdev) struct spi_controller *ctlr = dev_get_drvdata(&pdev->dev); struct mtk_nor *sp = spi_controller_get_devdata(ctlr); + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); pm_runtime_set_suspended(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); diff --git a/drivers/spi/spi-mxic.c b/drivers/spi/spi-mxic.c index eeaea6a5e310..eea4a588e8a0 100644 --- a/drivers/spi/spi-mxic.c +++ b/drivers/spi/spi-mxic.c @@ -833,9 +833,10 @@ static void mxic_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct mxic_spi *mxic = spi_controller_get_devdata(host); + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); mxic_spi_mem_ecc_remove(mxic); - spi_unregister_controller(host); } static const struct of_device_id mxic_spi_of_ids[] = { diff --git a/drivers/spi/spi-mxs.c b/drivers/spi/spi-mxs.c index 0ebcbdb1b1f7..d5ac5dddfbf6 100644 --- a/drivers/spi/spi-mxs.c +++ b/drivers/spi/spi-mxs.c @@ -619,7 +619,7 @@ static int mxs_spi_probe(struct platform_device *pdev) if (ret) goto out_pm_runtime_put; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "Cannot register SPI host, %d\n", ret); goto out_pm_runtime_put; @@ -650,11 +650,17 @@ static void mxs_spi_remove(struct platform_device *pdev) spi = spi_controller_get_devdata(host); ssp = &spi->ssp; + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) mxs_spi_runtime_suspend(&pdev->dev); dma_release_channel(ssp->dmach); + + spi_controller_put(host); } static struct platform_driver mxs_spi_driver = { diff --git a/drivers/spi/spi-npcm-pspi.c b/drivers/spi/spi-npcm-pspi.c index 98b6479b961c..ba1714923772 100644 --- a/drivers/spi/spi-npcm-pspi.c +++ b/drivers/spi/spi-npcm-pspi.c @@ -414,7 +414,7 @@ static int npcm_pspi_probe(struct platform_device *pdev) /* set to default clock rate */ npcm_pspi_set_baudrate(priv, NPCM_PSPI_DEFAULT_CLK); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_disable_clk; @@ -435,8 +435,14 @@ static void npcm_pspi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct npcm_pspi *priv = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + npcm_pspi_reset_hw(priv); clk_disable_unprepare(priv->clk); + + spi_controller_put(host); } static const struct of_device_id npcm_pspi_match[] = { diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index 69c2e9d9be3c..86b3d21e7761 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1585,7 +1585,7 @@ static int omap2_mcspi_probe(struct platform_device *pdev) if (status < 0) goto disable_pm; - status = devm_spi_register_controller(&pdev->dev, ctlr); + status = spi_register_controller(ctlr); if (status < 0) goto disable_pm; @@ -1606,11 +1606,17 @@ static void omap2_mcspi_remove(struct platform_device *pdev) struct spi_controller *ctlr = platform_get_drvdata(pdev); struct omap2_mcspi *mcspi = spi_controller_get_devdata(ctlr); + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + omap2_mcspi_release_dma(ctlr); pm_runtime_dont_use_autosuspend(mcspi->dev); pm_runtime_put_sync(mcspi->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(ctlr); } /* work with hotplug and coldplug */ diff --git a/drivers/spi/spi-orion.c b/drivers/spi/spi-orion.c index 43bd9f21137f..eb71043300a9 100644 --- a/drivers/spi/spi-orion.c +++ b/drivers/spi/spi-orion.c @@ -774,6 +774,7 @@ static int orion_spi_probe(struct platform_device *pdev) pm_runtime_set_active(&pdev->dev); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_set_autosuspend_delay(&pdev->dev, SPI_AUTOSUSPEND_TIMEOUT); + pm_runtime_get_noresume(&pdev->dev); pm_runtime_enable(&pdev->dev); status = orion_spi_reset(spi); @@ -785,10 +786,15 @@ static int orion_spi_probe(struct platform_device *pdev) if (status < 0) goto out_rel_pm; + pm_runtime_put_autosuspend(&pdev->dev); + return status; out_rel_pm: pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); out_rel_axi_clk: clk_disable_unprepare(spi->axi_clk); out: @@ -802,11 +808,19 @@ static void orion_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct orion_spi *spi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_get_sync(&pdev->dev); clk_disable_unprepare(spi->axi_clk); - spi_unregister_controller(host); + spi_controller_put(host); + pm_runtime_disable(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_set_suspended(&pdev->dev); + pm_runtime_dont_use_autosuspend(&pdev->dev); } MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/spi/spi-pic32-sqi.c b/drivers/spi/spi-pic32-sqi.c index fa0c1ee84532..a6b5a0ed99c9 100644 --- a/drivers/spi/spi-pic32-sqi.c +++ b/drivers/spi/spi-pic32-sqi.c @@ -642,7 +642,7 @@ static int pic32_sqi_probe(struct platform_device *pdev) host->prepare_transfer_hardware = pic32_sqi_prepare_hardware; host->unprepare_transfer_hardware = pic32_sqi_unprepare_hardware; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&host->dev, "failed registering spi host\n"); free_irq(sqi->irq, sqi); @@ -665,9 +665,15 @@ static void pic32_sqi_remove(struct platform_device *pdev) { struct pic32_sqi *sqi = platform_get_drvdata(pdev); + spi_controller_get(sqi->host); + + spi_unregister_controller(sqi->host); + /* release resources */ free_irq(sqi->irq, sqi); ring_desc_ring_free(sqi); + + spi_controller_put(sqi->host); } static const struct of_device_id pic32_sqi_of_ids[] = { diff --git a/drivers/spi/spi-pic32.c b/drivers/spi/spi-pic32.c index 369850d14313..70427e529945 100644 --- a/drivers/spi/spi-pic32.c +++ b/drivers/spi/spi-pic32.c @@ -821,7 +821,7 @@ static int pic32_spi_probe(struct platform_device *pdev) } /* register host */ - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&host->dev, "failed registering spi host\n"); goto err_bailout; @@ -840,11 +840,16 @@ static int pic32_spi_probe(struct platform_device *pdev) static void pic32_spi_remove(struct platform_device *pdev) { - struct pic32_spi *pic32s; + struct pic32_spi *pic32s = platform_get_drvdata(pdev); + + spi_controller_get(pic32s->host); + + spi_unregister_controller(pic32s->host); - pic32s = platform_get_drvdata(pdev); pic32_spi_disable(pic32s); pic32_spi_dma_unprep(pic32s); + + spi_controller_put(pic32s->host); } static const struct of_device_id pic32_spi_of_match[] = { diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c index 9e56e8774614..da00dfa734d9 100644 --- a/drivers/spi/spi-pl022.c +++ b/drivers/spi/spi-pl022.c @@ -1957,7 +1957,7 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id) /* Register with the SPI framework */ amba_set_drvdata(adev, pl022); - status = devm_spi_register_controller(&adev->dev, host); + status = spi_register_controller(host); if (status != 0) { dev_err_probe(&adev->dev, status, "problem registering spi host\n"); @@ -1998,6 +1998,10 @@ pl022_remove(struct amba_device *adev) if (!pl022) return; + spi_controller_get(pl022->host); + + spi_unregister_controller(pl022->host); + /* * undo pm_runtime_put() in probe. I assume that we're not * accessing the primecell here. @@ -2009,6 +2013,8 @@ pl022_remove(struct amba_device *adev) pl022_dma_remove(pl022); amba_release_regions(adev); + + spi_controller_put(pl022->host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-qup.c b/drivers/spi/spi-qup.c index 7d647edf6bc3..a5c549479c7d 100644 --- a/drivers/spi/spi-qup.c +++ b/drivers/spi/spi-qup.c @@ -1194,7 +1194,7 @@ static int spi_qup_probe(struct platform_device *pdev) pm_runtime_set_active(dev); pm_runtime_enable(dev); - ret = devm_spi_register_controller(dev, host); + ret = spi_register_controller(host); if (ret) goto disable_pm; @@ -1321,6 +1321,10 @@ static void spi_qup_remove(struct platform_device *pdev) struct spi_qup *controller = spi_controller_get_devdata(host); int ret; + spi_controller_get(host); + + spi_unregister_controller(host); + ret = pm_runtime_get_sync(&pdev->dev); if (ret >= 0) { @@ -1340,6 +1344,8 @@ static void spi_qup_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(host); } static const struct of_device_id spi_qup_dt_match[] = { diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 8e1d911b88b5..c90dfe521154 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -1171,8 +1171,14 @@ static void rspi_remove(struct platform_device *pdev) { struct rspi_data *rspi = platform_get_drvdata(pdev); + spi_controller_get(rspi->ctlr); + + spi_unregister_controller(rspi->ctlr); + rspi_release_dma(rspi->ctlr); pm_runtime_disable(&pdev->dev); + + spi_controller_put(rspi->ctlr); } static const struct spi_ops rspi_ops = { @@ -1377,9 +1383,9 @@ static int rspi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(&pdev->dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error3; } diff --git a/drivers/spi/spi-s3c64xx.c b/drivers/spi/spi-s3c64xx.c index 33c80daec5f6..851340f107b8 100644 --- a/drivers/spi/spi-s3c64xx.c +++ b/drivers/spi/spi-s3c64xx.c @@ -1370,7 +1370,7 @@ static int s3c64xx_spi_probe(struct platform_device *pdev) S3C64XX_SPI_INT_TX_OVERRUN_EN | S3C64XX_SPI_INT_TX_UNDERRUN_EN, sdd->regs + S3C64XX_SPI_INT_EN); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret != 0) { dev_err(&pdev->dev, "cannot register SPI host: %d\n", ret); goto err_pm_put; @@ -1400,6 +1400,8 @@ static void s3c64xx_spi_remove(struct platform_device *pdev) pm_runtime_get_sync(&pdev->dev); + spi_unregister_controller(host); + writel(0, sdd->regs + S3C64XX_SPI_INT_EN); pm_runtime_put_noidle(&pdev->dev); diff --git a/drivers/spi/spi-sh-hspi.c b/drivers/spi/spi-sh-hspi.c index 93017faeb7b5..8253ab9b8838 100644 --- a/drivers/spi/spi-sh-hspi.c +++ b/drivers/spi/spi-sh-hspi.c @@ -258,9 +258,9 @@ static int hspi_probe(struct platform_device *pdev) ctlr->transfer_one_message = hspi_transfer_one_message; ctlr->bits_per_word_mask = SPI_BPW_MASK(8); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(&pdev->dev, "devm_spi_register_controller error.\n"); + dev_err(&pdev->dev, "failed to register controller\n"); goto error2; } @@ -280,9 +280,15 @@ static void hspi_remove(struct platform_device *pdev) { struct hspi_priv *hspi = platform_get_drvdata(pdev); + spi_controller_get(hspi->ctlr); + + spi_unregister_controller(hspi->ctlr); + pm_runtime_disable(&pdev->dev); clk_put(hspi->clk); + + spi_controller_put(hspi->ctlr); } static const struct of_device_id hspi_of_match[] = { diff --git a/drivers/spi/spi-sh-msiof.c b/drivers/spi/spi-sh-msiof.c index b695870fae8c..7f4135a3bda2 100644 --- a/drivers/spi/spi-sh-msiof.c +++ b/drivers/spi/spi-sh-msiof.c @@ -1290,9 +1290,9 @@ static int sh_msiof_spi_probe(struct platform_device *pdev) if (ret < 0) dev_warn(dev, "DMA not available, using PIO\n"); - ret = devm_spi_register_controller(dev, ctlr); + ret = spi_register_controller(ctlr); if (ret < 0) { - dev_err(dev, "devm_spi_register_controller error.\n"); + dev_err(dev, "failed to register controller\n"); goto err2; } @@ -1310,8 +1310,14 @@ static void sh_msiof_spi_remove(struct platform_device *pdev) { struct sh_msiof_spi_priv *p = platform_get_drvdata(pdev); + spi_controller_get(p->ctlr); + + spi_unregister_controller(p->ctlr); + sh_msiof_release_dma(p); pm_runtime_disable(&pdev->dev); + + spi_controller_put(p->ctlr); } static const struct platform_device_id spi_driver_ids[] = { diff --git a/drivers/spi/spi-slave-mt27xx.c b/drivers/spi/spi-slave-mt27xx.c index e331df967385..c39d8e590ad7 100644 --- a/drivers/spi/spi-slave-mt27xx.c +++ b/drivers/spi/spi-slave-mt27xx.c @@ -454,7 +454,7 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); clk_disable_unprepare(mdata->spi_clk); if (ret) { dev_err(&pdev->dev, @@ -474,7 +474,15 @@ static int mtk_spi_slave_probe(struct platform_device *pdev) static void mtk_spi_slave_remove(struct platform_device *pdev) { + struct spi_controller *ctlr = platform_get_drvdata(pdev); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); + pm_runtime_disable(&pdev->dev); + + spi_controller_put(ctlr); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-sprd.c b/drivers/spi/spi-sprd.c index ad75f5f0f2bf..218c38841f05 100644 --- a/drivers/spi/spi-sprd.c +++ b/drivers/spi/spi-sprd.c @@ -978,7 +978,7 @@ static int sprd_spi_probe(struct platform_device *pdev) goto err_rpm_put; } - ret = devm_spi_register_controller(&pdev->dev, sctlr); + ret = spi_register_controller(sctlr); if (ret) goto err_rpm_put; @@ -1009,7 +1009,9 @@ static void sprd_spi_remove(struct platform_device *pdev) if (ret < 0) dev_err(ss->dev, "failed to resume SPI controller\n"); - spi_controller_suspend(sctlr); + spi_controller_get(sctlr); + + spi_unregister_controller(sctlr); if (ret >= 0) { if (ss->dma.enable) @@ -1018,6 +1020,8 @@ static void sprd_spi_remove(struct platform_device *pdev) } pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + + spi_controller_put(sctlr); } static int __maybe_unused sprd_spi_runtime_suspend(struct device *dev) diff --git a/drivers/spi/spi-st-ssc4.c b/drivers/spi/spi-st-ssc4.c index c07c61dc4938..23a306901c0f 100644 --- a/drivers/spi/spi-st-ssc4.c +++ b/drivers/spi/spi-st-ssc4.c @@ -349,7 +349,7 @@ static int spi_st_probe(struct platform_device *pdev) platform_set_drvdata(pdev, host); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) { dev_err(&pdev->dev, "Failed to register host\n"); goto rpm_disable; @@ -371,10 +371,16 @@ static void spi_st_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct spi_st *spi_st = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + pm_runtime_disable(&pdev->dev); clk_disable_unprepare(spi_st->clk); + spi_controller_put(host); + pinctrl_pm_select_sleep_state(&pdev->dev); } diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 48fb11fea55f..a28597b6b80d 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1416,7 +1416,7 @@ static int tegra_spi_probe(struct platform_device *pdev) } host->dev.of_node = pdev->dev.of_node; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "can not register to host err %d\n", ret); goto exit_free_irq; @@ -1442,6 +1442,10 @@ static void tegra_spi_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_spi_data *tspi = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + free_irq(tspi->irq, tspi); if (tspi->tx_dma_chan) @@ -1453,6 +1457,8 @@ static void tegra_spi_remove(struct platform_device *pdev) pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_spi_runtime_suspend(&pdev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c index d5c8ee20b8e5..dc3fcab5faa9 100644 --- a/drivers/spi/spi-tegra20-sflash.c +++ b/drivers/spi/spi-tegra20-sflash.c @@ -506,7 +506,7 @@ static int tegra_sflash_probe(struct platform_device *pdev) pm_runtime_put(&pdev->dev); host->dev.of_node = pdev->dev.of_node; - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret < 0) { dev_err(&pdev->dev, "can not register to host err %d\n", ret); goto exit_pm_disable; @@ -529,11 +529,17 @@ static void tegra_sflash_remove(struct platform_device *pdev) struct spi_controller *host = platform_get_drvdata(pdev); struct tegra_sflash_data *tsd = spi_controller_get_devdata(host); + spi_controller_get(host); + + spi_unregister_controller(host); + free_irq(tsd->irq, tsd); pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra_sflash_runtime_suspend(&pdev->dev); + + spi_controller_put(host); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/spi/spi-uniphier.c b/drivers/spi/spi-uniphier.c index ff2142f87277..75b7a0d3f865 100644 --- a/drivers/spi/spi-uniphier.c +++ b/drivers/spi/spi-uniphier.c @@ -666,28 +666,24 @@ static int uniphier_spi_probe(struct platform_device *pdev) } priv->base_dma_addr = res->start; - priv->clk = devm_clk_get(&pdev->dev, NULL); + priv->clk = devm_clk_get_enabled(&pdev->dev, NULL); if (IS_ERR(priv->clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(priv->clk); goto out_host_put; } - ret = clk_prepare_enable(priv->clk); - if (ret) - goto out_host_put; - irq = platform_get_irq(pdev, 0); if (irq < 0) { ret = irq; - goto out_disable_clk; + goto out_host_put; } ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler, 0, "uniphier-spi", priv); if (ret) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto out_disable_clk; + goto out_host_put; } init_completion(&priv->xfer_done); @@ -717,7 +713,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) if (IS_ERR_OR_NULL(host->dma_tx)) { if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) { ret = -EPROBE_DEFER; - goto out_disable_clk; + goto out_host_put; } host->dma_tx = NULL; dma_tx_burst = INT_MAX; @@ -751,7 +747,7 @@ static int uniphier_spi_probe(struct platform_device *pdev) host->max_dma_len = min(dma_tx_burst, dma_rx_burst); - ret = devm_spi_register_controller(&pdev->dev, host); + ret = spi_register_controller(host); if (ret) goto out_release_dma; @@ -767,9 +763,6 @@ static int uniphier_spi_probe(struct platform_device *pdev) host->dma_tx = NULL; } -out_disable_clk: - clk_disable_unprepare(priv->clk); - out_host_put: spi_controller_put(host); return ret; @@ -778,14 +771,17 @@ static int uniphier_spi_probe(struct platform_device *pdev) static void uniphier_spi_remove(struct platform_device *pdev) { struct spi_controller *host = platform_get_drvdata(pdev); - struct uniphier_spi_priv *priv = spi_controller_get_devdata(host); + + spi_controller_get(host); + + spi_unregister_controller(host); if (host->dma_tx) dma_release_channel(host->dma_tx); if (host->dma_rx) dma_release_channel(host->dma_rx); - clk_disable_unprepare(priv->clk); + spi_controller_put(host); } static const struct of_device_id uniphier_spi_match[] = { diff --git a/drivers/spi/spi-zynq-qspi.c b/drivers/spi/spi-zynq-qspi.c index 5232483c4a3a..406fd9d5337e 100644 --- a/drivers/spi/spi-zynq-qspi.c +++ b/drivers/spi/spi-zynq-qspi.c @@ -381,21 +381,10 @@ static int zynq_qspi_setup_op(struct spi_device *spi) { struct spi_controller *ctlr = spi->controller; struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr); - int ret; if (ctlr->busy) return -EBUSY; - ret = clk_enable(qspi->refclk); - if (ret) - return ret; - - ret = clk_enable(qspi->pclk); - if (ret) { - clk_disable(qspi->refclk); - return ret; - } - zynq_qspi_write(qspi, ZYNQ_QSPI_ENABLE_OFFSET, ZYNQ_QSPI_ENABLE_ENABLE_MASK); @@ -654,14 +643,14 @@ static int zynq_qspi_probe(struct platform_device *pdev) xqspi = spi_controller_get_devdata(ctlr); xqspi->dev = dev; - platform_set_drvdata(pdev, xqspi); + platform_set_drvdata(pdev, ctlr); xqspi->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(xqspi->regs)) { ret = PTR_ERR(xqspi->regs); goto remove_ctlr; } - xqspi->pclk = devm_clk_get(&pdev->dev, "pclk"); + xqspi->pclk = devm_clk_get_enabled(&pdev->dev, "pclk"); if (IS_ERR(xqspi->pclk)) { dev_err(&pdev->dev, "pclk clock not found.\n"); ret = PTR_ERR(xqspi->pclk); @@ -670,36 +659,24 @@ static int zynq_qspi_probe(struct platform_device *pdev) init_completion(&xqspi->data_completion); - xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk"); + xqspi->refclk = devm_clk_get_enabled(&pdev->dev, "ref_clk"); if (IS_ERR(xqspi->refclk)) { dev_err(&pdev->dev, "ref_clk clock not found.\n"); ret = PTR_ERR(xqspi->refclk); goto remove_ctlr; } - ret = clk_prepare_enable(xqspi->pclk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable APB clock.\n"); - goto remove_ctlr; - } - - ret = clk_prepare_enable(xqspi->refclk); - if (ret) { - dev_err(&pdev->dev, "Unable to enable device clock.\n"); - goto clk_dis_pclk; - } - xqspi->irq = platform_get_irq(pdev, 0); if (xqspi->irq < 0) { ret = xqspi->irq; - goto clk_dis_all; + goto remove_ctlr; } ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq, 0, pdev->name, xqspi); if (ret != 0) { ret = -ENXIO; dev_err(&pdev->dev, "request_irq failed\n"); - goto clk_dis_all; + goto remove_ctlr; } ret = of_property_read_u32(np, "num-cs", @@ -709,7 +686,7 @@ static int zynq_qspi_probe(struct platform_device *pdev) } else if (num_cs > ZYNQ_QSPI_MAX_NUM_CS) { ret = -EINVAL; dev_err(&pdev->dev, "only 2 chip selects are available\n"); - goto clk_dis_all; + goto remove_ctlr; } else { ctlr->num_chipselect = num_cs; } @@ -725,18 +702,14 @@ static int zynq_qspi_probe(struct platform_device *pdev) /* QSPI controller initializations */ zynq_qspi_init_hw(xqspi, ctlr->num_chipselect); - ret = devm_spi_register_controller(&pdev->dev, ctlr); + ret = spi_register_controller(ctlr); if (ret) { - dev_err(&pdev->dev, "devm_spi_register_controller failed\n"); - goto clk_dis_all; + dev_err(&pdev->dev, "failed to register controller\n"); + goto remove_ctlr; } return ret; -clk_dis_all: - clk_disable_unprepare(xqspi->refclk); -clk_dis_pclk: - clk_disable_unprepare(xqspi->pclk); remove_ctlr: spi_controller_put(ctlr); @@ -755,12 +728,16 @@ static int zynq_qspi_probe(struct platform_device *pdev) */ static void zynq_qspi_remove(struct platform_device *pdev) { - struct zynq_qspi *xqspi = platform_get_drvdata(pdev); + struct spi_controller *ctlr = platform_get_drvdata(pdev); + struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr); + + spi_controller_get(ctlr); + + spi_unregister_controller(ctlr); zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0); - clk_disable_unprepare(xqspi->refclk); - clk_disable_unprepare(xqspi->pclk); + spi_controller_put(ctlr); } static const struct of_device_id zynq_qspi_of_match[] = { diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index bb8b2f2213b0..2907ef2a37ed 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -1357,6 +1357,10 @@ static int atomisp_s_parm(struct file *file, void *fh, static long atomisp_vidioc_default(struct file *file, void *fh, bool valid_prio, unsigned int cmd, void *arg) { + /* Disable all private IOCTLs for now! */ + if (cmd) + return -EINVAL; + struct video_device *vdev = video_devdata(file); struct atomisp_sub_device *asd = atomisp_to_video_pipe(vdev)->asd; int err; diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index fd7e37d803e7..55a7d8f38465 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -97,9 +97,6 @@ struct csi_priv { /* the mipi virtual channel number at link validate */ int vc_num; - /* media bus config of the upstream subdevice CSI is receiving from */ - struct v4l2_mbus_config mbus_cfg; - spinlock_t irqlock; /* protect eof_irq handler */ struct timer_list eof_timeout_timer; int eof_irq; @@ -403,7 +400,8 @@ static void csi_idmac_unsetup_vb2_buf(struct csi_priv *priv, } /* init the SMFC IDMAC channel */ -static int csi_idmac_setup_channel(struct csi_priv *priv) +static int csi_idmac_setup_channel(struct csi_priv *priv, + struct v4l2_mbus_config *mbus_cfg) { struct imx_media_video_dev *vdev = priv->vdev; const struct imx_media_pixfmt *incc; @@ -432,7 +430,7 @@ static int csi_idmac_setup_channel(struct csi_priv *priv) image.phys0 = phys[0]; image.phys1 = phys[1]; - passthrough = requires_passthrough(&priv->mbus_cfg, infmt, incc); + passthrough = requires_passthrough(mbus_cfg, infmt, incc); passthrough_cycles = 1; /* @@ -572,11 +570,12 @@ static void csi_idmac_unsetup(struct csi_priv *priv, csi_idmac_unsetup_vb2_buf(priv, state); } -static int csi_idmac_setup(struct csi_priv *priv) +static int csi_idmac_setup(struct csi_priv *priv, + struct v4l2_mbus_config *mbus_cfg) { int ret; - ret = csi_idmac_setup_channel(priv); + ret = csi_idmac_setup_channel(priv, mbus_cfg); if (ret) return ret; @@ -595,7 +594,8 @@ static int csi_idmac_setup(struct csi_priv *priv) return 0; } -static int csi_idmac_start(struct csi_priv *priv) +static int csi_idmac_start(struct csi_priv *priv, + struct v4l2_mbus_config *mbus_cfg) { struct imx_media_video_dev *vdev = priv->vdev; int ret; @@ -619,7 +619,7 @@ static int csi_idmac_start(struct csi_priv *priv) priv->last_eof = false; priv->nfb4eof = false; - ret = csi_idmac_setup(priv); + ret = csi_idmac_setup(priv, mbus_cfg); if (ret) { v4l2_err(&priv->sd, "csi_idmac_setup failed: %d\n", ret); goto out_free_dma_buf; @@ -701,7 +701,8 @@ static void csi_idmac_stop(struct csi_priv *priv) } /* Update the CSI whole sensor and active windows */ -static int csi_setup(struct csi_priv *priv) +static int csi_setup(struct csi_priv *priv, + struct v4l2_mbus_config *mbus_cfg) { struct v4l2_mbus_framefmt *infmt, *outfmt; const struct imx_media_pixfmt *incc; @@ -719,7 +720,7 @@ static int csi_setup(struct csi_priv *priv) * if cycles is set, we need to handle this over multiple cycles as * generic/bayer data */ - if (is_parallel_bus(&priv->mbus_cfg) && incc->cycles) { + if (is_parallel_bus(mbus_cfg) && incc->cycles) { if_fmt.width *= incc->cycles; crop.width *= incc->cycles; } @@ -730,7 +731,7 @@ static int csi_setup(struct csi_priv *priv) priv->crop.width == 2 * priv->compose.width, priv->crop.height == 2 * priv->compose.height); - ipu_csi_init_interface(priv->csi, &priv->mbus_cfg, &if_fmt, outfmt); + ipu_csi_init_interface(priv->csi, mbus_cfg, &if_fmt, outfmt); ipu_csi_set_dest(priv->csi, priv->dest); @@ -745,9 +746,17 @@ static int csi_setup(struct csi_priv *priv) static int csi_start(struct csi_priv *priv) { + struct v4l2_mbus_config mbus_cfg = { .type = 0 }; struct v4l2_fract *input_fi, *output_fi; int ret; + ret = csi_get_upstream_mbus_config(priv, &mbus_cfg); + if (ret) { + v4l2_err(&priv->sd, + "failed to get upstream media bus configuration\n"); + return ret; + } + input_fi = &priv->frame_interval[CSI_SINK_PAD]; output_fi = &priv->frame_interval[priv->active_output_pad]; @@ -758,7 +767,7 @@ static int csi_start(struct csi_priv *priv) return ret; /* Skip first few frames from a BT.656 source */ - if (priv->mbus_cfg.type == V4L2_MBUS_BT656) { + if (mbus_cfg.type == V4L2_MBUS_BT656) { u32 delay_usec, bad_frames = 20; delay_usec = DIV_ROUND_UP_ULL((u64)USEC_PER_SEC * @@ -769,12 +778,12 @@ static int csi_start(struct csi_priv *priv) } if (priv->dest == IPU_CSI_DEST_IDMAC) { - ret = csi_idmac_start(priv); + ret = csi_idmac_start(priv, &mbus_cfg); if (ret) goto stop_upstream; } - ret = csi_setup(priv); + ret = csi_setup(priv, &mbus_cfg); if (ret) goto idmac_stop; @@ -1138,7 +1147,6 @@ static int csi_link_validate(struct v4l2_subdev *sd, mutex_lock(&priv->lock); - priv->mbus_cfg = mbus_cfg; is_csi2 = !is_parallel_bus(&mbus_cfg); if (is_csi2) { /* diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c6b7df5682b4..a1f99c3b5f37 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -114,23 +114,23 @@ void dwc3_enable_susphy(struct dwc3 *dwc, bool enable) int i; for (i = 0; i < dwc->num_usb3_ports; i++) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(i)); + reg = dwc3_readl(dwc, DWC3_GUSB3PIPECTL(i)); if (enable && !dwc->dis_u3_susphy_quirk) reg |= DWC3_GUSB3PIPECTL_SUSPHY; else reg &= ~DWC3_GUSB3PIPECTL_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(i), reg); + dwc3_writel(dwc, DWC3_GUSB3PIPECTL(i), reg); } for (i = 0; i < dwc->num_usb2_ports; i++) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(i)); if (enable && !dwc->dis_u2_susphy_quirk) reg |= DWC3_GUSB2PHYCFG_SUSPHY; else reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(i), reg); } } @@ -139,7 +139,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy) unsigned int hw_mode; u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); /* * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE and @@ -154,7 +154,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u32 mode, bool ignore_susphy) reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG)); reg |= DWC3_GCTL_PRTCAPDIR(mode); - dwc3_writel(dwc->regs, DWC3_GCTL, reg); + dwc3_writel(dwc, DWC3_GCTL, reg); dwc->current_dr_role = mode; trace_dwc3_set_prtcap(mode); @@ -214,9 +214,9 @@ static void __dwc3_set_mode(struct work_struct *work) if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) || DWC3_VER_IS_PRIOR(DWC31, 190A)) && desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) { - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); reg |= DWC3_GCTL_CORESOFTRESET; - dwc3_writel(dwc->regs, DWC3_GCTL, reg); + dwc3_writel(dwc, DWC3_GCTL, reg); /* * Wait for internal clocks to synchronized. DWC_usb31 and @@ -226,9 +226,9 @@ static void __dwc3_set_mode(struct work_struct *work) */ msleep(100); - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); reg &= ~DWC3_GCTL_CORESOFTRESET; - dwc3_writel(dwc->regs, DWC3_GCTL, reg); + dwc3_writel(dwc, DWC3_GCTL, reg); } spin_lock_irqsave(&dwc->lock, flags); @@ -252,9 +252,9 @@ static void __dwc3_set_mode(struct work_struct *work) phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST); if (dwc->dis_split_quirk) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); + reg = dwc3_readl(dwc, DWC3_GUCTL3); reg |= DWC3_GUCTL3_SPLITDISABLE; - dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); + dwc3_writel(dwc, DWC3_GUCTL3, reg); } } break; @@ -305,11 +305,11 @@ u32 dwc3_core_fifo_space(struct dwc3_ep *dep, u8 type) struct dwc3 *dwc = dep->dwc; u32 reg; - dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE, - DWC3_GDBGFIFOSPACE_NUM(dep->number) | - DWC3_GDBGFIFOSPACE_TYPE(type)); + dwc3_writel(dwc, DWC3_GDBGFIFOSPACE, + DWC3_GDBGFIFOSPACE_NUM(dep->number) | + DWC3_GDBGFIFOSPACE_TYPE(type)); - reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE); + reg = dwc3_readl(dwc, DWC3_GDBGFIFOSPACE); return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg); } @@ -331,7 +331,7 @@ int dwc3_core_soft_reset(struct dwc3 *dwc) if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST) return 0; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg |= DWC3_DCTL_CSFTRST; reg &= ~DWC3_DCTL_RUN_STOP; dwc3_gadget_dctl_write_safe(dwc, reg); @@ -346,7 +346,7 @@ int dwc3_core_soft_reset(struct dwc3 *dwc) retries = 10; do { - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (!(reg & DWC3_DCTL_CSFTRST)) goto done; @@ -386,12 +386,12 @@ static void dwc3_frame_length_adjustment(struct dwc3 *dwc) if (dwc->fladj == 0) return; - reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); + reg = dwc3_readl(dwc, DWC3_GFLADJ); dft = reg & DWC3_GFLADJ_30MHZ_MASK; if (dft != dwc->fladj) { reg &= ~DWC3_GFLADJ_30MHZ_MASK; reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj; - dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); + dwc3_writel(dwc, DWC3_GFLADJ, reg); } } @@ -423,10 +423,10 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc) return; } - reg = dwc3_readl(dwc->regs, DWC3_GUCTL); + reg = dwc3_readl(dwc, DWC3_GUCTL); reg &= ~DWC3_GUCTL_REFCLKPER_MASK; reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period); - dwc3_writel(dwc->regs, DWC3_GUCTL, reg); + dwc3_writel(dwc, DWC3_GUCTL, reg); if (DWC3_VER_IS_PRIOR(DWC3, 250A)) return; @@ -454,7 +454,7 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc) */ decr = 480000000 / rate; - reg = dwc3_readl(dwc->regs, DWC3_GFLADJ); + reg = dwc3_readl(dwc, DWC3_GFLADJ); reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK & ~DWC3_GFLADJ_240MHZDECR & ~DWC3_GFLADJ_240MHZDECR_PLS1; @@ -465,7 +465,7 @@ static void dwc3_ref_clk_period(struct dwc3 *dwc) if (dwc->gfladj_refclk_lpm_sel) reg |= DWC3_GFLADJ_REFCLK_LPM_SEL; - dwc3_writel(dwc->regs, DWC3_GFLADJ, reg); + dwc3_writel(dwc, DWC3_GFLADJ, reg); } /** @@ -568,16 +568,16 @@ int dwc3_event_buffers_setup(struct dwc3 *dwc) evt = dwc->ev_buf; evt->lpos = 0; - dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), - lower_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), - upper_32_bits(evt->dma)); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), - DWC3_GEVNTSIZ_SIZE(evt->length)); + dwc3_writel(dwc, DWC3_GEVNTADRLO(0), + lower_32_bits(evt->dma)); + dwc3_writel(dwc, DWC3_GEVNTADRHI(0), + upper_32_bits(evt->dma)); + dwc3_writel(dwc, DWC3_GEVNTSIZ(0), + DWC3_GEVNTSIZ_SIZE(evt->length)); /* Clear any stale event */ - reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg); + reg = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0)); + dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), reg); return 0; } @@ -592,7 +592,7 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc) * Exynos platforms may not be able to access event buffer if the * controller failed to halt on dwc3_core_exit(). */ - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); if (!(reg & DWC3_DSTS_DEVCTRLHLT)) return; @@ -600,14 +600,14 @@ void dwc3_event_buffers_cleanup(struct dwc3 *dwc) evt->lpos = 0; - dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0); - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK + dwc3_writel(dwc, DWC3_GEVNTADRLO(0), 0); + dwc3_writel(dwc, DWC3_GEVNTADRHI(0), 0); + dwc3_writel(dwc, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(0)); /* Clear any stale event */ - reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg); + reg = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0)); + dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), reg); } static void dwc3_core_num_eps(struct dwc3 *dwc) @@ -621,18 +621,18 @@ static void dwc3_cache_hwparams(struct dwc3 *dwc) { struct dwc3_hwparams *parms = &dwc->hwparams; - parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0); - parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1); - parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2); - parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3); - parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4); - parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5); - parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6); - parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7); - parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8); + parms->hwparams0 = dwc3_readl(dwc, DWC3_GHWPARAMS0); + parms->hwparams1 = dwc3_readl(dwc, DWC3_GHWPARAMS1); + parms->hwparams2 = dwc3_readl(dwc, DWC3_GHWPARAMS2); + parms->hwparams3 = dwc3_readl(dwc, DWC3_GHWPARAMS3); + parms->hwparams4 = dwc3_readl(dwc, DWC3_GHWPARAMS4); + parms->hwparams5 = dwc3_readl(dwc, DWC3_GHWPARAMS5); + parms->hwparams6 = dwc3_readl(dwc, DWC3_GHWPARAMS6); + parms->hwparams7 = dwc3_readl(dwc, DWC3_GHWPARAMS7); + parms->hwparams8 = dwc3_readl(dwc, DWC3_GHWPARAMS8); if (DWC3_IP_IS(DWC32)) - parms->hwparams9 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS9); + parms->hwparams9 = dwc3_readl(dwc, DWC3_GHWPARAMS9); } static void dwc3_config_soc_bus(struct dwc3 *dwc) @@ -640,10 +640,10 @@ static void dwc3_config_soc_bus(struct dwc3 *dwc) if (dwc->gsbuscfg0_reqinfo != DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0); + reg = dwc3_readl(dwc, DWC3_GSBUSCFG0); reg &= ~DWC3_GSBUSCFG0_REQINFO(~0); reg |= DWC3_GSBUSCFG0_REQINFO(dwc->gsbuscfg0_reqinfo); - dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, reg); + dwc3_writel(dwc, DWC3_GSBUSCFG0, reg); } } @@ -667,7 +667,7 @@ static int dwc3_ss_phy_setup(struct dwc3 *dwc, int index) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(index)); + reg = dwc3_readl(dwc, DWC3_GUSB3PIPECTL(index)); /* * Make sure UX_EXIT_PX is cleared as that causes issues with some @@ -705,7 +705,7 @@ static int dwc3_ss_phy_setup(struct dwc3 *dwc, int index) if (dwc->dis_del_phy_power_chg_quirk) reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE; - dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(index), reg); + dwc3_writel(dwc, DWC3_GUSB3PIPECTL(index), reg); return 0; } @@ -714,7 +714,7 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(index)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(index)); /* Select the HS PHY interface */ switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) { @@ -726,7 +726,7 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index) } else if (dwc->hsphy_interface && !strncmp(dwc->hsphy_interface, "ulpi", 4)) { reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(index), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(index), reg); } else { /* Relying on default value. */ if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI)) @@ -776,7 +776,7 @@ static int dwc3_hs_phy_setup(struct dwc3 *dwc, int index) if (dwc->ulpi_ext_vbus_drv) reg |= DWC3_GUSB2PHYCFG_ULPIEXTVBUSDRV; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(index), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(index), reg); return 0; } @@ -989,7 +989,7 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_GSNPSID); + reg = dwc3_readl(dwc, DWC3_GSNPSID); dwc->ip = DWC3_GSNPS_ID(reg); if (dwc->ip == DWC4_IP) dwc->ip = DWC32_IP; @@ -998,8 +998,8 @@ static bool dwc3_core_is_valid(struct dwc3 *dwc) if (DWC3_IP_IS(DWC3)) { dwc->revision = reg; } else if (DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) { - dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER); - dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE); + dwc->revision = dwc3_readl(dwc, DWC3_VER_NUMBER); + dwc->version_type = dwc3_readl(dwc, DWC3_VER_TYPE); } else { return false; } @@ -1013,7 +1013,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) unsigned int hw_mode; u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); reg &= ~DWC3_GCTL_SCALEDOWN_MASK; hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); power_opt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1); @@ -1091,7 +1091,7 @@ static void dwc3_core_setup_global_control(struct dwc3 *dwc) if (DWC3_VER_IS_PRIOR(DWC3, 190A)) reg |= DWC3_GCTL_U2RSTECN; - dwc3_writel(dwc->regs, DWC3_GCTL, reg); + dwc3_writel(dwc, DWC3_GCTL, reg); } static int dwc3_core_get_phy(struct dwc3 *dwc); @@ -1111,7 +1111,7 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc) int ret; int i; - cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0); + cfg = dwc3_readl(dwc, DWC3_GSBUSCFG0); /* * Handle property "snps,incr-burst-type-adjustment". @@ -1186,7 +1186,7 @@ static void dwc3_set_incr_burst_type(struct dwc3 *dwc) break; } - dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg); + dwc3_writel(dwc, DWC3_GSBUSCFG0, cfg); } static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc) @@ -1211,12 +1211,12 @@ static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc) * (3x or more) to be within the requirement. */ scale = DIV_ROUND_UP(clk_get_rate(dwc->susp_clk), 16000); - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); if ((reg & DWC3_GCTL_PWRDNSCALE_MASK) < DWC3_GCTL_PWRDNSCALE(scale) || (reg & DWC3_GCTL_PWRDNSCALE_MASK) > DWC3_GCTL_PWRDNSCALE(scale*3)) { reg &= ~(DWC3_GCTL_PWRDNSCALE_MASK); reg |= DWC3_GCTL_PWRDNSCALE(scale); - dwc3_writel(dwc->regs, DWC3_GCTL, reg); + dwc3_writel(dwc, DWC3_GCTL, reg); } } @@ -1239,7 +1239,7 @@ static void dwc3_config_threshold(struct dwc3 *dwc) tx_maxburst = dwc->tx_max_burst_prd; if (rx_thr_num && rx_maxburst) { - reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GRXTHRCFG); reg |= DWC31_RXTHRNUMPKTSEL_PRD; reg &= ~DWC31_RXTHRNUMPKT_PRD(~0); @@ -1248,11 +1248,11 @@ static void dwc3_config_threshold(struct dwc3 *dwc) reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0); reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst); - dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GRXTHRCFG, reg); } if (tx_thr_num && tx_maxburst) { - reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GTXTHRCFG); reg |= DWC31_TXTHRNUMPKTSEL_PRD; reg &= ~DWC31_TXTHRNUMPKT_PRD(~0); @@ -1261,7 +1261,7 @@ static void dwc3_config_threshold(struct dwc3 *dwc) reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0); reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst); - dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GTXTHRCFG, reg); } } @@ -1272,7 +1272,7 @@ static void dwc3_config_threshold(struct dwc3 *dwc) if (DWC3_IP_IS(DWC3)) { if (rx_thr_num && rx_maxburst) { - reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GRXTHRCFG); reg |= DWC3_GRXTHRCFG_PKTCNTSEL; reg &= ~DWC3_GRXTHRCFG_RXPKTCNT(~0); @@ -1281,11 +1281,11 @@ static void dwc3_config_threshold(struct dwc3 *dwc) reg &= ~DWC3_GRXTHRCFG_MAXRXBURSTSIZE(~0); reg |= DWC3_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst); - dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GRXTHRCFG, reg); } if (tx_thr_num && tx_maxburst) { - reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GTXTHRCFG); reg |= DWC3_GTXTHRCFG_PKTCNTSEL; reg &= ~DWC3_GTXTHRCFG_TXPKTCNT(~0); @@ -1294,11 +1294,11 @@ static void dwc3_config_threshold(struct dwc3 *dwc) reg &= ~DWC3_GTXTHRCFG_MAXTXBURSTSIZE(~0); reg |= DWC3_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst); - dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GTXTHRCFG, reg); } } else { if (rx_thr_num && rx_maxburst) { - reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GRXTHRCFG); reg |= DWC31_GRXTHRCFG_PKTCNTSEL; reg &= ~DWC31_GRXTHRCFG_RXPKTCNT(~0); @@ -1307,11 +1307,11 @@ static void dwc3_config_threshold(struct dwc3 *dwc) reg &= ~DWC31_GRXTHRCFG_MAXRXBURSTSIZE(~0); reg |= DWC31_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst); - dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GRXTHRCFG, reg); } if (tx_thr_num && tx_maxburst) { - reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GTXTHRCFG); reg |= DWC31_GTXTHRCFG_PKTCNTSEL; reg &= ~DWC31_GTXTHRCFG_TXPKTCNT(~0); @@ -1320,7 +1320,7 @@ static void dwc3_config_threshold(struct dwc3 *dwc) reg &= ~DWC31_GTXTHRCFG_MAXTXBURSTSIZE(~0); reg |= DWC31_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst); - dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GTXTHRCFG, reg); } } } @@ -1339,12 +1339,6 @@ static int dwc3_core_init(struct dwc3 *dwc) hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0); - /* - * Write Linux Version Code to our GUID register so it's easy to figure - * out which kernel version a bug was found. - */ - dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE); - ret = dwc3_phy_setup(dwc); if (ret) return ret; @@ -1376,6 +1370,12 @@ static int dwc3_core_init(struct dwc3 *dwc) if (ret) goto err_exit_phy; + /* + * Write Linux Version Code to our GUID register so it's easy to figure + * out which kernel version a bug was found. + */ + dwc3_writel(dwc, DWC3_GUID, LINUX_VERSION_CODE); + dwc3_core_setup_global_control(dwc); dwc3_core_num_eps(dwc); @@ -1408,9 +1408,9 @@ static int dwc3_core_init(struct dwc3 *dwc) * DWC_usb31 controller. */ if (DWC3_VER_IS_WITHIN(DWC3, 310A, ANY)) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); + reg = dwc3_readl(dwc, DWC3_GUCTL2); reg |= DWC3_GUCTL2_RST_ACTBITLATER; - dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); + dwc3_writel(dwc, DWC3_GUCTL2, reg); } /* @@ -1423,9 +1423,9 @@ static int dwc3_core_init(struct dwc3 *dwc) * setting GUCTL2[19] by default; instead, use GUCTL2[19] = 0. */ if (DWC3_VER_IS(DWC3, 320A)) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL2); + reg = dwc3_readl(dwc, DWC3_GUCTL2); reg &= ~DWC3_GUCTL2_LC_TIMER; - dwc3_writel(dwc->regs, DWC3_GUCTL2, reg); + dwc3_writel(dwc, DWC3_GUCTL2, reg); } /* @@ -1438,13 +1438,13 @@ static int dwc3_core_init(struct dwc3 *dwc) * legacy ULPI PHYs. */ if (dwc->resume_hs_terminations) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); + reg = dwc3_readl(dwc, DWC3_GUCTL1); reg |= DWC3_GUCTL1_RESUME_OPMODE_HS_HOST; - dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); + dwc3_writel(dwc, DWC3_GUCTL1, reg); } if (!DWC3_VER_IS_PRIOR(DWC3, 250A)) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL1); + reg = dwc3_readl(dwc, DWC3_GUCTL1); /* * Enable hardware control of sending remote wakeup @@ -1479,7 +1479,7 @@ static int dwc3_core_init(struct dwc3 *dwc) reg &= ~DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK; } - dwc3_writel(dwc->regs, DWC3_GUCTL1, reg); + dwc3_writel(dwc, DWC3_GUCTL1, reg); } dwc3_config_threshold(dwc); @@ -1494,9 +1494,9 @@ static int dwc3_core_init(struct dwc3 *dwc) int i; for (i = 0; i < dwc->num_usb3_ports; i++) { - reg = dwc3_readl(dwc->regs, DWC3_LLUCTL(i)); + reg = dwc3_readl(dwc, DWC3_LLUCTL(i)); reg |= DWC3_LLUCTL_FORCE_GEN1; - dwc3_writel(dwc->regs, DWC3_LLUCTL(i), reg); + dwc3_writel(dwc, DWC3_LLUCTL(i), reg); } } @@ -1515,9 +1515,9 @@ static int dwc3_core_init(struct dwc3 *dwc) * function is available only from version 1.70a. */ if (DWC3_VER_IS_WITHIN(DWC31, 170A, 180A)) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); + reg = dwc3_readl(dwc, DWC3_GUCTL3); reg |= DWC3_GUCTL3_USB20_RETRY_DISABLE; - dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); + dwc3_writel(dwc, DWC3_GUCTL3, reg); } return 0; @@ -2447,9 +2447,9 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) int ret; if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) { - dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) & + dwc->susphy_state = (dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)) & DWC3_GUSB2PHYCFG_SUSPHY) || - (dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)) & + (dwc3_readl(dwc, DWC3_GUSB3PIPECTL(0)) & DWC3_GUSB3PIPECTL_SUSPHY); /* * TI AM62 platform requires SUSPHY to be @@ -2479,10 +2479,10 @@ static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg) if (dwc->dis_u2_susphy_quirk || dwc->dis_enblslpm_quirk) { for (i = 0; i < dwc->num_usb2_ports; i++) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(i)); reg |= DWC3_GUSB2PHYCFG_ENBLSLPM | DWC3_GUSB2PHYCFG_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(i), reg); } /* Give some time for USB2 PHY to suspend */ @@ -2542,14 +2542,14 @@ static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg) } /* Restore GUSB2PHYCFG bits that were modified in suspend */ for (i = 0; i < dwc->num_usb2_ports; i++) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(i)); if (dwc->dis_u2_susphy_quirk) reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; if (dwc->dis_enblslpm_quirk) reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(i), reg); } for (i = 0; i < dwc->num_usb2_ports; i++) @@ -2732,9 +2732,9 @@ void dwc3_pm_complete(struct dwc3 *dwc) if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST && dwc->dis_split_quirk) { - reg = dwc3_readl(dwc->regs, DWC3_GUCTL3); + reg = dwc3_readl(dwc, DWC3_GUCTL3); reg |= DWC3_GUCTL3_SPLITDISABLE; - dwc3_writel(dwc->regs, DWC3_GUCTL3, reg); + dwc3_writel(dwc, DWC3_GUCTL3, reg); } } EXPORT_SYMBOL_GPL(dwc3_pm_complete); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 9cfc36d4bc25..a35b3db1f9f3 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -165,10 +165,10 @@ #define DWC3_DCFG1 0xc740 /* DWC_usb32 only */ #define DWC3_DEP_BASE(n) (0xc800 + ((n) * 0x10)) -#define DWC3_DEPCMDPAR2 0x00 -#define DWC3_DEPCMDPAR1 0x04 -#define DWC3_DEPCMDPAR0 0x08 -#define DWC3_DEPCMD 0x0c +#define DWC3_DEPCMDPAR2(n) (DWC3_DEP_BASE(n) + 0x00) +#define DWC3_DEPCMDPAR1(n) (DWC3_DEP_BASE(n) + 0x04) +#define DWC3_DEPCMDPAR0(n) (DWC3_DEP_BASE(n) + 0x08) +#define DWC3_DEPCMD(n) (DWC3_DEP_BASE(n) + 0x0c) #define DWC3_DEV_IMOD(n) (0xca00 + ((n) * 0x4)) @@ -749,8 +749,6 @@ struct dwc3_ep { struct list_head pending_list; struct list_head started_list; - void __iomem *regs; - struct dwc3_trb *trb_pool; dma_addr_t trb_pool_dma; struct dwc3 *dwc; diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index d18bf5e32cc8..ffb1101f55c7 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c @@ -36,23 +36,19 @@ #define dump_ep_register_set(n) \ { \ .name = "DEPCMDPAR2("__stringify(n)")", \ - .offset = DWC3_DEP_BASE(n) + \ - DWC3_DEPCMDPAR2, \ + .offset = DWC3_DEPCMDPAR2(n), \ }, \ { \ .name = "DEPCMDPAR1("__stringify(n)")", \ - .offset = DWC3_DEP_BASE(n) + \ - DWC3_DEPCMDPAR1, \ + .offset = DWC3_DEPCMDPAR1(n), \ }, \ { \ .name = "DEPCMDPAR0("__stringify(n)")", \ - .offset = DWC3_DEP_BASE(n) + \ - DWC3_DEPCMDPAR0, \ + .offset = DWC3_DEPCMDPAR0(n), \ }, \ { \ .name = "DEPCMD("__stringify(n)")", \ - .offset = DWC3_DEP_BASE(n) + \ - DWC3_DEPCMD, \ + .offset = DWC3_DEPCMD(n), \ } @@ -300,14 +296,14 @@ static void dwc3_host_lsp(struct seq_file *s) reg = DWC3_GDBGLSPMUX_HOSTSELECT(sel); - dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); - val = dwc3_readl(dwc->regs, DWC3_GDBGLSP); + dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg); + val = dwc3_readl(dwc, DWC3_GDBGLSP); seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", sel, val); if (dbc_enabled && sel < 256) { reg |= DWC3_GDBGLSPMUX_ENDBC; - dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); - val = dwc3_readl(dwc->regs, DWC3_GDBGLSP); + dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg); + val = dwc3_readl(dwc, DWC3_GDBGLSP); seq_printf(s, "GDBGLSP_DBC[%d] = 0x%08x\n", sel, val); } } @@ -320,8 +316,8 @@ static void dwc3_gadget_lsp(struct seq_file *s) for (i = 0; i < 16; i++) { reg = DWC3_GDBGLSPMUX_DEVSELECT(i); - dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); - reg = dwc3_readl(dwc->regs, DWC3_GDBGLSP); + dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg); + reg = dwc3_readl(dwc, DWC3_GDBGLSP); seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", i, reg); } } @@ -339,7 +335,7 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused) return ret; spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_GSTS); + reg = dwc3_readl(dwc, DWC3_GSTS); current_mode = DWC3_GSTS_CURMOD(reg); switch (current_mode) { @@ -410,7 +406,7 @@ static int dwc3_mode_show(struct seq_file *s, void *unused) return ret; spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); spin_unlock_irqrestore(&dwc->lock, flags); mode = DWC3_GCTL_PRTCAP(reg); @@ -482,7 +478,7 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused) return ret; spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= DWC3_DCTL_TSTCTRL_MASK; reg >>= 1; spin_unlock_irqrestore(&dwc->lock, flags); @@ -581,7 +577,7 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) return ret; spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_GSTS); + reg = dwc3_readl(dwc, DWC3_GSTS); if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { seq_puts(s, "Not available\n"); spin_unlock_irqrestore(&dwc->lock, flags); @@ -589,7 +585,7 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused) return 0; } - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); state = DWC3_DSTS_USBLNKST(reg); speed = reg & DWC3_DSTS_CONNECTSPD; @@ -643,14 +639,14 @@ static ssize_t dwc3_link_state_write(struct file *file, return ret; spin_lock_irqsave(&dwc->lock, flags); - reg = dwc3_readl(dwc->regs, DWC3_GSTS); + reg = dwc3_readl(dwc, DWC3_GSTS); if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) { spin_unlock_irqrestore(&dwc->lock, flags); pm_runtime_put_sync(dwc->dev); return -EINVAL; } - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); speed = reg & DWC3_DSTS_CONNECTSPD; if (speed < DWC3_DSTS_SUPERSPEED && @@ -946,10 +942,10 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused) spin_lock_irqsave(&dwc->lock, flags); reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number); - dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg); + dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg); - lower_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO0); - upper_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO1); + lower_32_bits = dwc3_readl(dwc, DWC3_GDBGEPINFO0); + upper_32_bits = dwc3_readl(dwc, DWC3_GDBGEPINFO1); ep_info = ((u64)upper_32_bits << 32) | lower_32_bits; seq_printf(s, "0x%016llx\n", ep_info); diff --git a/drivers/usb/dwc3/drd.c b/drivers/usb/dwc3/drd.c index 4c91240eb429..b229fb1fd932 100644 --- a/drivers/usb/dwc3/drd.c +++ b/drivers/usb/dwc3/drd.c @@ -18,25 +18,25 @@ static void dwc3_otg_disable_events(struct dwc3 *dwc, u32 disable_mask) { - u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN); + u32 reg = dwc3_readl(dwc, DWC3_OEVTEN); reg &= ~(disable_mask); - dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); + dwc3_writel(dwc, DWC3_OEVTEN, reg); } static void dwc3_otg_enable_events(struct dwc3 *dwc, u32 enable_mask) { - u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN); + u32 reg = dwc3_readl(dwc, DWC3_OEVTEN); reg |= (enable_mask); - dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); + dwc3_writel(dwc, DWC3_OEVTEN, reg); } static void dwc3_otg_clear_events(struct dwc3 *dwc) { - u32 reg = dwc3_readl(dwc->regs, DWC3_OEVT); + u32 reg = dwc3_readl(dwc, DWC3_OEVT); - dwc3_writel(dwc->regs, DWC3_OEVTEN, reg); + dwc3_writel(dwc, DWC3_OEVTEN, reg); } #define DWC3_OTG_ALL_EVENTS (DWC3_OEVTEN_XHCIRUNSTPSETEN | \ @@ -72,18 +72,18 @@ static irqreturn_t dwc3_otg_irq(int irq, void *_dwc) struct dwc3 *dwc = _dwc; irqreturn_t ret = IRQ_NONE; - reg = dwc3_readl(dwc->regs, DWC3_OEVT); + reg = dwc3_readl(dwc, DWC3_OEVT); if (reg) { /* ignore non OTG events, we can't disable them in OEVTEN */ if (!(reg & DWC3_OTG_ALL_EVENTS)) { - dwc3_writel(dwc->regs, DWC3_OEVT, reg); + dwc3_writel(dwc, DWC3_OEVT, reg); return IRQ_NONE; } if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST && !(reg & DWC3_OEVT_DEVICEMODE)) dwc->otg_restart_host = true; - dwc3_writel(dwc->regs, DWC3_OEVT, reg); + dwc3_writel(dwc, DWC3_OEVT, reg); ret = IRQ_WAKE_THREAD; } @@ -100,23 +100,23 @@ static void dwc3_otgregs_init(struct dwc3 *dwc) * the signal outputs sent to the PHY, the OTG FSM logic of the * core and also the resets to the VBUS filters inside the core. */ - reg = dwc3_readl(dwc->regs, DWC3_OCFG); + reg = dwc3_readl(dwc, DWC3_OCFG); reg |= DWC3_OCFG_SFTRSTMASK; - dwc3_writel(dwc->regs, DWC3_OCFG, reg); + dwc3_writel(dwc, DWC3_OCFG, reg); /* Disable hibernation for simplicity */ - reg = dwc3_readl(dwc->regs, DWC3_GCTL); + reg = dwc3_readl(dwc, DWC3_GCTL); reg &= ~DWC3_GCTL_GBLHIBERNATIONEN; - dwc3_writel(dwc->regs, DWC3_GCTL, reg); + dwc3_writel(dwc, DWC3_GCTL, reg); /* * Initialize OTG registers as per * Figure 11-4 OTG Driver Overall Programming Flow */ /* OCFG.SRPCap = 0, OCFG.HNPCap = 0 */ - reg = dwc3_readl(dwc->regs, DWC3_OCFG); + reg = dwc3_readl(dwc, DWC3_OCFG); reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP); - dwc3_writel(dwc->regs, DWC3_OCFG, reg); + dwc3_writel(dwc, DWC3_OCFG, reg); /* OEVT = FFFF */ dwc3_otg_clear_events(dwc); /* OEVTEN = 0 */ @@ -127,11 +127,11 @@ static void dwc3_otgregs_init(struct dwc3 *dwc) * OCTL.PeriMode = 1, OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0, * OCTL.HNPReq = 0 */ - reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg = dwc3_readl(dwc, DWC3_OCTL); reg |= DWC3_OCTL_PERIMODE; reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN | DWC3_OCTL_HNPREQ); - dwc3_writel(dwc->regs, DWC3_OCTL, reg); + dwc3_writel(dwc, DWC3_OCTL, reg); } static int dwc3_otg_get_irq(struct dwc3 *dwc) @@ -175,9 +175,9 @@ void dwc3_otg_init(struct dwc3 *dwc) /* GCTL.PrtCapDir=2'b11 */ dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG, true); /* GUSB2PHYCFG0.SusPHY=0 */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); /* Initialize OTG registers */ dwc3_otgregs_init(dwc); @@ -203,17 +203,17 @@ void dwc3_otg_host_init(struct dwc3 *dwc) * OCTL.PeriMode=0, OCTL.TermSelDLPulse = 0, * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0 */ - reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg = dwc3_readl(dwc, DWC3_OCTL); reg &= ~(DWC3_OCTL_PERIMODE | DWC3_OCTL_TERMSELIDPULSE | DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN); - dwc3_writel(dwc->regs, DWC3_OCTL, reg); + dwc3_writel(dwc, DWC3_OCTL, reg); /* * OCFG.DisPrtPwrCutoff = 0/1 */ - reg = dwc3_readl(dwc->regs, DWC3_OCFG); + reg = dwc3_readl(dwc, DWC3_OCFG); reg &= ~DWC3_OCFG_DISPWRCUTTOFF; - dwc3_writel(dwc->regs, DWC3_OCFG, reg); + dwc3_writel(dwc, DWC3_OCFG, reg); /* * OCFG.SRPCap = 1, OCFG.HNPCap = GHWPARAMS6.HNP_CAP @@ -229,15 +229,15 @@ void dwc3_otg_host_init(struct dwc3 *dwc) /* GUSB2PHYCFG.ULPIAutoRes = 1/0, GUSB2PHYCFG.SusPHY = 1 */ if (!dwc->dis_u2_susphy_quirk) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); } /* Set Port Power to enable VBUS: OCTL.PrtPwrCtl = 1 */ - reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg = dwc3_readl(dwc, DWC3_OCTL); reg |= DWC3_OCTL_PRTPWRCTL; - dwc3_writel(dwc->regs, DWC3_OCTL, reg); + dwc3_writel(dwc, DWC3_OCTL, reg); } /* should be called after Host controller driver is stopped */ @@ -258,9 +258,9 @@ static void dwc3_otg_host_exit(struct dwc3 *dwc) */ /* OCTL.HstSetHNPEn = 0, OCTL.PrtPwrCtl=0 */ - reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg = dwc3_readl(dwc, DWC3_OCTL); reg &= ~(DWC3_OCTL_HSTSETHNPEN | DWC3_OCTL_PRTPWRCTL); - dwc3_writel(dwc->regs, DWC3_OCTL, reg); + dwc3_writel(dwc, DWC3_OCTL, reg); } /* should be called before the gadget controller driver is started */ @@ -274,27 +274,27 @@ static void dwc3_otg_device_init(struct dwc3 *dwc) * OCFG.HNPCap = GHWPARAMS6.HNP_CAP, OCFG.SRPCap = 1 * but we keep them 0 for simple dual-role operation. */ - reg = dwc3_readl(dwc->regs, DWC3_OCFG); + reg = dwc3_readl(dwc, DWC3_OCFG); /* OCFG.OTGSftRstMsk = 0/1 */ reg |= DWC3_OCFG_SFTRSTMASK; - dwc3_writel(dwc->regs, DWC3_OCFG, reg); + dwc3_writel(dwc, DWC3_OCFG, reg); /* * OCTL.PeriMode = 1 * OCTL.TermSelDLPulse = 0/1, OCTL.HNPReq = 0 * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0 */ - reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg = dwc3_readl(dwc, DWC3_OCTL); reg |= DWC3_OCTL_PERIMODE; reg &= ~(DWC3_OCTL_TERMSELIDPULSE | DWC3_OCTL_HNPREQ | DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN); - dwc3_writel(dwc->regs, DWC3_OCTL, reg); + dwc3_writel(dwc, DWC3_OCTL, reg); /* OEVTEN.OTGBDevSesVldDetEvntEn = 1 */ dwc3_otg_enable_events(dwc, DWC3_OEVTEN_BDEVSESSVLDDETEN); /* GUSB2PHYCFG.ULPIAutoRes = 0, GUSB2PHYCFG0.SusPHY = 1 */ if (!dwc->dis_u2_susphy_quirk) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); reg |= DWC3_GUSB2PHYCFG_SUSPHY; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); } /* GCTL.GblHibernationEn = 0. Already 0. */ } @@ -319,10 +319,10 @@ static void dwc3_otg_device_exit(struct dwc3 *dwc) DWC3_OEVTEN_BDEVBHOSTENDEN); /* OCTL.DevSetHNPEn = 0, OCTL.HNPReq = 0, OCTL.PeriMode=1 */ - reg = dwc3_readl(dwc->regs, DWC3_OCTL); + reg = dwc3_readl(dwc, DWC3_OCTL); reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HNPREQ); reg |= DWC3_OCTL_PERIMODE; - dwc3_writel(dwc->regs, DWC3_OCTL, reg); + dwc3_writel(dwc, DWC3_OCTL, reg); } void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus) @@ -341,7 +341,7 @@ void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus) return; if (!ignore_idstatus) { - reg = dwc3_readl(dwc->regs, DWC3_OSTS); + reg = dwc3_readl(dwc, DWC3_OSTS); id = !!(reg & DWC3_OSTS_CONIDSTS); dwc->desired_otg_role = id ? DWC3_OTG_ROLE_DEVICE : diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index e0bad5708664..a8ff8db610d3 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -361,7 +361,7 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc, if ((dwc->speed == DWC3_DSTS_SUPERSPEED) || (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) { - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (reg & DWC3_DCTL_INITU1ENA) usb_status |= 1 << USB_DEV_STAT_U1_ENABLED; if (reg & DWC3_DCTL_INITU2ENA) @@ -417,12 +417,12 @@ static int dwc3_ep0_handle_u1(struct dwc3 *dwc, enum usb_device_state state, if (set && dwc->dis_u1_entry_quirk) return -EINVAL; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU1ENA; else reg &= ~DWC3_DCTL_INITU1ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); return 0; } @@ -441,12 +441,12 @@ static int dwc3_ep0_handle_u2(struct dwc3 *dwc, enum usb_device_state state, if (set && dwc->dis_u2_entry_quirk) return -EINVAL; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (set) reg |= DWC3_DCTL_INITU2ENA; else reg &= ~DWC3_DCTL_INITU2ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); return 0; } @@ -612,10 +612,10 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) return -EINVAL; } - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg &= ~(DWC3_DCFG_DEVADDR_MASK); reg |= DWC3_DCFG_DEVADDR(addr); - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); if (addr) usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS); @@ -672,12 +672,12 @@ static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl) * Enable transition to U1/U2 state when * nothing is pending from application. */ - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (!dwc->dis_u1_entry_quirk) reg |= DWC3_DCTL_ACCEPTU1ENA; if (!dwc->dis_u2_entry_quirk) reg |= DWC3_DCTL_ACCEPTU2ENA; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); } break; @@ -717,7 +717,7 @@ static void dwc3_ep0_set_sel_cmpl(struct usb_ep *ep, struct usb_request *req) dwc->u2sel = le16_to_cpu(timing.u2sel); dwc->u2pel = le16_to_cpu(timing.u2pel); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (reg & DWC3_DCTL_INITU2ENA) param = dwc->u2pel; if (reg & DWC3_DCTL_INITU1ENA) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index db5e5b77b1ea..89963cd77daa 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -42,7 +42,7 @@ int dwc3_gadget_set_test_mode(struct dwc3 *dwc, int mode) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~DWC3_DCTL_TSTCTRL_MASK; switch (mode) { @@ -73,7 +73,7 @@ int dwc3_gadget_get_link_state(struct dwc3 *dwc) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); return DWC3_DSTS_USBLNKST(reg); } @@ -97,7 +97,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) */ if (!DWC3_VER_IS_PRIOR(DWC3, 194A)) { while (--retries) { - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); if (reg & DWC3_DSTS_DCNRD) udelay(5); else @@ -108,15 +108,15 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) return -ETIMEDOUT; } - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; /* set no action before sending new link state change */ - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); /* set requested state */ reg |= DWC3_DCTL_ULSTCHNGREQ(state); - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); /* * The following code is racy when called from dwc3_gadget_wakeup, @@ -128,7 +128,7 @@ int dwc3_gadget_set_link_state(struct dwc3 *dwc, enum dwc3_link_state state) /* wait for a change in DSTS */ retries = 10000; while (--retries) { - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); if (DWC3_DSTS_USBLNKST(reg) == state) return 0; @@ -260,11 +260,11 @@ int dwc3_send_gadget_generic_command(struct dwc3 *dwc, unsigned int cmd, int ret = 0; u32 reg; - dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param); - dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT); + dwc3_writel(dwc, DWC3_DGCMDPAR, param); + dwc3_writel(dwc, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT); do { - reg = dwc3_readl(dwc->regs, DWC3_DGCMD); + reg = dwc3_readl(dwc, DWC3_DGCMD); if (!(reg & DWC3_DGCMD_CMDACT)) { status = DWC3_DGCMD_STATUS(reg); if (status) @@ -320,6 +320,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, int cmd_status = 0; int ret = -EINVAL; + u8 epnum = dep->number; /* * When operating in USB 2.0 speeds (HS/FS), if GUSB2PHYCFG.ENBLSLPM or @@ -333,7 +334,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, */ if (dwc->gadget->speed <= USB_SPEED_HIGH || DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) { saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; @@ -345,7 +346,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, } if (saved_config) - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); } /* @@ -355,9 +356,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, * improve performance. */ if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_UPDATETRANSFER) { - dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0); - dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1); - dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2); + dwc3_writel(dwc, DWC3_DEPCMDPAR0(epnum), params->param0); + dwc3_writel(dwc, DWC3_DEPCMDPAR1(epnum), params->param1); + dwc3_writel(dwc, DWC3_DEPCMDPAR2(epnum), params->param2); } /* @@ -381,7 +382,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, else cmd |= DWC3_DEPCMD_CMDACT; - dwc3_writel(dep->regs, DWC3_DEPCMD, cmd); + dwc3_writel(dwc, DWC3_DEPCMD(epnum), cmd); if (!(cmd & DWC3_DEPCMD_CMDACT) || (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER && @@ -391,7 +392,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, } do { - reg = dwc3_readl(dep->regs, DWC3_DEPCMD); + reg = dwc3_readl(dwc, DWC3_DEPCMD(epnum)); if (!(reg & DWC3_DEPCMD_CMDACT)) { cmd_status = DWC3_DEPCMD_STATUS(reg); @@ -447,9 +448,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_ep *dep, unsigned int cmd, mdelay(1); if (saved_config) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); reg |= saved_config; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); } return ret; @@ -726,7 +727,7 @@ static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc) u32 reg; /* Check if TXFIFOs start at non-zero addr */ - reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); + reg = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(0)); fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg); ram_depth -= (fifo_0_start >> 16); @@ -754,7 +755,7 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) /* Read ep0IN related TXFIFO size */ dep = dwc->eps[1]; - size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); + size = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(0)); if (DWC3_IP_IS(DWC3)) fifo_depth = DWC3_GTXFIFOSIZ_TXFDEP(size); else @@ -769,10 +770,10 @@ void dwc3_gadget_clear_tx_fifos(struct dwc3 *dwc) /* Don't change TXFRAMNUM on usb31 version */ size = DWC3_IP_IS(DWC3) ? 0 : - dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) & + dwc3_readl(dwc, DWC3_GTXFIFOSIZ(num >> 1)) & DWC31_GTXFIFOSIZ_TXFRAMNUM; - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size); + dwc3_writel(dwc, DWC3_GTXFIFOSIZ(num >> 1), size); dep->flags &= ~DWC3_EP_TXFIFO_RESIZED; } dwc->num_ep_resized = 0; @@ -875,7 +876,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) fifo_size++; /* Check if TXFIFOs start at non-zero addr */ - tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0)); + tmp = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(0)); fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp); fifo_size |= (fifo_0_start + (dwc->last_fifo_depth << 16)); @@ -898,7 +899,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep) return -ENOMEM; } - dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size); + dwc3_writel(dwc, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size); dep->flags |= DWC3_EP_TXFIFO_RESIZED; dwc->num_ep_resized++; @@ -942,9 +943,9 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, unsigned int action) dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; - reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); + reg = dwc3_readl(dwc, DWC3_DALEPENA); reg |= DWC3_DALEPENA_EP(dep->number); - dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + dwc3_writel(dwc, DWC3_DALEPENA, reg); dep->trb_dequeue = 0; dep->trb_enqueue = 0; @@ -1079,9 +1080,9 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) if (dep->flags & DWC3_EP_STALL) __dwc3_gadget_ep_set_halt(dep, 0, false); - reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); + reg = dwc3_readl(dwc, DWC3_DALEPENA); reg &= ~DWC3_DALEPENA_EP(dep->number); - dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + dwc3_writel(dwc, DWC3_DALEPENA, reg); dwc3_remove_requests(dwc, dep, -ESHUTDOWN); @@ -1742,7 +1743,7 @@ static int __dwc3_gadget_get_frame(struct dwc3 *dwc) { u32 reg; - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); return DWC3_DSTS_SOFFN(reg); } @@ -2350,13 +2351,13 @@ static void dwc3_gadget_enable_linksts_evts(struct dwc3 *dwc, bool set) if (DWC3_VER_IS_PRIOR(DWC3, 250A)) return; - reg = dwc3_readl(dwc->regs, DWC3_DEVTEN); + reg = dwc3_readl(dwc, DWC3_DEVTEN); if (set) reg |= DWC3_DEVTEN_ULSTCNGEN; else reg &= ~DWC3_DEVTEN_ULSTCNGEN; - dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); + dwc3_writel(dwc, DWC3_DEVTEN, reg); } static int dwc3_gadget_get_frame(struct usb_gadget *g) @@ -2379,7 +2380,7 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) * * We can check that via USB Link State bits in DSTS register. */ - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); link_state = DWC3_DSTS_USBLNKST(reg); @@ -2407,9 +2408,9 @@ static int __dwc3_gadget_wakeup(struct dwc3 *dwc) /* Recent versions do this automatically */ if (DWC3_VER_IS_PRIOR(DWC3, 194A)) { /* write zeroes to Link Change Request */ - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); } /* @@ -2529,7 +2530,7 @@ static void __dwc3_gadget_set_ssp_rate(struct dwc3 *dwc) if (ssp_rate == USB_SSP_GEN_UNKNOWN) ssp_rate = dwc->max_ssp_rate; - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg &= ~DWC3_DCFG_SPEED_MASK; reg &= ~DWC3_DCFG_NUMLANES(~0); @@ -2542,7 +2543,7 @@ static void __dwc3_gadget_set_ssp_rate(struct dwc3 *dwc) dwc->max_ssp_rate != USB_SSP_GEN_2x1) reg |= DWC3_DCFG_NUMLANES(1); - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); } static void __dwc3_gadget_set_speed(struct dwc3 *dwc) @@ -2560,7 +2561,7 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc) return; } - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg &= ~(DWC3_DCFG_SPEED_MASK); /* @@ -2611,7 +2612,7 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc) speed < USB_SPEED_SUPER_PLUS) reg &= ~DWC3_DCFG_NUMLANES(~0); - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); } static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) @@ -2636,7 +2637,7 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) * mentioned in the dwc3 programming guide. It has been tested on an * Exynos platforms. */ - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); if (reg & DWC3_GUSB2PHYCFG_SUSPHY) { saved_config |= DWC3_GUSB2PHYCFG_SUSPHY; reg &= ~DWC3_GUSB2PHYCFG_SUSPHY; @@ -2648,9 +2649,9 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) } if (saved_config) - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); if (is_on) { if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) { reg &= ~DWC3_DCTL_TRGTULST_MASK; @@ -2674,14 +2675,14 @@ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on) do { usleep_range(1000, 2000); - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); reg &= DWC3_DSTS_DEVCTRLHLT; } while (--timeout && !(!is_on ^ !reg)); if (saved_config) { - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); reg |= saved_config; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg); } if (!timeout) @@ -2857,13 +2858,13 @@ static void dwc3_gadget_enable_irq(struct dwc3 *dwc) if (!DWC3_VER_IS_PRIOR(DWC3, 230A)) reg |= DWC3_DEVTEN_U3L2L1SUSPEN; - dwc3_writel(dwc->regs, DWC3_DEVTEN, reg); + dwc3_writel(dwc, DWC3_DEVTEN, reg); } static void dwc3_gadget_disable_irq(struct dwc3 *dwc) { /* mask all interrupts */ - dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00); + dwc3_writel(dwc, DWC3_DEVTEN, 0x00); } static irqreturn_t dwc3_interrupt(int irq, void *_dwc); @@ -2904,10 +2905,10 @@ static void dwc3_gadget_setup_nump(struct dwc3 *dwc) nump = min_t(u32, nump, 16); /* update NumP */ - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg &= ~DWC3_DCFG_NUMP_MASK; reg |= nump << DWC3_DCFG_NUMP_SHIFT; - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); } static int __dwc3_gadget_start(struct dwc3 *dwc) @@ -2921,10 +2922,10 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) * the core supports IMOD, disable it. */ if (dwc->imod_interval) { - dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); + dwc3_writel(dwc, DWC3_DEV_IMOD(0), dwc->imod_interval); + dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); } else if (dwc3_has_imod(dwc)) { - dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0); + dwc3_writel(dwc, DWC3_DEV_IMOD(0), 0); } /* @@ -2934,13 +2935,13 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) * This way, we maximize the chances that we'll be able to get several * bursts of data without going through any sort of endpoint throttling. */ - reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG); + reg = dwc3_readl(dwc, DWC3_GRXTHRCFG); if (DWC3_IP_IS(DWC3)) reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL; else reg &= ~DWC31_GRXTHRCFG_PKTCNTSEL; - dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg); + dwc3_writel(dwc, DWC3_GRXTHRCFG, reg); dwc3_gadget_setup_nump(dwc); @@ -2951,15 +2952,15 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) * ACK with NumP=0 and PP=0 (for IN direction). This slightly improves * the stream performance. */ - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg |= DWC3_DCFG_IGNSTRMPP; - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); /* Enable MST by default if the device is capable of MST */ if (DWC3_MST_CAPABLE(&dwc->hwparams)) { - reg = dwc3_readl(dwc->regs, DWC3_DCFG1); + reg = dwc3_readl(dwc, DWC3_DCFG1); reg &= ~DWC3_DCFG1_DIS_MST_ENH; - dwc3_writel(dwc->regs, DWC3_DCFG1, reg); + dwc3_writel(dwc, DWC3_DCFG1, reg); } /* Start with SuperSpeed Default */ @@ -3237,7 +3238,7 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep) /* MDWIDTH is represented in bits, we need it in bytes */ mdwidth /= 8; - size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1)); + size = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(dep->number >> 1)); if (DWC3_IP_IS(DWC3)) size = DWC3_GTXFIFOSIZ_TXFDEP(size); else @@ -3286,7 +3287,7 @@ static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep) mdwidth /= 8; /* All OUT endpoints share a single RxFIFO space */ - size = dwc3_readl(dwc->regs, DWC3_GRXFIFOSIZ(0)); + size = dwc3_readl(dwc, DWC3_GRXFIFOSIZ(0)); if (DWC3_IP_IS(DWC3)) size = DWC3_GRXFIFOSIZ_RXFDEP(size); else @@ -3379,7 +3380,6 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 epnum) dep->dwc = dwc; dep->number = epnum; dep->direction = direction; - dep->regs = dwc->regs + DWC3_DEP_BASE(epnum); dwc->eps[epnum] = dep; dep->combo_num = 0; dep->start_cmd_status = 0; @@ -3740,9 +3740,9 @@ static bool dwc3_gadget_endpoint_trbs_complete(struct dwc3_ep *dep, return no_started_trb; } - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg |= dwc->u1u2; - dwc3_writel(dwc->regs, DWC3_DCTL, reg); + dwc3_writel(dwc, DWC3_DCTL, reg); dwc->u1u2 = 0; } @@ -4072,7 +4072,7 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc) dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~DWC3_DCTL_INITU1ENA; reg &= ~DWC3_DCTL_INITU2ENA; dwc3_gadget_dctl_write_safe(dwc, reg); @@ -4161,7 +4161,7 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_stop_active_transfers(dwc); dwc->connected = true; - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~DWC3_DCTL_TSTCTRL_MASK; dwc3_gadget_dctl_write_safe(dwc, reg); dwc->test_mode = false; @@ -4170,9 +4170,9 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc) dwc3_clear_stall_all_ep(dwc); /* Reset device address to zero */ - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg &= ~(DWC3_DCFG_DEVADDR_MASK); - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); } static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) @@ -4186,7 +4186,7 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) if (!dwc->softconnect) return; - reg = dwc3_readl(dwc->regs, DWC3_DSTS); + reg = dwc3_readl(dwc, DWC3_DSTS); speed = reg & DWC3_DSTS_CONNECTSPD; dwc->speed = speed; @@ -4261,11 +4261,11 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) !dwc->usb2_gadget_lpm_disable && (speed != DWC3_DSTS_SUPERSPEED) && (speed != DWC3_DSTS_SUPERSPEED_PLUS)) { - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg |= DWC3_DCFG_LPM_CAP; - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN); reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold | @@ -4288,12 +4288,12 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) dwc3_gadget_dctl_write_safe(dwc, reg); } else { if (dwc->usb2_gadget_lpm_disable) { - reg = dwc3_readl(dwc->regs, DWC3_DCFG); + reg = dwc3_readl(dwc, DWC3_DCFG); reg &= ~DWC3_DCFG_LPM_CAP; - dwc3_writel(dwc->regs, DWC3_DCFG, reg); + dwc3_writel(dwc, DWC3_DCFG, reg); } - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); reg &= ~DWC3_DCTL_HIRD_THRES_MASK; dwc3_gadget_dctl_write_safe(dwc, reg); } @@ -4399,7 +4399,7 @@ static void dwc3_gadget_linksts_change_interrupt(struct dwc3 *dwc, switch (dwc->link_state) { case DWC3_LINK_STATE_U1: case DWC3_LINK_STATE_U2: - reg = dwc3_readl(dwc->regs, DWC3_DCTL); + reg = dwc3_readl(dwc, DWC3_DCTL); u1u2 = reg & (DWC3_DCTL_INITU2ENA | DWC3_DCTL_ACCEPTU2ENA | DWC3_DCTL_INITU1ENA @@ -4556,7 +4556,7 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt) ret = IRQ_HANDLED; /* Unmask interrupt */ - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), + dwc3_writel(dwc, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_SIZE(evt->length)); evt->flags &= ~DWC3_EVENT_PENDING; @@ -4567,8 +4567,8 @@ static irqreturn_t dwc3_process_event_buf(struct dwc3_event_buffer *evt) wmb(); if (dwc->imod_interval) { - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); - dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval); + dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB); + dwc3_writel(dwc, DWC3_DEV_IMOD(0), dwc->imod_interval); } return ret; @@ -4617,7 +4617,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (evt->flags & DWC3_EVENT_PENDING) return IRQ_HANDLED; - count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0)); + count = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0)); count &= DWC3_GEVNTCOUNT_MASK; if (!count) return IRQ_NONE; @@ -4632,7 +4632,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) evt->flags |= DWC3_EVENT_PENDING; /* Mask interrupt */ - dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), + dwc3_writel(dwc, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length)); amount = min(count, evt->length - evt->lpos); @@ -4641,7 +4641,7 @@ static irqreturn_t dwc3_check_event_buf(struct dwc3_event_buffer *evt) if (amount < count) memcpy(evt->cache, evt->buf, count - amount); - dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count); + dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), count); return IRQ_WAKE_THREAD; } diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h index d73e735e4081..45f113b3c146 100644 --- a/drivers/usb/dwc3/gadget.h +++ b/drivers/usb/dwc3/gadget.h @@ -132,7 +132,7 @@ static inline void dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep) { u32 res_id; - res_id = dwc3_readl(dep->regs, DWC3_DEPCMD); + res_id = dwc3_readl(dep->dwc, DWC3_DEPCMD(dep->number)); dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id); } @@ -147,7 +147,7 @@ static inline void dwc3_gadget_ep_get_transfer_index(struct dwc3_ep *dep) static inline void dwc3_gadget_dctl_write_safe(struct dwc3 *dwc, u32 value) { value &= ~DWC3_DCTL_ULSTCHNGREQ_MASK; - dwc3_writel(dwc->regs, DWC3_DCTL, value); + dwc3_writel(dwc, DWC3_DCTL, value); } #endif /* __DRIVERS_USB_DWC3_GADGET_H */ diff --git a/drivers/usb/dwc3/io.h b/drivers/usb/dwc3/io.h index 1e96ea339d48..7dd0c1e0cf74 100644 --- a/drivers/usb/dwc3/io.h +++ b/drivers/usb/dwc3/io.h @@ -16,9 +16,10 @@ #include "debug.h" #include "core.h" -static inline u32 dwc3_readl(void __iomem *base, u32 offset) +static inline u32 dwc3_readl(struct dwc3 *dwc, u32 offset) { u32 value; + void __iomem *base = dwc->regs; /* * We requested the mem region starting from the Globals address @@ -37,8 +38,10 @@ static inline u32 dwc3_readl(void __iomem *base, u32 offset) return value; } -static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value) +static inline void dwc3_writel(struct dwc3 *dwc, u32 offset, u32 value) { + void __iomem *base = dwc->regs; + /* * We requested the mem region starting from the Globals address * space, see dwc3_probe in core.c. diff --git a/drivers/usb/dwc3/ulpi.c b/drivers/usb/dwc3/ulpi.c index f23f4c9a557e..57daad15f502 100644 --- a/drivers/usb/dwc3/ulpi.c +++ b/drivers/usb/dwc3/ulpi.c @@ -33,13 +33,13 @@ static int dwc3_ulpi_busyloop(struct dwc3 *dwc, u8 addr, bool read) if (read) ns += DWC3_ULPI_BASE_DELAY; - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)); if (reg & DWC3_GUSB2PHYCFG_SUSPHY) usleep_range(1000, 1200); while (count--) { ndelay(ns); - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYACC(0)); if (reg & DWC3_GUSB2PHYACC_DONE) return 0; cpu_relax(); @@ -55,13 +55,13 @@ static int dwc3_ulpi_read(struct device *dev, u8 addr) int ret; reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); - dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYACC(0), reg); ret = dwc3_ulpi_busyloop(dwc, addr, true); if (ret) return ret; - reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0)); + reg = dwc3_readl(dwc, DWC3_GUSB2PHYACC(0)); return DWC3_GUSB2PHYACC_DATA(reg); } @@ -73,7 +73,7 @@ static int dwc3_ulpi_write(struct device *dev, u8 addr, u8 val) reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr); reg |= DWC3_GUSB2PHYACC_WRITE | val; - dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg); + dwc3_writel(dwc, DWC3_GUSB2PHYACC(0), reg); return dwc3_ulpi_busyloop(dwc, addr, false); } diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index fe5a04f4cf14..336a0de9a911 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -5526,6 +5526,8 @@ static void run_state_machine(struct tcpm_port *port) usb_power_delivery_unregister_capabilities(port->partner_source_caps); port->partner_source_caps = NULL; tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP); + port->vdm_sm_running = false; + port->explicit_contract = false; tcpm_ams_finish(port); if (port->pwr_role == TYPEC_SOURCE) { port->upcoming_state = SRC_SEND_CAPABILITIES; diff --git a/drivers/video/fbdev/core/bitblit.c b/drivers/video/fbdev/core/bitblit.c index dc5ad3fcc7be..bed8ba18222b 100644 --- a/drivers/video/fbdev/core/bitblit.c +++ b/drivers/video/fbdev/core/bitblit.c @@ -261,10 +261,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; - int y = real_y(ops->p, vc->state.y); + int y = real_y(par->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1; char *src; @@ -278,10 +278,10 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, attribute = get_attribute(info, c); src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height)); - if (ops->cursor_state.image.data != src || - ops->cursor_reset) { - ops->cursor_state.image.data = src; - cursor.set |= FB_CUR_SETIMAGE; + if (par->cursor_state.image.data != src || + par->cursor_reset) { + par->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; } if (attribute) { @@ -290,46 +290,46 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); if (!dst) return; - kfree(ops->cursor_data); - ops->cursor_data = dst; + kfree(par->cursor_data); + par->cursor_data = dst; update_attr(dst, src, attribute, vc); src = dst; } - if (ops->cursor_state.image.fg_color != fg || - ops->cursor_state.image.bg_color != bg || - ops->cursor_reset) { - ops->cursor_state.image.fg_color = fg; - ops->cursor_state.image.bg_color = bg; + if (par->cursor_state.image.fg_color != fg || + par->cursor_state.image.bg_color != bg || + par->cursor_reset) { + par->cursor_state.image.fg_color = fg; + par->cursor_state.image.bg_color = bg; cursor.set |= FB_CUR_SETCMAP; } - if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) || - (ops->cursor_state.image.dy != (vc->vc_font.height * y)) || - ops->cursor_reset) { - ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x; - ops->cursor_state.image.dy = vc->vc_font.height * y; + if ((par->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) || + (par->cursor_state.image.dy != (vc->vc_font.height * y)) || + par->cursor_reset) { + par->cursor_state.image.dx = vc->vc_font.width * vc->state.x; + par->cursor_state.image.dy = vc->vc_font.height * y; cursor.set |= FB_CUR_SETPOS; } - if (ops->cursor_state.image.height != vc->vc_font.height || - ops->cursor_state.image.width != vc->vc_font.width || - ops->cursor_reset) { - ops->cursor_state.image.height = vc->vc_font.height; - ops->cursor_state.image.width = vc->vc_font.width; + if (par->cursor_state.image.height != vc->vc_font.height || + par->cursor_state.image.width != vc->vc_font.width || + par->cursor_reset) { + par->cursor_state.image.height = vc->vc_font.height; + par->cursor_state.image.width = vc->vc_font.width; cursor.set |= FB_CUR_SETSIZE; } - if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || - ops->cursor_reset) { - ops->cursor_state.hot.x = cursor.hot.y = 0; + if (par->cursor_state.hot.x || par->cursor_state.hot.y || + par->cursor_reset) { + par->cursor_state.hot.x = cursor.hot.y = 0; cursor.set |= FB_CUR_SETHOT; } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != ops->p->cursor_shape || - ops->cursor_state.mask == NULL || - ops->cursor_reset) { + vc->vc_cursor_type != par->p->cursor_shape || + par->cursor_state.mask == NULL || + par->cursor_reset) { char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); int cur_height, size, i = 0; u8 msk = 0xff; @@ -337,13 +337,13 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, if (!mask) return; - kfree(ops->cursor_state.mask); - ops->cursor_state.mask = mask; + kfree(par->cursor_state.mask); + par->cursor_state.mask = mask; - ops->p->cursor_shape = vc->vc_cursor_type; + par->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (CUR_SIZE(ops->p->cursor_shape)) { + switch (CUR_SIZE(par->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; @@ -372,19 +372,19 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, mask[i++] = msk; } - ops->cursor_state.enable = enable && !use_sw; + par->cursor_state.enable = enable && !use_sw; cursor.image.data = src; - cursor.image.fg_color = ops->cursor_state.image.fg_color; - cursor.image.bg_color = ops->cursor_state.image.bg_color; - cursor.image.dx = ops->cursor_state.image.dx; - cursor.image.dy = ops->cursor_state.image.dy; - cursor.image.height = ops->cursor_state.image.height; - cursor.image.width = ops->cursor_state.image.width; - cursor.hot.x = ops->cursor_state.hot.x; - cursor.hot.y = ops->cursor_state.hot.y; - cursor.mask = ops->cursor_state.mask; - cursor.enable = ops->cursor_state.enable; + cursor.image.fg_color = par->cursor_state.image.fg_color; + cursor.image.bg_color = par->cursor_state.image.bg_color; + cursor.image.dx = par->cursor_state.image.dx; + cursor.image.dy = par->cursor_state.image.dy; + cursor.image.height = par->cursor_state.image.height; + cursor.image.width = par->cursor_state.image.width; + cursor.hot.x = par->cursor_state.hot.x; + cursor.hot.y = par->cursor_state.hot.y; + cursor.mask = par->cursor_state.mask; + cursor.enable = par->cursor_state.enable; cursor.image.depth = 1; cursor.rop = ROP_XOR; @@ -394,31 +394,31 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, bool enable, if (err) soft_cursor(info, &cursor); - ops->cursor_reset = 0; + par->cursor_reset = 0; } static int bit_update_start(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int err; - err = fb_pan_display(info, &ops->var); - ops->var.xoffset = info->var.xoffset; - ops->var.yoffset = info->var.yoffset; - ops->var.vmode = info->var.vmode; + err = fb_pan_display(info, &par->var); + par->var.xoffset = info->var.xoffset; + par->var.yoffset = info->var.yoffset; + par->var.vmode = info->var.vmode; return err; } -void fbcon_set_bitops(struct fbcon_ops *ops) +void fbcon_set_bitops(struct fbcon_par *par) { - ops->bmove = bit_bmove; - ops->clear = bit_clear; - ops->putcs = bit_putcs; - ops->clear_margins = bit_clear_margins; - ops->cursor = bit_cursor; - ops->update_start = bit_update_start; - ops->rotate_font = NULL; - - if (ops->rotate) - fbcon_set_rotate(ops); + par->bmove = bit_bmove; + par->clear = bit_clear; + par->putcs = bit_putcs; + par->clear_margins = bit_clear_margins; + par->cursor = bit_cursor; + par->update_start = bit_update_start; + par->rotate_font = NULL; + + if (par->rotate) + fbcon_set_rotate(par); } diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 7453377f3433..8baad7ec1b85 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -200,27 +200,27 @@ static struct device *fbcon_device; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION static inline void fbcon_set_rotation(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; if (!(info->flags & FBINFO_MISC_TILEBLITTING) && - ops->p->con_rotate < 4) - ops->rotate = ops->p->con_rotate; + par->p->con_rotate < 4) + par->rotate = par->p->con_rotate; else - ops->rotate = 0; + par->rotate = 0; } static void fbcon_rotate(struct fb_info *info, u32 rotate) { - struct fbcon_ops *ops= info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_info *fb_info; - if (!ops || ops->currcon == -1) + if (!par || par->currcon == -1) return; - fb_info = fbcon_info_from_console(ops->currcon); + fb_info = fbcon_info_from_console(par->currcon); if (info == fb_info) { - struct fbcon_display *p = &fb_display[ops->currcon]; + struct fbcon_display *p = &fb_display[par->currcon]; if (rotate < 4) p->con_rotate = rotate; @@ -233,12 +233,12 @@ static void fbcon_rotate(struct fb_info *info, u32 rotate) static void fbcon_rotate_all(struct fb_info *info, u32 rotate) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; struct fbcon_display *p; int i; - if (!ops || ops->currcon < 0 || rotate > 3) + if (!par || par->currcon < 0 || rotate > 3) return; for (i = first_fb_vc; i <= last_fb_vc; i++) { @@ -256,9 +256,9 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate) #else static inline void fbcon_set_rotation(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - ops->rotate = FB_ROTATE_UR; + par->rotate = FB_ROTATE_UR; } static void fbcon_rotate(struct fb_info *info, u32 rotate) @@ -274,9 +274,9 @@ static void fbcon_rotate_all(struct fb_info *info, u32 rotate) static int fbcon_get_rotate(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - return (ops) ? ops->rotate : 0; + return (par) ? par->rotate : 0; } static bool fbcon_skip_panic(struct fb_info *info) @@ -286,10 +286,10 @@ static bool fbcon_skip_panic(struct fb_info *info) static inline bool fbcon_is_active(struct vc_data *vc, struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; return info->state == FBINFO_STATE_RUNNING && - vc->vc_mode == KD_TEXT && !ops->graphics && !fbcon_skip_panic(info); + vc->vc_mode == KD_TEXT && !par->graphics && !fbcon_skip_panic(info); } static int get_color(struct vc_data *vc, struct fb_info *info, @@ -371,7 +371,7 @@ static int get_bg_color(struct vc_data *vc, struct fb_info *info, u16 c) static void fb_flashcursor(struct work_struct *work) { - struct fbcon_ops *ops = container_of(work, struct fbcon_ops, cursor_work.work); + struct fbcon_par *par = container_of(work, struct fbcon_par, cursor_work.work); struct fb_info *info; struct vc_data *vc = NULL; int c; @@ -386,10 +386,10 @@ static void fb_flashcursor(struct work_struct *work) return; /* protected by console_lock */ - info = ops->info; + info = par->info; - if (ops->currcon != -1) - vc = vc_cons[ops->currcon].d; + if (par->currcon != -1) + vc = vc_cons[par->currcon].d; if (!vc || !con_is_visible(vc) || fbcon_info_from_console(vc->vc_num) != info || @@ -399,30 +399,30 @@ static void fb_flashcursor(struct work_struct *work) } c = scr_readw((u16 *) vc->vc_pos); - enable = ops->cursor_flash && !ops->cursor_state.enable; - ops->cursor(vc, info, enable, + enable = par->cursor_flash && !par->cursor_state.enable; + par->cursor(vc, info, enable, get_fg_color(vc, info, c), get_bg_color(vc, info, c)); console_unlock(); - queue_delayed_work(system_power_efficient_wq, &ops->cursor_work, - ops->cur_blink_jiffies); + queue_delayed_work(system_power_efficient_wq, &par->cursor_work, + par->cur_blink_jiffies); } static void fbcon_add_cursor_work(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; if (fbcon_cursor_blink) - queue_delayed_work(system_power_efficient_wq, &ops->cursor_work, - ops->cur_blink_jiffies); + queue_delayed_work(system_power_efficient_wq, &par->cursor_work, + par->cur_blink_jiffies); } static void fbcon_del_cursor_work(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - cancel_delayed_work_sync(&ops->cursor_work); + cancel_delayed_work_sync(&par->cursor_work); } #ifndef MODULE @@ -582,7 +582,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cols, int rows, int new_cols, int new_rows) { /* Need to make room for the logo */ - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int cnt, erase = vc->vc_video_erase_char, step; unsigned short *save = NULL, *r, *q; int logo_height; @@ -598,7 +598,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, */ if (fb_get_color_depth(&info->var, &info->fix) == 1) erase &= ~0x400; - logo_height = fb_prepare_logo(info, ops->rotate); + logo_height = fb_prepare_logo(info, par->rotate); logo_lines = DIV_ROUND_UP(logo_height, vc->vc_font.height); q = (unsigned short *) (vc->vc_origin + vc->vc_size_row * rows); @@ -670,15 +670,15 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, #ifdef CONFIG_FB_TILEBLITTING static void set_blitting_type(struct vc_data *vc, struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - ops->p = &fb_display[vc->vc_num]; + par->p = &fb_display[vc->vc_num]; if ((info->flags & FBINFO_MISC_TILEBLITTING)) fbcon_set_tileops(vc, info); else { fbcon_set_rotation(info); - fbcon_set_bitops(ops); + fbcon_set_bitops(par); } } @@ -695,12 +695,12 @@ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount) #else static void set_blitting_type(struct vc_data *vc, struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; info->flags &= ~FBINFO_MISC_TILEBLITTING; - ops->p = &fb_display[vc->vc_num]; + par->p = &fb_display[vc->vc_num]; fbcon_set_rotation(info); - fbcon_set_bitops(ops); + fbcon_set_bitops(par); } static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount) @@ -720,13 +720,13 @@ static void fbcon_release(struct fb_info *info) module_put(info->fbops->owner); if (info->fbcon_par) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; fbcon_del_cursor_work(info); - kfree(ops->cursor_state.mask); - kfree(ops->cursor_data); - kfree(ops->cursor_src); - kfree(ops->fontbuffer); + kfree(par->cursor_state.mask); + kfree(par->cursor_data); + kfree(par->cursor_src); + kfree(par->fontbuffer); kfree(info->fbcon_par); info->fbcon_par = NULL; } @@ -734,7 +734,7 @@ static void fbcon_release(struct fb_info *info) static int fbcon_open(struct fb_info *info) { - struct fbcon_ops *ops; + struct fbcon_par *par; if (!try_module_get(info->fbops->owner)) return -ENODEV; @@ -748,16 +748,16 @@ static int fbcon_open(struct fb_info *info) } unlock_fb_info(info); - ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL); - if (!ops) { + par = kzalloc(sizeof(*par), GFP_KERNEL); + if (!par) { fbcon_release(info); return -ENOMEM; } - INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor); - ops->info = info; - info->fbcon_par = ops; - ops->cur_blink_jiffies = HZ / 5; + INIT_DELAYED_WORK(&par->cursor_work, fb_flashcursor); + par->info = info; + info->fbcon_par = par; + par->cur_blink_jiffies = HZ / 5; return 0; } @@ -804,12 +804,12 @@ static void con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, int unit, int show_logo) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int ret; - ops->currcon = fg_console; + par->currcon = fg_console; - if (info->fbops->fb_set_par && !ops->initialized) { + if (info->fbops->fb_set_par && !par->initialized) { ret = info->fbops->fb_set_par(info); if (ret) @@ -818,8 +818,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, "error code %d\n", ret); } - ops->initialized = true; - ops->graphics = 0; + par->initialized = true; + par->graphics = 0; fbcon_set_disp(info, &info->var, unit); if (show_logo) { @@ -956,7 +956,7 @@ static const char *fbcon_startup(void) struct vc_data *vc = vc_cons[fg_console].d; const struct font_desc *font = NULL; struct fb_info *info = NULL; - struct fbcon_ops *ops; + struct fbcon_par *par; int rows, cols; /* @@ -976,10 +976,10 @@ static const char *fbcon_startup(void) if (fbcon_open(info)) return NULL; - ops = info->fbcon_par; - ops->currcon = -1; - ops->graphics = 1; - ops->cur_rotate = -1; + par = info->fbcon_par; + par->currcon = -1; + par->graphics = 1; + par->cur_rotate = -1; p->con_rotate = initial_rotation; if (p->con_rotate == -1) @@ -1002,8 +1002,8 @@ static const char *fbcon_startup(void) vc->vc_font.charcount = font->charcount; } - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; vc_resize(vc, cols, rows); @@ -1021,7 +1021,7 @@ static const char *fbcon_startup(void) static void fbcon_init(struct vc_data *vc, bool init) { struct fb_info *info; - struct fbcon_ops *ops; + struct fbcon_par *par; struct vc_data **default_mode = vc->vc_display_fg; struct vc_data *svc = *default_mode; struct fbcon_display *t, *p = &fb_display[vc->vc_num]; @@ -1096,8 +1096,8 @@ static void fbcon_init(struct vc_data *vc, bool init) if (!*vc->uni_pagedict_loc) con_copy_unimap(vc, svc); - ops = info->fbcon_par; - ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); + par = info->fbcon_par; + par->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); p->con_rotate = initial_rotation; if (p->con_rotate == -1) @@ -1109,8 +1109,8 @@ static void fbcon_init(struct vc_data *vc, bool init) cols = vc->vc_cols; rows = vc->vc_rows; - new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + new_cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); + new_rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); new_cols /= vc->vc_font.width; new_rows /= vc->vc_font.height; @@ -1122,7 +1122,7 @@ static void fbcon_init(struct vc_data *vc, bool init) * We need to do it in fbcon_init() to prevent screen corruption. */ if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) { - if (info->fbops->fb_set_par && !ops->initialized) { + if (info->fbops->fb_set_par && !par->initialized) { ret = info->fbops->fb_set_par(info); if (ret) @@ -1131,10 +1131,10 @@ static void fbcon_init(struct vc_data *vc, bool init) "error code %d\n", ret); } - ops->initialized = true; + par->initialized = true; } - ops->graphics = 0; + par->graphics = 0; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION if ((info->flags & FBINFO_HWACCEL_COPYAREA) && @@ -1158,12 +1158,12 @@ static void fbcon_init(struct vc_data *vc, bool init) if (logo) fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows); - if (ops->rotate_font && ops->rotate_font(info, vc)) { - ops->rotate = FB_ROTATE_UR; + if (par->rotate_font && par->rotate_font(info, vc)) { + par->rotate = FB_ROTATE_UR; set_blitting_type(vc, info); } - ops->p = &fb_display[fg_console]; + par->p = &fb_display[fg_console]; } static void fbcon_free_font(struct fbcon_display *p) @@ -1201,7 +1201,7 @@ static void fbcon_deinit(struct vc_data *vc) { struct fbcon_display *p = &fb_display[vc->vc_num]; struct fb_info *info; - struct fbcon_ops *ops; + struct fbcon_par *par; int idx; fbcon_free_font(p); @@ -1215,15 +1215,15 @@ static void fbcon_deinit(struct vc_data *vc) if (!info) goto finished; - ops = info->fbcon_par; + par = info->fbcon_par; - if (!ops) + if (!par) goto finished; if (con_is_visible(vc)) fbcon_del_cursor_work(info); - ops->initialized = false; + par->initialized = false; finished: fbcon_free_font(p); @@ -1270,7 +1270,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, unsigned int height, unsigned int width) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int fg, bg; struct fbcon_display *p = &fb_display[vc->vc_num]; u_int y_break; @@ -1285,7 +1285,7 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, vc->vc_top = 0; /* * If the font dimensions are not an integral of the display - * dimensions then the ops->clear below won't end up clearing + * dimensions then the par->clear below won't end up clearing * the margins. Call clear_margins here in case the logo * bitmap stretched into the margin area. */ @@ -1299,11 +1299,10 @@ static void __fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, y_break = p->vrows - p->yscroll; if (sy < y_break && sy + height - 1 >= y_break) { u_int b = y_break - sy; - ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); - ops->clear(vc, info, real_y(p, sy + b), sx, height - b, - width, fg, bg); + par->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg); + par->clear(vc, info, real_y(p, sy + b), sx, height - b, width, fg, bg); } else - ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); + par->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg); } static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx, @@ -1317,10 +1316,10 @@ static void fbcon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, { struct fb_info *info = fbcon_info_from_console(vc->vc_num); struct fbcon_display *p = &fb_display[vc->vc_num]; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; if (fbcon_is_active(vc, info)) - ops->putcs(vc, info, s, count, real_y(p, ypos), xpos, + par->putcs(vc, info, s, count, real_y(p, ypos), xpos, get_fg_color(vc, info, scr_readw(s)), get_bg_color(vc, info, scr_readw(s))); } @@ -1328,19 +1327,19 @@ static void fbcon_putcs(struct vc_data *vc, const u16 *s, unsigned int count, static void fbcon_clear_margins(struct vc_data *vc, int bottom_only) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; if (fbcon_is_active(vc, info)) - ops->clear_margins(vc, info, margin_color, bottom_only); + par->clear_margins(vc, info, margin_color, bottom_only); } static void fbcon_cursor(struct vc_data *vc, bool enable) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int c = scr_readw((u16 *) vc->vc_pos); - ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); + par->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms); if (!fbcon_is_active(vc, info) || vc->vc_deccm != 1) return; @@ -1350,12 +1349,12 @@ static void fbcon_cursor(struct vc_data *vc, bool enable) else fbcon_add_cursor_work(info); - ops->cursor_flash = enable; + par->cursor_flash = enable; - if (!ops->cursor) + if (!par->cursor) return; - ops->cursor(vc, info, enable, + par->cursor(vc, info, enable, get_fg_color(vc, info, c), get_bg_color(vc, info, c)); } @@ -1370,7 +1369,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, struct fbcon_display *p, *t; struct vc_data **default_mode, *vc; struct vc_data *svc; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int rows, cols; unsigned long ret = 0; @@ -1403,7 +1402,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, var->yoffset = info->var.yoffset; var->xoffset = info->var.xoffset; fb_set_var(info, var); - ops->var = info->var; + par->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (vc->vc_font.charcount == 256) { @@ -1419,8 +1418,8 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, if (!*vc->uni_pagedict_loc) con_copy_unimap(vc, svc); - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; ret = vc_resize(vc, cols, rows); @@ -1432,16 +1431,16 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, static __inline__ void ywrap_up(struct vc_data *vc, int count) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; - ops->var.xoffset = 0; - ops->var.yoffset = p->yscroll * vc->vc_font.height; - ops->var.vmode |= FB_VMODE_YWRAP; - ops->update_start(info); + par->var.xoffset = 0; + par->var.yoffset = p->yscroll * vc->vc_font.height; + par->var.vmode |= FB_VMODE_YWRAP; + par->update_start(info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1451,16 +1450,16 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) static __inline__ void ywrap_down(struct vc_data *vc, int count) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; - ops->var.xoffset = 0; - ops->var.yoffset = p->yscroll * vc->vc_font.height; - ops->var.vmode |= FB_VMODE_YWRAP; - ops->update_start(info); + par->var.xoffset = 0; + par->var.yoffset = p->yscroll * vc->vc_font.height; + par->var.vmode |= FB_VMODE_YWRAP; + par->update_start(info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1471,19 +1470,19 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); struct fbcon_display *p = &fb_display[vc->vc_num]; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; p->yscroll += count; if (p->yscroll > p->vrows - vc->vc_rows) { - ops->bmove(vc, info, p->vrows - vc->vc_rows, + par->bmove(vc, info, p->vrows - vc->vc_rows, 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } - ops->var.xoffset = 0; - ops->var.yoffset = p->yscroll * vc->vc_font.height; - ops->var.vmode &= ~FB_VMODE_YWRAP; - ops->update_start(info); + par->var.xoffset = 0; + par->var.yoffset = p->yscroll * vc->vc_font.height; + par->var.vmode &= ~FB_VMODE_YWRAP; + par->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1494,7 +1493,7 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; p->yscroll += count; @@ -1504,10 +1503,10 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); } - ops->var.xoffset = 0; - ops->var.yoffset = p->yscroll * vc->vc_font.height; - ops->var.vmode &= ~FB_VMODE_YWRAP; - ops->update_start(info); + par->var.xoffset = 0; + par->var.yoffset = p->yscroll * vc->vc_font.height; + par->var.vmode &= ~FB_VMODE_YWRAP; + par->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1519,19 +1518,19 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); struct fbcon_display *p = &fb_display[vc->vc_num]; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; p->yscroll -= count; if (p->yscroll < 0) { - ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, + par->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows, 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } - ops->var.xoffset = 0; - ops->var.yoffset = p->yscroll * vc->vc_font.height; - ops->var.vmode &= ~FB_VMODE_YWRAP; - ops->update_start(info); + par->var.xoffset = 0; + par->var.yoffset = p->yscroll * vc->vc_font.height; + par->var.vmode &= ~FB_VMODE_YWRAP; + par->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1542,7 +1541,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; p->yscroll -= count; @@ -1552,10 +1551,10 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); } - ops->var.xoffset = 0; - ops->var.yoffset = p->yscroll * vc->vc_font.height; - ops->var.vmode &= ~FB_VMODE_YWRAP; - ops->update_start(info); + par->var.xoffset = 0; + par->var.yoffset = p->yscroll * vc->vc_font.height; + par->var.vmode &= ~FB_VMODE_YWRAP; + par->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1604,7 +1603,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, unsigned short *d = (unsigned short *) (vc->vc_origin + vc->vc_size_row * line); unsigned short *s = d + offset; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; while (count--) { unsigned short *start = s; @@ -1617,8 +1616,8 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, if (c == scr_readw(d)) { if (s > start) { - ops->bmove(vc, info, line + ycount, x, - line, x, 1, s-start); + par->bmove(vc, info, line + ycount, x, + line, x, 1, s - start); x += s - start + 1; start = s + 1; } else { @@ -1633,8 +1632,7 @@ static void fbcon_redraw_blit(struct vc_data *vc, struct fb_info *info, d++; } while (s < le); if (s > start) - ops->bmove(vc, info, line + ycount, x, line, x, 1, - s-start); + par->bmove(vc, info, line + ycount, x, line, x, 1, s - start); console_conditional_schedule(); if (ycount > 0) line++; @@ -1705,7 +1703,7 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, int dy, int dx, int height, int width, u_int y_break) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u_int b; if (sy < y_break && sy + height > y_break) { @@ -1739,8 +1737,7 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct fbcon_display *p, int sy, } return; } - ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, - height, width); + par->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, height, width); } static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx, @@ -1967,15 +1964,13 @@ static void updatescrollmode_accel(struct fbcon_display *p, struct vc_data *vc) { #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int cap = info->flags; u16 t = 0; - int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, - info->fix.xpanstep); - int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); - int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); - int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, - info->var.xres_virtual); + int ypan = FBCON_SWAP(par->rotate, info->fix.ypanstep, info->fix.xpanstep); + int ywrap = FBCON_SWAP(par->rotate, info->fix.ywrapstep, t); + int yres = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); + int vyres = FBCON_SWAP(par->rotate, info->var.yres_virtual, info->var.xres_virtual); int good_pan = (cap & FBINFO_HWACCEL_YPAN) && divides(ypan, vc->vc_font.height) && vyres > yres; int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && @@ -2008,11 +2003,10 @@ static void updatescrollmode(struct fbcon_display *p, struct fb_info *info, struct vc_data *vc) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int fh = vc->vc_font.height; - int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); - int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, - info->var.xres_virtual); + int yres = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); + int vyres = FBCON_SWAP(par->rotate, info->var.yres_virtual, info->var.xres_virtual); p->vrows = vyres/fh; if (yres > (fh * (vc->vc_rows + 1))) @@ -2031,7 +2025,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, unsigned int height, bool from_user) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var = info->var; int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; @@ -2054,12 +2048,10 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, return -EINVAL; } - virt_w = FBCON_SWAP(ops->rotate, width, height); - virt_h = FBCON_SWAP(ops->rotate, height, width); - virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width, - vc->vc_font.height); - virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height, - vc->vc_font.width); + virt_w = FBCON_SWAP(par->rotate, width, height); + virt_h = FBCON_SWAP(par->rotate, height, width); + virt_fw = FBCON_SWAP(par->rotate, vc->vc_font.width, vc->vc_font.height); + virt_fh = FBCON_SWAP(par->rotate, vc->vc_font.height, vc->vc_font.width); var.xres = virt_w * virt_fw; var.yres = virt_h * virt_fh; x_diff = info->var.xres - var.xres; @@ -2085,7 +2077,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, fb_set_var(info, &var); } var_to_display(p, &info->var, info); - ops->var = info->var; + par->var = info->var; } updatescrollmode(p, info, vc); return 0; @@ -2094,13 +2086,13 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, static bool fbcon_switch(struct vc_data *vc) { struct fb_info *info, *old_info = NULL; - struct fbcon_ops *ops; + struct fbcon_par *par; struct fbcon_display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; int i, ret, prev_console; info = fbcon_info_from_console(vc->vc_num); - ops = info->fbcon_par; + par = info->fbcon_par; if (logo_shown >= 0) { struct vc_data *conp2 = vc_cons[logo_shown].d; @@ -2111,7 +2103,7 @@ static bool fbcon_switch(struct vc_data *vc) logo_shown = FBCON_LOGO_CANSHOW; } - prev_console = ops->currcon; + prev_console = par->currcon; if (prev_console != -1) old_info = fbcon_info_from_console(prev_console); /* @@ -2124,9 +2116,9 @@ static bool fbcon_switch(struct vc_data *vc) */ fbcon_for_each_registered_fb(i) { if (fbcon_registered_fb[i]->fbcon_par) { - struct fbcon_ops *o = fbcon_registered_fb[i]->fbcon_par; + struct fbcon_par *par = fbcon_registered_fb[i]->fbcon_par; - o->currcon = vc->vc_num; + par->currcon = vc->vc_num; } } memset(&var, 0, sizeof(struct fb_var_screeninfo)); @@ -2140,7 +2132,7 @@ static bool fbcon_switch(struct vc_data *vc) info->var.activate = var.activate; var.vmode |= info->var.vmode & ~FB_VMODE_MASK; fb_set_var(info, &var); - ops->var = info->var; + par->var = info->var; if (old_info != NULL && (old_info != info || info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { @@ -2157,17 +2149,16 @@ static bool fbcon_switch(struct vc_data *vc) fbcon_del_cursor_work(old_info); } - if (!fbcon_is_active(vc, info) || - ops->blank_state != FB_BLANK_UNBLANK) + if (!fbcon_is_active(vc, info) || par->blank_state != FB_BLANK_UNBLANK) fbcon_del_cursor_work(info); else fbcon_add_cursor_work(info); set_blitting_type(vc, info); - ops->cursor_reset = 1; + par->cursor_reset = 1; - if (ops->rotate_font && ops->rotate_font(info, vc)) { - ops->rotate = FB_ROTATE_UR; + if (par->rotate_font && par->rotate_font(info, vc)) { + par->rotate = FB_ROTATE_UR; set_blitting_type(vc, info); } @@ -2198,8 +2189,8 @@ static bool fbcon_switch(struct vc_data *vc) scrollback_current = 0; if (fbcon_is_active(vc, info)) { - ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; - ops->update_start(info); + par->var.xoffset = par->var.yoffset = p->yscroll = 0; + par->update_start(info); } fbcon_set_palette(vc, color_table); @@ -2208,7 +2199,7 @@ static bool fbcon_switch(struct vc_data *vc) if (logo_shown == FBCON_LOGO_DRAW) { logo_shown = fg_console; - fb_show_logo(info, ops->rotate); + fb_show_logo(info, par->rotate); update_region(vc, vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_size_row * (vc->vc_bottom - @@ -2237,27 +2228,27 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank, bool mode_switch) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; if (mode_switch) { struct fb_var_screeninfo var = info->var; - ops->graphics = 1; + par->graphics = 1; if (!blank) { var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE | FB_ACTIVATE_KD_TEXT; fb_set_var(info, &var); - ops->graphics = 0; - ops->var = info->var; + par->graphics = 0; + par->var = info->var; } } if (fbcon_is_active(vc, info)) { - if (ops->blank_state != blank) { - ops->blank_state = blank; + if (par->blank_state != blank) { + par->blank_state = blank; fbcon_cursor(vc, !blank); - ops->cursor_flash = (!blank); + par->cursor_flash = (!blank); if (fb_blank(info, blank)) fbcon_generic_blank(vc, info, blank); @@ -2267,8 +2258,7 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank, update_screen(vc); } - if (mode_switch || !fbcon_is_active(vc, info) || - ops->blank_state != FB_BLANK_UNBLANK) + if (mode_switch || !fbcon_is_active(vc, info) || par->blank_state != FB_BLANK_UNBLANK) fbcon_del_cursor_work(info); else fbcon_add_cursor_work(info); @@ -2279,10 +2269,10 @@ static bool fbcon_blank(struct vc_data *vc, enum vesa_blank_mode blank, static void fbcon_debug_enter(struct vc_data *vc) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - ops->save_graphics = ops->graphics; - ops->graphics = 0; + par->save_graphics = par->graphics; + par->graphics = 0; if (info->fbops->fb_debug_enter) info->fbops->fb_debug_enter(info); fbcon_set_palette(vc, color_table); @@ -2291,9 +2281,9 @@ static void fbcon_debug_enter(struct vc_data *vc) static void fbcon_debug_leave(struct vc_data *vc) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - ops->graphics = ops->save_graphics; + par->graphics = par->save_graphics; if (info->fbops->fb_debug_leave) info->fbops->fb_debug_leave(info); } @@ -2428,7 +2418,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, const u8 * data, int userfont) { struct fb_info *info = fbcon_info_from_console(vc->vc_num); - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fbcon_display *p = &fb_display[vc->vc_num]; int resize, ret, old_userfont, old_width, old_height, old_charcount; u8 *old_data = vc->vc_font.data; @@ -2454,8 +2444,8 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, int charcount, if (resize) { int cols, rows; - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); cols /= w; rows /= h; ret = vc_resize(vc, cols, rows); @@ -2654,11 +2644,11 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) void fbcon_suspended(struct fb_info *info) { struct vc_data *vc = NULL; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - if (!ops || ops->currcon < 0) + if (!par || par->currcon < 0) return; - vc = vc_cons[ops->currcon].d; + vc = vc_cons[par->currcon].d; /* Clear cursor, restore saved data */ fbcon_cursor(vc, false); @@ -2667,27 +2657,27 @@ void fbcon_suspended(struct fb_info *info) void fbcon_resumed(struct fb_info *info) { struct vc_data *vc; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - if (!ops || ops->currcon < 0) + if (!par || par->currcon < 0) return; - vc = vc_cons[ops->currcon].d; + vc = vc_cons[par->currcon].d; update_screen(vc); } static void fbcon_modechanged(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; struct fbcon_display *p; int rows, cols; - if (!ops || ops->currcon < 0) + if (!par || par->currcon < 0) return; - vc = vc_cons[ops->currcon].d; + vc = vc_cons[par->currcon].d; if (vc->vc_mode != KD_TEXT || - fbcon_info_from_console(ops->currcon) != info) + fbcon_info_from_console(par->currcon) != info) return; p = &fb_display[vc->vc_num]; @@ -2695,8 +2685,8 @@ static void fbcon_modechanged(struct fb_info *info) if (con_is_visible(vc)) { var_to_display(p, &info->var, info); - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; vc_resize(vc, cols, rows); @@ -2705,8 +2695,8 @@ static void fbcon_modechanged(struct fb_info *info) scrollback_current = 0; if (fbcon_is_active(vc, info)) { - ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; - ops->update_start(info); + par->var.xoffset = par->var.yoffset = p->yscroll = 0; + par->update_start(info); } fbcon_set_palette(vc, color_table); @@ -2716,12 +2706,12 @@ static void fbcon_modechanged(struct fb_info *info) static void fbcon_set_all_vcs(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; struct fbcon_display *p; int i, rows, cols, fg = -1; - if (!ops || ops->currcon < 0) + if (!par || par->currcon < 0) return; for (i = first_fb_vc; i <= last_fb_vc; i++) { @@ -2738,8 +2728,8 @@ static void fbcon_set_all_vcs(struct fb_info *info) p = &fb_display[vc->vc_num]; set_blitting_type(vc, info); var_to_display(p, &info->var, info); - cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); - rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres); cols /= vc->vc_font.width; rows /= vc->vc_font.height; vc_resize(vc, cols, rows); @@ -2762,13 +2752,13 @@ EXPORT_SYMBOL(fbcon_update_vcs); /* let fbcon check if it supports a new screen resolution */ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; unsigned int i; WARN_CONSOLE_UNLOCKED(); - if (!ops) + if (!par) return 0; /* prevent setting a screen size which is smaller than font size */ @@ -3066,15 +3056,14 @@ int fbcon_fb_registered(struct fb_info *info) void fbcon_fb_blanked(struct fb_info *info, int blank) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; - if (!ops || ops->currcon < 0) + if (!par || par->currcon < 0) return; - vc = vc_cons[ops->currcon].d; - if (vc->vc_mode != KD_TEXT || - fbcon_info_from_console(ops->currcon) != info) + vc = vc_cons[par->currcon].d; + if (vc->vc_mode != KD_TEXT || fbcon_info_from_console(par->currcon) != info) return; if (con_is_visible(vc)) { @@ -3083,7 +3072,7 @@ void fbcon_fb_blanked(struct fb_info *info, int blank) else do_unblank_screen(0); } - ops->blank_state = blank; + par->blank_state = blank; } void fbcon_new_modelist(struct fb_info *info) @@ -3273,7 +3262,7 @@ static ssize_t cursor_blink_show(struct device *device, struct device_attribute *attr, char *buf) { struct fb_info *info; - struct fbcon_ops *ops; + struct fbcon_par *par; int idx, blink = -1; console_lock(); @@ -3283,12 +3272,12 @@ static ssize_t cursor_blink_show(struct device *device, goto err; info = fbcon_registered_fb[idx]; - ops = info->fbcon_par; + par = info->fbcon_par; - if (!ops) + if (!par) goto err; - blink = delayed_work_pending(&ops->cursor_work); + blink = delayed_work_pending(&par->cursor_work); err: console_unlock(); return sysfs_emit(buf, "%d\n", blink); diff --git a/drivers/video/fbdev/core/fbcon.h b/drivers/video/fbdev/core/fbcon.h index 7e21c8b33669..b22c33e278c1 100644 --- a/drivers/video/fbdev/core/fbcon.h +++ b/drivers/video/fbdev/core/fbcon.h @@ -50,7 +50,7 @@ struct fbcon_display { const struct fb_videomode *mode; }; -struct fbcon_ops { +struct fbcon_par { void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width); void (*clear)(struct vc_data *vc, struct fb_info *info, int sy, @@ -185,7 +185,7 @@ static inline u_short fb_scrollmode(struct fbcon_display *fb) #ifdef CONFIG_FB_TILEBLITTING extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info); #endif -extern void fbcon_set_bitops(struct fbcon_ops *ops); +extern void fbcon_set_bitops(struct fbcon_par *par); extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); #define FBCON_ATTRIBUTE_UNDERLINE 1 @@ -224,7 +224,7 @@ static inline int get_attribute(struct fb_info *info, u16 c) (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION -extern void fbcon_set_rotate(struct fbcon_ops *ops); +extern void fbcon_set_rotate(struct fbcon_par *par); #else #define fbcon_set_rotate(x) do {} while(0) #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ diff --git a/drivers/video/fbdev/core/fbcon_ccw.c b/drivers/video/fbdev/core/fbcon_ccw.c index 89ef4ba7e867..2ba8ec4c3e2b 100644 --- a/drivers/video/fbdev/core/fbcon_ccw.c +++ b/drivers/video/fbdev/core/fbcon_ccw.c @@ -63,9 +63,9 @@ static void ccw_update_attr(u8 *dst, u8 *src, int attribute, static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_copyarea area; - u32 vyres = GETVYRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); area.sx = sy * vc->vc_font.height; area.sy = vyres - ((sx + width) * vc->vc_font.width); @@ -80,9 +80,9 @@ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy, static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width, int fg, int bg) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_fillrect region; - u32 vyres = GETVYRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); region.color = bg; region.dx = sy * vc->vc_font.height; @@ -99,13 +99,13 @@ static inline void ccw_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 d_pitch, u32 s_pitch, u32 cellsize, struct fb_image *image, u8 *buf, u8 *dst) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; u32 idx = (vc->vc_font.height + 7) >> 3; u8 *src; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize; if (attr) { ccw_update_attr(buf, src, attr, vc); @@ -130,7 +130,7 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, int fg, int bg) { struct fb_image image; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u32 width = (vc->vc_font.height + 7)/8; u32 cellsize = width * vc->vc_font.width; u32 maxcnt = info->pixmap.size/cellsize; @@ -139,9 +139,9 @@ static void ccw_putcs(struct vc_data *vc, struct fb_info *info, u32 cnt, pitch, size; u32 attribute = get_attribute(info, scr_readw(s)); u8 *dst, *buf = NULL; - u32 vyres = GETVYRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); - if (!ops->fontbuffer) + if (!par->fontbuffer) return; image.fg_color = fg; @@ -221,28 +221,28 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(ops->p, vc->state.y); + int y = real_y(par->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; - u32 vyres = GETVYRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); - if (!ops->fontbuffer) + if (!par->fontbuffer) return; cursor.set = 0; c = scr_readw((u16 *) vc->vc_pos); attribute = get_attribute(info, c); - src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); - if (ops->cursor_state.image.data != src || - ops->cursor_reset) { - ops->cursor_state.image.data = src; - cursor.set |= FB_CUR_SETIMAGE; + if (par->cursor_state.image.data != src || + par->cursor_reset) { + par->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; } if (attribute) { @@ -251,49 +251,49 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC); if (!dst) return; - kfree(ops->cursor_data); - ops->cursor_data = dst; + kfree(par->cursor_data); + par->cursor_data = dst; ccw_update_attr(dst, src, attribute, vc); src = dst; } - if (ops->cursor_state.image.fg_color != fg || - ops->cursor_state.image.bg_color != bg || - ops->cursor_reset) { - ops->cursor_state.image.fg_color = fg; - ops->cursor_state.image.bg_color = bg; + if (par->cursor_state.image.fg_color != fg || + par->cursor_state.image.bg_color != bg || + par->cursor_reset) { + par->cursor_state.image.fg_color = fg; + par->cursor_state.image.bg_color = bg; cursor.set |= FB_CUR_SETCMAP; } - if (ops->cursor_state.image.height != vc->vc_font.width || - ops->cursor_state.image.width != vc->vc_font.height || - ops->cursor_reset) { - ops->cursor_state.image.height = vc->vc_font.width; - ops->cursor_state.image.width = vc->vc_font.height; + if (par->cursor_state.image.height != vc->vc_font.width || + par->cursor_state.image.width != vc->vc_font.height || + par->cursor_reset) { + par->cursor_state.image.height = vc->vc_font.width; + par->cursor_state.image.width = vc->vc_font.height; cursor.set |= FB_CUR_SETSIZE; } dx = y * vc->vc_font.height; dy = vyres - ((vc->state.x + 1) * vc->vc_font.width); - if (ops->cursor_state.image.dx != dx || - ops->cursor_state.image.dy != dy || - ops->cursor_reset) { - ops->cursor_state.image.dx = dx; - ops->cursor_state.image.dy = dy; + if (par->cursor_state.image.dx != dx || + par->cursor_state.image.dy != dy || + par->cursor_reset) { + par->cursor_state.image.dx = dx; + par->cursor_state.image.dy = dy; cursor.set |= FB_CUR_SETPOS; } - if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || - ops->cursor_reset) { - ops->cursor_state.hot.x = cursor.hot.y = 0; + if (par->cursor_state.hot.x || par->cursor_state.hot.y || + par->cursor_reset) { + par->cursor_state.hot.x = cursor.hot.y = 0; cursor.set |= FB_CUR_SETHOT; } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != ops->p->cursor_shape || - ops->cursor_state.mask == NULL || - ops->cursor_reset) { + vc->vc_cursor_type != par->p->cursor_shape || + par->cursor_state.mask == NULL || + par->cursor_reset) { char *tmp, *mask = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC); int cur_height, size, i = 0; @@ -309,13 +309,13 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, return; } - kfree(ops->cursor_state.mask); - ops->cursor_state.mask = mask; + kfree(par->cursor_state.mask); + par->cursor_state.mask = mask; - ops->p->cursor_shape = vc->vc_cursor_type; + par->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (CUR_SIZE(ops->p->cursor_shape)) { + switch (CUR_SIZE(par->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; @@ -348,19 +348,19 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, kfree(tmp); } - ops->cursor_state.enable = enable && !use_sw; + par->cursor_state.enable = enable && !use_sw; cursor.image.data = src; - cursor.image.fg_color = ops->cursor_state.image.fg_color; - cursor.image.bg_color = ops->cursor_state.image.bg_color; - cursor.image.dx = ops->cursor_state.image.dx; - cursor.image.dy = ops->cursor_state.image.dy; - cursor.image.height = ops->cursor_state.image.height; - cursor.image.width = ops->cursor_state.image.width; - cursor.hot.x = ops->cursor_state.hot.x; - cursor.hot.y = ops->cursor_state.hot.y; - cursor.mask = ops->cursor_state.mask; - cursor.enable = ops->cursor_state.enable; + cursor.image.fg_color = par->cursor_state.image.fg_color; + cursor.image.bg_color = par->cursor_state.image.bg_color; + cursor.image.dx = par->cursor_state.image.dx; + cursor.image.dy = par->cursor_state.image.dy; + cursor.image.height = par->cursor_state.image.height; + cursor.image.width = par->cursor_state.image.width; + cursor.hot.x = par->cursor_state.hot.x; + cursor.hot.y = par->cursor_state.hot.y; + cursor.mask = par->cursor_state.mask; + cursor.enable = par->cursor_state.enable; cursor.image.depth = 1; cursor.rop = ROP_XOR; @@ -370,32 +370,32 @@ static void ccw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, if (err) soft_cursor(info, &cursor); - ops->cursor_reset = 0; + par->cursor_reset = 0; } static int ccw_update_start(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u32 yoffset; - u32 vyres = GETVYRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); int err; - yoffset = (vyres - info->var.yres) - ops->var.xoffset; - ops->var.xoffset = ops->var.yoffset; - ops->var.yoffset = yoffset; - err = fb_pan_display(info, &ops->var); - ops->var.xoffset = info->var.xoffset; - ops->var.yoffset = info->var.yoffset; - ops->var.vmode = info->var.vmode; + yoffset = (vyres - info->var.yres) - par->var.xoffset; + par->var.xoffset = par->var.yoffset; + par->var.yoffset = yoffset; + err = fb_pan_display(info, &par->var); + par->var.xoffset = info->var.xoffset; + par->var.yoffset = info->var.yoffset; + par->var.vmode = info->var.vmode; return err; } -void fbcon_rotate_ccw(struct fbcon_ops *ops) +void fbcon_rotate_ccw(struct fbcon_par *par) { - ops->bmove = ccw_bmove; - ops->clear = ccw_clear; - ops->putcs = ccw_putcs; - ops->clear_margins = ccw_clear_margins; - ops->cursor = ccw_cursor; - ops->update_start = ccw_update_start; + par->bmove = ccw_bmove; + par->clear = ccw_clear; + par->putcs = ccw_putcs; + par->clear_margins = ccw_clear_margins; + par->cursor = ccw_cursor; + par->update_start = ccw_update_start; } diff --git a/drivers/video/fbdev/core/fbcon_cw.c b/drivers/video/fbdev/core/fbcon_cw.c index b9dac7940fb7..4bd22d5ee5f4 100644 --- a/drivers/video/fbdev/core/fbcon_cw.c +++ b/drivers/video/fbdev/core/fbcon_cw.c @@ -48,9 +48,9 @@ static void cw_update_attr(u8 *dst, u8 *src, int attribute, static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_copyarea area; - u32 vxres = GETVXRES(ops->p, info); + u32 vxres = GETVXRES(par->p, info); area.sx = vxres - ((sy + height) * vc->vc_font.height); area.sy = sx * vc->vc_font.width; @@ -65,9 +65,9 @@ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy, static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width, int fg, int bg) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_fillrect region; - u32 vxres = GETVXRES(ops->p, info); + u32 vxres = GETVXRES(par->p, info); region.color = bg; region.dx = vxres - ((sy + height) * vc->vc_font.height); @@ -84,13 +84,13 @@ static inline void cw_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 d_pitch, u32 s_pitch, u32 cellsize, struct fb_image *image, u8 *buf, u8 *dst) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; u32 idx = (vc->vc_font.height + 7) >> 3; u8 *src; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize; + src = par->fontbuffer + (scr_readw(s++) & charmask) * cellsize; if (attr) { cw_update_attr(buf, src, attr, vc); @@ -115,7 +115,7 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, int fg, int bg) { struct fb_image image; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u32 width = (vc->vc_font.height + 7)/8; u32 cellsize = width * vc->vc_font.width; u32 maxcnt = info->pixmap.size/cellsize; @@ -124,9 +124,9 @@ static void cw_putcs(struct vc_data *vc, struct fb_info *info, u32 cnt, pitch, size; u32 attribute = get_attribute(info, scr_readw(s)); u8 *dst, *buf = NULL; - u32 vxres = GETVXRES(ops->p, info); + u32 vxres = GETVXRES(par->p, info); - if (!ops->fontbuffer) + if (!par->fontbuffer) return; image.fg_color = fg; @@ -204,28 +204,28 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.height + 7) >> 3, c; - int y = real_y(ops->p, vc->state.y); + int y = real_y(par->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; - u32 vxres = GETVXRES(ops->p, info); + u32 vxres = GETVXRES(par->p, info); - if (!ops->fontbuffer) + if (!par->fontbuffer) return; cursor.set = 0; c = scr_readw((u16 *) vc->vc_pos); attribute = get_attribute(info, c); - src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); + src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width)); - if (ops->cursor_state.image.data != src || - ops->cursor_reset) { - ops->cursor_state.image.data = src; - cursor.set |= FB_CUR_SETIMAGE; + if (par->cursor_state.image.data != src || + par->cursor_reset) { + par->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; } if (attribute) { @@ -234,49 +234,49 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC); if (!dst) return; - kfree(ops->cursor_data); - ops->cursor_data = dst; + kfree(par->cursor_data); + par->cursor_data = dst; cw_update_attr(dst, src, attribute, vc); src = dst; } - if (ops->cursor_state.image.fg_color != fg || - ops->cursor_state.image.bg_color != bg || - ops->cursor_reset) { - ops->cursor_state.image.fg_color = fg; - ops->cursor_state.image.bg_color = bg; + if (par->cursor_state.image.fg_color != fg || + par->cursor_state.image.bg_color != bg || + par->cursor_reset) { + par->cursor_state.image.fg_color = fg; + par->cursor_state.image.bg_color = bg; cursor.set |= FB_CUR_SETCMAP; } - if (ops->cursor_state.image.height != vc->vc_font.width || - ops->cursor_state.image.width != vc->vc_font.height || - ops->cursor_reset) { - ops->cursor_state.image.height = vc->vc_font.width; - ops->cursor_state.image.width = vc->vc_font.height; + if (par->cursor_state.image.height != vc->vc_font.width || + par->cursor_state.image.width != vc->vc_font.height || + par->cursor_reset) { + par->cursor_state.image.height = vc->vc_font.width; + par->cursor_state.image.width = vc->vc_font.height; cursor.set |= FB_CUR_SETSIZE; } dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height); dy = vc->state.x * vc->vc_font.width; - if (ops->cursor_state.image.dx != dx || - ops->cursor_state.image.dy != dy || - ops->cursor_reset) { - ops->cursor_state.image.dx = dx; - ops->cursor_state.image.dy = dy; + if (par->cursor_state.image.dx != dx || + par->cursor_state.image.dy != dy || + par->cursor_reset) { + par->cursor_state.image.dx = dx; + par->cursor_state.image.dy = dy; cursor.set |= FB_CUR_SETPOS; } - if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || - ops->cursor_reset) { - ops->cursor_state.hot.x = cursor.hot.y = 0; + if (par->cursor_state.hot.x || par->cursor_state.hot.y || + par->cursor_reset) { + par->cursor_state.hot.x = cursor.hot.y = 0; cursor.set |= FB_CUR_SETHOT; } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != ops->p->cursor_shape || - ops->cursor_state.mask == NULL || - ops->cursor_reset) { + vc->vc_cursor_type != par->p->cursor_shape || + par->cursor_state.mask == NULL || + par->cursor_reset) { char *tmp, *mask = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC); int cur_height, size, i = 0; @@ -292,13 +292,13 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, return; } - kfree(ops->cursor_state.mask); - ops->cursor_state.mask = mask; + kfree(par->cursor_state.mask); + par->cursor_state.mask = mask; - ops->p->cursor_shape = vc->vc_cursor_type; + par->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (CUR_SIZE(ops->p->cursor_shape)) { + switch (CUR_SIZE(par->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; @@ -331,19 +331,19 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, kfree(tmp); } - ops->cursor_state.enable = enable && !use_sw; + par->cursor_state.enable = enable && !use_sw; cursor.image.data = src; - cursor.image.fg_color = ops->cursor_state.image.fg_color; - cursor.image.bg_color = ops->cursor_state.image.bg_color; - cursor.image.dx = ops->cursor_state.image.dx; - cursor.image.dy = ops->cursor_state.image.dy; - cursor.image.height = ops->cursor_state.image.height; - cursor.image.width = ops->cursor_state.image.width; - cursor.hot.x = ops->cursor_state.hot.x; - cursor.hot.y = ops->cursor_state.hot.y; - cursor.mask = ops->cursor_state.mask; - cursor.enable = ops->cursor_state.enable; + cursor.image.fg_color = par->cursor_state.image.fg_color; + cursor.image.bg_color = par->cursor_state.image.bg_color; + cursor.image.dx = par->cursor_state.image.dx; + cursor.image.dy = par->cursor_state.image.dy; + cursor.image.height = par->cursor_state.image.height; + cursor.image.width = par->cursor_state.image.width; + cursor.hot.x = par->cursor_state.hot.x; + cursor.hot.y = par->cursor_state.hot.y; + cursor.mask = par->cursor_state.mask; + cursor.enable = par->cursor_state.enable; cursor.image.depth = 1; cursor.rop = ROP_XOR; @@ -353,32 +353,32 @@ static void cw_cursor(struct vc_data *vc, struct fb_info *info, bool enable, if (err) soft_cursor(info, &cursor); - ops->cursor_reset = 0; + par->cursor_reset = 0; } static int cw_update_start(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; - u32 vxres = GETVXRES(ops->p, info); + struct fbcon_par *par = info->fbcon_par; + u32 vxres = GETVXRES(par->p, info); u32 xoffset; int err; - xoffset = vxres - (info->var.xres + ops->var.yoffset); - ops->var.yoffset = ops->var.xoffset; - ops->var.xoffset = xoffset; - err = fb_pan_display(info, &ops->var); - ops->var.xoffset = info->var.xoffset; - ops->var.yoffset = info->var.yoffset; - ops->var.vmode = info->var.vmode; + xoffset = vxres - (info->var.xres + par->var.yoffset); + par->var.yoffset = par->var.xoffset; + par->var.xoffset = xoffset; + err = fb_pan_display(info, &par->var); + par->var.xoffset = info->var.xoffset; + par->var.yoffset = info->var.yoffset; + par->var.vmode = info->var.vmode; return err; } -void fbcon_rotate_cw(struct fbcon_ops *ops) +void fbcon_rotate_cw(struct fbcon_par *par) { - ops->bmove = cw_bmove; - ops->clear = cw_clear; - ops->putcs = cw_putcs; - ops->clear_margins = cw_clear_margins; - ops->cursor = cw_cursor; - ops->update_start = cw_update_start; + par->bmove = cw_bmove; + par->clear = cw_clear; + par->putcs = cw_putcs; + par->clear_margins = cw_clear_margins; + par->cursor = cw_cursor; + par->update_start = cw_update_start; } diff --git a/drivers/video/fbdev/core/fbcon_rotate.c b/drivers/video/fbdev/core/fbcon_rotate.c index ec3c883400f7..a3f507825eed 100644 --- a/drivers/video/fbdev/core/fbcon_rotate.c +++ b/drivers/video/fbdev/core/fbcon_rotate.c @@ -20,32 +20,36 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int len, err = 0; int s_cellsize, d_cellsize, i; const u8 *src; u8 *dst; - if (vc->vc_font.data == ops->fontdata && - ops->p->con_rotate == ops->cur_rotate) + if (vc->vc_font.data == par->fontdata && + par->p->con_rotate == par->cur_rotate) goto finished; - src = ops->fontdata = vc->vc_font.data; - ops->cur_rotate = ops->p->con_rotate; + src = par->fontdata = vc->vc_font.data; + par->cur_rotate = par->p->con_rotate; len = vc->vc_font.charcount; s_cellsize = ((vc->vc_font.width + 7)/8) * vc->vc_font.height; d_cellsize = s_cellsize; - if (ops->rotate == FB_ROTATE_CW || - ops->rotate == FB_ROTATE_CCW) + if (par->rotate == FB_ROTATE_CW || + par->rotate == FB_ROTATE_CCW) d_cellsize = ((vc->vc_font.height + 7)/8) * vc->vc_font.width; if (info->fbops->fb_sync) info->fbops->fb_sync(info); - if (ops->fd_size < d_cellsize * len) { + if (par->fd_size < d_cellsize * len) { + kfree(par->fontbuffer); + par->fontbuffer = NULL; + par->fd_size = 0; + dst = kmalloc_array(len, d_cellsize, GFP_KERNEL); if (dst == NULL) { @@ -53,15 +57,14 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) goto finished; } - ops->fd_size = d_cellsize * len; - kfree(ops->fontbuffer); - ops->fontbuffer = dst; + par->fd_size = d_cellsize * len; + par->fontbuffer = dst; } - dst = ops->fontbuffer; - memset(dst, 0, ops->fd_size); + dst = par->fontbuffer; + memset(dst, 0, par->fd_size); - switch (ops->rotate) { + switch (par->rotate) { case FB_ROTATE_UD: for (i = len; i--; ) { rotate_ud(src, dst, vc->vc_font.width, @@ -93,19 +96,19 @@ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc) return err; } -void fbcon_set_rotate(struct fbcon_ops *ops) +void fbcon_set_rotate(struct fbcon_par *par) { - ops->rotate_font = fbcon_rotate_font; + par->rotate_font = fbcon_rotate_font; - switch(ops->rotate) { + switch (par->rotate) { case FB_ROTATE_CW: - fbcon_rotate_cw(ops); + fbcon_rotate_cw(par); break; case FB_ROTATE_UD: - fbcon_rotate_ud(ops); + fbcon_rotate_ud(par); break; case FB_ROTATE_CCW: - fbcon_rotate_ccw(ops); + fbcon_rotate_ccw(par); break; } } diff --git a/drivers/video/fbdev/core/fbcon_rotate.h b/drivers/video/fbdev/core/fbcon_rotate.h index 01cbe303b8a2..48305e1a0763 100644 --- a/drivers/video/fbdev/core/fbcon_rotate.h +++ b/drivers/video/fbdev/core/fbcon_rotate.h @@ -90,7 +90,7 @@ static inline void rotate_ccw(const char *in, char *out, u32 width, u32 height) } } -extern void fbcon_rotate_cw(struct fbcon_ops *ops); -extern void fbcon_rotate_ud(struct fbcon_ops *ops); -extern void fbcon_rotate_ccw(struct fbcon_ops *ops); +extern void fbcon_rotate_cw(struct fbcon_par *par); +extern void fbcon_rotate_ud(struct fbcon_par *par); +extern void fbcon_rotate_ccw(struct fbcon_par *par); #endif diff --git a/drivers/video/fbdev/core/fbcon_ud.c b/drivers/video/fbdev/core/fbcon_ud.c index 0af7913a2abd..14b40e2bf323 100644 --- a/drivers/video/fbdev/core/fbcon_ud.c +++ b/drivers/video/fbdev/core/fbcon_ud.c @@ -48,10 +48,10 @@ static void ud_update_attr(u8 *dst, u8 *src, int attribute, static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_copyarea area; - u32 vyres = GETVYRES(ops->p, info); - u32 vxres = GETVXRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); + u32 vxres = GETVXRES(par->p, info); area.sy = vyres - ((sy + height) * vc->vc_font.height); area.sx = vxres - ((sx + width) * vc->vc_font.width); @@ -66,10 +66,10 @@ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy, static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy, int sx, int height, int width, int fg, int bg) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; struct fb_fillrect region; - u32 vyres = GETVYRES(ops->p, info); - u32 vxres = GETVXRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); + u32 vxres = GETVXRES(par->p, info); region.color = bg; region.dy = vyres - ((sy + height) * vc->vc_font.height); @@ -86,13 +86,13 @@ static inline void ud_putcs_aligned(struct vc_data *vc, struct fb_info *info, u32 d_pitch, u32 s_pitch, u32 cellsize, struct fb_image *image, u8 *buf, u8 *dst) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; u32 idx = vc->vc_font.width >> 3; u8 *src; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize; if (attr) { ud_update_attr(buf, src, attr, vc); @@ -119,7 +119,7 @@ static inline void ud_putcs_unaligned(struct vc_data *vc, struct fb_image *image, u8 *buf, u8 *dst) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; u32 shift_low = 0, mod = vc->vc_font.width % 8; u32 shift_high = 8; @@ -127,7 +127,7 @@ static inline void ud_putcs_unaligned(struct vc_data *vc, u8 *src; while (cnt--) { - src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize; + src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize; if (attr) { ud_update_attr(buf, src, attr, vc); @@ -152,7 +152,7 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, int fg, int bg) { struct fb_image image; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; u32 width = (vc->vc_font.width + 7)/8; u32 cellsize = width * vc->vc_font.height; u32 maxcnt = info->pixmap.size/cellsize; @@ -161,10 +161,10 @@ static void ud_putcs(struct vc_data *vc, struct fb_info *info, u32 mod = vc->vc_font.width % 8, cnt, pitch, size; u32 attribute = get_attribute(info, scr_readw(s)); u8 *dst, *buf = NULL; - u32 vyres = GETVYRES(ops->p, info); - u32 vxres = GETVXRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); + u32 vxres = GETVXRES(par->p, info); - if (!ops->fontbuffer) + if (!par->fontbuffer) return; image.fg_color = fg; @@ -251,29 +251,29 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, int fg, int bg) { struct fb_cursor cursor; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; int w = (vc->vc_font.width + 7) >> 3, c; - int y = real_y(ops->p, vc->state.y); + int y = real_y(par->p, vc->state.y); int attribute, use_sw = vc->vc_cursor_type & CUR_SW; int err = 1, dx, dy; char *src; - u32 vyres = GETVYRES(ops->p, info); - u32 vxres = GETVXRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); + u32 vxres = GETVXRES(par->p, info); - if (!ops->fontbuffer) + if (!par->fontbuffer) return; cursor.set = 0; c = scr_readw((u16 *) vc->vc_pos); attribute = get_attribute(info, c); - src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); + src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.height)); - if (ops->cursor_state.image.data != src || - ops->cursor_reset) { - ops->cursor_state.image.data = src; - cursor.set |= FB_CUR_SETIMAGE; + if (par->cursor_state.image.data != src || + par->cursor_reset) { + par->cursor_state.image.data = src; + cursor.set |= FB_CUR_SETIMAGE; } if (attribute) { @@ -282,49 +282,49 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); if (!dst) return; - kfree(ops->cursor_data); - ops->cursor_data = dst; + kfree(par->cursor_data); + par->cursor_data = dst; ud_update_attr(dst, src, attribute, vc); src = dst; } - if (ops->cursor_state.image.fg_color != fg || - ops->cursor_state.image.bg_color != bg || - ops->cursor_reset) { - ops->cursor_state.image.fg_color = fg; - ops->cursor_state.image.bg_color = bg; + if (par->cursor_state.image.fg_color != fg || + par->cursor_state.image.bg_color != bg || + par->cursor_reset) { + par->cursor_state.image.fg_color = fg; + par->cursor_state.image.bg_color = bg; cursor.set |= FB_CUR_SETCMAP; } - if (ops->cursor_state.image.height != vc->vc_font.height || - ops->cursor_state.image.width != vc->vc_font.width || - ops->cursor_reset) { - ops->cursor_state.image.height = vc->vc_font.height; - ops->cursor_state.image.width = vc->vc_font.width; + if (par->cursor_state.image.height != vc->vc_font.height || + par->cursor_state.image.width != vc->vc_font.width || + par->cursor_reset) { + par->cursor_state.image.height = vc->vc_font.height; + par->cursor_state.image.width = vc->vc_font.width; cursor.set |= FB_CUR_SETSIZE; } dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height); dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width); - if (ops->cursor_state.image.dx != dx || - ops->cursor_state.image.dy != dy || - ops->cursor_reset) { - ops->cursor_state.image.dx = dx; - ops->cursor_state.image.dy = dy; + if (par->cursor_state.image.dx != dx || + par->cursor_state.image.dy != dy || + par->cursor_reset) { + par->cursor_state.image.dx = dx; + par->cursor_state.image.dy = dy; cursor.set |= FB_CUR_SETPOS; } - if (ops->cursor_state.hot.x || ops->cursor_state.hot.y || - ops->cursor_reset) { - ops->cursor_state.hot.x = cursor.hot.y = 0; + if (par->cursor_state.hot.x || par->cursor_state.hot.y || + par->cursor_reset) { + par->cursor_state.hot.x = cursor.hot.y = 0; cursor.set |= FB_CUR_SETHOT; } if (cursor.set & FB_CUR_SETSIZE || - vc->vc_cursor_type != ops->p->cursor_shape || - ops->cursor_state.mask == NULL || - ops->cursor_reset) { + vc->vc_cursor_type != par->p->cursor_shape || + par->cursor_state.mask == NULL || + par->cursor_reset) { char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC); int cur_height, size, i = 0; u8 msk = 0xff; @@ -332,13 +332,13 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, if (!mask) return; - kfree(ops->cursor_state.mask); - ops->cursor_state.mask = mask; + kfree(par->cursor_state.mask); + par->cursor_state.mask = mask; - ops->p->cursor_shape = vc->vc_cursor_type; + par->p->cursor_shape = vc->vc_cursor_type; cursor.set |= FB_CUR_SETSHAPE; - switch (CUR_SIZE(ops->p->cursor_shape)) { + switch (CUR_SIZE(par->p->cursor_shape)) { case CUR_NONE: cur_height = 0; break; @@ -371,19 +371,19 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, mask[i++] = ~msk; } - ops->cursor_state.enable = enable && !use_sw; + par->cursor_state.enable = enable && !use_sw; cursor.image.data = src; - cursor.image.fg_color = ops->cursor_state.image.fg_color; - cursor.image.bg_color = ops->cursor_state.image.bg_color; - cursor.image.dx = ops->cursor_state.image.dx; - cursor.image.dy = ops->cursor_state.image.dy; - cursor.image.height = ops->cursor_state.image.height; - cursor.image.width = ops->cursor_state.image.width; - cursor.hot.x = ops->cursor_state.hot.x; - cursor.hot.y = ops->cursor_state.hot.y; - cursor.mask = ops->cursor_state.mask; - cursor.enable = ops->cursor_state.enable; + cursor.image.fg_color = par->cursor_state.image.fg_color; + cursor.image.bg_color = par->cursor_state.image.bg_color; + cursor.image.dx = par->cursor_state.image.dx; + cursor.image.dy = par->cursor_state.image.dy; + cursor.image.height = par->cursor_state.image.height; + cursor.image.width = par->cursor_state.image.width; + cursor.hot.x = par->cursor_state.hot.x; + cursor.hot.y = par->cursor_state.hot.y; + cursor.mask = par->cursor_state.mask; + cursor.enable = par->cursor_state.enable; cursor.image.depth = 1; cursor.rop = ROP_XOR; @@ -393,36 +393,36 @@ static void ud_cursor(struct vc_data *vc, struct fb_info *info, bool enable, if (err) soft_cursor(info, &cursor); - ops->cursor_reset = 0; + par->cursor_reset = 0; } static int ud_update_start(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int xoffset, yoffset; - u32 vyres = GETVYRES(ops->p, info); - u32 vxres = GETVXRES(ops->p, info); + u32 vyres = GETVYRES(par->p, info); + u32 vxres = GETVXRES(par->p, info); int err; - xoffset = vxres - info->var.xres - ops->var.xoffset; - yoffset = vyres - info->var.yres - ops->var.yoffset; + xoffset = vxres - info->var.xres - par->var.xoffset; + yoffset = vyres - info->var.yres - par->var.yoffset; if (yoffset < 0) yoffset += vyres; - ops->var.xoffset = xoffset; - ops->var.yoffset = yoffset; - err = fb_pan_display(info, &ops->var); - ops->var.xoffset = info->var.xoffset; - ops->var.yoffset = info->var.yoffset; - ops->var.vmode = info->var.vmode; + par->var.xoffset = xoffset; + par->var.yoffset = yoffset; + err = fb_pan_display(info, &par->var); + par->var.xoffset = info->var.xoffset; + par->var.yoffset = info->var.yoffset; + par->var.vmode = info->var.vmode; return err; } -void fbcon_rotate_ud(struct fbcon_ops *ops) +void fbcon_rotate_ud(struct fbcon_par *par) { - ops->bmove = ud_bmove; - ops->clear = ud_clear; - ops->putcs = ud_putcs; - ops->clear_margins = ud_clear_margins; - ops->cursor = ud_cursor; - ops->update_start = ud_update_start; + par->bmove = ud_bmove; + par->clear = ud_clear; + par->putcs = ud_putcs; + par->clear_margins = ud_clear_margins; + par->cursor = ud_cursor; + par->update_start = ud_update_start; } diff --git a/drivers/video/fbdev/core/softcursor.c b/drivers/video/fbdev/core/softcursor.c index 29e5b21cf373..900788c05915 100644 --- a/drivers/video/fbdev/core/softcursor.c +++ b/drivers/video/fbdev/core/softcursor.c @@ -21,7 +21,7 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; unsigned int scan_align = info->pixmap.scan_align - 1; unsigned int buf_align = info->pixmap.buf_align - 1; unsigned int i, size, dsize, s_pitch, d_pitch; @@ -34,19 +34,19 @@ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) s_pitch = (cursor->image.width + 7) >> 3; dsize = s_pitch * cursor->image.height; - if (dsize + sizeof(struct fb_image) != ops->cursor_size) { - kfree(ops->cursor_src); - ops->cursor_size = dsize + sizeof(struct fb_image); + if (dsize + sizeof(struct fb_image) != par->cursor_size) { + kfree(par->cursor_src); + par->cursor_size = dsize + sizeof(struct fb_image); - ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC); - if (!ops->cursor_src) { - ops->cursor_size = 0; + par->cursor_src = kmalloc(par->cursor_size, GFP_ATOMIC); + if (!par->cursor_src) { + par->cursor_size = 0; return -ENOMEM; } } - src = ops->cursor_src + sizeof(struct fb_image); - image = (struct fb_image *)ops->cursor_src; + src = par->cursor_src + sizeof(struct fb_image); + image = (struct fb_image *)par->cursor_src; *image = cursor->image; d_pitch = (s_pitch + scan_align) & ~scan_align; diff --git a/drivers/video/fbdev/core/tileblit.c b/drivers/video/fbdev/core/tileblit.c index d342b90c42b7..4428f2bcd3f8 100644 --- a/drivers/video/fbdev/core/tileblit.c +++ b/drivers/video/fbdev/core/tileblit.c @@ -151,34 +151,34 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, bool enable, static int tile_update_start(struct fb_info *info) { - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; int err; - err = fb_pan_display(info, &ops->var); - ops->var.xoffset = info->var.xoffset; - ops->var.yoffset = info->var.yoffset; - ops->var.vmode = info->var.vmode; + err = fb_pan_display(info, &par->var); + par->var.xoffset = info->var.xoffset; + par->var.yoffset = info->var.yoffset; + par->var.vmode = info->var.vmode; return err; } void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info) { struct fb_tilemap map; - struct fbcon_ops *ops = info->fbcon_par; + struct fbcon_par *par = info->fbcon_par; - ops->bmove = tile_bmove; - ops->clear = tile_clear; - ops->putcs = tile_putcs; - ops->clear_margins = tile_clear_margins; - ops->cursor = tile_cursor; - ops->update_start = tile_update_start; + par->bmove = tile_bmove; + par->clear = tile_clear; + par->putcs = tile_putcs; + par->clear_margins = tile_clear_margins; + par->cursor = tile_cursor; + par->update_start = tile_update_start; - if (ops->p) { + if (par->p) { map.width = vc->vc_font.width; map.height = vc->vc_font.height; map.depth = 1; map.length = vc->vc_font.charcount; - map.data = ops->p->fontdata; + map.data = par->p->fontdata; info->tileops->fb_settile(info, &map); } } diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index bfe253c2849a..c0691e93e0a5 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -3025,7 +3025,7 @@ static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info, return -ENOMEM; space_args.total_spaces = 0; - dest = kmalloc(alloc_size, GFP_KERNEL); + dest = kzalloc(alloc_size, GFP_KERNEL); if (!dest) return -ENOMEM; dest_orig = dest; @@ -3081,7 +3081,8 @@ static long btrfs_ioctl_space_info(struct btrfs_fs_info *fs_info, user_dest = (struct btrfs_ioctl_space_info __user *) (arg + sizeof(struct btrfs_ioctl_space_args)); - if (copy_to_user(user_dest, dest_orig, alloc_size)) + if (copy_to_user(user_dest, dest_orig, + space_args.total_spaces * sizeof(*dest_orig))) ret = -EFAULT; kfree(dest_orig); diff --git a/fs/btrfs/space-info.c b/fs/btrfs/space-info.c index a815308e2db9..b3ff2e1da89b 100644 --- a/fs/btrfs/space-info.c +++ b/fs/btrfs/space-info.c @@ -275,11 +275,9 @@ static int create_space_info_sub_group(struct btrfs_space_info *parent, u64 flag sub_group->parent = parent; sub_group->subgroup_id = id; - ret = btrfs_sysfs_add_space_info_type(fs_info, sub_group); - if (ret) { - kfree(sub_group); + ret = btrfs_sysfs_add_space_info_type(sub_group); + if (ret) parent->sub_group[index] = NULL; - } return ret; } @@ -309,7 +307,7 @@ static int create_space_info(struct btrfs_fs_info *info, u64 flags) goto out_free; } - ret = btrfs_sysfs_add_space_info_type(info, space_info); + ret = btrfs_sysfs_add_space_info_type(space_info); if (ret) return ret; diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 81f52c1f55ce..d66681ce2b3d 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -1981,13 +1981,12 @@ static const char *alloc_name(struct btrfs_space_info *space_info) * Create a sysfs entry for a space info type at path * /sys/fs/btrfs/UUID/allocation/TYPE */ -int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, - struct btrfs_space_info *space_info) +int btrfs_sysfs_add_space_info_type(struct btrfs_space_info *space_info) { int ret; ret = kobject_init_and_add(&space_info->kobj, &space_info_ktype, - fs_info->space_info_kobj, "%s", + space_info->fs_info->space_info_kobj, "%s", alloc_name(space_info)); if (ret) { kobject_put(&space_info->kobj); diff --git a/fs/btrfs/sysfs.h b/fs/btrfs/sysfs.h index 0f94ae923210..05498e5346c3 100644 --- a/fs/btrfs/sysfs.h +++ b/fs/btrfs/sysfs.h @@ -37,8 +37,7 @@ void __cold btrfs_exit_sysfs(void); int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info); void btrfs_sysfs_remove_mounted(struct btrfs_fs_info *fs_info); void btrfs_sysfs_add_block_group_type(struct btrfs_block_group *cache); -int btrfs_sysfs_add_space_info_type(struct btrfs_fs_info *fs_info, - struct btrfs_space_info *space_info); +int btrfs_sysfs_add_space_info_type(struct btrfs_space_info *space_info); void btrfs_sysfs_remove_space_info(struct btrfs_space_info *space_info); void btrfs_sysfs_update_devid(struct btrfs_device *device); diff --git a/include/linux/damon.h b/include/linux/damon.h index 6fe6f7fcf83d..d90238195090 100644 --- a/include/linux/damon.h +++ b/include/linux/damon.h @@ -949,6 +949,7 @@ bool damon_initialized(void); int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive); int damon_stop(struct damon_ctx **ctxs, int nr_ctxs); bool damon_is_running(struct damon_ctx *ctx); +int damon_kdamond_pid(struct damon_ctx *ctx); int damon_call(struct damon_ctx *ctx, struct damon_call_control *control); int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control); diff --git a/include/linux/fprobe.h b/include/linux/fprobe.h index 7964db96e41a..0a3bcd1718f3 100644 --- a/include/linux/fprobe.h +++ b/include/linux/fprobe.h @@ -7,6 +7,7 @@ #include #include #include +#include #include struct fprobe; @@ -26,7 +27,7 @@ typedef void (*fprobe_exit_cb)(struct fprobe *fp, unsigned long entry_ip, * @fp: The fprobe which owns this. */ struct fprobe_hlist_node { - struct hlist_node hlist; + struct rhlist_head hlist; unsigned long addr; struct fprobe *fp; }; diff --git a/include/linux/sched/ext.h b/include/linux/sched/ext.h index d82b7a9b0658..9848aeab2786 100644 --- a/include/linux/sched/ext.h +++ b/include/linux/sched/ext.h @@ -228,6 +228,7 @@ struct scx_task_group { u64 bw_period_us; u64 bw_quota_us; u64 bw_burst_us; + bool idle; #endif }; diff --git a/io_uring/zcrx.c b/io_uring/zcrx.c index d17ff07779de..b768f43f0fd1 100644 --- a/io_uring/zcrx.c +++ b/io_uring/zcrx.c @@ -696,9 +696,10 @@ static void io_zcrx_return_niov_freelist(struct net_iov *niov) { struct io_zcrx_area *area = io_zcrx_iov_to_area(niov); - spin_lock_bh(&area->freelist_lock); + guard(spinlock_bh)(&area->freelist_lock); + if (WARN_ON_ONCE(area->free_count >= area->nia.num_niovs)) + return; area->freelist[area->free_count++] = net_iov_idx(niov); - spin_unlock_bh(&area->freelist_lock); } static void io_zcrx_return_niov(struct net_iov *niov) @@ -829,7 +830,8 @@ static void io_zcrx_refill_slow(struct page_pool *pp, struct io_zcrx_ifq *ifq) { struct io_zcrx_area *area = ifq->area; - spin_lock_bh(&area->freelist_lock); + guard(spinlock_bh)(&area->freelist_lock); + while (area->free_count && pp->alloc.count < PP_ALLOC_CACHE_REFILL) { struct net_iov *niov = __io_zcrx_get_free_niov(area); netmem_ref netmem = net_iov_to_netmem(niov); @@ -838,7 +840,6 @@ static void io_zcrx_refill_slow(struct page_pool *pp, struct io_zcrx_ifq *ifq) io_zcrx_sync_for_device(pp, niov); net_mp_netmem_place_in_cache(pp, netmem); } - spin_unlock_bh(&area->freelist_lock); } static netmem_ref io_pp_zc_alloc_netmems(struct page_pool *pp, gfp_t gfp) @@ -975,10 +976,10 @@ static struct net_iov *io_alloc_fallback_niov(struct io_zcrx_ifq *ifq) if (area->mem.is_dmabuf) return NULL; - spin_lock_bh(&area->freelist_lock); - if (area->free_count) - niov = __io_zcrx_get_free_niov(area); - spin_unlock_bh(&area->freelist_lock); + scoped_guard(spinlock_bh, &area->freelist_lock) { + if (area->free_count) + niov = __io_zcrx_get_free_niov(area); + } if (niov) page_pool_fragment_netmem(net_iov_to_netmem(niov), 1); diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c index ee031ba877d9..177bbf31116d 100644 --- a/kernel/sched/ext.c +++ b/kernel/sched/ext.c @@ -3118,6 +3118,7 @@ void scx_tg_init(struct task_group *tg) tg->scx.weight = CGROUP_WEIGHT_DFL; tg->scx.bw_period_us = default_bw_period_us(); tg->scx.bw_quota_us = RUNTIME_INF; + tg->scx.idle = false; } int scx_tg_online(struct task_group *tg) @@ -3250,9 +3251,10 @@ void scx_cgroup_cancel_attach(struct cgroup_taskset *tset) void scx_group_set_weight(struct task_group *tg, unsigned long weight) { - struct scx_sched *sch = scx_root; + struct scx_sched *sch; percpu_down_read(&scx_cgroup_ops_rwsem); + sch = scx_root; if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_weight) && tg->scx.weight != weight) @@ -3266,15 +3268,28 @@ void scx_group_set_weight(struct task_group *tg, unsigned long weight) void scx_group_set_idle(struct task_group *tg, bool idle) { - /* TODO: Implement ops->cgroup_set_idle() */ + struct scx_sched *sch; + + percpu_down_read(&scx_cgroup_ops_rwsem); + sch = scx_root; + + if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_idle)) + SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_idle, NULL, + tg_cgrp(tg), idle); + + /* Update the task group's idle state */ + tg->scx.idle = idle; + + percpu_up_read(&scx_cgroup_ops_rwsem); } void scx_group_set_bandwidth(struct task_group *tg, u64 period_us, u64 quota_us, u64 burst_us) { - struct scx_sched *sch = scx_root; + struct scx_sched *sch; percpu_down_read(&scx_cgroup_ops_rwsem); + sch = scx_root; if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_bandwidth) && (tg->scx.bw_period_us != period_us || @@ -5126,6 +5141,7 @@ static void sched_ext_ops__cgroup_move(struct task_struct *p, struct cgroup *fro static void sched_ext_ops__cgroup_cancel_move(struct task_struct *p, struct cgroup *from, struct cgroup *to) {} static void sched_ext_ops__cgroup_set_weight(struct cgroup *cgrp, u32 weight) {} static void sched_ext_ops__cgroup_set_bandwidth(struct cgroup *cgrp, u64 period_us, u64 quota_us, u64 burst_us) {} +static void sched_ext_ops__cgroup_set_idle(struct cgroup *cgrp, bool idle) {} #endif static void sched_ext_ops__cpu_online(s32 cpu) {} static void sched_ext_ops__cpu_offline(s32 cpu) {} @@ -5164,6 +5180,7 @@ static struct sched_ext_ops __bpf_ops_sched_ext_ops = { .cgroup_cancel_move = sched_ext_ops__cgroup_cancel_move, .cgroup_set_weight = sched_ext_ops__cgroup_set_weight, .cgroup_set_bandwidth = sched_ext_ops__cgroup_set_bandwidth, + .cgroup_set_idle = sched_ext_ops__cgroup_set_idle, #endif .cpu_online = sched_ext_ops__cpu_online, .cpu_offline = sched_ext_ops__cpu_offline, diff --git a/kernel/sched/ext_internal.h b/kernel/sched/ext_internal.h index 8039a750490f..5b2dd105fa92 100644 --- a/kernel/sched/ext_internal.h +++ b/kernel/sched/ext_internal.h @@ -697,12 +697,23 @@ struct sched_ext_ops { * 2_500_000. @cgrp is entitled to 2.5 CPUs. @burst_us can be * interpreted in the same fashion and specifies how much @cgrp can * burst temporarily. The specific control mechanism and thus the - * interpretation of @period_us and burstiness is upto to the BPF + * interpretation of @period_us and burstiness is up to the BPF * scheduler. */ void (*cgroup_set_bandwidth)(struct cgroup *cgrp, u64 period_us, u64 quota_us, u64 burst_us); + /** + * @cgroup_set_idle: A cgroup's idle state is being changed + * @cgrp: cgroup whose idle state is being updated + * @idle: whether the cgroup is entering or exiting idle state + * + * Update @cgrp's idle state to @idle. This callback is invoked when + * a cgroup transitions between idle and non-idle states, allowing the + * BPF scheduler to adjust its behavior accordingly. + */ + void (*cgroup_set_idle)(struct cgroup *cgrp, bool idle); + #endif /* CONFIG_EXT_GROUP_SCHED */ /* diff --git a/kernel/trace/fprobe.c b/kernel/trace/fprobe.c index 43b27f07730c..8fa5bff2c26f 100644 --- a/kernel/trace/fprobe.c +++ b/kernel/trace/fprobe.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -42,60 +43,74 @@ * - RCU hlist traversal under disabling preempt */ static struct hlist_head fprobe_table[FPROBE_TABLE_SIZE]; -static struct hlist_head fprobe_ip_table[FPROBE_IP_TABLE_SIZE]; +static struct rhltable fprobe_ip_table; static DEFINE_MUTEX(fprobe_mutex); -/* - * Find first fprobe in the hlist. It will be iterated twice in the entry - * probe, once for correcting the total required size, the second time is - * calling back the user handlers. - * Thus the hlist in the fprobe_table must be sorted and new probe needs to - * be added *before* the first fprobe. - */ -static struct fprobe_hlist_node *find_first_fprobe_node(unsigned long ip) +static u32 fprobe_node_hashfn(const void *data, u32 len, u32 seed) { - struct fprobe_hlist_node *node; - struct hlist_head *head; + return hash_ptr(*(unsigned long **)data, 32); +} - head = &fprobe_ip_table[hash_ptr((void *)ip, FPROBE_IP_HASH_BITS)]; - hlist_for_each_entry_rcu(node, head, hlist, - lockdep_is_held(&fprobe_mutex)) { - if (node->addr == ip) - return node; - } - return NULL; +static int fprobe_node_cmp(struct rhashtable_compare_arg *arg, + const void *ptr) +{ + unsigned long key = *(unsigned long *)arg->key; + const struct fprobe_hlist_node *n = ptr; + + return n->addr != key; } -NOKPROBE_SYMBOL(find_first_fprobe_node); + +static u32 fprobe_node_obj_hashfn(const void *data, u32 len, u32 seed) +{ + const struct fprobe_hlist_node *n = data; + + return hash_ptr((void *)n->addr, 32); +} + +static const struct rhashtable_params fprobe_rht_params = { + .head_offset = offsetof(struct fprobe_hlist_node, hlist), + .key_offset = offsetof(struct fprobe_hlist_node, addr), + .key_len = sizeof_field(struct fprobe_hlist_node, addr), + .hashfn = fprobe_node_hashfn, + .obj_hashfn = fprobe_node_obj_hashfn, + .obj_cmpfn = fprobe_node_cmp, + .automatic_shrinking = true, +}; /* Node insertion and deletion requires the fprobe_mutex */ -static void insert_fprobe_node(struct fprobe_hlist_node *node) +static int insert_fprobe_node(struct fprobe_hlist_node *node, struct fprobe *fp) { - unsigned long ip = node->addr; - struct fprobe_hlist_node *next; - struct hlist_head *head; + int ret; lockdep_assert_held(&fprobe_mutex); - next = find_first_fprobe_node(ip); - if (next) { - hlist_add_before_rcu(&node->hlist, &next->hlist); - return; - } - head = &fprobe_ip_table[hash_ptr((void *)ip, FPROBE_IP_HASH_BITS)]; - hlist_add_head_rcu(&node->hlist, head); + ret = rhltable_insert(&fprobe_ip_table, &node->hlist, fprobe_rht_params); + /* Set the fprobe pointer if insertion was successful. */ + if (!ret) + WRITE_ONCE(node->fp, fp); + return ret; } /* Return true if there are synonims */ static bool delete_fprobe_node(struct fprobe_hlist_node *node) { + bool ret; + lockdep_assert_held(&fprobe_mutex); - /* Avoid double deleting */ + /* Avoid double deleting and non-inserted nodes */ if (READ_ONCE(node->fp) != NULL) { WRITE_ONCE(node->fp, NULL); - hlist_del_rcu(&node->hlist); + rhltable_remove(&fprobe_ip_table, &node->hlist, + fprobe_rht_params); } - return !!find_first_fprobe_node(node->addr); + + rcu_read_lock(); + ret = !!rhltable_lookup(&fprobe_ip_table, &node->addr, + fprobe_rht_params); + rcu_read_unlock(); + + return ret; } /* Check existence of the fprobe */ @@ -244,12 +259,112 @@ static inline int __fprobe_kprobe_handler(unsigned long ip, unsigned long parent return ret; } -static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops, - struct ftrace_regs *fregs) +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS +/* ftrace_ops callback, this processes fprobes which have only entry_handler. */ +static void fprobe_ftrace_entry(unsigned long ip, unsigned long parent_ip, + struct ftrace_ops *ops, struct ftrace_regs *fregs) +{ + struct fprobe_hlist_node *node; + struct rhlist_head *head, *pos; + struct fprobe *fp; + int bit; + + bit = ftrace_test_recursion_trylock(ip, parent_ip); + if (bit < 0) + return; + + /* + * ftrace_test_recursion_trylock() disables preemption, but + * rhltable_lookup() checks whether rcu_read_lcok is held. + * So we take rcu_read_lock() here. + */ + rcu_read_lock(); + head = rhltable_lookup(&fprobe_ip_table, &ip, fprobe_rht_params); + + rhl_for_each_entry_rcu(node, pos, head, hlist) { + if (node->addr != ip) + break; + fp = READ_ONCE(node->fp); + if (unlikely(!fp || fprobe_disabled(fp) || fp->exit_handler)) + continue; + + if (fprobe_shared_with_kprobes(fp)) + __fprobe_kprobe_handler(ip, parent_ip, fp, fregs, NULL); + else + __fprobe_handler(ip, parent_ip, fp, fregs, NULL); + } + rcu_read_unlock(); + ftrace_test_recursion_unlock(bit); +} +NOKPROBE_SYMBOL(fprobe_ftrace_entry); + +static struct ftrace_ops fprobe_ftrace_ops = { + .func = fprobe_ftrace_entry, + .flags = FTRACE_OPS_FL_SAVE_REGS, +}; +static int fprobe_ftrace_active; + +static int fprobe_ftrace_add_ips(unsigned long *addrs, int num) +{ + int ret; + + lockdep_assert_held(&fprobe_mutex); + + ret = ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 0, 0); + if (ret) + return ret; + + if (!fprobe_ftrace_active) { + ret = register_ftrace_function(&fprobe_ftrace_ops); + if (ret) { + ftrace_free_filter(&fprobe_ftrace_ops); + return ret; + } + } + fprobe_ftrace_active++; + return 0; +} + +static void fprobe_ftrace_remove_ips(unsigned long *addrs, int num) +{ + lockdep_assert_held(&fprobe_mutex); + + fprobe_ftrace_active--; + if (!fprobe_ftrace_active) { + unregister_ftrace_function(&fprobe_ftrace_ops); + ftrace_free_filter(&fprobe_ftrace_ops); + } else if (num) + ftrace_set_filter_ips(&fprobe_ftrace_ops, addrs, num, 1, 0); +} + +static bool fprobe_is_ftrace(struct fprobe *fp) +{ + return !fp->exit_handler; +} +#else +static int fprobe_ftrace_add_ips(unsigned long *addrs, int num) +{ + return -ENOENT; +} + +static void fprobe_ftrace_remove_ips(unsigned long *addrs, int num) +{ +} + +static bool fprobe_is_ftrace(struct fprobe *fp) +{ + return false; +} +#endif + +/* fgraph_ops callback, this processes fprobes which have exit_handler. */ +static int fprobe_fgraph_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops, + struct ftrace_regs *fregs) { - struct fprobe_hlist_node *node, *first; unsigned long *fgraph_data = NULL; unsigned long func = trace->func; + struct fprobe_hlist_node *node; + struct rhlist_head *head, *pos; unsigned long ret_ip; int reserved_words; struct fprobe *fp; @@ -258,14 +373,11 @@ static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops, if (WARN_ON_ONCE(!fregs)) return 0; - first = node = find_first_fprobe_node(func); - if (unlikely(!first)) - return 0; - + head = rhltable_lookup(&fprobe_ip_table, &func, fprobe_rht_params); reserved_words = 0; - hlist_for_each_entry_from_rcu(node, hlist) { + rhl_for_each_entry_rcu(node, pos, head, hlist) { if (node->addr != func) - break; + continue; fp = READ_ONCE(node->fp); if (!fp || !fp->exit_handler) continue; @@ -276,15 +388,14 @@ static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops, reserved_words += FPROBE_HEADER_SIZE_IN_LONG + SIZE_IN_LONG(fp->entry_data_size); } - node = first; if (reserved_words) { fgraph_data = fgraph_reserve_data(gops->idx, reserved_words * sizeof(long)); if (unlikely(!fgraph_data)) { - hlist_for_each_entry_from_rcu(node, hlist) { + rhl_for_each_entry_rcu(node, pos, head, hlist) { if (node->addr != func) - break; + continue; fp = READ_ONCE(node->fp); - if (fp && !fprobe_disabled(fp)) + if (fp && !fprobe_disabled(fp) && !fprobe_is_ftrace(fp)) fp->nmissed++; } return 0; @@ -297,14 +408,14 @@ static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops, */ ret_ip = ftrace_regs_get_return_address(fregs); used = 0; - hlist_for_each_entry_from_rcu(node, hlist) { + rhl_for_each_entry_rcu(node, pos, head, hlist) { int data_size; void *data; if (node->addr != func) - break; + continue; fp = READ_ONCE(node->fp); - if (!fp || fprobe_disabled(fp)) + if (unlikely(!fp || fprobe_disabled(fp) || fprobe_is_ftrace(fp))) continue; data_size = fp->entry_data_size; @@ -332,7 +443,7 @@ static int fprobe_entry(struct ftrace_graph_ent *trace, struct fgraph_ops *gops, /* If any exit_handler is set, data must be used. */ return used != 0; } -NOKPROBE_SYMBOL(fprobe_entry); +NOKPROBE_SYMBOL(fprobe_fgraph_entry); static void fprobe_return(struct ftrace_graph_ret *trace, struct fgraph_ops *gops, @@ -371,7 +482,7 @@ static void fprobe_return(struct ftrace_graph_ret *trace, NOKPROBE_SYMBOL(fprobe_return); static struct fgraph_ops fprobe_graph_ops = { - .entryfunc = fprobe_entry, + .entryfunc = fprobe_fgraph_entry, .retfunc = fprobe_return, }; static int fprobe_graph_active; @@ -405,10 +516,10 @@ static void fprobe_graph_remove_ips(unsigned long *addrs, int num) fprobe_graph_active--; /* Q: should we unregister it ? */ - if (!fprobe_graph_active) + if (!fprobe_graph_active) { unregister_ftrace_graph(&fprobe_graph_ops); - - if (num) + ftrace_free_filter(&fprobe_graph_ops.ops); + } else if (num) ftrace_set_filter_ips(&fprobe_graph_ops.ops, addrs, num, 1, 0); } @@ -447,25 +558,21 @@ static int fprobe_addr_list_add(struct fprobe_addr_list *alist, unsigned long ad return 0; } -static void fprobe_remove_node_in_module(struct module *mod, struct hlist_head *head, - struct fprobe_addr_list *alist) +static void fprobe_remove_node_in_module(struct module *mod, struct fprobe_hlist_node *node, + struct fprobe_addr_list *alist) { - struct fprobe_hlist_node *node; int ret = 0; - hlist_for_each_entry_rcu(node, head, hlist, - lockdep_is_held(&fprobe_mutex)) { - if (!within_module(node->addr, mod)) - continue; - if (delete_fprobe_node(node)) - continue; - /* - * If failed to update alist, just continue to update hlist. - * Therefore, at list user handler will not hit anymore. - */ - if (!ret) - ret = fprobe_addr_list_add(alist, node->addr); - } + if (!within_module(node->addr, mod)) + return; + if (delete_fprobe_node(node)) + return; + /* + * If failed to update alist, just continue to update hlist. + * Therefore, at list user handler will not hit anymore. + */ + if (!ret) + ret = fprobe_addr_list_add(alist, node->addr); } /* Handle module unloading to manage fprobe_ip_table. */ @@ -473,8 +580,9 @@ static int fprobe_module_callback(struct notifier_block *nb, unsigned long val, void *data) { struct fprobe_addr_list alist = {.size = FPROBE_IPS_BATCH_INIT}; + struct fprobe_hlist_node *node; + struct rhashtable_iter iter; struct module *mod = data; - int i; if (val != MODULE_STATE_GOING) return NOTIFY_DONE; @@ -485,12 +593,25 @@ static int fprobe_module_callback(struct notifier_block *nb, return NOTIFY_DONE; mutex_lock(&fprobe_mutex); - for (i = 0; i < FPROBE_IP_TABLE_SIZE; i++) - fprobe_remove_node_in_module(mod, &fprobe_ip_table[i], &alist); + rhltable_walk_enter(&fprobe_ip_table, &iter); + do { + rhashtable_walk_start(&iter); + + while ((node = rhashtable_walk_next(&iter)) && !IS_ERR(node)) + fprobe_remove_node_in_module(mod, node, &alist); + + rhashtable_walk_stop(&iter); + } while (node == ERR_PTR(-EAGAIN)); + rhashtable_walk_exit(&iter); - if (alist.index > 0) + if (alist.index > 0) { ftrace_set_filter_ips(&fprobe_graph_ops.ops, alist.addrs, alist.index, 1, 0); +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + ftrace_set_filter_ips(&fprobe_ftrace_ops, + alist.addrs, alist.index, 1, 0); +#endif + } mutex_unlock(&fprobe_mutex); kfree(alist.addrs); @@ -634,7 +755,6 @@ static int fprobe_init(struct fprobe *fp, unsigned long *addrs, int num) fp->hlist_array = hlist_array; hlist_array->fp = fp; for (i = 0; i < num; i++) { - hlist_array->array[i].fp = fp; addr = ftrace_location(addrs[i]); if (!addr) { fprobe_fail_cleanup(fp); @@ -698,6 +818,8 @@ int register_fprobe(struct fprobe *fp, const char *filter, const char *notfilter } EXPORT_SYMBOL_GPL(register_fprobe); +static int unregister_fprobe_nolock(struct fprobe *fp); + /** * register_fprobe_ips() - Register fprobe to ftrace by address. * @fp: A fprobe data structure to be registered. @@ -724,16 +846,25 @@ int register_fprobe_ips(struct fprobe *fp, unsigned long *addrs, int num) if (ret) return ret; - hlist_array = fp->hlist_array; - ret = fprobe_graph_add_ips(addrs, num); - if (!ret) { - add_fprobe_hash(fp); - for (i = 0; i < hlist_array->size; i++) - insert_fprobe_node(&hlist_array->array[i]); + if (fprobe_is_ftrace(fp)) + ret = fprobe_ftrace_add_ips(addrs, num); + else + ret = fprobe_graph_add_ips(addrs, num); + if (ret) { + fprobe_fail_cleanup(fp); + return ret; } - if (ret) - fprobe_fail_cleanup(fp); + hlist_array = fp->hlist_array; + ret = add_fprobe_hash(fp); + for (i = 0; i < hlist_array->size && !ret; i++) + ret = insert_fprobe_node(&hlist_array->array[i], fp); + + if (ret) { + unregister_fprobe_nolock(fp); + /* In error case, wait for clean up safely. */ + synchronize_rcu(); + } return ret; } @@ -777,50 +908,63 @@ bool fprobe_is_registered(struct fprobe *fp) return true; } -/** - * unregister_fprobe() - Unregister fprobe. - * @fp: A fprobe data structure to be unregistered. - * - * Unregister fprobe (and remove ftrace hooks from the function entries). - * - * Return 0 if @fp is unregistered successfully, -errno if not. - */ -int unregister_fprobe(struct fprobe *fp) +static int unregister_fprobe_nolock(struct fprobe *fp) { - struct fprobe_hlist *hlist_array; + struct fprobe_hlist *hlist_array = fp->hlist_array; unsigned long *addrs = NULL; - int ret = 0, i, count; - - mutex_lock(&fprobe_mutex); - if (!fp || !fprobe_registered(fp)) { - ret = -EINVAL; - goto out; - } + int i, count; - hlist_array = fp->hlist_array; addrs = kcalloc(hlist_array->size, sizeof(unsigned long), GFP_KERNEL); - if (!addrs) { - ret = -ENOMEM; /* TODO: Fallback to one-by-one loop */ - goto out; - } + /* + * This will remove fprobe_hash_node from the hash table even if + * memory allocation fails. However, ftrace_ops will not be updated. + * Anyway, when the last fprobe is unregistered, ftrace_ops is also + * unregistered. + */ + if (!addrs) + pr_warn("Failed to allocate working array. ftrace_ops may not sync.\n"); /* Remove non-synonim ips from table and hash */ count = 0; for (i = 0; i < hlist_array->size; i++) { - if (!delete_fprobe_node(&hlist_array->array[i])) + if (!delete_fprobe_node(&hlist_array->array[i]) && addrs) addrs[count++] = hlist_array->array[i].addr; } del_fprobe_hash(fp); - fprobe_graph_remove_ips(addrs, count); + if (fprobe_is_ftrace(fp)) + fprobe_ftrace_remove_ips(addrs, count); + else + fprobe_graph_remove_ips(addrs, count); kfree_rcu(hlist_array, rcu); fp->hlist_array = NULL; + kfree(addrs); -out: - mutex_unlock(&fprobe_mutex); + return 0; +} - kfree(addrs); - return ret; +/** + * unregister_fprobe() - Unregister fprobe. + * @fp: A fprobe data structure to be unregistered. + * + * Unregister fprobe (and remove ftrace hooks from the function entries). + * + * Return 0 if @fp is unregistered successfully, -errno if not. + */ +int unregister_fprobe(struct fprobe *fp) +{ + guard(mutex)(&fprobe_mutex); + if (!fp || !fprobe_registered(fp)) + return -EINVAL; + + return unregister_fprobe_nolock(fp); } EXPORT_SYMBOL_GPL(unregister_fprobe); + +static int __init fprobe_initcall(void) +{ + rhltable_init(&fprobe_ip_table, &fprobe_rht_params); + return 0; +} +late_initcall(fprobe_initcall); diff --git a/mm/damon/core.c b/mm/damon/core.c index c46236b73b2d..00c80b7c8c3f 100644 --- a/mm/damon/core.c +++ b/mm/damon/core.c @@ -1436,6 +1436,23 @@ bool damon_is_running(struct damon_ctx *ctx) return running; } +/** + * damon_kdamond_pid() - Return pid of a given DAMON context's worker thread. + * @ctx: The DAMON context of the question. + * + * Return: pid if @ctx is running, negative error code otherwise. + */ +int damon_kdamond_pid(struct damon_ctx *ctx) +{ + int pid = -EINVAL; + + mutex_lock(&ctx->kdamond_lock); + if (ctx->kdamond) + pid = ctx->kdamond->pid; + mutex_unlock(&ctx->kdamond_lock); + return pid; +} + /** * damon_call() - Invoke a given function on DAMON worker thread (kdamond). * @ctx: DAMON context to call the function for. @@ -2118,7 +2135,8 @@ static unsigned long damos_quota_score(struct damos_quota *quota) /* * Called only if quota->ms, or quota->sz are set, or quota->goals is not empty */ -static void damos_set_effective_quota(struct damos_quota *quota) +static void damos_set_effective_quota(struct damos_quota *quota, + struct damon_ctx *ctx) { unsigned long throughput; unsigned long esz = ULONG_MAX; @@ -2144,6 +2162,7 @@ static void damos_set_effective_quota(struct damos_quota *quota) else throughput = PAGE_SIZE * 1024; esz = min(throughput * quota->ms, esz); + esz = max(ctx->min_sz_region, esz); } if (quota->sz && quota->sz < esz) @@ -2180,7 +2199,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s) /* First charge window */ if (!quota->total_charged_sz && !quota->charged_from) { quota->charged_from = jiffies; - damos_set_effective_quota(quota); + damos_set_effective_quota(quota, c); } /* New charge window starts */ @@ -2194,7 +2213,7 @@ static void damos_adjust_quota(struct damon_ctx *c, struct damos *s) quota->charged_sz = 0; if (trace_damos_esz_enabled()) cached_esz = quota->esz; - damos_set_effective_quota(quota); + damos_set_effective_quota(quota, c); if (trace_damos_esz_enabled() && quota->esz != cached_esz) damos_trace_esz(c, s, quota); } diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c index 42b9a656f9de..0c2274fefd76 100644 --- a/mm/damon/lru_sort.c +++ b/mm/damon/lru_sort.c @@ -118,15 +118,6 @@ module_param(monitor_region_end, ulong, 0600); */ static unsigned long addr_unit __read_mostly = 1; -/* - * PID of the DAMON thread - * - * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread. - * Else, -1. - */ -static int kdamond_pid __read_mostly = -1; -module_param(kdamond_pid, int, 0400); - static struct damos_stat damon_lru_sort_hot_stat; DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_hot_stat, lru_sort_tried_hot_regions, lru_sorted_hot_regions, @@ -288,12 +279,8 @@ static int damon_lru_sort_turn(bool on) { int err; - if (!on) { - err = damon_stop(&ctx, 1); - if (!err) - kdamond_pid = -1; - return err; - } + if (!on) + return damon_stop(&ctx, 1); err = damon_lru_sort_apply_parameters(); if (err) @@ -302,7 +289,6 @@ static int damon_lru_sort_turn(bool on) err = damon_start(&ctx, 1, true); if (err) return err; - kdamond_pid = ctx->kdamond->pid; return damon_call(ctx, &call_control); } @@ -330,42 +316,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); MODULE_PARM_DESC(addr_unit, "Scale factor for DAMON_LRU_SORT to ops address conversion (default: 1)"); +static bool damon_lru_sort_enabled(void) +{ + if (!ctx) + return false; + return damon_is_running(ctx); +} + static int damon_lru_sort_enabled_store(const char *val, const struct kernel_param *kp) { - bool is_enabled = enabled; - bool enable; int err; - err = kstrtobool(val, &enable); + err = kstrtobool(val, &enabled); if (err) return err; - if (is_enabled == enable) + if (damon_lru_sort_enabled() == enabled) return 0; /* Called before init function. The function will handle this. */ if (!damon_initialized()) - goto set_param_out; + return 0; - err = damon_lru_sort_turn(enable); - if (err) - return err; + return damon_lru_sort_turn(enabled); +} -set_param_out: - enabled = enable; - return err; +static int damon_lru_sort_enabled_load(char *buffer, + const struct kernel_param *kp) +{ + return sprintf(buffer, "%c\n", damon_lru_sort_enabled() ? 'Y' : 'N'); } static const struct kernel_param_ops enabled_param_ops = { .set = damon_lru_sort_enabled_store, - .get = param_get_bool, + .get = damon_lru_sort_enabled_load, }; module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); MODULE_PARM_DESC(enabled, "Enable or disable DAMON_LRU_SORT (default: disabled)"); +static int damon_lru_sort_kdamond_pid_store(const char *val, + const struct kernel_param *kp) +{ + /* + * kdamond_pid is read-only, but kernel command line could write it. + * Do nothing here. + */ + return 0; +} + +static int damon_lru_sort_kdamond_pid_load(char *buffer, + const struct kernel_param *kp) +{ + int kdamond_pid = -1; + + if (ctx) { + kdamond_pid = damon_kdamond_pid(ctx); + if (kdamond_pid < 0) + kdamond_pid = -1; + } + return sprintf(buffer, "%d\n", kdamond_pid); +} + +static const struct kernel_param_ops kdamond_pid_param_ops = { + .set = damon_lru_sort_kdamond_pid_store, + .get = damon_lru_sort_kdamond_pid_load, +}; + +/* + * PID of the DAMON thread + * + * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread. + * Else, -1. + */ +module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400); + static int __init damon_lru_sort_init(void) { int err; diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c index 7ba3d0f9a19a..9446e7a1b476 100644 --- a/mm/damon/reclaim.c +++ b/mm/damon/reclaim.c @@ -144,15 +144,6 @@ static unsigned long addr_unit __read_mostly = 1; static bool skip_anon __read_mostly; module_param(skip_anon, bool, 0600); -/* - * PID of the DAMON thread - * - * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. - * Else, -1. - */ -static int kdamond_pid __read_mostly = -1; -module_param(kdamond_pid, int, 0400); - static struct damos_stat damon_reclaim_stat; DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_reclaim_stat, reclaim_tried_regions, reclaimed_regions, quota_exceeds); @@ -292,12 +283,8 @@ static int damon_reclaim_turn(bool on) { int err; - if (!on) { - err = damon_stop(&ctx, 1); - if (!err) - kdamond_pid = -1; - return err; - } + if (!on) + return damon_stop(&ctx, 1); err = damon_reclaim_apply_parameters(); if (err) @@ -306,7 +293,6 @@ static int damon_reclaim_turn(bool on) err = damon_start(&ctx, 1, true); if (err) return err; - kdamond_pid = ctx->kdamond->pid; return damon_call(ctx, &call_control); } @@ -334,42 +320,83 @@ module_param_cb(addr_unit, &addr_unit_param_ops, &addr_unit, 0600); MODULE_PARM_DESC(addr_unit, "Scale factor for DAMON_RECLAIM to ops address conversion (default: 1)"); +static bool damon_reclaim_enabled(void) +{ + if (!ctx) + return false; + return damon_is_running(ctx); +} + static int damon_reclaim_enabled_store(const char *val, const struct kernel_param *kp) { - bool is_enabled = enabled; - bool enable; int err; - err = kstrtobool(val, &enable); + err = kstrtobool(val, &enabled); if (err) return err; - if (is_enabled == enable) + if (damon_reclaim_enabled() == enabled) return 0; /* Called before init function. The function will handle this. */ if (!damon_initialized()) - goto set_param_out; + return 0; - err = damon_reclaim_turn(enable); - if (err) - return err; + return damon_reclaim_turn(enabled); +} -set_param_out: - enabled = enable; - return err; +static int damon_reclaim_enabled_load(char *buffer, + const struct kernel_param *kp) +{ + return sprintf(buffer, "%c\n", damon_reclaim_enabled() ? 'Y' : 'N'); } static const struct kernel_param_ops enabled_param_ops = { .set = damon_reclaim_enabled_store, - .get = param_get_bool, + .get = damon_reclaim_enabled_load, }; module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); MODULE_PARM_DESC(enabled, "Enable or disable DAMON_RECLAIM (default: disabled)"); +static int damon_reclaim_kdamond_pid_store(const char *val, + const struct kernel_param *kp) +{ + /* + * kdamond_pid is read-only, but kernel command line could write it. + * Do nothing here. + */ + return 0; +} + +static int damon_reclaim_kdamond_pid_load(char *buffer, + const struct kernel_param *kp) +{ + int kdamond_pid = -1; + + if (ctx) { + kdamond_pid = damon_kdamond_pid(ctx); + if (kdamond_pid < 0) + kdamond_pid = -1; + } + return sprintf(buffer, "%d\n", kdamond_pid); +} + +static const struct kernel_param_ops kdamond_pid_param_ops = { + .set = damon_reclaim_kdamond_pid_store, + .get = damon_reclaim_kdamond_pid_load, +}; + +/* + * PID of the DAMON thread + * + * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. + * Else, -1. + */ +module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400); + static int __init damon_reclaim_init(void) { int err; diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index f28e9cbf8ad5..74ef7dc2b2f9 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c @@ -173,19 +173,12 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr) static struct batadv_neigh_node * batadv_iv_ogm_neigh_new(struct batadv_hard_iface *hard_iface, const u8 *neigh_addr, - struct batadv_orig_node *orig_node, - struct batadv_orig_node *orig_neigh) + struct batadv_orig_node *orig_node) { struct batadv_neigh_node *neigh_node; neigh_node = batadv_neigh_node_get_or_create(orig_node, hard_iface, neigh_addr); - if (!neigh_node) - goto out; - - neigh_node->orig_node = orig_neigh; - -out: return neigh_node; } @@ -335,7 +328,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, struct batadv_priv *bat_priv = netdev_priv(hard_iface->mesh_iface); const char *fwd_str; u8 packet_num; - s16 buff_pos; + int buff_pos; struct batadv_ogm_packet *batadv_ogm_packet; struct sk_buff *skb; u8 *packet_pos; @@ -906,6 +899,31 @@ static u8 batadv_iv_orig_ifinfo_sum(struct batadv_orig_node *orig_node, return sum; } +/** + * batadv_iv_ogm_neigh_ifinfo_sum() - Get bcast_own sum for a last-hop neighbor + * @bat_priv: the bat priv with all the mesh interface information + * @neigh_node: last-hop neighbor of an originator + * + * Return: Number of replied (rebroadcasted) OGMs for the originator currently + * announced by the neighbor. Returns 0 if the neighbor's originator entry is + * not available anymore. + */ +static u8 batadv_iv_ogm_neigh_ifinfo_sum(struct batadv_priv *bat_priv, + const struct batadv_neigh_node *neigh_node) +{ + struct batadv_orig_node *orig_neigh; + u8 sum; + + orig_neigh = batadv_orig_hash_find(bat_priv, neigh_node->addr); + if (!orig_neigh) + return 0; + + sum = batadv_iv_orig_ifinfo_sum(orig_neigh, neigh_node->if_incoming); + batadv_orig_node_put(orig_neigh); + + return sum; +} + /** * batadv_iv_ogm_orig_update() - use OGM to update corresponding data in an * originator @@ -975,17 +993,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, } if (!neigh_node) { - struct batadv_orig_node *orig_tmp; - - orig_tmp = batadv_iv_ogm_orig_get(bat_priv, ethhdr->h_source); - if (!orig_tmp) - goto unlock; - neigh_node = batadv_iv_ogm_neigh_new(if_incoming, ethhdr->h_source, - orig_node, orig_tmp); - - batadv_orig_node_put(orig_tmp); + orig_node); if (!neigh_node) goto unlock; } else { @@ -1037,10 +1047,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, */ if (router_ifinfo && neigh_ifinfo->bat_iv.tq_avg == router_ifinfo->bat_iv.tq_avg) { - sum_orig = batadv_iv_orig_ifinfo_sum(router->orig_node, - router->if_incoming); - sum_neigh = batadv_iv_orig_ifinfo_sum(neigh_node->orig_node, - neigh_node->if_incoming); + sum_orig = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, router); + sum_neigh = batadv_iv_ogm_neigh_ifinfo_sum(bat_priv, + neigh_node); if (sum_orig >= sum_neigh) goto out; } @@ -1106,7 +1115,6 @@ static bool batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, if (!neigh_node) neigh_node = batadv_iv_ogm_neigh_new(if_incoming, orig_neigh_node->orig, - orig_neigh_node, orig_neigh_node); if (!neigh_node) @@ -1302,6 +1310,32 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, return ret; } +/** + * batadv_orig_to_direct_router() - get direct next hop neighbor to an orig address + * @bat_priv: the bat priv with all the mesh interface information + * @orig_addr: the originator MAC address to search the best next hop router for + * @if_outgoing: the interface where the OGM should be sent to + * + * Return: A neighbor node which is the best router towards the given originator + * address. Bonding candidates are ignored. + */ +static struct batadv_neigh_node * +batadv_orig_to_direct_router(struct batadv_priv *bat_priv, u8 *orig_addr, + struct batadv_hard_iface *if_outgoing) +{ + struct batadv_neigh_node *neigh_node; + struct batadv_orig_node *orig_node; + + orig_node = batadv_orig_hash_find(bat_priv, orig_addr); + if (!orig_node) + return NULL; + + neigh_node = batadv_orig_router_get(orig_node, if_outgoing); + batadv_orig_node_put(orig_node); + + return neigh_node; +} + /** * batadv_iv_ogm_process_per_outif() - process a batman iv OGM for an outgoing * interface @@ -1372,8 +1406,9 @@ batadv_iv_ogm_process_per_outif(const struct sk_buff *skb, int ogm_offset, router = batadv_orig_router_get(orig_node, if_outgoing); if (router) { - router_router = batadv_orig_router_get(router->orig_node, - if_outgoing); + router_router = batadv_orig_to_direct_router(bat_priv, + router->addr, + if_outgoing); router_ifinfo = batadv_neigh_ifinfo_get(router, if_outgoing); } diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index d4f4e97a27f1..2d7971424aa0 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c @@ -319,8 +319,8 @@ batadv_bla_del_backbone_claims(struct batadv_bla_backbone_gw *backbone_gw) if (claim->backbone_gw != backbone_gw) continue; - batadv_claim_put(claim); hlist_del_rcu(&claim->hash_entry); + batadv_claim_put(claim); } spin_unlock_bh(list_lock); } @@ -724,6 +724,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, if (unlikely(hash_added != 0)) { /* only local changes happened. */ + batadv_backbone_gw_put(backbone_gw); kfree(claim); return; } @@ -1289,6 +1290,13 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv, rcu_read_lock(); hlist_for_each_entry_rcu(claim, head, hash_entry) { + /* only purge claims not currently in the process of being released. + * Such claims could otherwise have a NULL-ptr backbone_gw set because + * they already went through batadv_claim_release() + */ + if (!kref_get_unless_zero(&claim->refcount)) + continue; + backbone_gw = batadv_bla_claim_get_backbone_gw(claim); if (now) goto purge_now; @@ -1314,6 +1322,7 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv, claim->addr, claim->vid); skip: batadv_backbone_gw_put(backbone_gw); + batadv_claim_put(claim); } rcu_read_unlock(); } diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 3a35aadd8b41..a4d33ee0fda5 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -249,6 +249,7 @@ void batadv_mesh_free(struct net_device *mesh_iface) atomic_set(&bat_priv->mesh_state, BATADV_MESH_DEACTIVATING); batadv_purge_outstanding_packets(bat_priv, NULL); + batadv_tp_stop_all(bat_priv); batadv_gw_node_free(bat_priv); diff --git a/net/batman-adv/tp_meter.c b/net/batman-adv/tp_meter.c index 350b149e48be..76ece4014384 100644 --- a/net/batman-adv/tp_meter.c +++ b/net/batman-adv/tp_meter.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -365,23 +366,38 @@ static void batadv_tp_vars_put(struct batadv_tp_vars *tp_vars) } /** - * batadv_tp_sender_cleanup() - cleanup sender data and drop and timer - * @bat_priv: the bat priv with all the mesh interface information - * @tp_vars: the private data of the current TP meter session to cleanup + * batadv_tp_list_detach() - remove tp session from mesh session list once + * @tp_vars: the private data of the current TP meter session */ -static void batadv_tp_sender_cleanup(struct batadv_priv *bat_priv, - struct batadv_tp_vars *tp_vars) +static void batadv_tp_list_detach(struct batadv_tp_vars *tp_vars) { - cancel_delayed_work(&tp_vars->finish_work); + bool detached = false; spin_lock_bh(&tp_vars->bat_priv->tp_list_lock); - hlist_del_rcu(&tp_vars->list); + if (!hlist_unhashed(&tp_vars->list)) { + hlist_del_init_rcu(&tp_vars->list); + detached = true; + } spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock); + if (!detached) + return; + + atomic_dec(&tp_vars->bat_priv->tp_num); + /* drop list reference */ batadv_tp_vars_put(tp_vars); +} - atomic_dec(&tp_vars->bat_priv->tp_num); +/** + * batadv_tp_sender_cleanup() - cleanup sender data and drop and timer + * @tp_vars: the private data of the current TP meter session to cleanup + */ +static void batadv_tp_sender_cleanup(struct batadv_tp_vars *tp_vars) +{ + cancel_delayed_work_sync(&tp_vars->finish_work); + + batadv_tp_list_detach(tp_vars); /* kill the timer and remove its reference */ timer_delete_sync(&tp_vars->timer); @@ -886,7 +902,8 @@ static int batadv_tp_send(void *arg) batadv_orig_node_put(orig_node); batadv_tp_sender_end(bat_priv, tp_vars); - batadv_tp_sender_cleanup(bat_priv, tp_vars); + batadv_tp_sender_cleanup(tp_vars); + complete(&tp_vars->finished); batadv_tp_vars_put(tp_vars); @@ -918,7 +935,8 @@ static void batadv_tp_start_kthread(struct batadv_tp_vars *tp_vars) batadv_tp_vars_put(tp_vars); /* cleanup of failed tp meter variables */ - batadv_tp_sender_cleanup(bat_priv, tp_vars); + batadv_tp_sender_cleanup(tp_vars); + complete(&tp_vars->finished); return; } @@ -947,6 +965,13 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, /* look for an already existing test towards this node */ spin_lock_bh(&bat_priv->tp_list_lock); + if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) { + spin_unlock_bh(&bat_priv->tp_list_lock); + batadv_tp_batctl_error_notify(BATADV_TP_REASON_DST_UNREACHABLE, + dst, bat_priv, session_cookie); + return; + } + tp_vars = batadv_tp_list_find(bat_priv, dst); if (tp_vars) { spin_unlock_bh(&bat_priv->tp_list_lock); @@ -969,6 +994,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, tp_vars = kmalloc(sizeof(*tp_vars), GFP_ATOMIC); if (!tp_vars) { + atomic_dec(&bat_priv->tp_num); spin_unlock_bh(&bat_priv->tp_list_lock); batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Meter: %s cannot allocate list elements\n", @@ -1017,6 +1043,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, tp_vars->start_time = jiffies; init_waitqueue_head(&tp_vars->more_bytes); + init_completion(&tp_vars->finished); spin_lock_init(&tp_vars->unacked_lock); INIT_LIST_HEAD(&tp_vars->unacked_list); @@ -1119,14 +1146,7 @@ static void batadv_tp_receiver_shutdown(struct timer_list *t) "Shutting down for inactivity (more than %dms) from %pM\n", BATADV_TP_RECV_TIMEOUT, tp_vars->other_end); - spin_lock_bh(&tp_vars->bat_priv->tp_list_lock); - hlist_del_rcu(&tp_vars->list); - spin_unlock_bh(&tp_vars->bat_priv->tp_list_lock); - - /* drop list reference */ - batadv_tp_vars_put(tp_vars); - - atomic_dec(&bat_priv->tp_num); + batadv_tp_list_detach(tp_vars); spin_lock_bh(&tp_vars->unacked_lock); list_for_each_entry_safe(un, safe, &tp_vars->unacked_list, list) { @@ -1329,9 +1349,12 @@ static struct batadv_tp_vars * batadv_tp_init_recv(struct batadv_priv *bat_priv, const struct batadv_icmp_tp_packet *icmp) { - struct batadv_tp_vars *tp_vars; + struct batadv_tp_vars *tp_vars = NULL; spin_lock_bh(&bat_priv->tp_list_lock); + if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) + goto out_unlock; + tp_vars = batadv_tp_list_find_session(bat_priv, icmp->orig, icmp->session); if (tp_vars) @@ -1344,8 +1367,10 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, } tp_vars = kmalloc(sizeof(*tp_vars), GFP_ATOMIC); - if (!tp_vars) + if (!tp_vars) { + atomic_dec(&bat_priv->tp_num); goto out_unlock; + } ether_addr_copy(tp_vars->other_end, icmp->orig); tp_vars->role = BATADV_TP_RECEIVER; @@ -1464,6 +1489,9 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb) { struct batadv_icmp_tp_packet *icmp; + if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) + goto out; + icmp = (struct batadv_icmp_tp_packet *)skb->data; switch (icmp->subtype) { @@ -1478,9 +1506,57 @@ void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb) "Received unknown TP Metric packet type %u\n", icmp->subtype); } + +out: consume_skb(skb); } +/** + * batadv_tp_stop_all() - stop all currently running tp meter sessions + * @bat_priv: the bat priv with all the mesh interface information + */ +void batadv_tp_stop_all(struct batadv_priv *bat_priv) +{ + struct batadv_tp_vars *tp_vars[BATADV_TP_MAX_NUM]; + struct batadv_tp_vars *tp_var; + size_t count = 0; + size_t i; + + spin_lock_bh(&bat_priv->tp_list_lock); + hlist_for_each_entry(tp_var, &bat_priv->tp_list, list) { + if (WARN_ON_ONCE(count >= BATADV_TP_MAX_NUM)) + break; + + if (!kref_get_unless_zero(&tp_var->refcount)) + continue; + + tp_vars[count++] = tp_var; + } + spin_unlock_bh(&bat_priv->tp_list_lock); + + for (i = 0; i < count; i++) { + tp_var = tp_vars[i]; + + switch (tp_var->role) { + case BATADV_TP_SENDER: + batadv_tp_sender_shutdown(tp_var, + BATADV_TP_REASON_CANCEL); + wake_up(&tp_var->more_bytes); + wait_for_completion(&tp_var->finished); + break; + case BATADV_TP_RECEIVER: + batadv_tp_list_detach(tp_var); + if (timer_shutdown_sync(&tp_var->timer)) + batadv_tp_vars_put(tp_var); + break; + } + + batadv_tp_vars_put(tp_var); + } + + synchronize_net(); +} + /** * batadv_tp_meter_init() - initialize global tp_meter structures */ diff --git a/net/batman-adv/tp_meter.h b/net/batman-adv/tp_meter.h index f0046d366eac..4e97cd10cd02 100644 --- a/net/batman-adv/tp_meter.h +++ b/net/batman-adv/tp_meter.h @@ -17,6 +17,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst, u32 test_length, u32 *cookie); void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst, u8 return_value); +void batadv_tp_stop_all(struct batadv_priv *bat_priv); void batadv_tp_meter_recv(struct batadv_priv *bat_priv, struct sk_buff *skb); #endif /* _NET_BATMAN_ADV_TP_METER_H_ */ diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index ae1d7a8dc480..41c1d19f786b 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -1328,6 +1329,9 @@ struct batadv_tp_vars { /** @finish_work: work item for the finishing procedure */ struct delayed_work finish_work; + /** @finished: completion signaled when a sender thread exits */ + struct completion finished; + /** @test_length: test length in milliseconds */ u32 test_length; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 71a24be2a6d6..1b63bc2753a2 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -2113,6 +2113,9 @@ static int create_big_sync(struct hci_dev *hdev, void *data) u32 flags = 0; int err; + if (!hci_conn_valid(hdev, conn)) + return -ECANCELED; + if (qos->bcast.out.phy == 0x02) flags |= MGMT_ADV_FLAG_SEC_2M; @@ -2188,11 +2191,24 @@ static void create_big_complete(struct hci_dev *hdev, void *data, int err) bt_dev_dbg(hdev, "conn %p", conn); + if (err == -ECANCELED) + goto done; + + hci_dev_lock(hdev); + + if (!hci_conn_valid(hdev, conn)) + goto unlock; + if (err) { bt_dev_err(hdev, "Unable to create BIG: %d", err); hci_connect_cfm(conn, err); hci_conn_del(conn); } + +unlock: + hci_dev_unlock(hdev); +done: + hci_conn_put(conn); } struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid, @@ -2309,10 +2325,11 @@ struct hci_conn *hci_connect_bis(struct hci_dev *hdev, bdaddr_t *dst, BT_BOUND, &data); /* Queue start periodic advertising and create BIG */ - err = hci_cmd_sync_queue(hdev, create_big_sync, conn, + err = hci_cmd_sync_queue(hdev, create_big_sync, hci_conn_get(conn), create_big_complete); if (err < 0) { hci_conn_drop(conn); + hci_conn_put(conn); return ERR_PTR(err); } diff --git a/net/sctp/socket.c b/net/sctp/socket.c index d190e75e4645..c57a53192bee 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1985,6 +1985,15 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len) goto out_unlock; iov_iter_revert(&msg->msg_iter, err); + + /* sctp_sendmsg_to_asoc() may have released the socket + * lock (sctp_wait_for_sndbuf), during which other + * associations on ep->asocs could have been peeled + * off or freed. @asoc itself is revalidated by the + * base.dead and base.sk checks in sctp_wait_for_sndbuf, + * so re-derive the cached cursor from it. + */ + tmp = list_next_entry(asoc, asocs); } goto out_unlock; diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index cbd649bf0145..9d0e1915abbe 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1846,12 +1846,12 @@ static void vsock_update_buffer_size(struct vsock_sock *vsk, const struct vsock_transport *transport, u64 val) { - if (val > vsk->buffer_max_size) - val = vsk->buffer_max_size; - if (val < vsk->buffer_min_size) val = vsk->buffer_min_size; + if (val > vsk->buffer_max_size) + val = vsk->buffer_max_size; + if (val != vsk->buffer_size && transport && transport->notify_buffer_size) transport->notify_buffer_size(vsk, &val); diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index d3e26025ef58..41be06c4bd7f 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -139,27 +139,6 @@ static void virtio_transport_init_hdr(struct sk_buff *skb, hdr->fwd_cnt = cpu_to_le32(0); } -static void virtio_transport_copy_nonlinear_skb(const struct sk_buff *skb, - void *dst, - size_t len) -{ - struct iov_iter iov_iter = { 0 }; - struct kvec kvec; - size_t to_copy; - - kvec.iov_base = dst; - kvec.iov_len = len; - - iov_iter.iter_type = ITER_KVEC; - iov_iter.kvec = &kvec; - iov_iter.nr_segs = 1; - - to_copy = min_t(size_t, len, skb->len); - - skb_copy_datagram_iter(skb, VIRTIO_VSOCK_SKB_CB(skb)->offset, - &iov_iter, to_copy); -} - /* Packet capture */ static struct sk_buff *virtio_transport_build_skb(void *opaque) { @@ -169,12 +148,12 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) struct sk_buff *skb; size_t payload_len; - /* A packet could be split to fit the RX buffer, so we can retrieve - * the payload length from the header and the buffer pointer taking - * care of the offset in the original packet. + /* A packet could be split to fit the RX buffer, so we use + * the payload length from the header, which has been updated + * by the sender to reflect the fragment size. */ pkt_hdr = virtio_vsock_hdr(pkt); - payload_len = pkt->len; + payload_len = le32_to_cpu(pkt_hdr->len); skb = alloc_skb(sizeof(*hdr) + sizeof(*pkt_hdr) + payload_len, GFP_ATOMIC); @@ -217,12 +196,18 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) skb_put_data(skb, pkt_hdr, sizeof(*pkt_hdr)); if (payload_len) { - if (skb_is_nonlinear(pkt)) { - void *data = skb_put(skb, payload_len); - - virtio_transport_copy_nonlinear_skb(pkt, data, payload_len); - } else { - skb_put_data(skb, pkt->data, payload_len); + struct iov_iter iov_iter; + struct kvec kvec; + void *data = skb_put(skb, payload_len); + + kvec.iov_base = data; + kvec.iov_len = payload_len; + iov_iter_kvec(&iov_iter, ITER_DEST, &kvec, 1, payload_len); + + if (skb_copy_datagram_iter(pkt, VIRTIO_VSOCK_SKB_CB(pkt)->offset, + &iov_iter, payload_len)) { + kfree_skb(skb); + return NULL; } } @@ -546,9 +531,8 @@ virtio_transport_stream_do_peek(struct vsock_sock *vsk, skb_queue_walk(&vvs->rx_queue, skb) { size_t bytes; - bytes = len - total; - if (bytes > skb->len) - bytes = skb->len; + bytes = min_t(size_t, len - total, + skb->len - VIRTIO_VSOCK_SKB_CB(skb)->offset); spin_unlock_bh(&vvs->rx_lock); @@ -1544,8 +1528,6 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb, return -ENOMEM; } - sk_acceptq_added(sk); - lock_sock_nested(child, SINGLE_DEPTH_NESTING); child->sk_state = TCP_ESTABLISHED; @@ -1567,6 +1549,7 @@ virtio_transport_recv_listen(struct sock *sk, struct sk_buff *skb, return ret; } + sk_acceptq_added(sk); if (virtio_transport_space_update(child, skb)) child->sk_write_space(child);