diff --git a/Documentation/ABI/testing/evm b/Documentation/ABI/testing/evm index 3c477ba48a31233186fa4fe106f8846c3fd5c88b..2243b72e41107097ba5d503eb7c63b9e4d557401 100644 --- a/Documentation/ABI/testing/evm +++ b/Documentation/ABI/testing/evm @@ -49,8 +49,30 @@ Description: modification of EVM-protected metadata and disable all further modification of policy - Note that once a key has been loaded, it will no longer be - possible to enable metadata modification. + Echoing a value is additive, the new value is added to the + existing initialization flags. + + For example, after:: + + echo 2 ><securityfs>/evm + + another echo can be performed:: + + echo 1 ><securityfs>/evm + + and the resulting value will be 3. + + Note that once an HMAC key has been loaded, it will no longer + be possible to enable metadata modification. Signaling that an + HMAC key has been loaded will clear the corresponding flag. + For example, if the current value is 6 (2 and 4 set):: + + echo 1 ><securityfs>/evm + + will set the new value to 3 (4 cleared). + + Loading an HMAC key is the only way to disable metadata + modification. Until key loading has been signaled EVM can not create or validate the 'security.evm' xattr, but returns diff --git a/Documentation/ABI/testing/sysfs-bus-papr-pmem b/Documentation/ABI/testing/sysfs-bus-papr-pmem index 8316c33862a047b86fb508a75122bcae16ca9768..0aa02bf2bde5c9265efd8b923b009cabb1c1711c 100644 --- a/Documentation/ABI/testing/sysfs-bus-papr-pmem +++ b/Documentation/ABI/testing/sysfs-bus-papr-pmem @@ -39,9 +39,11 @@ KernelVersion: v5.9 Contact: linuxppc-dev <linuxppc-dev@lists.ozlabs.org>, linux-nvdimm@lists.01.org, Description: (RO) Report various performance stats related to papr-scm NVDIMM - device. Each stat is reported on a new line with each line - composed of a stat-identifier followed by it value. Below are - currently known dimm performance stats which are reported: + device. This attribute is only available for NVDIMM devices + that support reporting NVDIMM performance stats. Each stat is + reported on a new line with each line composed of a + stat-identifier followed by it value. Below are currently known + dimm performance stats which are reported: * "CtlResCt" : Controller Reset Count * "CtlResTm" : Controller Reset Elapsed Time diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 26bfe7ae711b8ed7e706ce8ed835c5517ce08035..f103667d3727fa53c1172dc1445a1c87a51fd156 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -577,6 +577,12 @@ loops can be debugged more effectively on production systems. + clocksource.max_cswd_read_retries= [KNL] + Number of clocksource_watchdog() retries due to + external delays before the clock will be marked + unstable. Defaults to three retries, that is, + four attempts to read the clock under test. + clearcpuid=BITNUM[,BITNUM...] [X86] Disable CPUID feature X for the kernel. See arch/x86/include/asm/cpufeatures.h for the valid bit diff --git a/Documentation/devicetree/bindings/i2c/i2c-at91.txt b/Documentation/devicetree/bindings/i2c/i2c-at91.txt index 96c914e048f594dc2128453cc8b9917e6b930ef7..2015f50aed0f9a98ca296ac18b51a06a3eebda6e 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-at91.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-at91.txt @@ -73,7 +73,7 @@ i2c0: i2c@f8034600 { pinctrl-0 = <&pinctrl_i2c0>; pinctrl-1 = <&pinctrl_i2c0_gpio>; sda-gpios = <&pioA 30 GPIO_ACTIVE_HIGH>; - scl-gpios = <&pioA 31 GPIO_ACTIVE_HIGH>; + scl-gpios = <&pioA 31 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; wm8731: wm8731@1a { compatible = "wm8731"; diff --git a/Documentation/filesystems/f2fs.rst b/Documentation/filesystems/f2fs.rst index b8ee761c9922a8a9eb9006ca675a74ee0616caac..8c0fbdd8ce6fba671b8efc2b74678ef86cf676e1 100644 --- a/Documentation/filesystems/f2fs.rst +++ b/Documentation/filesystems/f2fs.rst @@ -688,10 +688,10 @@ users. ===================== ======================== =================== User F2FS Block ===================== ======================== =================== - META WRITE_LIFE_NOT_SET - HOT_NODE " - WARM_NODE " - COLD_NODE " +N/A META WRITE_LIFE_NOT_SET +N/A HOT_NODE " +N/A WARM_NODE " +N/A COLD_NODE " ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME extension list " " @@ -717,10 +717,10 @@ WRITE_LIFE_LONG " WRITE_LIFE_LONG ===================== ======================== =================== User F2FS Block ===================== ======================== =================== - META WRITE_LIFE_MEDIUM; - HOT_NODE WRITE_LIFE_NOT_SET - WARM_NODE " - COLD_NODE WRITE_LIFE_NONE +N/A META WRITE_LIFE_MEDIUM; +N/A HOT_NODE WRITE_LIFE_NOT_SET +N/A WARM_NODE " +N/A COLD_NODE WRITE_LIFE_NONE ioctl(COLD) COLD_DATA WRITE_LIFE_EXTREME extension list " " diff --git a/Documentation/hwmon/max31790.rst b/Documentation/hwmon/max31790.rst index f301385d8cef3388cb8643be46adfcfaa463edc9..7b097c3b9b908afc45f45e53e4ee6f0509309379 100644 --- a/Documentation/hwmon/max31790.rst +++ b/Documentation/hwmon/max31790.rst @@ -38,6 +38,7 @@ Sysfs entries fan[1-12]_input RO fan tachometer speed in RPM fan[1-12]_fault RO fan experienced fault fan[1-6]_target RW desired fan speed in RPM -pwm[1-6]_enable RW regulator mode, 0=disabled, 1=manual mode, 2=rpm mode -pwm[1-6] RW fan target duty cycle (0-255) +pwm[1-6]_enable RW regulator mode, 0=disabled (duty cycle=0%), 1=manual mode, 2=rpm mode +pwm[1-6] RW read: current pwm duty cycle, + write: target pwm duty cycle (0-255) ================== === ======================================================= diff --git a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst index ce728c757eaf8d64b5d15be20b4ef7e682762dfd..b864869b42bc86bd364d72c16945091e46bc7a33 100644 --- a/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst +++ b/Documentation/userspace-api/media/v4l/ext-ctrls-codec.rst @@ -4030,7 +4030,7 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - :stub-columns: 0 :widths: 1 1 2 - * - ``V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT`` + * - ``V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED`` - 0x00000001 - * - ``V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT`` @@ -4238,6 +4238,9 @@ enum v4l2_mpeg_video_hevc_size_of_length_field - * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED`` - 0x00000100 - + * - ``V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT`` + - 0x00000200 + - .. c:type:: v4l2_hevc_dpb_entry diff --git a/Documentation/vm/arch_pgtable_helpers.rst b/Documentation/vm/arch_pgtable_helpers.rst index f3591ee3aaa89ab7274bf3cef6be6c21f9a3e1a0..552567d863b86584b814d3540c69b033e5f1b005 100644 --- a/Documentation/vm/arch_pgtable_helpers.rst +++ b/Documentation/vm/arch_pgtable_helpers.rst @@ -50,7 +50,7 @@ PTE Page Table Helpers +---------------------------+--------------------------------------------------+ | pte_mkwrite | Creates a writable PTE | +---------------------------+--------------------------------------------------+ -| pte_mkwrprotect | Creates a write protected PTE | +| pte_wrprotect | Creates a write protected PTE | +---------------------------+--------------------------------------------------+ | pte_mkspecial | Creates a special PTE | +---------------------------+--------------------------------------------------+ @@ -120,7 +120,7 @@ PMD Page Table Helpers +---------------------------+--------------------------------------------------+ | pmd_mkwrite | Creates a writable PMD | +---------------------------+--------------------------------------------------+ -| pmd_mkwrprotect | Creates a write protected PMD | +| pmd_wrprotect | Creates a write protected PMD | +---------------------------+--------------------------------------------------+ | pmd_mkspecial | Creates a special PMD | +---------------------------+--------------------------------------------------+ @@ -186,7 +186,7 @@ PUD Page Table Helpers +---------------------------+--------------------------------------------------+ | pud_mkwrite | Creates a writable PUD | +---------------------------+--------------------------------------------------+ -| pud_mkwrprotect | Creates a write protected PUD | +| pud_wrprotect | Creates a write protected PUD | +---------------------------+--------------------------------------------------+ | pud_mkdevmap | Creates a ZONE_DEVICE mapped PUD | +---------------------------+--------------------------------------------------+ @@ -224,7 +224,7 @@ HugeTLB Page Table Helpers +---------------------------+--------------------------------------------------+ | huge_pte_mkwrite | Creates a writable HugeTLB | +---------------------------+--------------------------------------------------+ -| huge_pte_mkwrprotect | Creates a write protected HugeTLB | +| huge_pte_wrprotect | Creates a write protected HugeTLB | +---------------------------+--------------------------------------------------+ | huge_ptep_get_and_clear | Clears a HugeTLB | +---------------------------+--------------------------------------------------+ diff --git a/Makefile b/Makefile index 7ab22f105a032d4fa2abeb566df4705162af8ddb..23d656936d405534b0d777230f6dbf63bf5b8f26 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 5 PATCHLEVEL = 10 -SUBLEVEL = 46 +SUBLEVEL = 52 EXTRAVERSION = NAME = Dare mighty things @@ -978,7 +978,7 @@ LDFLAGS_vmlinux += $(call ld-option, -X,) endif ifeq ($(CONFIG_RELR),y) -LDFLAGS_vmlinux += --pack-dyn-relocs=relr +LDFLAGS_vmlinux += --pack-dyn-relocs=relr --use-android-relr-tags endif # We never want expected sections to be placed heuristically by the diff --git a/arch/alpha/kernel/smp.c b/arch/alpha/kernel/smp.c index f4dd9f3f30010ba5f62d0bfa10ada7876837d3fa..4b2575f936d46e77c82e9c003bd53b98e1f9291b 100644 --- a/arch/alpha/kernel/smp.c +++ b/arch/alpha/kernel/smp.c @@ -166,7 +166,6 @@ smp_callin(void) DBGS(("smp_callin: commencing CPU %d current %p active_mm %p\n", cpuid, current, current->active_mm)); - preempt_disable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } diff --git a/arch/arc/kernel/smp.c b/arch/arc/kernel/smp.c index 52906d3145371b4a5a0bbaba5d1d9239480465da..db0e104d68355b6dd0a35524960983291ccda9c4 100644 --- a/arch/arc/kernel/smp.c +++ b/arch/arc/kernel/smp.c @@ -189,7 +189,6 @@ void start_kernel_secondary(void) pr_info("## CPU%u LIVE ##: Executing Code...\n", cpu); local_irq_enable(); - preempt_disable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } diff --git a/arch/arm/boot/dts/am335x-cm-t335.dts b/arch/arm/boot/dts/am335x-cm-t335.dts index c6fe9db660e2bffeabe84f0c4100885be17c610c..08c89f1768456cf2477d1fee35d09fb16e03ab00 100644 --- a/arch/arm/boot/dts/am335x-cm-t335.dts +++ b/arch/arm/boot/dts/am335x-cm-t335.dts @@ -496,7 +496,7 @@ status = "okay"; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <&spi0_pins>; - ti,pindir-d0-out-d1-in = <1>; + ti,pindir-d0-out-d1-in; /* WLS1271 WiFi */ wlcore: wlcore@1 { compatible = "ti,wl1271"; diff --git a/arch/arm/boot/dts/am43x-epos-evm.dts b/arch/arm/boot/dts/am43x-epos-evm.dts index f517d1e843cf4cc2d0803c4f95c77a7f27aa765f..8b696107eef8c2388200ebb4e9b1504b119e4fa9 100644 --- a/arch/arm/boot/dts/am43x-epos-evm.dts +++ b/arch/arm/boot/dts/am43x-epos-evm.dts @@ -860,7 +860,7 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&spi0_pins_default>; pinctrl-1 = <&spi0_pins_sleep>; - ti,pindir-d0-out-d1-in = <1>; + ti,pindir-d0-out-d1-in; }; &spi1 { @@ -868,7 +868,7 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&spi1_pins_default>; pinctrl-1 = <&spi1_pins_sleep>; - ti,pindir-d0-out-d1-in = <1>; + ti,pindir-d0-out-d1-in; }; &usb2_phy1 { diff --git a/arch/arm/boot/dts/am5718.dtsi b/arch/arm/boot/dts/am5718.dtsi index ebf4d3cc1cfbebe80c07805902b00873ea1fd2a1..6d7530a48c73f0f8d712528f6af788f7838358c0 100644 --- a/arch/arm/boot/dts/am5718.dtsi +++ b/arch/arm/boot/dts/am5718.dtsi @@ -17,17 +17,13 @@ * VCP1, VCP2 * MLB * ISS - * USB3, USB4 + * USB3 */ &usb3_tm { status = "disabled"; }; -&usb4_tm { - status = "disabled"; -}; - &atl_tm { status = "disabled"; }; diff --git a/arch/arm/boot/dts/bcm5301x.dtsi b/arch/arm/boot/dts/bcm5301x.dtsi index ac3a99cf20793aa3559e0e63398f4196857cf9f2..72b0df6910bd51c07d078a383f49221b087c39cb 100644 --- a/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi @@ -515,27 +515,27 @@ <0x1811b408 0x004>, <0x180293a0 0x01c>; reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg"; - interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, + interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "spi_lr_fullness_reached", + <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "mspi_done", + "mspi_halted", + "spi_lr_fullness_reached", "spi_lr_session_aborted", "spi_lr_impatient", "spi_lr_session_done", - "spi_lr_overhead", - "mspi_done", - "mspi_halted"; + "spi_lr_overread"; clocks = <&iprocmed>; clock-names = "iprocmed"; num-cs = <2>; #address-cells = <1>; #size-cells = <0>; - spi_nor: spi-nor@0 { + spi_nor: flash@0 { compatible = "jedec,spi-nor"; reg = <0>; spi-max-frequency = <20000000>; diff --git a/arch/arm/boot/dts/dra7-l4.dtsi b/arch/arm/boot/dts/dra7-l4.dtsi index a294a02f2d232e0994d037d536c3a3df32e30def..1dafce92fc767fb20db1eca19e588b29ae172fa5 100644 --- a/arch/arm/boot/dts/dra7-l4.dtsi +++ b/arch/arm/boot/dts/dra7-l4.dtsi @@ -4095,28 +4095,6 @@ }; }; - usb4_tm: target-module@140000 { /* 0x48940000, ap 75 3c.0 */ - compatible = "ti,sysc-omap4", "ti,sysc"; - reg = <0x140000 0x4>, - <0x140010 0x4>; - reg-names = "rev", "sysc"; - ti,sysc-mask = <SYSC_OMAP4_DMADISABLE>; - ti,sysc-midle = <SYSC_IDLE_FORCE>, - <SYSC_IDLE_NO>, - <SYSC_IDLE_SMART>, - <SYSC_IDLE_SMART_WKUP>; - ti,sysc-sidle = <SYSC_IDLE_FORCE>, - <SYSC_IDLE_NO>, - <SYSC_IDLE_SMART>, - <SYSC_IDLE_SMART_WKUP>; - /* Domains (P, C): l3init_pwrdm, l3init_clkdm */ - clocks = <&l3init_clkctrl DRA7_L3INIT_USB_OTG_SS4_CLKCTRL 0>; - clock-names = "fck"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x140000 0x20000>; - }; - target-module@170000 { /* 0x48970000, ap 21 0a.0 */ compatible = "ti,sysc-omap4", "ti,sysc"; reg = <0x170010 0x4>; diff --git a/arch/arm/boot/dts/dra71x.dtsi b/arch/arm/boot/dts/dra71x.dtsi index cad0e4a2bd8df1e1d6691d7b6aadb39defd62114..9c270d8f75d5bd7f6f54cad2677fd18e242e9a92 100644 --- a/arch/arm/boot/dts/dra71x.dtsi +++ b/arch/arm/boot/dts/dra71x.dtsi @@ -11,7 +11,3 @@ &rtctarget { status = "disabled"; }; - -&usb4_tm { - status = "disabled"; -}; diff --git a/arch/arm/boot/dts/dra72x.dtsi b/arch/arm/boot/dts/dra72x.dtsi index d403acc754b688192a3c7decc12b7f341ff945b0..f3e934ef7d3e2a2716a037d77d4a682a11c3e4b7 100644 --- a/arch/arm/boot/dts/dra72x.dtsi +++ b/arch/arm/boot/dts/dra72x.dtsi @@ -108,7 +108,3 @@ &pcie2_rc { compatible = "ti,dra726-pcie-rc", "ti,dra7-pcie"; }; - -&usb4_tm { - status = "disabled"; -}; diff --git a/arch/arm/boot/dts/dra74x.dtsi b/arch/arm/boot/dts/dra74x.dtsi index e1850d6c841a705d777ff875f2cc4eeefbc33071..b4e07d99ffde178d6c3fc6235df0887dc2e04bc1 100644 --- a/arch/arm/boot/dts/dra74x.dtsi +++ b/arch/arm/boot/dts/dra74x.dtsi @@ -49,49 +49,6 @@ reg = <0x41500000 0x100>; }; - target-module@48940000 { - compatible = "ti,sysc-omap4", "ti,sysc"; - reg = <0x48940000 0x4>, - <0x48940010 0x4>; - reg-names = "rev", "sysc"; - ti,sysc-mask = <SYSC_OMAP4_DMADISABLE>; - ti,sysc-midle = <SYSC_IDLE_FORCE>, - <SYSC_IDLE_NO>, - <SYSC_IDLE_SMART>, - <SYSC_IDLE_SMART_WKUP>; - ti,sysc-sidle = <SYSC_IDLE_FORCE>, - <SYSC_IDLE_NO>, - <SYSC_IDLE_SMART>, - <SYSC_IDLE_SMART_WKUP>; - clocks = <&l3init_clkctrl DRA7_L3INIT_USB_OTG_SS4_CLKCTRL 0>; - clock-names = "fck"; - #address-cells = <1>; - #size-cells = <1>; - ranges = <0x0 0x48940000 0x20000>; - - omap_dwc3_4: omap_dwc3_4@0 { - compatible = "ti,dwc3"; - reg = <0 0x10000>; - interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>; - #address-cells = <1>; - #size-cells = <1>; - utmi-mode = <2>; - ranges; - status = "disabled"; - usb4: usb@10000 { - compatible = "snps,dwc3"; - reg = <0x10000 0x17000>; - interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>, - <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>; - interrupt-names = "peripheral", - "host", - "otg"; - maximum-speed = "high-speed"; - dr_mode = "otg"; - }; - }; - }; target-module@41501000 { compatible = "ti,sysc-omap2", "ti,sysc"; @@ -224,3 +181,52 @@ &pcie2_rc { compatible = "ti,dra746-pcie-rc", "ti,dra7-pcie"; }; + +&l4_per3 { + segment@0 { + usb4_tm: target-module@140000 { /* 0x48940000, ap 75 3c.0 */ + compatible = "ti,sysc-omap4", "ti,sysc"; + reg = <0x140000 0x4>, + <0x140010 0x4>; + reg-names = "rev", "sysc"; + ti,sysc-mask = <SYSC_OMAP4_DMADISABLE>; + ti,sysc-midle = <SYSC_IDLE_FORCE>, + <SYSC_IDLE_NO>, + <SYSC_IDLE_SMART>, + <SYSC_IDLE_SMART_WKUP>; + ti,sysc-sidle = <SYSC_IDLE_FORCE>, + <SYSC_IDLE_NO>, + <SYSC_IDLE_SMART>, + <SYSC_IDLE_SMART_WKUP>; + /* Domains (P, C): l3init_pwrdm, l3init_clkdm */ + clocks = <&l3init_clkctrl DRA7_L3INIT_USB_OTG_SS4_CLKCTRL 0>; + clock-names = "fck"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x140000 0x20000>; + + omap_dwc3_4: omap_dwc3_4@0 { + compatible = "ti,dwc3"; + reg = <0 0x10000>; + interrupts = <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>; + #address-cells = <1>; + #size-cells = <1>; + utmi-mode = <2>; + ranges; + status = "disabled"; + usb4: usb@10000 { + compatible = "snps,dwc3"; + reg = <0x10000 0x17000>; + interrupts = <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 345 IRQ_TYPE_LEVEL_HIGH>, + <GIC_SPI 346 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "peripheral", + "host", + "otg"; + maximum-speed = "high-speed"; + dr_mode = "otg"; + }; + }; + }; + }; +}; diff --git a/arch/arm/boot/dts/exynos5422-odroidhc1.dts b/arch/arm/boot/dts/exynos5422-odroidhc1.dts index 812659260278634ac1c3f739af96b32e30db5dfe..88f5c150a30a17df075a166472572e6724cd42d4 100644 --- a/arch/arm/boot/dts/exynos5422-odroidhc1.dts +++ b/arch/arm/boot/dts/exynos5422-odroidhc1.dts @@ -22,7 +22,7 @@ label = "blue:heartbeat"; pwms = <&pwm 2 2000000 0>; pwm-names = "pwm2"; - max_brightness = <255>; + max-brightness = <255>; linux,default-trigger = "heartbeat"; }; }; diff --git a/arch/arm/boot/dts/exynos5422-odroidxu4.dts b/arch/arm/boot/dts/exynos5422-odroidxu4.dts index ddd55d3bcadd00756f9172e6b5f88d0372cf4dff..4ef0dbc84b0ca4c1543ef3822590e71d06a19d7d 100644 --- a/arch/arm/boot/dts/exynos5422-odroidxu4.dts +++ b/arch/arm/boot/dts/exynos5422-odroidxu4.dts @@ -24,7 +24,7 @@ label = "blue:heartbeat"; pwms = <&pwm 2 2000000 0>; pwm-names = "pwm2"; - max_brightness = <255>; + max-brightness = <255>; linux,default-trigger = "heartbeat"; }; }; diff --git a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi index 56acd832f0b3c3effef5aca5f62ea8f8eea77eb5..16e1087ec7172b93a0c273826f991976d11655ed 100644 --- a/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi +++ b/arch/arm/boot/dts/exynos54xx-odroidxu-leds.dtsi @@ -22,7 +22,7 @@ * Green LED is much brighter than the others * so limit its max brightness */ - max_brightness = <127>; + max-brightness = <127>; linux,default-trigger = "mmc0"; }; @@ -30,7 +30,7 @@ label = "blue:heartbeat"; pwms = <&pwm 2 2000000 0>; pwm-names = "pwm2"; - max_brightness = <255>; + max-brightness = <255>; linux,default-trigger = "heartbeat"; }; }; diff --git a/arch/arm/boot/dts/gemini-rut1xx.dts b/arch/arm/boot/dts/gemini-rut1xx.dts index 9611ddf067927451018d6797369c9348e1dea8a1..08091d2a64e1526d1930b8db4ddff07634e2a5ef 100644 --- a/arch/arm/boot/dts/gemini-rut1xx.dts +++ b/arch/arm/boot/dts/gemini-rut1xx.dts @@ -125,18 +125,6 @@ }; }; - ethernet@60000000 { - status = "okay"; - - ethernet-port@0 { - phy-mode = "rgmii"; - phy-handle = <&phy0>; - }; - ethernet-port@1 { - /* Not used in this platform */ - }; - }; - usb@68000000 { status = "okay"; }; diff --git a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi index d0768ae429faaf7d897715e8bfad042bf5630880..e3de2b487cf490f350da531fb169f63c58c66c34 100644 --- a/arch/arm/boot/dts/imx6q-dhcom-som.dtsi +++ b/arch/arm/boot/dts/imx6q-dhcom-som.dtsi @@ -96,30 +96,40 @@ reg = <0>; max-speed = <100>; reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; - reset-delay-us = <1000>; - reset-post-delay-us = <1000>; + reset-assert-us = <1000>; + reset-deassert-us = <1000>; + smsc,disable-energy-detect; /* Make plugin detection reliable */ }; }; }; &i2c1 { clock-frequency = <100000>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c1>; + pinctrl-1 = <&pinctrl_i2c1_gpio>; + scl-gpios = <&gpio3 21 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio3 28 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; }; &i2c2 { clock-frequency = <100000>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c2>; + pinctrl-1 = <&pinctrl_i2c2_gpio>; + scl-gpios = <&gpio4 12 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio4 13 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; }; &i2c3 { clock-frequency = <100000>; - pinctrl-names = "default"; + pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c3>; + pinctrl-1 = <&pinctrl_i2c3_gpio>; + scl-gpios = <&gpio1 3 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; + sda-gpios = <&gpio1 6 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>; status = "okay"; ltc3676: pmic@3c { @@ -285,6 +295,13 @@ >; }; + pinctrl_i2c1_gpio: i2c1-gpio-grp { + fsl,pins = < + MX6QDL_PAD_EIM_D21__GPIO3_IO21 0x4001b8b1 + MX6QDL_PAD_EIM_D28__GPIO3_IO28 0x4001b8b1 + >; + }; + pinctrl_i2c2: i2c2-grp { fsl,pins = < MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 @@ -292,6 +309,13 @@ >; }; + pinctrl_i2c2_gpio: i2c2-gpio-grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__GPIO4_IO12 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__GPIO4_IO13 0x4001b8b1 + >; + }; + pinctrl_i2c3: i2c3-grp { fsl,pins = < MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 @@ -299,6 +323,13 @@ >; }; + pinctrl_i2c3_gpio: i2c3-gpio-grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__GPIO1_IO03 0x4001b8b1 + MX6QDL_PAD_GPIO_6__GPIO1_IO06 0x4001b8b1 + >; + }; + pinctrl_pmic_hw300: pmic-hw300-grp { fsl,pins = < MX6QDL_PAD_EIM_A25__GPIO5_IO02 0x1B0B0 diff --git a/arch/arm/boot/dts/r8a7779-marzen.dts b/arch/arm/boot/dts/r8a7779-marzen.dts index d2240b89ee52929bfb5e1dead1e5c4b2131e1823..46584532349590d180b26e09bb42b3b225b09c81 100644 --- a/arch/arm/boot/dts/r8a7779-marzen.dts +++ b/arch/arm/boot/dts/r8a7779-marzen.dts @@ -145,7 +145,7 @@ status = "okay"; clocks = <&mstp1_clks R8A7779_CLK_DU>, <&x3_clk>; - clock-names = "du", "dclkin.0"; + clock-names = "du.0", "dclkin.0"; ports { port@0 { diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi index 74d7e9084eabe17391157b7023c9c1706dd2bf01..3c5fcdfe16b871826c6541940fddac357154b5e1 100644 --- a/arch/arm/boot/dts/r8a7779.dtsi +++ b/arch/arm/boot/dts/r8a7779.dtsi @@ -463,6 +463,7 @@ reg = <0xfff80000 0x40000>; interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>; clocks = <&mstp1_clks R8A7779_CLK_DU>; + clock-names = "du.0"; power-domains = <&sysc R8A7779_PD_ALWAYS_ON>; status = "disabled"; diff --git a/arch/arm/boot/dts/sama5d4.dtsi b/arch/arm/boot/dts/sama5d4.dtsi index 04f24cf752d34935d53a03abb5f10e4998141ca4..e5c2c52013e3e24b6c3e06adda11c32cd77b168b 100644 --- a/arch/arm/boot/dts/sama5d4.dtsi +++ b/arch/arm/boot/dts/sama5d4.dtsi @@ -809,7 +809,7 @@ 0xffffffff 0x3ffcfe7c 0x1c010101 /* pioA */ 0x7fffffff 0xfffccc3a 0x3f00cc3a /* pioB */ 0xffffffff 0x3ff83fff 0xff00ffff /* pioC */ - 0x0003ff00 0x8002a800 0x00000000 /* pioD */ + 0xb003ff00 0x8002a800 0x00000000 /* pioD */ 0xffffffff 0x7fffffff 0x76fff1bf /* pioE */ >; diff --git a/arch/arm/boot/dts/ste-href.dtsi b/arch/arm/boot/dts/ste-href.dtsi index ff47cbf6ed3b7c6b66298c7022f9f897f53de852..359c1219b0babebe92187847c64ec60d3c6d587c 100644 --- a/arch/arm/boot/dts/ste-href.dtsi +++ b/arch/arm/boot/dts/ste-href.dtsi @@ -4,6 +4,7 @@ */ #include <dt-bindings/interrupt-controller/irq.h> +#include <dt-bindings/leds/common.h> #include "ste-href-family-pinctrl.dtsi" / { @@ -64,17 +65,20 @@ reg = <0>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; + color = <LED_COLOR_ID_BLUE>; linux,default-trigger = "heartbeat"; }; chan@1 { reg = <1>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; + color = <LED_COLOR_ID_BLUE>; }; chan@2 { reg = <2>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; + color = <LED_COLOR_ID_BLUE>; }; }; lp5521@34 { @@ -88,16 +92,19 @@ reg = <0>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; + color = <LED_COLOR_ID_BLUE>; }; chan@1 { reg = <1>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; + color = <LED_COLOR_ID_BLUE>; }; chan@2 { reg = <2>; led-cur = /bits/ 8 <0x2f>; max-cur = /bits/ 8 <0x5f>; + color = <LED_COLOR_ID_BLUE>; }; }; bh1780@29 { diff --git a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi b/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi index 2d027dafb7bce991d87a73bb9de8713ff7a70581..27f19575fada6a30b2892cf619f9c182329e8194 100644 --- a/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi +++ b/arch/arm/boot/dts/stm32mp15xx-dhcom-som.dtsi @@ -118,7 +118,6 @@ max-speed = <100>; phy-handle = <&phy0>; st,eth-ref-clk-sel; - phy-reset-gpios = <&gpioh 3 GPIO_ACTIVE_LOW>; mdio0 { #address-cells = <1>; @@ -127,6 +126,15 @@ phy0: ethernet-phy@1 { reg = <1>; + /* LAN8710Ai */ + compatible = "ethernet-phy-id0007.c0f0", + "ethernet-phy-ieee802.3-c22"; + clocks = <&rcc ETHCK_K>; + reset-gpios = <&gpioh 3 GPIO_ACTIVE_LOW>; + reset-assert-us = <500>; + reset-deassert-us = <500>; + interrupt-parent = <&gpioi>; + interrupts = <11 IRQ_TYPE_LEVEL_LOW>; }; }; }; diff --git a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts index 97f497854e05d26819a692139f0a1e336c8de9a1..d05fa679dcd30558aab6d7a8e33e5308a6b16f98 100644 --- a/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts +++ b/arch/arm/boot/dts/sun8i-h3-orangepi-plus.dts @@ -85,7 +85,7 @@ pinctrl-0 = <&emac_rgmii_pins>; phy-supply = <®_gmac_3v3>; phy-handle = <&ext_rgmii_phy>; - phy-mode = "rgmii"; + phy-mode = "rgmii-id"; status = "okay"; }; diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c index 2924d7910b106bd10f16364852ebee0f87190367..eb2190477da10ae8631efee2d647c9fc9c76081d 100644 --- a/arch/arm/kernel/perf_event_v7.c +++ b/arch/arm/kernel/perf_event_v7.c @@ -773,10 +773,10 @@ static inline void armv7pmu_write_counter(struct perf_event *event, u64 value) pr_err("CPU%u writing wrong counter %d\n", smp_processor_id(), idx); } else if (idx == ARMV7_IDX_CYCLE_COUNTER) { - asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" (value)); + asm volatile("mcr p15, 0, %0, c9, c13, 0" : : "r" ((u32)value)); } else { armv7_pmnc_select_counter(idx); - asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" (value)); + asm volatile("mcr p15, 0, %0, c9, c13, 2" : : "r" ((u32)value)); } } diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index f90479d8b50c8aa2909aba845b8d5dde2e26498f..b06602cea99c786bc478bdd6b23e835efa9885b2 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -544,9 +544,11 @@ void notrace cpu_init(void) * In Thumb-2, msr with an immediate value is not allowed. */ #ifdef CONFIG_THUMB2_KERNEL -#define PLC "r" +#define PLC_l "l" +#define PLC_r "r" #else -#define PLC "I" +#define PLC_l "I" +#define PLC_r "I" #endif /* @@ -568,15 +570,15 @@ void notrace cpu_init(void) "msr cpsr_c, %9" : : "r" (stk), - PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), + PLC_r (PSR_F_BIT | PSR_I_BIT | IRQ_MODE), "I" (offsetof(struct stack, irq[0])), - PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE), + PLC_r (PSR_F_BIT | PSR_I_BIT | ABT_MODE), "I" (offsetof(struct stack, abt[0])), - PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE), + PLC_r (PSR_F_BIT | PSR_I_BIT | UND_MODE), "I" (offsetof(struct stack, und[0])), - PLC (PSR_F_BIT | PSR_I_BIT | FIQ_MODE), + PLC_r (PSR_F_BIT | PSR_I_BIT | FIQ_MODE), "I" (offsetof(struct stack, fiq[0])), - PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE) + PLC_l (PSR_F_BIT | PSR_I_BIT | SVC_MODE) : "r14"); #endif } diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 48099c6e1e4a631f1269faba4f9cf96bb666b938..8aa7fa949c2322d2401f9751c6c3bd14896cf37c 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -432,7 +432,6 @@ asmlinkage void secondary_start_kernel(void) #endif pr_debug("CPU%u: Booted secondary processor\n", cpu); - preempt_disable(); trace_hardirqs_off(); /* diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c index 700763e07083d547296461c26293f8469573509d..83d1d1327f96e012e5136a69e95bfbb1543d19ad 100644 --- a/arch/arm/mach-exynos/exynos.c +++ b/arch/arm/mach-exynos/exynos.c @@ -55,6 +55,7 @@ void __init exynos_sysram_init(void) sysram_base_addr = of_iomap(node, 0); sysram_base_phys = of_translate_address(node, of_get_address(node, 0, NULL, NULL)); + of_node_put(node); break; } @@ -62,6 +63,7 @@ void __init exynos_sysram_init(void) if (!of_device_is_available(node)) continue; sysram_ns_base_addr = of_iomap(node, 0); + of_node_put(node); break; } } diff --git a/arch/arm/probes/kprobes/test-thumb.c b/arch/arm/probes/kprobes/test-thumb.c index 456c181a7bfe8c966537881d679c464272573972..4e11f0b760f89e49d5ea9b2d1067d4f94df5a36b 100644 --- a/arch/arm/probes/kprobes/test-thumb.c +++ b/arch/arm/probes/kprobes/test-thumb.c @@ -441,21 +441,21 @@ void kprobe_thumb32_test_cases(void) "3: mvn r0, r0 \n\t" "2: nop \n\t") - TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,"]", + TEST_RX("tbh [pc, r",7, (9f-(1f+4))>>1,", lsl #1]", "9: \n\t" ".short (2f-1b-4)>>1 \n\t" ".short (3f-1b-4)>>1 \n\t" "3: mvn r0, r0 \n\t" "2: nop \n\t") - TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,"]", + TEST_RX("tbh [pc, r",12, ((9f-(1f+4))>>1)+1,", lsl #1]", "9: \n\t" ".short (2f-1b-4)>>1 \n\t" ".short (3f-1b-4)>>1 \n\t" "3: mvn r0, r0 \n\t" "2: nop \n\t") - TEST_RRX("tbh [r",1,9f, ", r",14,1,"]", + TEST_RRX("tbh [r",1,9f, ", r",14,1,", lsl #1]", "9: \n\t" ".short (2f-1b-4)>>1 \n\t" ".short (3f-1b-4)>>1 \n\t" @@ -468,10 +468,10 @@ void kprobe_thumb32_test_cases(void) TEST_UNSUPPORTED("strexb r0, r1, [r2]") TEST_UNSUPPORTED("strexh r0, r1, [r2]") - TEST_UNSUPPORTED("strexd r0, r1, [r2]") + TEST_UNSUPPORTED("strexd r0, r1, r2, [r2]") TEST_UNSUPPORTED("ldrexb r0, [r1]") TEST_UNSUPPORTED("ldrexh r0, [r1]") - TEST_UNSUPPORTED("ldrexd r0, [r1]") + TEST_UNSUPPORTED("ldrexd r0, r1, [r1]") TEST_GROUP("Data-processing (shifted register) and (modified immediate)") diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts index d4069749d72164c29b87627f40a845cf67318a2c..068cbd955bfc22e3359151cd357df949a8e09ea2 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine-baseboard.dts @@ -79,7 +79,7 @@ &emac { pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; - phy-mode = "rgmii-id"; + phy-mode = "rgmii-txid"; phy-handle = <&ext_rgmii_phy>; phy-supply = <®_dc1sw>; status = "okay"; diff --git a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi index a89e47d95eef22fb51f841cbdd47e2684f7c6ed1..879115dfdf828ce949e9e78c8c41ca54070c0bdf 100644 --- a/arch/arm64/boot/dts/marvell/armada-37xx.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-37xx.dtsi @@ -134,7 +134,7 @@ uart0: serial@12000 { compatible = "marvell,armada-3700-uart"; - reg = <0x12000 0x200>; + reg = <0x12000 0x18>; clocks = <&xtalclk>; interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>, diff --git a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi index bf875589d3640330e0788e90defc9ac454b9a763..5b2a616c6257b8a0a53d2568a0ffb72eb74b0ecf 100644 --- a/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi +++ b/arch/arm64/boot/dts/qcom/sc7180-trogdor.dtsi @@ -622,6 +622,8 @@ edp_brij_i2c: &i2c2 { clocks = <&rpmhcc RPMH_LN_BB_CLK3>; clock-names = "refclk"; + no-hpd; + ports { #address-cells = <1>; #size-cells = <0>; diff --git a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi index c15f1c571eb0d6f7fd97396fef9158b9fe8ae50c..db091fa7511519513ab0eafc7fd39927873ffb29 100644 --- a/arch/arm64/boot/dts/renesas/r8a774a1.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a774a1.dtsi @@ -76,6 +76,7 @@ opp-hz = /bits/ 64 <1500000000>; opp-microvolt = <820000>; clock-latency-ns = <300000>; + opp-suspend; }; }; diff --git a/arch/arm64/boot/dts/renesas/r8a77960.dtsi b/arch/arm64/boot/dts/renesas/r8a77960.dtsi index f379c8d1511d91e526d0dbaf17dfe25b96a0480b..fa9567ed55e4d910172bc82f7c9f31ca53283950 100644 --- a/arch/arm64/boot/dts/renesas/r8a77960.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77960.dtsi @@ -63,18 +63,19 @@ opp-500000000 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <820000>; + opp-microvolt = <830000>; clock-latency-ns = <300000>; }; opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <820000>; + opp-microvolt = <830000>; clock-latency-ns = <300000>; }; opp-1500000000 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <820000>; + opp-microvolt = <830000>; clock-latency-ns = <300000>; + opp-suspend; }; opp-1600000000 { opp-hz = /bits/ 64 <1600000000>; diff --git a/arch/arm64/boot/dts/renesas/r8a77961.dtsi b/arch/arm64/boot/dts/renesas/r8a77961.dtsi index 1ba30313c8b82ac56454046411c30ee684833bf0..b23f49b89cadc5b49f44e5549fc4d178f79c0f23 100644 --- a/arch/arm64/boot/dts/renesas/r8a77961.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a77961.dtsi @@ -52,18 +52,19 @@ opp-500000000 { opp-hz = /bits/ 64 <500000000>; - opp-microvolt = <820000>; + opp-microvolt = <830000>; clock-latency-ns = <300000>; }; opp-1000000000 { opp-hz = /bits/ 64 <1000000000>; - opp-microvolt = <820000>; + opp-microvolt = <830000>; clock-latency-ns = <300000>; }; opp-1500000000 { opp-hz = /bits/ 64 <1500000000>; - opp-microvolt = <820000>; + opp-microvolt = <830000>; clock-latency-ns = <300000>; + opp-suspend; }; opp-1600000000 { opp-hz = /bits/ 64 <1600000000>; diff --git a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts index 668a1ece9af00420c40934004c069e1065fafaee..0c66cc0a136741e7c6715d7c99262d810fc32cd3 100644 --- a/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts +++ b/arch/arm64/boot/dts/renesas/r8a77970-v3msk.dts @@ -59,7 +59,7 @@ memory@48000000 { device_type = "memory"; /* first 128MB is reserved for secure area. */ - reg = <0x0 0x48000000 0x0 0x38000000>; + reg = <0x0 0x48000000 0x0 0x78000000>; }; osc5_clk: osc5-clock { diff --git a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi index 86ec32a919d296a983b7091940ff9489579c76d2..bfbb53bf53757048228440c89404b1b846859ce2 100644 --- a/arch/arm64/boot/dts/renesas/r8a779a0.dtsi +++ b/arch/arm64/boot/dts/renesas/r8a779a0.dtsi @@ -111,7 +111,6 @@ <0x0 0xf1060000 0 0x110000>; interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>; - power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>; }; prr: chipid@fff00044 { diff --git a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts index 86cfb5c50a949db9757f803d4bb0864a55fb4a4b..95ab6928cfd40fa544bbda7c78a1e0384ee4bca4 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts +++ b/arch/arm64/boot/dts/rockchip/rk3328-rock64.dts @@ -384,6 +384,11 @@ status = "okay"; }; +&usbdrd3 { + dr_mode = "host"; + status = "okay"; +}; + &usb_host0_ehci { status = "okay"; }; diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi index 93c734d8a46c252fc89bd03e996edd288900dbe2..de1e5e8a0e885f3183c8b3824228aa4ef0347db8 100644 --- a/arch/arm64/boot/dts/rockchip/rk3328.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3328.dtsi @@ -984,6 +984,25 @@ status = "disabled"; }; + usbdrd3: usb@ff600000 { + compatible = "rockchip,rk3328-dwc3", "snps,dwc3"; + reg = <0x0 0xff600000 0x0 0x100000>; + interrupts = <GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&cru SCLK_USB3OTG_REF>, <&cru SCLK_USB3OTG_SUSPEND>, + <&cru ACLK_USB3OTG>; + clock-names = "ref_clk", "suspend_clk", + "bus_clk"; + dr_mode = "otg"; + phy_type = "utmi_wide"; + snps,dis-del-phy-power-chg-quirk; + snps,dis_enblslpm_quirk; + snps,dis-tx-ipgap-linecheck-quirk; + snps,dis-u2-freeclk-exists-quirk; + snps,dis_u2_susphy_quirk; + snps,dis_u3_susphy_quirk; + status = "disabled"; + }; + gic: interrupt-controller@ff811000 { compatible = "arm,gic-400"; #interrupt-cells = <3>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi index 20309076dbac069acb62bd048dbb555e1d2ec53f..35b7ab3bf10c677e1f71cba0ddbb885ccc925f9b 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-roc-pc.dtsi @@ -384,6 +384,7 @@ vcc_sdio: LDO_REG4 { regulator-name = "vcc_sdio"; + regulator-always-on; regulator-boot-on; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <3000000>; @@ -488,6 +489,8 @@ regulator-min-microvolt = <712500>; regulator-max-microvolt = <1500000>; regulator-ramp-delay = <1000>; + regulator-always-on; + regulator-boot-on; vin-supply = <&vcc3v3_sys>; regulator-state-mem { diff --git a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi index 689538244392c97e70ef540afc531105e696d613..5832ad830ed149c06c371bc3f39734e2a76e5905 100644 --- a/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j7200-main.dtsi @@ -446,6 +446,7 @@ "otg"; maximum-speed = "super-speed"; dr_mode = "otg"; + cdns,phyrst-a-enable; }; }; }; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts index 52e121155563ab702beddbed6d2d68530e40c85e..7cd31ac67f88084a6fc85709f8b4f1474b36be87 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts +++ b/arch/arm64/boot/dts/ti/k3-j721e-common-proc-board.dts @@ -560,6 +560,10 @@ status = "okay"; }; +&cmn_refclk1 { + clock-frequency = <100000000>; +}; + &serdes0 { serdes0_pcie_link: link@0 { reg = <0>; diff --git a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi index c66ded9079be415234f0f0f530448524dcbc6144..6ffdebd6012231e58050118bd3bac7852e52096e 100644 --- a/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi +++ b/arch/arm64/boot/dts/ti/k3-j721e-main.dtsi @@ -8,6 +8,20 @@ #include <dt-bindings/mux/mux.h> #include <dt-bindings/mux/ti-serdes.h> +/ { + cmn_refclk: clock-cmnrefclk { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; + + cmn_refclk1: clock-cmnrefclk1 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <0>; + }; +}; + &cbass_main { msmc_ram: sram@70000000 { compatible = "mmio-sram"; @@ -369,24 +383,12 @@ pinctrl-single,function-mask = <0xffffffff>; }; - dummy_cmn_refclk: dummy-cmn-refclk { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <100000000>; - }; - - dummy_cmn_refclk1: dummy-cmn-refclk1 { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <100000000>; - }; - serdes_wiz0: wiz@5000000 { compatible = "ti,j721e-wiz-16g"; #address-cells = <1>; #size-cells = <1>; power-domains = <&k3_pds 292 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 292 5>, <&k3_clks 292 11>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 292 5>, <&k3_clks 292 11>, <&cmn_refclk>; clock-names = "fck", "core_ref_clk", "ext_ref_clk"; assigned-clocks = <&k3_clks 292 11>, <&k3_clks 292 0>; assigned-clock-parents = <&k3_clks 292 15>, <&k3_clks 292 4>; @@ -395,21 +397,21 @@ ranges = <0x5000000 0x0 0x5000000 0x10000>; wiz0_pll0_refclk: pll0-refclk { - clocks = <&k3_clks 292 11>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 292 11>, <&cmn_refclk>; #clock-cells = <0>; assigned-clocks = <&wiz0_pll0_refclk>; assigned-clock-parents = <&k3_clks 292 11>; }; wiz0_pll1_refclk: pll1-refclk { - clocks = <&k3_clks 292 0>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 292 0>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz0_pll1_refclk>; assigned-clock-parents = <&k3_clks 292 0>; }; wiz0_refclk_dig: refclk-dig { - clocks = <&k3_clks 292 11>, <&k3_clks 292 0>, <&dummy_cmn_refclk>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 292 11>, <&k3_clks 292 0>, <&cmn_refclk>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz0_refclk_dig>; assigned-clock-parents = <&k3_clks 292 11>; @@ -443,7 +445,7 @@ #address-cells = <1>; #size-cells = <1>; power-domains = <&k3_pds 293 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 293 5>, <&k3_clks 293 13>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 293 5>, <&k3_clks 293 13>, <&cmn_refclk>; clock-names = "fck", "core_ref_clk", "ext_ref_clk"; assigned-clocks = <&k3_clks 293 13>, <&k3_clks 293 0>; assigned-clock-parents = <&k3_clks 293 17>, <&k3_clks 293 4>; @@ -452,21 +454,21 @@ ranges = <0x5010000 0x0 0x5010000 0x10000>; wiz1_pll0_refclk: pll0-refclk { - clocks = <&k3_clks 293 13>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 293 13>, <&cmn_refclk>; #clock-cells = <0>; assigned-clocks = <&wiz1_pll0_refclk>; assigned-clock-parents = <&k3_clks 293 13>; }; wiz1_pll1_refclk: pll1-refclk { - clocks = <&k3_clks 293 0>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 293 0>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz1_pll1_refclk>; assigned-clock-parents = <&k3_clks 293 0>; }; wiz1_refclk_dig: refclk-dig { - clocks = <&k3_clks 293 13>, <&k3_clks 293 0>, <&dummy_cmn_refclk>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 293 13>, <&k3_clks 293 0>, <&cmn_refclk>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz1_refclk_dig>; assigned-clock-parents = <&k3_clks 293 13>; @@ -500,7 +502,7 @@ #address-cells = <1>; #size-cells = <1>; power-domains = <&k3_pds 294 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 294 5>, <&k3_clks 294 11>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 294 5>, <&k3_clks 294 11>, <&cmn_refclk>; clock-names = "fck", "core_ref_clk", "ext_ref_clk"; assigned-clocks = <&k3_clks 294 11>, <&k3_clks 294 0>; assigned-clock-parents = <&k3_clks 294 15>, <&k3_clks 294 4>; @@ -509,21 +511,21 @@ ranges = <0x5020000 0x0 0x5020000 0x10000>; wiz2_pll0_refclk: pll0-refclk { - clocks = <&k3_clks 294 11>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 294 11>, <&cmn_refclk>; #clock-cells = <0>; assigned-clocks = <&wiz2_pll0_refclk>; assigned-clock-parents = <&k3_clks 294 11>; }; wiz2_pll1_refclk: pll1-refclk { - clocks = <&k3_clks 294 0>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 294 0>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz2_pll1_refclk>; assigned-clock-parents = <&k3_clks 294 0>; }; wiz2_refclk_dig: refclk-dig { - clocks = <&k3_clks 294 11>, <&k3_clks 294 0>, <&dummy_cmn_refclk>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 294 11>, <&k3_clks 294 0>, <&cmn_refclk>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz2_refclk_dig>; assigned-clock-parents = <&k3_clks 294 11>; @@ -557,7 +559,7 @@ #address-cells = <1>; #size-cells = <1>; power-domains = <&k3_pds 295 TI_SCI_PD_EXCLUSIVE>; - clocks = <&k3_clks 295 5>, <&k3_clks 295 9>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 295 5>, <&k3_clks 295 9>, <&cmn_refclk>; clock-names = "fck", "core_ref_clk", "ext_ref_clk"; assigned-clocks = <&k3_clks 295 9>, <&k3_clks 295 0>; assigned-clock-parents = <&k3_clks 295 13>, <&k3_clks 295 4>; @@ -566,21 +568,21 @@ ranges = <0x5030000 0x0 0x5030000 0x10000>; wiz3_pll0_refclk: pll0-refclk { - clocks = <&k3_clks 295 9>, <&dummy_cmn_refclk>; + clocks = <&k3_clks 295 9>, <&cmn_refclk>; #clock-cells = <0>; assigned-clocks = <&wiz3_pll0_refclk>; assigned-clock-parents = <&k3_clks 295 9>; }; wiz3_pll1_refclk: pll1-refclk { - clocks = <&k3_clks 295 0>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 295 0>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz3_pll1_refclk>; assigned-clock-parents = <&k3_clks 295 0>; }; wiz3_refclk_dig: refclk-dig { - clocks = <&k3_clks 295 9>, <&k3_clks 295 0>, <&dummy_cmn_refclk>, <&dummy_cmn_refclk1>; + clocks = <&k3_clks 295 9>, <&k3_clks 295 0>, <&cmn_refclk>, <&cmn_refclk1>; #clock-cells = <0>; assigned-clocks = <&wiz3_refclk_dig>; assigned-clock-parents = <&k3_clks 295 9>; diff --git a/arch/arm64/include/asm/asm-uaccess.h b/arch/arm64/include/asm/asm-uaccess.h index f68a0e64482a1eb2acceb89a000b517175aba6d4..5ef624fef44a2f453803c2480ac56c0c1d8beaeb 100644 --- a/arch/arm64/include/asm/asm-uaccess.h +++ b/arch/arm64/include/asm/asm-uaccess.h @@ -15,10 +15,10 @@ .macro __uaccess_ttbr0_disable, tmp1 mrs \tmp1, ttbr1_el1 // swapper_pg_dir bic \tmp1, \tmp1, #TTBR_ASID_MASK - sub \tmp1, \tmp1, #RESERVED_TTBR0_SIZE // reserved_ttbr0 just before swapper_pg_dir + sub \tmp1, \tmp1, #PAGE_SIZE // reserved_pg_dir just before swapper_pg_dir msr ttbr0_el1, \tmp1 // set reserved TTBR0_EL1 isb - add \tmp1, \tmp1, #RESERVED_TTBR0_SIZE + add \tmp1, \tmp1, #PAGE_SIZE msr ttbr1_el1, \tmp1 // set reserved ASID isb .endm diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index 19ca76ea60d98ae6338b677988dc4ccc5cda6b15..587c504a4c8b2d5162a23c566283e6b019d60dff 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -89,12 +89,6 @@ #define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end)) #define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE) -#ifdef CONFIG_ARM64_SW_TTBR0_PAN -#define RESERVED_TTBR0_SIZE (PAGE_SIZE) -#else -#define RESERVED_TTBR0_SIZE (0) -#endif - /* Initial memory map size */ #if ARM64_SWAPPER_USES_SECTION_MAPS #define SWAPPER_BLOCK_SHIFT SECTION_SHIFT diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h index 4e2ba947784503d92fafe3175a28d4b39d75801a..5a54a5ab5f928bab4a199b40e599191e22b837b6 100644 --- a/arch/arm64/include/asm/mmu_context.h +++ b/arch/arm64/include/asm/mmu_context.h @@ -36,11 +36,11 @@ static inline void contextidr_thread_switch(struct task_struct *next) } /* - * Set TTBR0 to empty_zero_page. No translations will be possible via TTBR0. + * Set TTBR0 to reserved_pg_dir. No translations will be possible via TTBR0. */ static inline void cpu_set_reserved_ttbr0(void) { - unsigned long ttbr = phys_to_ttbr(__pa_symbol(empty_zero_page)); + unsigned long ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir)); write_sysreg(ttbr, ttbr0_el1); isb(); @@ -192,9 +192,9 @@ static inline void update_saved_ttbr0(struct task_struct *tsk, return; if (mm == &init_mm) - ttbr = __pa_symbol(empty_zero_page); + ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir)); else - ttbr = virt_to_phys(mm->pgd) | ASID(mm) << 48; + ttbr = phys_to_ttbr(virt_to_phys(mm->pgd)) | ASID(mm) << 48; WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr); } diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index f9d3b54a2656bff49c039de39c3ed2c722e34b4e..de457cb9c38c3694a72266f81966b2c44e660e63 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -535,6 +535,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern pgd_t idmap_pg_dir[PTRS_PER_PGD]; extern pgd_t idmap_pg_end[]; extern pgd_t tramp_pg_dir[PTRS_PER_PGD]; +extern pgd_t reserved_pg_dir[PTRS_PER_PGD]; extern void set_swapper_pgd(pgd_t *pgdp, pgd_t pgd); diff --git a/arch/arm64/include/asm/preempt.h b/arch/arm64/include/asm/preempt.h index 80e946b2abee276479fde238d3f01e5d7eecacb3..e83f0982b99c1a6a773401e276b90a1f32fefb0a 100644 --- a/arch/arm64/include/asm/preempt.h +++ b/arch/arm64/include/asm/preempt.h @@ -23,7 +23,7 @@ static inline void preempt_count_set(u64 pc) } while (0) #define init_idle_preempt_count(p, cpu) do { \ - task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \ + task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \ } while (0) static inline void set_preempt_need_resched(void) diff --git a/arch/arm64/include/asm/tlb.h b/arch/arm64/include/asm/tlb.h index 61c97d3b58c7080a8b20ac7bd12accf25a9f81ab..c995d1f4594f6692936425d49436ece7491cf425 100644 --- a/arch/arm64/include/asm/tlb.h +++ b/arch/arm64/include/asm/tlb.h @@ -28,6 +28,10 @@ static void tlb_flush(struct mmu_gather *tlb); */ static inline int tlb_get_level(struct mmu_gather *tlb) { + /* The TTL field is only valid for the leaf entry. */ + if (tlb->freed_tables) + return 0; + if (tlb->cleared_ptes && !(tlb->cleared_pmds || tlb->cleared_puds || tlb->cleared_p4ds)) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 991dd5f031e4613cdfceab311d37aec32ee4d60a..385a189f7d39eada61a81079bc1697603381b858 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -113,8 +113,8 @@ static inline void __uaccess_ttbr0_disable(void) local_irq_save(flags); ttbr = read_sysreg(ttbr1_el1); ttbr &= ~TTBR_ASID_MASK; - /* reserved_ttbr0 placed before swapper_pg_dir */ - write_sysreg(ttbr - RESERVED_TTBR0_SIZE, ttbr0_el1); + /* reserved_pg_dir placed before swapper_pg_dir */ + write_sysreg(ttbr - PAGE_SIZE, ttbr0_el1); isb(); /* Set reserved ASID */ write_sysreg(ttbr, ttbr1_el1); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 60d39912336004fd10fa87ca55aa1135de32ef49..fe83d6d67ec3dc72ae9e3a3d07d4eb8e5149b7c7 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -770,9 +770,10 @@ SYM_CODE_END(ret_to_user) */ .pushsection ".entry.tramp.text", "ax" + // Move from tramp_pg_dir to swapper_pg_dir .macro tramp_map_kernel, tmp mrs \tmp, ttbr1_el1 - add \tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE) + add \tmp, \tmp, #(2 * PAGE_SIZE) bic \tmp, \tmp, #USER_ASID_FLAG msr ttbr1_el1, \tmp #ifdef CONFIG_QCOM_FALKOR_ERRATUM_1003 @@ -789,9 +790,10 @@ alternative_else_nop_endif #endif /* CONFIG_QCOM_FALKOR_ERRATUM_1003 */ .endm + // Move from swapper_pg_dir to tramp_pg_dir .macro tramp_unmap_kernel, tmp mrs \tmp, ttbr1_el1 - sub \tmp, \tmp, #(PAGE_SIZE + RESERVED_TTBR0_SIZE) + sub \tmp, \tmp, #(2 * PAGE_SIZE) orr \tmp, \tmp, #USER_ASID_FLAG msr ttbr1_el1, \tmp /* diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c index 11852e05ee32a93b56fb209753d4d777ec8510d1..cdb3d4549b3a97c45bcb8de79a5f864b09e3d40f 100644 --- a/arch/arm64/kernel/perf_event.c +++ b/arch/arm64/kernel/perf_event.c @@ -312,7 +312,7 @@ static ssize_t slots_show(struct device *dev, struct device_attribute *attr, struct arm_pmu *cpu_pmu = container_of(pmu, struct arm_pmu, pmu); u32 slots = cpu_pmu->reg_pmmir & ARMV8_PMU_SLOTS_MASK; - return snprintf(page, PAGE_SIZE, "0x%08x\n", slots); + return sysfs_emit(page, "0x%08x\n", slots); } static DEVICE_ATTR_RO(slots); diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 133257ffd8591d692f5f64abf8f41fb2d0e0910c..eb4b24652c105d601a39732f02435060a79fc966 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -366,7 +366,7 @@ void __init __no_sanitize_address setup_arch(char **cmdline_p) * faults in case uaccess_enable() is inadvertently called by the init * thread. */ - init_task.thread_info.ttbr0 = __pa_symbol(empty_zero_page); + init_task.thread_info.ttbr0 = phys_to_ttbr(__pa_symbol(reserved_pg_dir)); #endif if (boot_args[1] || boot_args[2] || boot_args[3]) { diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 21f0eb2f63220d2ff3be1c47790da4b7104f406e..547eaf158376c01d6ebf2d9e01bbada3f12888d2 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -223,7 +223,6 @@ asmlinkage notrace void secondary_start_kernel(void) init_gic_priority_masking(); rcu_cpu_starting(cpu); - preempt_disable(); trace_hardirqs_off(); /* diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 1bda604f4c704bd22f810c02fcacd60d720c43e4..30c102978942748b995d51729ca3a4e0b82dddba 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -164,13 +164,11 @@ SECTIONS . += PAGE_SIZE; #endif -#ifdef CONFIG_ARM64_SW_TTBR0_PAN - reserved_ttbr0 = .; - . += RESERVED_TTBR0_SIZE; -#endif + reserved_pg_dir = .; + . += PAGE_SIZE; + swapper_pg_dir = .; . += PAGE_SIZE; - swapper_pg_end = .; . = ALIGN(SEGMENT_ALIGN); __init_begin = .; diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c index 2dd164bb1c5a91175f417b49f6458d8143d12bb8..4b30260e1abf49324a5ffc9f8aa39611245558e6 100644 --- a/arch/arm64/kvm/pmu-emul.c +++ b/arch/arm64/kvm/pmu-emul.c @@ -578,6 +578,7 @@ void kvm_pmu_handle_pmcr(struct kvm_vcpu *vcpu, u64 val) kvm_pmu_set_counter_value(vcpu, ARMV8_PMU_CYCLE_IDX, 0); if (val & ARMV8_PMU_PMCR_P) { + mask &= ~BIT(ARMV8_PMU_CYCLE_IDX); for_each_set_bit(i, &mask, 32) kvm_pmu_set_counter_value(vcpu, i, 0); } diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index a14927360be267d676cb000f3147bc7bf3f1a052..aacc7eab9b2ffa676dfb16fc23f09438b0d4ea2a 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -168,7 +168,7 @@ SYM_FUNC_END(cpu_do_resume) .pushsection ".idmap.text", "awx" .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 - adrp \tmp1, empty_zero_page + adrp \tmp1, reserved_pg_dir phys_to_ttbr \tmp2, \tmp1 offset_ttbr1 \tmp2, \tmp1 msr ttbr1_el1, \tmp2 diff --git a/arch/csky/kernel/smp.c b/arch/csky/kernel/smp.c index 041d0de6a1b6771de342bf1ed74292f93f87d872..1a8d7eaf1ff718a71788f644fa2aa5de105f1466 100644 --- a/arch/csky/kernel/smp.c +++ b/arch/csky/kernel/smp.c @@ -282,7 +282,6 @@ void csky_start_secondary(void) pr_info("CPU%u Online: %s...\n", cpu, __func__); local_irq_enable(); - preempt_disable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } diff --git a/arch/csky/mm/syscache.c b/arch/csky/mm/syscache.c index ffade2f9a4c87914af5c8322fdfc1b9600a204c1..cd847ad62c7ee4ccd45207473d118846afe432f3 100644 --- a/arch/csky/mm/syscache.c +++ b/arch/csky/mm/syscache.c @@ -12,14 +12,17 @@ SYSCALL_DEFINE3(cacheflush, int, cache) { switch (cache) { - case ICACHE: case BCACHE: - flush_icache_mm_range(current->mm, - (unsigned long)addr, - (unsigned long)addr + bytes); case DCACHE: dcache_wb_range((unsigned long)addr, (unsigned long)addr + bytes); + if (cache != BCACHE) + break; + fallthrough; + case ICACHE: + flush_icache_mm_range(current->mm, + (unsigned long)addr, + (unsigned long)addr + bytes); break; default: return -EINVAL; diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile index c168c6980d0507af134e2842e94619de45356a50..74b644ea8a00a882fcac2063421f61448cdd501e 100644 --- a/arch/hexagon/Makefile +++ b/arch/hexagon/Makefile @@ -10,6 +10,9 @@ LDFLAGS_vmlinux += -G0 # Do not use single-byte enums; these will overflow. KBUILD_CFLAGS += -fno-short-enums +# We must use long-calls: +KBUILD_CFLAGS += -mlong-calls + # Modules must use either long-calls, or use pic/plt. # Use long-calls for now, it's easier. And faster. # KBUILD_CFLAGS_MODULE += -fPIC @@ -30,9 +33,6 @@ TIR_NAME := r19 KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__ KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME) -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name 2>/dev/null) -libs-y += $(LIBGCC) - head-y := arch/hexagon/kernel/head.o core-y += arch/hexagon/kernel/ \ diff --git a/arch/hexagon/include/asm/futex.h b/arch/hexagon/include/asm/futex.h index 6b9c554aee78e8be81c749fc35ddaaae1a7432a6..9fb00a0ae89f7cc2c689c9c2fd91d33dfdb80999 100644 --- a/arch/hexagon/include/asm/futex.h +++ b/arch/hexagon/include/asm/futex.h @@ -21,7 +21,7 @@ "3:\n" \ ".section .fixup,\"ax\"\n" \ "4: %1 = #%5;\n" \ - " jump 3b\n" \ + " jump ##3b\n" \ ".previous\n" \ ".section __ex_table,\"a\"\n" \ ".long 1b,4b,2b,4b\n" \ @@ -90,7 +90,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, "3:\n" ".section .fixup,\"ax\"\n" "4: %0 = #%6\n" - " jump 3b\n" + " jump ##3b\n" ".previous\n" ".section __ex_table,\"a\"\n" ".long 1b,4b,2b,4b\n" diff --git a/arch/hexagon/include/asm/timex.h b/arch/hexagon/include/asm/timex.h index 78338d8ada83fc0c200dd0c2b50ed5109dc2d965..8d4ec76fceb458ab3f21e4fa858fae264d1ef166 100644 --- a/arch/hexagon/include/asm/timex.h +++ b/arch/hexagon/include/asm/timex.h @@ -8,6 +8,7 @@ #include <asm-generic/timex.h> #include <asm/timer-regs.h> +#include <asm/hexagon_vm.h> /* Using TCX0 as our clock. CLOCK_TICK_RATE scheduled to be removed. */ #define CLOCK_TICK_RATE TCX0_CLK_RATE @@ -16,7 +17,7 @@ static inline int read_current_timer(unsigned long *timer_val) { - *timer_val = (unsigned long) __vmgettime(); + *timer_val = __vmgettime(); return 0; } diff --git a/arch/hexagon/kernel/hexagon_ksyms.c b/arch/hexagon/kernel/hexagon_ksyms.c index 6fb1aaab1c298b01ac682f2173c250162f22a1f3..35545a7386a06d4fc3fa5b5d13f72d8853e7f5b1 100644 --- a/arch/hexagon/kernel/hexagon_ksyms.c +++ b/arch/hexagon/kernel/hexagon_ksyms.c @@ -35,8 +35,8 @@ EXPORT_SYMBOL(_dflt_cache_att); DECLARE_EXPORT(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes); /* Additional functions */ -DECLARE_EXPORT(__divsi3); -DECLARE_EXPORT(__modsi3); -DECLARE_EXPORT(__udivsi3); -DECLARE_EXPORT(__umodsi3); +DECLARE_EXPORT(__hexagon_divsi3); +DECLARE_EXPORT(__hexagon_modsi3); +DECLARE_EXPORT(__hexagon_udivsi3); +DECLARE_EXPORT(__hexagon_umodsi3); DECLARE_EXPORT(csum_tcpudp_magic); diff --git a/arch/hexagon/kernel/ptrace.c b/arch/hexagon/kernel/ptrace.c index a5a89e944257c95f45899fe6dad803c094d3b114..8975f9b4cedf08b927b51497a682bf53b6b280fa 100644 --- a/arch/hexagon/kernel/ptrace.c +++ b/arch/hexagon/kernel/ptrace.c @@ -35,7 +35,7 @@ void user_disable_single_step(struct task_struct *child) static int genregs_get(struct task_struct *target, const struct user_regset *regset, - srtuct membuf to) + struct membuf to) { struct pt_regs *regs = task_pt_regs(target); @@ -54,7 +54,7 @@ static int genregs_get(struct task_struct *target, membuf_store(&to, regs->m0); membuf_store(&to, regs->m1); membuf_store(&to, regs->usr); - membuf_store(&to, regs->p3_0); + membuf_store(&to, regs->preds); membuf_store(&to, regs->gp); membuf_store(&to, regs->ugp); membuf_store(&to, pt_elr(regs)); // pc diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S index 35b18e55eae80ca396d7ee4361d7c210f9ef26aa..57465bff1fe49717cbf0b68280bae499e337b9d7 100644 --- a/arch/hexagon/kernel/vmlinux.lds.S +++ b/arch/hexagon/kernel/vmlinux.lds.S @@ -38,6 +38,8 @@ SECTIONS .text : AT(ADDR(.text)) { _text = .; TEXT_TEXT + IRQENTRY_TEXT + SOFTIRQENTRY_TEXT SCHED_TEXT CPUIDLE_TEXT LOCK_TEXT @@ -59,14 +61,9 @@ SECTIONS _end = .; - /DISCARD/ : { - EXIT_TEXT - EXIT_DATA - EXIT_CALL - } - STABS_DEBUG DWARF_DEBUG ELF_DETAILS + DISCARDS } diff --git a/arch/hexagon/lib/Makefile b/arch/hexagon/lib/Makefile index 54be529d17a2525400f8f198777a589904b0b3fe..a64641e89d5fe7f6cc79de06525aea7c03611dd2 100644 --- a/arch/hexagon/lib/Makefile +++ b/arch/hexagon/lib/Makefile @@ -2,4 +2,5 @@ # # Makefile for hexagon-specific library files. # -obj-y = checksum.o io.o memcpy.o memset.o +obj-y = checksum.o io.o memcpy.o memset.o memcpy_likely_aligned.o \ + divsi3.o modsi3.o udivsi3.o umodsi3.o diff --git a/arch/hexagon/lib/divsi3.S b/arch/hexagon/lib/divsi3.S new file mode 100644 index 0000000000000000000000000000000000000000..783e09424c2c8ded28b2cf38897bcafb0765b4c7 --- /dev/null +++ b/arch/hexagon/lib/divsi3.S @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/linkage.h> + +SYM_FUNC_START(__hexagon_divsi3) + { + p0 = cmp.gt(r0,#-1) + p1 = cmp.gt(r1,#-1) + r3:2 = vabsw(r1:0) + } + { + p3 = xor(p0,p1) + r4 = sub(r2,r3) + r6 = cl0(r2) + p0 = cmp.gtu(r3,r2) + } + { + r0 = mux(p3,#-1,#1) + r7 = cl0(r3) + p1 = cmp.gtu(r3,r4) + } + { + r0 = mux(p0,#0,r0) + p0 = or(p0,p1) + if (p0.new) jumpr:nt r31 + r6 = sub(r7,r6) + } + { + r7 = r6 + r5:4 = combine(#1,r3) + r6 = add(#1,lsr(r6,#1)) + p0 = cmp.gtu(r6,#4) + } + { + r5:4 = vaslw(r5:4,r7) + if (!p0) r6 = #3 + } + { + loop0(1f,r6) + r7:6 = vlsrw(r5:4,#1) + r1:0 = #0 + } + .falign +1: + { + r5:4 = vlsrw(r5:4,#2) + if (!p0.new) r0 = add(r0,r5) + if (!p0.new) r2 = sub(r2,r4) + p0 = cmp.gtu(r4,r2) + } + { + r7:6 = vlsrw(r7:6,#2) + if (!p0.new) r0 = add(r0,r7) + if (!p0.new) r2 = sub(r2,r6) + p0 = cmp.gtu(r6,r2) + }:endloop0 + { + if (!p0) r0 = add(r0,r7) + } + { + if (p3) r0 = sub(r1,r0) + jumpr r31 + } +SYM_FUNC_END(__hexagon_divsi3) diff --git a/arch/hexagon/lib/memcpy_likely_aligned.S b/arch/hexagon/lib/memcpy_likely_aligned.S new file mode 100644 index 0000000000000000000000000000000000000000..6a541fb90a5406a1b939c42319dbd2ba8bd24b66 --- /dev/null +++ b/arch/hexagon/lib/memcpy_likely_aligned.S @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/linkage.h> + +SYM_FUNC_START(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes) + { + p0 = bitsclr(r1,#7) + p0 = bitsclr(r0,#7) + if (p0.new) r5:4 = memd(r1) + if (p0.new) r7:6 = memd(r1+#8) + } + { + if (!p0) jump:nt .Lmemcpy_call + if (p0) r9:8 = memd(r1+#16) + if (p0) r11:10 = memd(r1+#24) + p0 = cmp.gtu(r2,#64) + } + { + if (p0) jump:nt .Lmemcpy_call + if (!p0) memd(r0) = r5:4 + if (!p0) memd(r0+#8) = r7:6 + p0 = cmp.gtu(r2,#32) + } + { + p1 = cmp.gtu(r2,#40) + p2 = cmp.gtu(r2,#48) + if (p0) r13:12 = memd(r1+#32) + if (p1.new) r15:14 = memd(r1+#40) + } + { + memd(r0+#16) = r9:8 + memd(r0+#24) = r11:10 + } + { + if (p0) memd(r0+#32) = r13:12 + if (p1) memd(r0+#40) = r15:14 + if (!p2) jumpr:t r31 + } + { + p0 = cmp.gtu(r2,#56) + r5:4 = memd(r1+#48) + if (p0.new) r7:6 = memd(r1+#56) + } + { + memd(r0+#48) = r5:4 + if (p0) memd(r0+#56) = r7:6 + jumpr r31 + } + +.Lmemcpy_call: + jump memcpy + +SYM_FUNC_END(__hexagon_memcpy_likely_aligned_min32bytes_mult8bytes) diff --git a/arch/hexagon/lib/modsi3.S b/arch/hexagon/lib/modsi3.S new file mode 100644 index 0000000000000000000000000000000000000000..9ea1c86efac2bac4f4fb712fa76abd0180073c3c --- /dev/null +++ b/arch/hexagon/lib/modsi3.S @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/linkage.h> + +SYM_FUNC_START(__hexagon_modsi3) + { + p2 = cmp.ge(r0,#0) + r2 = abs(r0) + r1 = abs(r1) + } + { + r3 = cl0(r2) + r4 = cl0(r1) + p0 = cmp.gtu(r1,r2) + } + { + r3 = sub(r4,r3) + if (p0) jumpr r31 + } + { + p1 = cmp.eq(r3,#0) + loop0(1f,r3) + r0 = r2 + r2 = lsl(r1,r3) + } + .falign +1: + { + p0 = cmp.gtu(r2,r0) + if (!p0.new) r0 = sub(r0,r2) + r2 = lsr(r2,#1) + if (p1) r1 = #0 + }:endloop0 + { + p0 = cmp.gtu(r2,r0) + if (!p0.new) r0 = sub(r0,r1) + if (p2) jumpr r31 + } + { + r0 = neg(r0) + jumpr r31 + } +SYM_FUNC_END(__hexagon_modsi3) diff --git a/arch/hexagon/lib/udivsi3.S b/arch/hexagon/lib/udivsi3.S new file mode 100644 index 0000000000000000000000000000000000000000..477f27b9311cd4c912fc457b35456da59e54966b --- /dev/null +++ b/arch/hexagon/lib/udivsi3.S @@ -0,0 +1,38 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/linkage.h> + +SYM_FUNC_START(__hexagon_udivsi3) + { + r2 = cl0(r0) + r3 = cl0(r1) + r5:4 = combine(#1,#0) + p0 = cmp.gtu(r1,r0) + } + { + r6 = sub(r3,r2) + r4 = r1 + r1:0 = combine(r0,r4) + if (p0) jumpr r31 + } + { + r3:2 = vlslw(r5:4,r6) + loop0(1f,r6) + } + .falign +1: + { + p0 = cmp.gtu(r2,r1) + if (!p0.new) r1 = sub(r1,r2) + if (!p0.new) r0 = add(r0,r3) + r3:2 = vlsrw(r3:2,#1) + }:endloop0 + { + p0 = cmp.gtu(r2,r1) + if (!p0.new) r0 = add(r0,r3) + jumpr r31 + } +SYM_FUNC_END(__hexagon_udivsi3) diff --git a/arch/hexagon/lib/umodsi3.S b/arch/hexagon/lib/umodsi3.S new file mode 100644 index 0000000000000000000000000000000000000000..280bf06a55e7dd34168070a446cbb93069779c5a --- /dev/null +++ b/arch/hexagon/lib/umodsi3.S @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021, The Linux Foundation. All rights reserved. + */ + +#include <linux/linkage.h> + +SYM_FUNC_START(__hexagon_umodsi3) + { + r2 = cl0(r0) + r3 = cl0(r1) + p0 = cmp.gtu(r1,r0) + } + { + r2 = sub(r3,r2) + if (p0) jumpr r31 + } + { + loop0(1f,r2) + p1 = cmp.eq(r2,#0) + r2 = lsl(r1,r2) + } + .falign +1: + { + p0 = cmp.gtu(r2,r0) + if (!p0.new) r0 = sub(r0,r2) + r2 = lsr(r2,#1) + if (p1) r1 = #0 + }:endloop0 + { + p0 = cmp.gtu(r2,r0) + if (!p0.new) r0 = sub(r0,r1) + jumpr r31 + } +SYM_FUNC_END(__hexagon_umodsi3) diff --git a/arch/ia64/kernel/mca_drv.c b/arch/ia64/kernel/mca_drv.c index 4d0ab323dee8c7d65cb0db3a1adb1b186970cda6..2a40268c3d494c13ed92a5d1274bfb822b8bacc6 100644 --- a/arch/ia64/kernel/mca_drv.c +++ b/arch/ia64/kernel/mca_drv.c @@ -343,7 +343,7 @@ init_record_index_pools(void) /* - 2 - */ sect_min_size = sal_log_sect_min_sizes[0]; - for (i = 1; i < sizeof sal_log_sect_min_sizes/sizeof(size_t); i++) + for (i = 1; i < ARRAY_SIZE(sal_log_sect_min_sizes); i++) if (sect_min_size > sal_log_sect_min_sizes[i]) sect_min_size = sal_log_sect_min_sizes[i]; diff --git a/arch/ia64/kernel/smpboot.c b/arch/ia64/kernel/smpboot.c index 093040f7e626a1ef79aaed1cdfa17f513808cc2a..0cad990385c04acb239d074a710727b1e8455bf0 100644 --- a/arch/ia64/kernel/smpboot.c +++ b/arch/ia64/kernel/smpboot.c @@ -440,7 +440,6 @@ start_secondary (void *unused) #endif efi_map_pal_code(); cpu_init(); - preempt_disable(); smp_callin(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); diff --git a/arch/m68k/Kconfig.machine b/arch/m68k/Kconfig.machine index 17e8c3a292d77043f387ee63f2eaa837f0983a90..e161a4e1493b42a2064319c972d5e41eac9706f5 100644 --- a/arch/m68k/Kconfig.machine +++ b/arch/m68k/Kconfig.machine @@ -23,6 +23,9 @@ config ATARI this kernel on an Atari, say Y here and browse the material available in <file:Documentation/m68k>; otherwise say N. +config ATARI_KBD_CORE + bool + config MAC bool "Macintosh support" depends on MMU diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 1917ccd3925640cf569e7d06cf4e033ff36df3a1..1a63f592034ebda5a6cbe5ff7e10eaa877a265f4 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -418,6 +418,8 @@ config MACH_INGENIC_SOC select MIPS_GENERIC select MACH_INGENIC select SYS_SUPPORTS_ZBOOT_UART16550 + select CPU_SUPPORTS_CPUFREQ + select MIPS_EXTERNAL_TIMER config LANTIQ bool "Lantiq based platforms" diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile index 337ab1d18cc1f9a2d415d768869b4b79708f16d3..eae0fad30f27e6e25eaa085a5471f9459db853d6 100644 --- a/arch/mips/boot/compressed/Makefile +++ b/arch/mips/boot/compressed/Makefile @@ -39,7 +39,7 @@ KCOV_INSTRUMENT := n UBSAN_SANITIZE := n # decompressor objects (linked with vmlinuz) -vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o +vmlinuzobjs-y := $(obj)/head.o $(obj)/decompress.o $(obj)/string.o $(obj)/bswapsi.o ifdef CONFIG_DEBUG_ZBOOT vmlinuzobjs-$(CONFIG_DEBUG_ZBOOT) += $(obj)/dbg.o @@ -53,7 +53,7 @@ extra-y += uart-ath79.c $(obj)/uart-ath79.c: $(srctree)/arch/mips/ath79/early_printk.c $(call cmd,shipped) -vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o $(obj)/bswapsi.o +vmlinuzobjs-$(CONFIG_KERNEL_XZ) += $(obj)/ashldi3.o extra-y += ashldi3.c $(obj)/ashldi3.c: $(obj)/%.c: $(srctree)/lib/%.c FORCE diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c index e3946b06e840a6b2e6c5a297e81f16db50a4c914..1e91155bed803528eb66702595dc95de9f0596b7 100644 --- a/arch/mips/boot/compressed/decompress.c +++ b/arch/mips/boot/compressed/decompress.c @@ -7,6 +7,8 @@ * Author: Wu Zhangjin <wuzhangjin@gmail.com> */ +#define DISABLE_BRANCH_PROFILING + #include <linux/types.h> #include <linux/kernel.h> #include <linux/string.h> diff --git a/arch/mips/generic/board-boston.its.S b/arch/mips/generic/board-boston.its.S index a7f51f97b9102f79dd4e75fa1894ee42e24e099e..c45ad27594218c6e2f19d1b7451c34173abad294 100644 --- a/arch/mips/generic/board-boston.its.S +++ b/arch/mips/generic/board-boston.its.S @@ -1,22 +1,22 @@ / { images { - fdt@boston { + fdt-boston { description = "img,boston Device Tree"; data = /incbin/("boot/dts/img/boston.dtb"); type = "flat_dt"; arch = "mips"; compression = "none"; - hash@0 { + hash { algo = "sha1"; }; }; }; configurations { - conf@boston { + conf-boston { description = "Boston Linux kernel"; - kernel = "kernel@0"; - fdt = "fdt@boston"; + kernel = "kernel"; + fdt = "fdt-boston"; }; }; }; diff --git a/arch/mips/generic/board-ni169445.its.S b/arch/mips/generic/board-ni169445.its.S index e4cb4f95a8cc1015f31d63570c962703b7fddca8..0a2e8f7a8526f3532ea40e2067cd0ea1da07e950 100644 --- a/arch/mips/generic/board-ni169445.its.S +++ b/arch/mips/generic/board-ni169445.its.S @@ -1,22 +1,22 @@ / { images { - fdt@ni169445 { + fdt-ni169445 { description = "NI 169445 device tree"; data = /incbin/("boot/dts/ni/169445.dtb"); type = "flat_dt"; arch = "mips"; compression = "none"; - hash@0 { + hash { algo = "sha1"; }; }; }; configurations { - conf@ni169445 { + conf-ni169445 { description = "NI 169445 Linux Kernel"; - kernel = "kernel@0"; - fdt = "fdt@ni169445"; + kernel = "kernel"; + fdt = "fdt-ni169445"; }; }; }; diff --git a/arch/mips/generic/board-ocelot.its.S b/arch/mips/generic/board-ocelot.its.S index 3da23988149a66e0fec419f2fee93108d4fce64a..8c7e3a1b68d3da410e0bacbe5d58003ee4bc3802 100644 --- a/arch/mips/generic/board-ocelot.its.S +++ b/arch/mips/generic/board-ocelot.its.S @@ -1,40 +1,40 @@ /* SPDX-License-Identifier: (GPL-2.0 OR MIT) */ / { images { - fdt@ocelot_pcb123 { + fdt-ocelot_pcb123 { description = "MSCC Ocelot PCB123 Device Tree"; data = /incbin/("boot/dts/mscc/ocelot_pcb123.dtb"); type = "flat_dt"; arch = "mips"; compression = "none"; - hash@0 { + hash { algo = "sha1"; }; }; - fdt@ocelot_pcb120 { + fdt-ocelot_pcb120 { description = "MSCC Ocelot PCB120 Device Tree"; data = /incbin/("boot/dts/mscc/ocelot_pcb120.dtb"); type = "flat_dt"; arch = "mips"; compression = "none"; - hash@0 { + hash { algo = "sha1"; }; }; }; configurations { - conf@ocelot_pcb123 { + conf-ocelot_pcb123 { description = "Ocelot Linux kernel"; - kernel = "kernel@0"; - fdt = "fdt@ocelot_pcb123"; + kernel = "kernel"; + fdt = "fdt-ocelot_pcb123"; }; - conf@ocelot_pcb120 { + conf-ocelot_pcb120 { description = "Ocelot Linux kernel"; - kernel = "kernel@0"; - fdt = "fdt@ocelot_pcb120"; + kernel = "kernel"; + fdt = "fdt-ocelot_pcb120"; }; }; }; diff --git a/arch/mips/generic/board-xilfpga.its.S b/arch/mips/generic/board-xilfpga.its.S index a2e773d3f14f411c51d9c4dd039e12a6b8288cd6..08c1e900eb4ed3b261efd00980bb743e129100de 100644 --- a/arch/mips/generic/board-xilfpga.its.S +++ b/arch/mips/generic/board-xilfpga.its.S @@ -1,22 +1,22 @@ / { images { - fdt@xilfpga { + fdt-xilfpga { description = "MIPSfpga (xilfpga) Device Tree"; data = /incbin/("boot/dts/xilfpga/nexys4ddr.dtb"); type = "flat_dt"; arch = "mips"; compression = "none"; - hash@0 { + hash { algo = "sha1"; }; }; }; configurations { - conf@xilfpga { + conf-xilfpga { description = "MIPSfpga Linux kernel"; - kernel = "kernel@0"; - fdt = "fdt@xilfpga"; + kernel = "kernel"; + fdt = "fdt-xilfpga"; }; }; }; diff --git a/arch/mips/generic/vmlinux.its.S b/arch/mips/generic/vmlinux.its.S index 1a08438fd8930c43eb543cc64bbc2ba787a1b939..3e254676540f45ba787fa65a81b742dc74df4653 100644 --- a/arch/mips/generic/vmlinux.its.S +++ b/arch/mips/generic/vmlinux.its.S @@ -6,7 +6,7 @@ #address-cells = <ADDR_CELLS>; images { - kernel@0 { + kernel { description = KERNEL_NAME; data = /incbin/(VMLINUX_BINARY); type = "kernel"; @@ -15,18 +15,18 @@ compression = VMLINUX_COMPRESSION; load = /bits/ ADDR_BITS <VMLINUX_LOAD_ADDRESS>; entry = /bits/ ADDR_BITS <VMLINUX_ENTRY_ADDRESS>; - hash@0 { + hash { algo = "sha1"; }; }; }; configurations { - default = "conf@default"; + default = "conf-default"; - conf@default { + conf-default { description = "Generic Linux kernel"; - kernel = "kernel@0"; + kernel = "kernel"; }; }; }; diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index f2e216eef7da5ec78cbb31e02843021ffd59f9a0..8294eaa6f902deaf957514ca12ea9cc90598fd0c 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -64,6 +64,8 @@ ((MIPS_ISA_REV >= (ge)) && (MIPS_ISA_REV < (lt))) #define __isa_range_or_flag(ge, lt, flag) \ (__isa_range(ge, lt) || ((MIPS_ISA_REV < (lt)) && __isa(flag))) +#define __isa_range_and_ase(ge, lt, ase) \ + (__isa_range(ge, lt) && __ase(ase)) /* * SMP assumption: Options of CPU 0 are a superset of all processors. @@ -423,7 +425,7 @@ #endif #ifndef cpu_has_mipsmt -#define cpu_has_mipsmt __isa_lt_and_ase(6, MIPS_ASE_MIPSMT) +#define cpu_has_mipsmt __isa_range_and_ase(2, 6, MIPS_ASE_MIPSMT) #endif #ifndef cpu_has_vp diff --git a/arch/mips/include/asm/highmem.h b/arch/mips/include/asm/highmem.h index f1f788b5716663f6037bfd24e7be3abd3c695e32..9f021cf51aa718467607225be88fb44e0dd87343 100644 --- a/arch/mips/include/asm/highmem.h +++ b/arch/mips/include/asm/highmem.h @@ -36,7 +36,7 @@ extern pte_t *pkmap_page_table; * easily, subsequent pte tables have to be allocated in one physical * chunk of RAM. */ -#ifdef CONFIG_PHYS_ADDR_T_64BIT +#if defined(CONFIG_PHYS_ADDR_T_64BIT) || defined(CONFIG_MIPS_HUGE_TLB_SUPPORT) #define LAST_PKMAP 512 #else #define LAST_PKMAP 1024 diff --git a/arch/mips/include/asm/hugetlb.h b/arch/mips/include/asm/hugetlb.h index 10e3be870df78593d80dd4fd91cb5904f55fc487..c2144409c0c40db371a25c1805a85d36df0dedbe 100644 --- a/arch/mips/include/asm/hugetlb.h +++ b/arch/mips/include/asm/hugetlb.h @@ -46,7 +46,13 @@ static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, static inline void huge_ptep_clear_flush(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) { - flush_tlb_page(vma, addr & huge_page_mask(hstate_vma(vma))); + /* + * clear the huge pte entry firstly, so that the other smp threads will + * not get old pte entry after finishing flush_tlb_page and before + * setting new huge pte entry + */ + huge_ptep_get_and_clear(vma->vm_mm, addr, ptep); + flush_tlb_page(vma, addr); } #define __HAVE_ARCH_HUGE_PTE_NONE diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index a0e8ae5497b61775ed67f87987f6337297bdce96..7a7467d3f7f0587eb327783df16d6ce57d1989ca 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -2073,7 +2073,7 @@ _ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c) ({ int __res; \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips32r2\n\t" \ + ".set\tmips32r5\n\t" \ _ASM_SET_VIRT \ "mfgc0\t%0, " #source ", %1\n\t" \ ".set\tpop" \ @@ -2086,7 +2086,7 @@ _ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c) ({ unsigned long long __res; \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips64r2\n\t" \ + ".set\tmips64r5\n\t" \ _ASM_SET_VIRT \ "dmfgc0\t%0, " #source ", %1\n\t" \ ".set\tpop" \ @@ -2099,7 +2099,7 @@ _ASM_MACRO_0(tlbginvf, _ASM_INSN_IF_MIPS(0x4200000c) do { \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips32r2\n\t" \ + ".set\tmips32r5\n\t" \ _ASM_SET_VIRT \ "mtgc0\t%z0, " #register ", %1\n\t" \ ".set\tpop" \ @@ -2111,7 +2111,7 @@ do { \ do { \ __asm__ __volatile__( \ ".set\tpush\n\t" \ - ".set\tmips64r2\n\t" \ + ".set\tmips64r5\n\t" \ _ASM_SET_VIRT \ "dmtgc0\t%z0, " #register ", %1\n\t" \ ".set\tpop" \ diff --git a/arch/mips/include/asm/pgalloc.h b/arch/mips/include/asm/pgalloc.h index 8b18424b31208c36a92514beecd8b9efc98ae7a2..d0cf997b4ba84008f9da329419c3f9885ffd0f0c 100644 --- a/arch/mips/include/asm/pgalloc.h +++ b/arch/mips/include/asm/pgalloc.h @@ -59,11 +59,15 @@ do { \ static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) { - pmd_t *pmd; + pmd_t *pmd = NULL; + struct page *pg; - pmd = (pmd_t *) __get_free_pages(GFP_KERNEL, PMD_ORDER); - if (pmd) + pg = alloc_pages(GFP_KERNEL | __GFP_ACCOUNT, PMD_ORDER); + if (pg) { + pgtable_pmd_page_ctor(pg); + pmd = (pmd_t *)page_address(pg); pmd_init((unsigned long)pmd, (unsigned long)invalid_pte_table); + } return pmd; } diff --git a/arch/mips/include/asm/vdso/vdso.h b/arch/mips/include/asm/vdso/vdso.h index 737ddfc3411cb224b1cf2739a871ab482c9f18ee..a327ca21270eccfa5ace49ca33f502242dd825e1 100644 --- a/arch/mips/include/asm/vdso/vdso.h +++ b/arch/mips/include/asm/vdso/vdso.h @@ -67,7 +67,7 @@ static inline const struct vdso_data *get_vdso_data(void) static inline void __iomem *get_gic(const struct vdso_data *data) { - return (void __iomem *)data - PAGE_SIZE; + return (void __iomem *)((unsigned long)data & PAGE_MASK) - PAGE_SIZE; } #endif /* CONFIG_CLKSRC_MIPS_GIC */ diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index e6ae2bcdbeda067ae9d3181b4686bc1de022b057..067cb3eb16141650cf64085d07cf8ce65e39fd45 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -1827,6 +1827,11 @@ static inline void cpu_probe_ingenic(struct cpuinfo_mips *c, unsigned int cpu) */ case PRID_COMP_INGENIC_D0: c->isa_level &= ~MIPS_CPU_ISA_M32R2; + + /* FPU is not properly detected on JZ4760(B). */ + if (c->processor_id == 0x2ed0024f) + c->options |= MIPS_CPU_FPU; + fallthrough; /* diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index 48d84d5fcc36157d8a47f7a82183272bd2cfd568..ff25926c5458c691a75d1283e612683c2b5a7e29 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -348,7 +348,6 @@ asmlinkage void start_secondary(void) */ calibrate_delay(); - preempt_disable(); cpu = smp_processor_id(); cpu_data[cpu].udelay_val = loops_per_jiffy; diff --git a/arch/mips/loongson64/numa.c b/arch/mips/loongson64/numa.c index cf9459f79f9b4021475e22589630563fb8ea2eeb..e4c461df3ee648391cb50488f462b1629c8286f2 100644 --- a/arch/mips/loongson64/numa.c +++ b/arch/mips/loongson64/numa.c @@ -182,6 +182,9 @@ static void __init node_mem_init(unsigned int node) if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) memblock_reserve((node_addrspace_offset | 0xfe000000), 32 << 20); + + /* Reserve pfn range 0~node[0]->node_start_pfn */ + memblock_reserve(0, PAGE_SIZE * start_pfn); } } diff --git a/arch/openrisc/kernel/smp.c b/arch/openrisc/kernel/smp.c index 29c82ef2e207ce098918a6a7a682311ab2d75eba..e4dad76066aed1438b977e4759075f2fb0a7d68f 100644 --- a/arch/openrisc/kernel/smp.c +++ b/arch/openrisc/kernel/smp.c @@ -134,8 +134,6 @@ asmlinkage __init void secondary_start_kernel(void) set_cpu_online(cpu, true); local_irq_enable(); - - preempt_disable(); /* * OK, it's off to the idle thread for us */ diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 10227f667c8a6ed09f68dc2e9e3e75f6d7a4a171..1405b603b91b6be6909530825ad455ee150ebbf3 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -302,7 +302,6 @@ void __init smp_callin(unsigned long pdce_proc) #endif smp_cpu_init(slave_id); - preempt_disable(); flush_cache_all_local(); /* start with known state */ flush_tlb_all_local(NULL); diff --git a/arch/powerpc/boot/devtree.c b/arch/powerpc/boot/devtree.c index 5d91036ad626d5a330a83ded285afba9c4d04c52..58fbcfcc98c9e9a31ba585300b14ef507c509a0a 100644 --- a/arch/powerpc/boot/devtree.c +++ b/arch/powerpc/boot/devtree.c @@ -13,6 +13,7 @@ #include "string.h" #include "stdio.h" #include "ops.h" +#include "of.h" void dt_fixup_memory(u64 start, u64 size) { @@ -23,21 +24,25 @@ void dt_fixup_memory(u64 start, u64 size) root = finddevice("/"); if (getprop(root, "#address-cells", &naddr, sizeof(naddr)) < 0) naddr = 2; + else + naddr = be32_to_cpu(naddr); if (naddr < 1 || naddr > 2) fatal("Can't cope with #address-cells == %d in /\n\r", naddr); if (getprop(root, "#size-cells", &nsize, sizeof(nsize)) < 0) nsize = 1; + else + nsize = be32_to_cpu(nsize); if (nsize < 1 || nsize > 2) fatal("Can't cope with #size-cells == %d in /\n\r", nsize); i = 0; if (naddr == 2) - memreg[i++] = start >> 32; - memreg[i++] = start & 0xffffffff; + memreg[i++] = cpu_to_be32(start >> 32); + memreg[i++] = cpu_to_be32(start & 0xffffffff); if (nsize == 2) - memreg[i++] = size >> 32; - memreg[i++] = size & 0xffffffff; + memreg[i++] = cpu_to_be32(size >> 32); + memreg[i++] = cpu_to_be32(size & 0xffffffff); memory = finddevice("/memory"); if (! memory) { @@ -45,9 +50,9 @@ void dt_fixup_memory(u64 start, u64 size) setprop_str(memory, "device_type", "memory"); } - printf("Memory <- <0x%x", memreg[0]); + printf("Memory <- <0x%x", be32_to_cpu(memreg[0])); for (i = 1; i < (naddr + nsize); i++) - printf(" 0x%x", memreg[i]); + printf(" 0x%x", be32_to_cpu(memreg[i])); printf("> (%ldMB)\n\r", (unsigned long)(size >> 20)); setprop(memory, "reg", memreg, (naddr + nsize)*sizeof(u32)); @@ -65,10 +70,10 @@ void dt_fixup_cpu_clocks(u32 cpu, u32 tb, u32 bus) printf("CPU bus-frequency <- 0x%x (%dMHz)\n\r", bus, MHZ(bus)); while ((devp = find_node_by_devtype(devp, "cpu"))) { - setprop_val(devp, "clock-frequency", cpu); - setprop_val(devp, "timebase-frequency", tb); + setprop_val(devp, "clock-frequency", cpu_to_be32(cpu)); + setprop_val(devp, "timebase-frequency", cpu_to_be32(tb)); if (bus > 0) - setprop_val(devp, "bus-frequency", bus); + setprop_val(devp, "bus-frequency", cpu_to_be32(bus)); } timebase_period_ns = 1000000000 / tb; @@ -80,7 +85,7 @@ void dt_fixup_clock(const char *path, u32 freq) if (devp) { printf("%s: clock-frequency <- %x (%dMHz)\n\r", path, freq, MHZ(freq)); - setprop_val(devp, "clock-frequency", freq); + setprop_val(devp, "clock-frequency", cpu_to_be32(freq)); } } @@ -133,8 +138,12 @@ void dt_get_reg_format(void *node, u32 *naddr, u32 *nsize) { if (getprop(node, "#address-cells", naddr, 4) != 4) *naddr = 2; + else + *naddr = be32_to_cpu(*naddr); if (getprop(node, "#size-cells", nsize, 4) != 4) *nsize = 1; + else + *nsize = be32_to_cpu(*nsize); } static void copy_val(u32 *dest, u32 *src, int naddr) @@ -163,9 +172,9 @@ static int add_reg(u32 *reg, u32 *add, int naddr) int i, carry = 0; for (i = MAX_ADDR_CELLS - 1; i >= MAX_ADDR_CELLS - naddr; i--) { - u64 tmp = (u64)reg[i] + add[i] + carry; + u64 tmp = (u64)be32_to_cpu(reg[i]) + be32_to_cpu(add[i]) + carry; carry = tmp >> 32; - reg[i] = (u32)tmp; + reg[i] = cpu_to_be32((u32)tmp); } return !carry; @@ -180,18 +189,18 @@ static int compare_reg(u32 *reg, u32 *range, u32 *rangesize) u32 end; for (i = 0; i < MAX_ADDR_CELLS; i++) { - if (reg[i] < range[i]) + if (be32_to_cpu(reg[i]) < be32_to_cpu(range[i])) return 0; - if (reg[i] > range[i]) + if (be32_to_cpu(reg[i]) > be32_to_cpu(range[i])) break; } for (i = 0; i < MAX_ADDR_CELLS; i++) { - end = range[i] + rangesize[i]; + end = be32_to_cpu(range[i]) + be32_to_cpu(rangesize[i]); - if (reg[i] < end) + if (be32_to_cpu(reg[i]) < end) break; - if (reg[i] > end) + if (be32_to_cpu(reg[i]) > end) return 0; } @@ -240,7 +249,6 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, return 0; dt_get_reg_format(parent, &naddr, &nsize); - if (nsize > 2) return 0; @@ -252,10 +260,10 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, copy_val(last_addr, prop_buf + offset, naddr); - ret_size = prop_buf[offset + naddr]; + ret_size = be32_to_cpu(prop_buf[offset + naddr]); if (nsize == 2) { ret_size <<= 32; - ret_size |= prop_buf[offset + naddr + 1]; + ret_size |= be32_to_cpu(prop_buf[offset + naddr + 1]); } for (;;) { @@ -278,7 +286,6 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, offset = find_range(last_addr, prop_buf, prev_naddr, naddr, prev_nsize, buflen / 4); - if (offset < 0) return 0; @@ -296,8 +303,7 @@ static int dt_xlate(void *node, int res, int reglen, unsigned long *addr, if (naddr > 2) return 0; - ret_addr = ((u64)last_addr[2] << 32) | last_addr[3]; - + ret_addr = ((u64)be32_to_cpu(last_addr[2]) << 32) | be32_to_cpu(last_addr[3]); if (sizeof(void *) == 4 && (ret_addr >= 0x100000000ULL || ret_size > 0x100000000ULL || ret_addr + ret_size > 0x100000000ULL)) @@ -350,11 +356,14 @@ int dt_is_compatible(void *node, const char *compat) int dt_get_virtual_reg(void *node, void **addr, int nres) { unsigned long xaddr; - int n; + int n, i; n = getprop(node, "virtual-reg", addr, nres * 4); - if (n > 0) + if (n > 0) { + for (i = 0; i < n/4; i ++) + ((u32 *)addr)[i] = be32_to_cpu(((u32 *)addr)[i]); return n / 4; + } for (n = 0; n < nres; n++) { if (!dt_xlate_reg(node, n, &xaddr, NULL)) diff --git a/arch/powerpc/boot/ns16550.c b/arch/powerpc/boot/ns16550.c index b0da4466d41983590326abb8b08f69a4a7d64ebd..f16d2be1d0f311726a83b3ce70c4c09bf0445462 100644 --- a/arch/powerpc/boot/ns16550.c +++ b/arch/powerpc/boot/ns16550.c @@ -15,6 +15,7 @@ #include "stdio.h" #include "io.h" #include "ops.h" +#include "of.h" #define UART_DLL 0 /* Out: Divisor Latch Low */ #define UART_DLM 1 /* Out: Divisor Latch High */ @@ -58,16 +59,20 @@ int ns16550_console_init(void *devp, struct serial_console_data *scdp) int n; u32 reg_offset; - if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1) + if (dt_get_virtual_reg(devp, (void **)®_base, 1) < 1) { + printf("virt reg parse fail...\r\n"); return -1; + } n = getprop(devp, "reg-offset", ®_offset, sizeof(reg_offset)); if (n == sizeof(reg_offset)) - reg_base += reg_offset; + reg_base += be32_to_cpu(reg_offset); n = getprop(devp, "reg-shift", ®_shift, sizeof(reg_shift)); if (n != sizeof(reg_shift)) reg_shift = 0; + else + reg_shift = be32_to_cpu(reg_shift); scdp->open = ns16550_open; scdp->putc = ns16550_putc; diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h index f53c4238083273560c8764c0e449c16cb40c6496..8c14f84a8770b5cb7ee43c0535de55e5713bb07b 100644 --- a/arch/powerpc/include/asm/barrier.h +++ b/arch/powerpc/include/asm/barrier.h @@ -46,6 +46,8 @@ # define SMPWMB eieio #endif +/* clang defines this macro for a builtin, which will not work with runtime patching */ +#undef __lwsync #define __lwsync() __asm__ __volatile__ (stringify_in_c(LWSYNC) : : :"memory") #define dma_rmb() __lwsync() #define dma_wmb() __asm__ __volatile__ (stringify_in_c(SMPWMB) : : :"memory") diff --git a/arch/powerpc/include/asm/cputhreads.h b/arch/powerpc/include/asm/cputhreads.h index 98c8bd155bf9d28aaded8cb8310aed785181adcb..b167186aaee4af09e4743142c71cd752892d3d1e 100644 --- a/arch/powerpc/include/asm/cputhreads.h +++ b/arch/powerpc/include/asm/cputhreads.h @@ -98,6 +98,36 @@ static inline int cpu_last_thread_sibling(int cpu) return cpu | (threads_per_core - 1); } +/* + * tlb_thread_siblings are siblings which share a TLB. This is not + * architected, is not something a hypervisor could emulate and a future + * CPU may change behaviour even in compat mode, so this should only be + * used on PowerNV, and only with care. + */ +static inline int cpu_first_tlb_thread_sibling(int cpu) +{ + if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8)) + return cpu & ~0x6; /* Big Core */ + else + return cpu_first_thread_sibling(cpu); +} + +static inline int cpu_last_tlb_thread_sibling(int cpu) +{ + if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8)) + return cpu | 0x6; /* Big Core */ + else + return cpu_last_thread_sibling(cpu); +} + +static inline int cpu_tlb_thread_sibling_step(void) +{ + if (cpu_has_feature(CPU_FTR_ARCH_300) && (threads_per_core == 8)) + return 2; /* Big Core */ + else + return 1; +} + static inline u32 get_tensr(void) { #ifdef CONFIG_BOOKE diff --git a/arch/powerpc/include/asm/ps3.h b/arch/powerpc/include/asm/ps3.h index cb89e4bf55ceff01a25e31973e2278869e3e76c9..964063765662b6cc90bbf5c5faf324023ecc9b42 100644 --- a/arch/powerpc/include/asm/ps3.h +++ b/arch/powerpc/include/asm/ps3.h @@ -71,6 +71,7 @@ struct ps3_dma_region_ops; * @bus_addr: The 'translated' bus address of the region. * @len: The length in bytes of the region. * @offset: The offset from the start of memory of the region. + * @dma_mask: Device dma_mask. * @ioid: The IOID of the device who owns this region * @chunk_list: Opaque variable used by the ioc page manager. * @region_ops: struct ps3_dma_region_ops - dma region operations @@ -85,6 +86,7 @@ struct ps3_dma_region { enum ps3_dma_region_type region_type; unsigned long len; unsigned long offset; + u64 dma_mask; /* driver variables (set by ps3_dma_region_create) */ unsigned long bus_addr; diff --git a/arch/powerpc/kernel/mce_power.c b/arch/powerpc/kernel/mce_power.c index b7e173754a2e9b1cf5affdb451fe550c12a5f360..ea8b002820cec0f4af46b9269b25fb793abac112 100644 --- a/arch/powerpc/kernel/mce_power.c +++ b/arch/powerpc/kernel/mce_power.c @@ -475,12 +475,11 @@ static int mce_find_instr_ea_and_phys(struct pt_regs *regs, uint64_t *addr, return -1; } -static int mce_handle_ierror(struct pt_regs *regs, +static int mce_handle_ierror(struct pt_regs *regs, unsigned long srr1, const struct mce_ierror_table table[], struct mce_error_info *mce_err, uint64_t *addr, uint64_t *phys_addr) { - uint64_t srr1 = regs->msr; int handled = 0; int i; @@ -683,19 +682,19 @@ static long mce_handle_ue_error(struct pt_regs *regs, } static long mce_handle_error(struct pt_regs *regs, + unsigned long srr1, const struct mce_derror_table dtable[], const struct mce_ierror_table itable[]) { struct mce_error_info mce_err = { 0 }; uint64_t addr, phys_addr = ULONG_MAX; - uint64_t srr1 = regs->msr; long handled; if (SRR1_MC_LOADSTORE(srr1)) handled = mce_handle_derror(regs, dtable, &mce_err, &addr, &phys_addr); else - handled = mce_handle_ierror(regs, itable, &mce_err, &addr, + handled = mce_handle_ierror(regs, srr1, itable, &mce_err, &addr, &phys_addr); if (!handled && mce_err.error_type == MCE_ERROR_TYPE_UE) @@ -711,16 +710,20 @@ long __machine_check_early_realmode_p7(struct pt_regs *regs) /* P7 DD1 leaves top bits of DSISR undefined */ regs->dsisr &= 0x0000ffff; - return mce_handle_error(regs, mce_p7_derror_table, mce_p7_ierror_table); + return mce_handle_error(regs, regs->msr, + mce_p7_derror_table, mce_p7_ierror_table); } long __machine_check_early_realmode_p8(struct pt_regs *regs) { - return mce_handle_error(regs, mce_p8_derror_table, mce_p8_ierror_table); + return mce_handle_error(regs, regs->msr, + mce_p8_derror_table, mce_p8_ierror_table); } long __machine_check_early_realmode_p9(struct pt_regs *regs) { + unsigned long srr1 = regs->msr; + /* * On POWER9 DD2.1 and below, it's possible to get a machine check * caused by a paste instruction where only DSISR bit 25 is set. This @@ -734,10 +737,39 @@ long __machine_check_early_realmode_p9(struct pt_regs *regs) if (SRR1_MC_LOADSTORE(regs->msr) && regs->dsisr == 0x02000000) return 1; - return mce_handle_error(regs, mce_p9_derror_table, mce_p9_ierror_table); + /* + * Async machine check due to bad real address from store or foreign + * link time out comes with the load/store bit (PPC bit 42) set in + * SRR1, but the cause comes in SRR1 not DSISR. Clear bit 42 so we're + * directed to the ierror table so it will find the cause (which + * describes it correctly as a store error). + */ + if (SRR1_MC_LOADSTORE(srr1) && + ((srr1 & 0x081c0000) == 0x08140000 || + (srr1 & 0x081c0000) == 0x08180000)) { + srr1 &= ~PPC_BIT(42); + } + + return mce_handle_error(regs, srr1, + mce_p9_derror_table, mce_p9_ierror_table); } long __machine_check_early_realmode_p10(struct pt_regs *regs) { - return mce_handle_error(regs, mce_p10_derror_table, mce_p10_ierror_table); + unsigned long srr1 = regs->msr; + + /* + * Async machine check due to bad real address from store comes with + * the load/store bit (PPC bit 42) set in SRR1, but the cause comes in + * SRR1 not DSISR. Clear bit 42 so we're directed to the ierror table + * so it will find the cause (which describes it correctly as a store + * error). + */ + if (SRR1_MC_LOADSTORE(srr1) && + (srr1 & 0x081c0000) == 0x08140000) { + srr1 &= ~PPC_BIT(42); + } + + return mce_handle_error(regs, srr1, + mce_p10_derror_table, mce_p10_ierror_table); } diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 1a1d2657fe8ddc3bf46c6f4644951150c1a6ec36..3064694afea1729d64273d008019df88a526cd33 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c @@ -1227,6 +1227,19 @@ struct task_struct *__switch_to(struct task_struct *prev, __flush_tlb_pending(batch); batch->active = 0; } + + /* + * On POWER9 the copy-paste buffer can only paste into + * foreign real addresses, so unprivileged processes can not + * see the data or use it in any way unless they have + * foreign real mappings. If the new process has the foreign + * real address mappings, we must issue a cp_abort to clear + * any state and prevent snooping, corruption or a covert + * channel. ISA v3.1 supports paste into local memory. + */ + if (new->mm && (cpu_has_feature(CPU_FTR_ARCH_31) || + atomic_read(&new->mm->context.vas_windows))) + asm volatile(PPC_CP_ABORT); #endif /* CONFIG_PPC_BOOK3S_64 */ #ifdef CONFIG_PPC_ADV_DEBUG_REGS @@ -1272,30 +1285,33 @@ struct task_struct *__switch_to(struct task_struct *prev, last = _switch(old_thread, new_thread); + /* + * Nothing after _switch will be run for newly created tasks, + * because they switch directly to ret_from_fork/ret_from_kernel_thread + * etc. Code added here should have a comment explaining why that is + * okay. + */ + #ifdef CONFIG_PPC_BOOK3S_64 + /* + * This applies to a process that was context switched while inside + * arch_enter_lazy_mmu_mode(), to re-activate the batch that was + * deactivated above, before _switch(). This will never be the case + * for new tasks. + */ if (current_thread_info()->local_flags & _TLF_LAZY_MMU) { current_thread_info()->local_flags &= ~_TLF_LAZY_MMU; batch = this_cpu_ptr(&ppc64_tlb_batch); batch->active = 1; } - if (current->thread.regs) { + /* + * Math facilities are masked out of the child MSR in copy_thread. + * A new task does not need to restore_math because it will + * demand fault them. + */ + if (current->thread.regs) restore_math(current->thread.regs); - - /* - * On POWER9 the copy-paste buffer can only paste into - * foreign real addresses, so unprivileged processes can not - * see the data or use it in any way unless they have - * foreign real mappings. If the new process has the foreign - * real address mappings, we must issue a cp_abort to clear - * any state and prevent snooping, corruption or a covert - * channel. ISA v3.1 supports paste into local memory. - */ - if (current->mm && - (cpu_has_feature(CPU_FTR_ARCH_31) || - atomic_read(¤t->mm->context.vas_windows))) - asm volatile(PPC_CP_ABORT); - } #endif /* CONFIG_PPC_BOOK3S_64 */ return last; diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index db7ac77bea3a791fe12d6be3a9dc52ee7d4392e3..26a028a9233afd9cdd8da0a688973cfbfe135aae 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c @@ -600,6 +600,8 @@ static void nmi_stop_this_cpu(struct pt_regs *regs) /* * IRQs are already hard disabled by the smp_handle_nmi_ipi. */ + set_cpu_online(smp_processor_id(), false); + spin_begin(); while (1) spin_cpu_relax(); @@ -615,6 +617,15 @@ void smp_send_stop(void) static void stop_this_cpu(void *dummy) { hard_irq_disable(); + + /* + * Offlining CPUs in stop_this_cpu can result in scheduler warnings, + * (see commit de6e5d38417e), but printk_safe_flush_on_panic() wants + * to know other CPUs are offline before it breaks locks to flush + * printk buffers, in case we panic()ed while holding the lock. + */ + set_cpu_online(smp_processor_id(), false); + spin_begin(); while (1) spin_cpu_relax(); @@ -1426,7 +1437,6 @@ void start_secondary(void *unused) smp_store_cpu_info(cpu); set_dec(tb_ticks_per_jiffy); rcu_cpu_starting(cpu); - preempt_disable(); cpu_callin_map[cpu] = 1; if (smp_ops->setup_cpu) diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index b6440657ef92d065930a39d20ab6cc23d2d01ddd..2f926ea9b7b94de139a7053afa70d430a1d32a14 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c @@ -19,6 +19,7 @@ #include <asm/ptrace.h> #include <asm/processor.h> #include <linux/ftrace.h> +#include <linux/delay.h> #include <asm/kprobes.h> #include <asm/paca.h> @@ -230,17 +231,31 @@ static void handle_backtrace_ipi(struct pt_regs *regs) static void raise_backtrace_ipi(cpumask_t *mask) { + struct paca_struct *p; unsigned int cpu; + u64 delay_us; for_each_cpu(cpu, mask) { - if (cpu == smp_processor_id()) + if (cpu == smp_processor_id()) { handle_backtrace_ipi(NULL); - else - smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, 5 * USEC_PER_SEC); - } + continue; + } - for_each_cpu(cpu, mask) { - struct paca_struct *p = paca_ptrs[cpu]; + delay_us = 5 * USEC_PER_SEC; + + if (smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, delay_us)) { + // Now wait up to 5s for the other CPU to do its backtrace + while (cpumask_test_cpu(cpu, mask) && delay_us) { + udelay(1); + delay_us--; + } + + // Other CPU cleared itself from the mask + if (delay_us) + continue; + } + + p = paca_ptrs[cpu]; cpumask_clear_cpu(cpu, mask); diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 280f7992ae9936c8602735a6854e67af8fe73b3a..2325b7a6e95f89cd96f7a94a3c09513f210979b7 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -2578,7 +2578,7 @@ static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) cpumask_t *cpu_in_guest; int i; - cpu = cpu_first_thread_sibling(cpu); + cpu = cpu_first_tlb_thread_sibling(cpu); if (nested) { cpumask_set_cpu(cpu, &nested->need_tlb_flush); cpu_in_guest = &nested->cpu_in_guest; @@ -2592,9 +2592,10 @@ static void radix_flush_cpu(struct kvm *kvm, int cpu, struct kvm_vcpu *vcpu) * the other side is the first smp_mb() in kvmppc_run_core(). */ smp_mb(); - for (i = 0; i < threads_per_core; ++i) - if (cpumask_test_cpu(cpu + i, cpu_in_guest)) - smp_call_function_single(cpu + i, do_nothing, NULL, 1); + for (i = cpu; i <= cpu_last_tlb_thread_sibling(cpu); + i += cpu_tlb_thread_sibling_step()) + if (cpumask_test_cpu(i, cpu_in_guest)) + smp_call_function_single(i, do_nothing, NULL, 1); } static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu) @@ -2625,8 +2626,8 @@ static void kvmppc_prepare_radix_vcpu(struct kvm_vcpu *vcpu, int pcpu) */ if (prev_cpu != pcpu) { if (prev_cpu >= 0 && - cpu_first_thread_sibling(prev_cpu) != - cpu_first_thread_sibling(pcpu)) + cpu_first_tlb_thread_sibling(prev_cpu) != + cpu_first_tlb_thread_sibling(pcpu)) radix_flush_cpu(kvm, prev_cpu, vcpu); if (nested) nested->prev_cpu[vcpu->arch.nested_vcpu_id] = pcpu; @@ -3583,6 +3584,7 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, unsigned long host_tidr = mfspr(SPRN_TIDR); unsigned long host_iamr = mfspr(SPRN_IAMR); unsigned long host_amr = mfspr(SPRN_AMR); + unsigned long host_fscr = mfspr(SPRN_FSCR); s64 dec; u64 tb; int trap, save_pmu; @@ -3726,6 +3728,9 @@ static int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, if (host_amr != vcpu->arch.amr) mtspr(SPRN_AMR, host_amr); + if (host_fscr != vcpu->arch.fscr) + mtspr(SPRN_FSCR, host_fscr); + msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX); store_fp_state(&vcpu->arch.fp); #ifdef CONFIG_ALTIVEC diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 8f58dd20b362a9cb4727b8b7bb9eb97621ca189f..4621905bdd9ea05bbe0cfaf578958d1e3f6fb7a1 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c @@ -893,7 +893,7 @@ void kvmppc_check_need_tlb_flush(struct kvm *kvm, int pcpu, * Thus we make all 4 threads use the same bit. */ if (cpu_has_feature(CPU_FTR_ARCH_300)) - pcpu = cpu_first_thread_sibling(pcpu); + pcpu = cpu_first_tlb_thread_sibling(pcpu); if (nested) need_tlb_flush = &nested->need_tlb_flush; diff --git a/arch/powerpc/kvm/book3s_hv_nested.c b/arch/powerpc/kvm/book3s_hv_nested.c index 33b58549a9aaf6a801e8130480a0aefd13dba4e7..065738819db9b5e4d3d3ff0915a281fd5ce39118 100644 --- a/arch/powerpc/kvm/book3s_hv_nested.c +++ b/arch/powerpc/kvm/book3s_hv_nested.c @@ -51,7 +51,8 @@ void kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr) hr->ppr = vcpu->arch.ppr; } -static void byteswap_pt_regs(struct pt_regs *regs) +/* Use noinline_for_stack due to https://bugs.llvm.org/show_bug.cgi?id=49610 */ +static noinline_for_stack void byteswap_pt_regs(struct pt_regs *regs) { unsigned long *addr = (unsigned long *) regs; diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 88da2764c1bb9c63d87a795bedaa5caf08593e75..3ddc83d2e8493eca06ec0ae0bbcb692fb49e5db1 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c @@ -67,7 +67,7 @@ static int global_invalidates(struct kvm *kvm) * so use the bit for the first thread to represent the core. */ if (cpu_has_feature(CPU_FTR_ARCH_300)) - cpu = cpu_first_thread_sibling(cpu); + cpu = cpu_first_tlb_thread_sibling(cpu); cpumask_clear_cpu(cpu, &kvm->arch.need_tlb_flush); } diff --git a/arch/powerpc/mm/book3s64/radix_tlb.c b/arch/powerpc/mm/book3s64/radix_tlb.c index b487b489d4b6835769e282f728da875ddbddcbd9..4c2f75916a7eafec68afae624e8810e56205e14d 100644 --- a/arch/powerpc/mm/book3s64/radix_tlb.c +++ b/arch/powerpc/mm/book3s64/radix_tlb.c @@ -282,22 +282,30 @@ static inline void fixup_tlbie_lpid(unsigned long lpid) /* * We use 128 set in radix mode and 256 set in hpt mode. */ -static __always_inline void _tlbiel_pid(unsigned long pid, unsigned long ric) +static inline void _tlbiel_pid(unsigned long pid, unsigned long ric) { int set; asm volatile("ptesync": : :"memory"); - /* - * Flush the first set of the TLB, and if we're doing a RIC_FLUSH_ALL, - * also flush the entire Page Walk Cache. - */ - __tlbiel_pid(pid, 0, ric); + switch (ric) { + case RIC_FLUSH_PWC: - /* For PWC, only one flush is needed */ - if (ric == RIC_FLUSH_PWC) { + /* For PWC, only one flush is needed */ + __tlbiel_pid(pid, 0, RIC_FLUSH_PWC); ppc_after_tlbiel_barrier(); return; + case RIC_FLUSH_TLB: + __tlbiel_pid(pid, 0, RIC_FLUSH_TLB); + break; + case RIC_FLUSH_ALL: + default: + /* + * Flush the first set of the TLB, and if + * we're doing a RIC_FLUSH_ALL, also flush + * the entire Page Walk Cache. + */ + __tlbiel_pid(pid, 0, RIC_FLUSH_ALL); } /* For the remaining sets, just flush the TLB */ @@ -1068,7 +1076,7 @@ void radix__tlb_flush(struct mmu_gather *tlb) } } -static __always_inline void __radix__flush_tlb_range_psize(struct mm_struct *mm, +static void __radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start, unsigned long end, int psize, bool also_pwc) { diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 72e1b51beb10c5ba19d0948ac1b6e177f7595679..55fdba8ba21cad25b97ffe50360529502062b1e7 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -198,9 +198,7 @@ static bool bad_kernel_fault(struct pt_regs *regs, unsigned long error_code, { int is_exec = TRAP(regs) == 0x400; - /* NX faults set DSISR_PROTFAULT on the 8xx, DSISR_NOEXEC_OR_G on others */ - if (is_exec && (error_code & (DSISR_NOEXEC_OR_G | DSISR_KEYFAULT | - DSISR_PROTFAULT))) { + if (is_exec) { pr_crit_ratelimited("kernel tried to execute %s page (%lx) - exploit attempt? (uid: %d)\n", address >= TASK_SIZE ? "exec-protected" : "user", address, diff --git a/arch/powerpc/platforms/cell/smp.c b/arch/powerpc/platforms/cell/smp.c index c855a0aeb49cc8cfcffebae4c2a1c39cded46ddf..d7ab868aab54afe63395be9e5bf105f6d29f04ac 100644 --- a/arch/powerpc/platforms/cell/smp.c +++ b/arch/powerpc/platforms/cell/smp.c @@ -78,9 +78,6 @@ static inline int smp_startup_cpu(unsigned int lcpu) pcpu = get_hard_smp_processor_id(lcpu); - /* Fixup atomic count: it exited inside IRQ handler. */ - task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count = 0; - /* * If the RTAS start-cpu token does not exist then presume the * cpu is already spinning. diff --git a/arch/powerpc/platforms/powernv/vas-window.c b/arch/powerpc/platforms/powernv/vas-window.c index 5f5fe63a3d1cebbde434d87cd8b9026b8d9b8dea..7ba0840fc3b557bcabafda5be5da814a3a7f37f7 100644 --- a/arch/powerpc/platforms/powernv/vas-window.c +++ b/arch/powerpc/platforms/powernv/vas-window.c @@ -1093,9 +1093,9 @@ struct vas_window *vas_tx_win_open(int vasid, enum vas_cop_type cop, /* * Process closes window during exit. In the case of * multithread application, the child thread can open - * window and can exit without closing it. Expects parent - * thread to use and close the window. So do not need - * to take pid reference for parent thread. + * window and can exit without closing it. so takes tgid + * reference until window closed to make sure tgid is not + * reused. */ txwin->tgid = find_get_pid(task_tgid_vnr(current)); /* @@ -1339,8 +1339,9 @@ int vas_win_close(struct vas_window *window) /* if send window, drop reference to matching receive window */ if (window->tx_win) { if (window->user_win) { - /* Drop references to pid and mm */ + /* Drop references to pid. tgid and mm */ put_pid(window->pid); + put_pid(window->tgid); if (window->mm) { mm_context_remove_vas_window(window->mm); mmdrop(window->mm); diff --git a/arch/powerpc/platforms/ps3/mm.c b/arch/powerpc/platforms/ps3/mm.c index d094321964fb035ce74f8ebbf87b95c092c284c8..a81eac35d9009d20d0fd96e8df7f90eadc9d1b90 100644 --- a/arch/powerpc/platforms/ps3/mm.c +++ b/arch/powerpc/platforms/ps3/mm.c @@ -6,6 +6,7 @@ * Copyright 2006 Sony Corp. */ +#include <linux/dma-mapping.h> #include <linux/kernel.h> #include <linux/export.h> #include <linux/memblock.h> @@ -1118,6 +1119,7 @@ int ps3_dma_region_init(struct ps3_system_bus_device *dev, enum ps3_dma_region_type region_type, void *addr, unsigned long len) { unsigned long lpar_addr; + int result; lpar_addr = addr ? ps3_mm_phys_to_lpar(__pa(addr)) : 0; @@ -1129,6 +1131,16 @@ int ps3_dma_region_init(struct ps3_system_bus_device *dev, r->offset -= map.r1.offset; r->len = len ? len : ALIGN(map.total, 1 << r->page_size); + dev->core.dma_mask = &r->dma_mask; + + result = dma_set_mask_and_coherent(&dev->core, DMA_BIT_MASK(32)); + + if (result < 0) { + dev_err(&dev->core, "%s:%d: dma_set_mask_and_coherent failed: %d\n", + __func__, __LINE__, result); + return result; + } + switch (dev->dev_type) { case PS3_DEVICE_TYPE_SB: r->region_ops = (USE_DYNAMIC_DMA) diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c index 835163f54244ab005041989f275ccb54774da000..057acbb9116dd3f0808313a7f4a5f6ca95eacc2c 100644 --- a/arch/powerpc/platforms/pseries/papr_scm.c +++ b/arch/powerpc/platforms/pseries/papr_scm.c @@ -18,6 +18,7 @@ #include <asm/plpar_wrappers.h> #include <asm/papr_pdsm.h> #include <asm/mce.h> +#include <asm/unaligned.h> #define BIND_ANY_ADDR (~0ul) @@ -867,6 +868,20 @@ static ssize_t flags_show(struct device *dev, } DEVICE_ATTR_RO(flags); +static umode_t papr_nd_attribute_visible(struct kobject *kobj, + struct attribute *attr, int n) +{ + struct device *dev = kobj_to_dev(kobj); + struct nvdimm *nvdimm = to_nvdimm(dev); + struct papr_scm_priv *p = nvdimm_provider_data(nvdimm); + + /* For if perf-stats not available remove perf_stats sysfs */ + if (attr == &dev_attr_perf_stats.attr && p->stat_buffer_len == 0) + return 0; + + return attr->mode; +} + /* papr_scm specific dimm attributes */ static struct attribute *papr_nd_attributes[] = { &dev_attr_flags.attr, @@ -876,6 +891,7 @@ static struct attribute *papr_nd_attributes[] = { static struct attribute_group papr_nd_attribute_group = { .name = "papr", + .is_visible = papr_nd_attribute_visible, .attrs = papr_nd_attributes, }; @@ -891,7 +907,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) struct nd_region_desc ndr_desc; unsigned long dimm_flags; int target_nid, online_nid; - ssize_t stat_size; p->bus_desc.ndctl = papr_scm_ndctl; p->bus_desc.module = THIS_MODULE; @@ -962,16 +977,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p) list_add_tail(&p->region_list, &papr_nd_regions); mutex_unlock(&papr_ndr_lock); - /* Try retriving the stat buffer and see if its supported */ - stat_size = drc_pmem_query_stats(p, NULL, 0); - if (stat_size > 0) { - p->stat_buffer_len = stat_size; - dev_dbg(&p->pdev->dev, "Max perf-stat size %lu-bytes\n", - p->stat_buffer_len); - } else { - dev_info(&p->pdev->dev, "Dimm performance stats unavailable\n"); - } - return 0; err: nvdimm_bus_unregister(p->bus); @@ -1047,8 +1052,10 @@ static int papr_scm_probe(struct platform_device *pdev) u32 drc_index, metadata_size; u64 blocks, block_size; struct papr_scm_priv *p; + u8 uuid_raw[UUID_SIZE]; const char *uuid_str; - u64 uuid[2]; + ssize_t stat_size; + uuid_t uuid; int rc; /* check we have all the required DT properties */ @@ -1090,16 +1097,23 @@ static int papr_scm_probe(struct platform_device *pdev) p->is_volatile = !of_property_read_bool(dn, "ibm,cache-flush-required"); /* We just need to ensure that set cookies are unique across */ - uuid_parse(uuid_str, (uuid_t *) uuid); + uuid_parse(uuid_str, &uuid); + /* - * cookie1 and cookie2 are not really little endian - * we store a little endian representation of the - * uuid str so that we can compare this with the label - * area cookie irrespective of the endian config with which - * the kernel is built. + * The cookie1 and cookie2 are not really little endian. + * We store a raw buffer representation of the + * uuid string so that we can compare this with the label + * area cookie irrespective of the endian configuration + * with which the kernel is built. + * + * Historically we stored the cookie in the below format. + * for a uuid string 72511b67-0b3b-42fd-8d1d-5be3cae8bcaa + * cookie1 was 0xfd423b0b671b5172 + * cookie2 was 0xaabce8cae35b1d8d */ - p->nd_set.cookie1 = cpu_to_le64(uuid[0]); - p->nd_set.cookie2 = cpu_to_le64(uuid[1]); + export_uuid(uuid_raw, &uuid); + p->nd_set.cookie1 = get_unaligned_le64(&uuid_raw[0]); + p->nd_set.cookie2 = get_unaligned_le64(&uuid_raw[8]); /* might be zero */ p->metadata_size = metadata_size; @@ -1124,6 +1138,14 @@ static int papr_scm_probe(struct platform_device *pdev) p->res.name = pdev->name; p->res.flags = IORESOURCE_MEM; + /* Try retrieving the stat buffer and see if its supported */ + stat_size = drc_pmem_query_stats(p, NULL, 0); + if (stat_size > 0) { + p->stat_buffer_len = stat_size; + dev_dbg(&p->pdev->dev, "Max perf-stat size %lu-bytes\n", + p->stat_buffer_len); + } + rc = papr_scm_nvdimm_init(p); if (rc) goto err2; diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 92922491a81c6bd161f0e704529c4ada1d2edab0..624e80b00eb1882c28e00f5f4cd6bf90b1c32c81 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c @@ -104,9 +104,6 @@ static inline int smp_startup_cpu(unsigned int lcpu) return 1; } - /* Fixup atomic count: it exited inside IRQ handler. */ - task_thread_info(paca_ptrs[lcpu]->__current)->preempt_count = 0; - /* * If the RTAS start-cpu token does not exist then presume the * cpu is already spinning. diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index e241e0e85ac812dbb3c33daf7e806866dd578e42..226c366072da3be17be66608b97376cf8bd6a6eb 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -14,7 +14,7 @@ ifeq ($(CONFIG_DYNAMIC_FTRACE),y) LDFLAGS_vmlinux := --no-relax endif -ifeq ($(CONFIG_64BIT)$(CONFIG_CMODEL_MEDLOW),yy) +ifeq ($(CONFIG_CMODEL_MEDLOW),y) KBUILD_CFLAGS_MODULE += -mcmodel=medany endif diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c index 96167d55ed9845a23debad56fcbeb009c600c7d1..0b04e0eae3ab5bfe0e9ff714e6ebef512b83dafd 100644 --- a/arch/riscv/kernel/smpboot.c +++ b/arch/riscv/kernel/smpboot.c @@ -166,7 +166,6 @@ asmlinkage __visible void smp_callin(void) * Disable preemption before enabling interrupts, so we don't try to * schedule a CPU that hasn't actually started yet. */ - preempt_disable(); local_irq_enable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 4a2a12be04c964c6f4df1a227d90135761e5dd53..896b68e541b2e28148603e5ed5ce11a5308105d2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -154,6 +154,8 @@ config S390 select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_GCC_PLUGINS select HAVE_GENERIC_VDSO + select HAVE_IOREMAP_PROT if PCI + select HAVE_IRQ_EXIT_ON_IRQ_STACK select HAVE_KERNEL_BZIP2 select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZ4 @@ -856,7 +858,7 @@ config CMM_IUCV config APPLDATA_BASE def_bool n prompt "Linux - VM Monitor Stream, base infrastructure" - depends on PROC_FS + depends on PROC_SYSCTL help This provides a kernel interface for creating and updating z/VM APPLDATA monitor records. The monitor records are updated at certain time diff --git a/arch/s390/Makefile b/arch/s390/Makefile index ba94b03c8b2f4e0871848f487a03aafdbcc37380..92506918da633ebe9026ecde26fcb9cfb403d6c1 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -28,6 +28,7 @@ KBUILD_CFLAGS_DECOMPRESSOR += -DDISABLE_BRANCH_PROFILING -D__NO_FORTIFY KBUILD_CFLAGS_DECOMPRESSOR += -fno-delete-null-pointer-checks -msoft-float KBUILD_CFLAGS_DECOMPRESSOR += -fno-asynchronous-unwind-tables KBUILD_CFLAGS_DECOMPRESSOR += -ffreestanding +KBUILD_CFLAGS_DECOMPRESSOR += -fno-stack-protector KBUILD_CFLAGS_DECOMPRESSOR += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO),-g) KBUILD_CFLAGS_DECOMPRESSOR += $(if $(CONFIG_DEBUG_INFO_DWARF4), $(call cc-option, -gdwarf-4,)) diff --git a/arch/s390/boot/ipl_parm.c b/arch/s390/boot/ipl_parm.c index f94b91d72620ec740eaa77aaa5496c84dc392d5c..c56bbf58a945ece9a61b7beadcbaed506b2bd67c 100644 --- a/arch/s390/boot/ipl_parm.c +++ b/arch/s390/boot/ipl_parm.c @@ -28,22 +28,25 @@ static inline int __diag308(unsigned long subcode, void *addr) register unsigned long _addr asm("0") = (unsigned long)addr; register unsigned long _rc asm("1") = 0; unsigned long reg1, reg2; - psw_t old = S390_lowcore.program_new_psw; + psw_t old; asm volatile( + " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" " epsw %0,%1\n" - " st %0,%[psw_pgm]\n" - " st %1,%[psw_pgm]+4\n" + " st %0,0(%[psw_pgm])\n" + " st %1,4(%[psw_pgm])\n" " larl %0,1f\n" - " stg %0,%[psw_pgm]+8\n" + " stg %0,8(%[psw_pgm])\n" " diag %[addr],%[subcode],0x308\n" - "1: nopr %%r7\n" + "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" : "=&d" (reg1), "=&a" (reg2), - [psw_pgm] "=Q" (S390_lowcore.program_new_psw), + "+Q" (S390_lowcore.program_new_psw), + "=Q" (old), [addr] "+d" (_addr), "+d" (_rc) - : [subcode] "d" (subcode) + : [subcode] "d" (subcode), + [psw_old] "a" (&old), + [psw_pgm] "a" (&S390_lowcore.program_new_psw) : "cc", "memory"); - S390_lowcore.program_new_psw = old; return _rc; } diff --git a/arch/s390/boot/mem_detect.c b/arch/s390/boot/mem_detect.c index 62e7c13ce85c7e2d6e078c133ca15750dd13f0c7..85049541c191e38dc68bd43bade1df6052e1c0b7 100644 --- a/arch/s390/boot/mem_detect.c +++ b/arch/s390/boot/mem_detect.c @@ -70,24 +70,27 @@ static int __diag260(unsigned long rx1, unsigned long rx2) register unsigned long _ry asm("4") = 0x10; /* storage configuration */ int rc = -1; /* fail */ unsigned long reg1, reg2; - psw_t old = S390_lowcore.program_new_psw; + psw_t old; asm volatile( + " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" " epsw %0,%1\n" - " st %0,%[psw_pgm]\n" - " st %1,%[psw_pgm]+4\n" + " st %0,0(%[psw_pgm])\n" + " st %1,4(%[psw_pgm])\n" " larl %0,1f\n" - " stg %0,%[psw_pgm]+8\n" + " stg %0,8(%[psw_pgm])\n" " diag %[rx],%[ry],0x260\n" " ipm %[rc]\n" " srl %[rc],28\n" - "1:\n" + "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" : "=&d" (reg1), "=&a" (reg2), - [psw_pgm] "=Q" (S390_lowcore.program_new_psw), + "+Q" (S390_lowcore.program_new_psw), + "=Q" (old), [rc] "+&d" (rc), [ry] "+d" (_ry) - : [rx] "d" (_rx1), "d" (_rx2) + : [rx] "d" (_rx1), "d" (_rx2), + [psw_old] "a" (&old), + [psw_pgm] "a" (&S390_lowcore.program_new_psw) : "cc", "memory"); - S390_lowcore.program_new_psw = old; return rc == 0 ? _ry : -1; } @@ -112,24 +115,30 @@ static int diag260(void) static int tprot(unsigned long addr) { - unsigned long pgm_addr; + unsigned long reg1, reg2; int rc = -EFAULT; - psw_t old = S390_lowcore.program_new_psw; + psw_t old; - S390_lowcore.program_new_psw.mask = __extract_psw(); asm volatile( - " larl %[pgm_addr],1f\n" - " stg %[pgm_addr],%[psw_pgm_addr]\n" + " mvc 0(16,%[psw_old]),0(%[psw_pgm])\n" + " epsw %[reg1],%[reg2]\n" + " st %[reg1],0(%[psw_pgm])\n" + " st %[reg2],4(%[psw_pgm])\n" + " larl %[reg1],1f\n" + " stg %[reg1],8(%[psw_pgm])\n" " tprot 0(%[addr]),0\n" " ipm %[rc]\n" " srl %[rc],28\n" - "1:\n" - : [pgm_addr] "=&d"(pgm_addr), - [psw_pgm_addr] "=Q"(S390_lowcore.program_new_psw.addr), - [rc] "+&d"(rc) - : [addr] "a"(addr) + "1: mvc 0(16,%[psw_pgm]),0(%[psw_old])\n" + : [reg1] "=&d" (reg1), + [reg2] "=&a" (reg2), + [rc] "+&d" (rc), + "=Q" (S390_lowcore.program_new_psw.addr), + "=Q" (old) + : [psw_old] "a" (&old), + [psw_pgm] "a" (&S390_lowcore.program_new_psw), + [addr] "a" (addr) : "cc", "memory"); - S390_lowcore.program_new_psw = old; return rc; } diff --git a/arch/s390/boot/uv.c b/arch/s390/boot/uv.c index 87641dd65ccf915e8d11aa5062dcc0433f34eeb4..b3501ea5039e464b6da2e8425581586f514e488b 100644 --- a/arch/s390/boot/uv.c +++ b/arch/s390/boot/uv.c @@ -36,6 +36,7 @@ void uv_query_info(void) uv_info.max_sec_stor_addr = ALIGN(uvcb.max_guest_stor_addr, PAGE_SIZE); uv_info.max_num_sec_conf = uvcb.max_num_sec_conf; uv_info.max_guest_cpu_id = uvcb.max_guest_cpu_id; + uv_info.uv_feature_indications = uvcb.uv_feature_indications; } #ifdef CONFIG_PROTECTED_VIRTUALIZATION_GUEST diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index b5dbae78969b9876dc24c29c22e9a69298b5478b..2338345912a31e6312bf083348ce07103d218000 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -864,6 +864,25 @@ static inline int pte_unused(pte_t pte) return pte_val(pte) & _PAGE_UNUSED; } +/* + * Extract the pgprot value from the given pte while at the same time making it + * usable for kernel address space mappings where fault driven dirty and + * young/old accounting is not supported, i.e _PAGE_PROTECT and _PAGE_INVALID + * must not be set. + */ +static inline pgprot_t pte_pgprot(pte_t pte) +{ + unsigned long pte_flags = pte_val(pte) & _PAGE_CHG_MASK; + + if (pte_write(pte)) + pte_flags |= pgprot_val(PAGE_KERNEL); + else + pte_flags |= pgprot_val(PAGE_KERNEL_RO); + pte_flags |= pte_val(pte) & mio_wb_bit_mask; + + return __pgprot(pte_flags); +} + /* * pgd/pmd/pte modification functions */ diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h index 6ede29907fbf76424ed52de165db93af0e600933..b5f545db461a4ff4d427c5d51e8533ff9d3aeedd 100644 --- a/arch/s390/include/asm/preempt.h +++ b/arch/s390/include/asm/preempt.h @@ -29,12 +29,6 @@ static inline void preempt_count_set(int pc) old, new) != old); } -#define init_task_preempt_count(p) do { } while (0) - -#define init_idle_preempt_count(p, cpu) do { \ - S390_lowcore.preempt_count = PREEMPT_ENABLED; \ -} while (0) - static inline void set_preempt_need_resched(void) { __atomic_and(~PREEMPT_NEED_RESCHED, &S390_lowcore.preempt_count); @@ -88,12 +82,6 @@ static inline void preempt_count_set(int pc) S390_lowcore.preempt_count = pc; } -#define init_task_preempt_count(p) do { } while (0) - -#define init_idle_preempt_count(p, cpu) do { \ - S390_lowcore.preempt_count = PREEMPT_ENABLED; \ -} while (0) - static inline void set_preempt_need_resched(void) { } @@ -130,6 +118,10 @@ static inline bool should_resched(int preempt_offset) #endif /* CONFIG_HAVE_MARCH_Z196_FEATURES */ +#define init_task_preempt_count(p) do { } while (0) +/* Deferred to CPU bringup time */ +#define init_idle_preempt_count(p, cpu) do { } while (0) + #ifdef CONFIG_PREEMPTION extern asmlinkage void preempt_schedule(void); #define __preempt_schedule() preempt_schedule() diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 962da04234af406ec471d4a01def45f48e9699cc..0987c3fc45f589d986352928b8e66280d5246d47 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h @@ -211,7 +211,7 @@ static __always_inline unsigned long current_stack_pointer(void) return sp; } -static __no_kasan_or_inline unsigned short stap(void) +static __always_inline unsigned short stap(void) { unsigned short cpu_address; @@ -250,7 +250,7 @@ static inline void __load_psw(psw_t psw) * Set PSW mask to specified value, while leaving the * PSW addr pointing to the next instruction. */ -static __no_kasan_or_inline void __load_psw_mask(unsigned long mask) +static __always_inline void __load_psw_mask(unsigned long mask) { unsigned long addr; psw_t psw; diff --git a/arch/s390/include/asm/stacktrace.h b/arch/s390/include/asm/stacktrace.h index ee056f4a4fa3061b45df8a97a0d10703c7952aab..ee582896b6a3f7ad5187ccf1ed7f3541ce1a817c 100644 --- a/arch/s390/include/asm/stacktrace.h +++ b/arch/s390/include/asm/stacktrace.h @@ -90,12 +90,16 @@ struct stack_frame { CALL_ARGS_4(arg1, arg2, arg3, arg4); \ register unsigned long r4 asm("6") = (unsigned long)(arg5) -#define CALL_FMT_0 "=&d" (r2) : -#define CALL_FMT_1 "+&d" (r2) : -#define CALL_FMT_2 CALL_FMT_1 "d" (r3), -#define CALL_FMT_3 CALL_FMT_2 "d" (r4), -#define CALL_FMT_4 CALL_FMT_3 "d" (r5), -#define CALL_FMT_5 CALL_FMT_4 "d" (r6), +/* + * To keep this simple mark register 2-6 as being changed (volatile) + * by the called function, even though register 6 is saved/nonvolatile. + */ +#define CALL_FMT_0 "=&d" (r2) +#define CALL_FMT_1 "+&d" (r2) +#define CALL_FMT_2 CALL_FMT_1, "+&d" (r3) +#define CALL_FMT_3 CALL_FMT_2, "+&d" (r4) +#define CALL_FMT_4 CALL_FMT_3, "+&d" (r5) +#define CALL_FMT_5 CALL_FMT_4, "+&d" (r6) #define CALL_CLOBBER_5 "0", "1", "14", "cc", "memory" #define CALL_CLOBBER_4 CALL_CLOBBER_5 @@ -117,7 +121,7 @@ struct stack_frame { " brasl 14,%[_fn]\n" \ " la 15,0(%[_prev])\n" \ : [_prev] "=&a" (prev), CALL_FMT_##nr \ - [_stack] "R" (stack), \ + : [_stack] "R" (stack), \ [_bc] "i" (offsetof(struct stack_frame, back_chain)), \ [_frame] "d" (frame), \ [_fn] "X" (fn) : CALL_CLOBBER_##nr); \ diff --git a/arch/s390/include/asm/uv.h b/arch/s390/include/asm/uv.h index 7b98d4caee779cfd128182f62a6f56fbc4dae1e2..12c5f006c1364b714c4a7187b659c3c2fb71d0d2 100644 --- a/arch/s390/include/asm/uv.h +++ b/arch/s390/include/asm/uv.h @@ -73,6 +73,10 @@ enum uv_cmds_inst { BIT_UVC_CMD_UNPIN_PAGE_SHARED = 22, }; +enum uv_feat_ind { + BIT_UV_FEAT_MISC = 0, +}; + struct uv_cb_header { u16 len; u16 cmd; /* Command Code */ @@ -97,7 +101,8 @@ struct uv_cb_qui { u64 max_guest_stor_addr; u8 reserved88[158 - 136]; u16 max_guest_cpu_id; - u8 reserveda0[200 - 160]; + u64 uv_feature_indications; + u8 reserveda0[200 - 168]; } __packed __aligned(8); /* Initialize Ultravisor */ @@ -274,6 +279,7 @@ struct uv_info { unsigned long max_sec_stor_addr; unsigned int max_num_sec_conf; unsigned short max_guest_cpu_id; + unsigned long uv_feature_indications; }; extern struct uv_info uv_info; diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index e83ce909686c5e7024cd905d4ae1764bb3083348..5cd9d20af31e95438985816f6eab945e4be01d0f 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -166,7 +166,7 @@ static void __init set_preferred_console(void) else if (CONSOLE_IS_3270) add_preferred_console("tty3270", 0, NULL); else if (CONSOLE_IS_VT220) - add_preferred_console("ttyS", 1, NULL); + add_preferred_console("ttysclp", 0, NULL); else if (CONSOLE_IS_HVC) add_preferred_console("hvc", 0, NULL); } @@ -454,6 +454,7 @@ static void __init setup_lowcore_dat_off(void) lc->br_r1_trampoline = 0x07f1; /* br %r1 */ lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW); lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); + lc->preempt_count = PREEMPT_DISABLED; set_prefix((u32)(unsigned long) lc); lowcore_ptr[0] = lc; diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 791bc373418bd3d7ad44c8deef8da7f2e715953a..5674792726cd9107f1f0cccace2cd4eada98db3b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -215,6 +215,7 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) lc->br_r1_trampoline = 0x07f1; /* br %r1 */ lc->return_lpswe = gen_lpswe(__LC_RETURN_PSW); lc->return_mcck_lpswe = gen_lpswe(__LC_RETURN_MCCK_PSW); + lc->preempt_count = PREEMPT_DISABLED; if (nmi_alloc_per_cpu(lc)) goto out_async; if (vdso_alloc_per_cpu(lc)) @@ -863,7 +864,6 @@ static void smp_init_secondary(void) set_cpu_flag(CIF_ASCE_SECONDARY); cpu_init(); rcu_cpu_starting(cpu); - preempt_disable(); init_cpu_timer(); vtime_init(); pfault_init(); diff --git a/arch/s390/kernel/uv.c b/arch/s390/kernel/uv.c index b2d2ad1530676ddad2142c3963bdd41bd0a72da7..c811b2313100be65524202ef8194cd30e685ec62 100644 --- a/arch/s390/kernel/uv.c +++ b/arch/s390/kernel/uv.c @@ -364,6 +364,15 @@ static ssize_t uv_query_facilities(struct kobject *kobj, static struct kobj_attribute uv_query_facilities_attr = __ATTR(facilities, 0444, uv_query_facilities, NULL); +static ssize_t uv_query_feature_indications(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sysfs_emit(buf, "%lx\n", uv_info.uv_feature_indications); +} + +static struct kobj_attribute uv_query_feature_indications_attr = + __ATTR(feature_indications, 0444, uv_query_feature_indications, NULL); + static ssize_t uv_query_max_guest_cpus(struct kobject *kobj, struct kobj_attribute *attr, char *page) { @@ -396,6 +405,7 @@ static struct kobj_attribute uv_query_max_guest_addr_attr = static struct attribute *uv_query_attrs[] = { &uv_query_facilities_attr.attr, + &uv_query_feature_indications_attr.attr, &uv_query_max_guest_cpus_attr.attr, &uv_query_max_guest_vms_attr.attr, &uv_query_max_guest_addr_attr.attr, diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 20afffd6b9820c313c935294d28475308071a2d7..f94b4f78d4dabf1ba897f3c87a93ee4867cbe5da 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -327,31 +327,31 @@ static void allow_cpu_feat(unsigned long nr) static inline int plo_test_bit(unsigned char nr) { - register unsigned long r0 asm("0") = (unsigned long) nr | 0x100; + unsigned long function = (unsigned long)nr | 0x100; int cc; asm volatile( + " lgr 0,%[function]\n" /* Parameter registers are ignored for "test bit" */ " plo 0,0,0,0(0)\n" " ipm %0\n" " srl %0,28\n" : "=d" (cc) - : "d" (r0) - : "cc"); + : [function] "d" (function) + : "cc", "0"); return cc == 0; } static __always_inline void __insn32_query(unsigned int opcode, u8 *query) { - register unsigned long r0 asm("0") = 0; /* query function */ - register unsigned long r1 asm("1") = (unsigned long) query; - asm volatile( - /* Parameter regs are ignored */ + " lghi 0,0\n" + " lgr 1,%[query]\n" + /* Parameter registers are ignored */ " .insn rrf,%[opc] << 16,2,4,6,0\n" : - : "d" (r0), "a" (r1), [opc] "i" (opcode) - : "cc", "memory"); + : [query] "d" ((unsigned long)query), [opc] "i" (opcode) + : "cc", "memory", "0", "1"); } #define INSN_SORTL 0xb938 diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 996884dcc9fdb0bbdb9cf1033ad56ed6df6289cc..ed517fad0d035f6f99ca9b8a8408d243807ee3f6 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -805,6 +805,32 @@ void do_secure_storage_access(struct pt_regs *regs) struct page *page; int rc; + /* + * bit 61 tells us if the address is valid, if it's not we + * have a major problem and should stop the kernel or send a + * SIGSEGV to the process. Unfortunately bit 61 is not + * reliable without the misc UV feature so we need to check + * for that as well. + */ + if (test_bit_inv(BIT_UV_FEAT_MISC, &uv_info.uv_feature_indications) && + !test_bit_inv(61, ®s->int_parm_long)) { + /* + * When this happens, userspace did something that it + * was not supposed to do, e.g. branching into secure + * memory. Trigger a segmentation fault. + */ + if (user_mode(regs)) { + send_sig(SIGSEGV, current, 0); + return; + } + + /* + * The kernel should never run into this case and we + * have no way out of this situation. + */ + panic("Unexpected PGM 0x3d with TEID bit 61=0"); + } + switch (get_fault_type(regs)) { case USER_FAULT: mm = current->mm; diff --git a/arch/s390/purgatory/Makefile b/arch/s390/purgatory/Makefile index c57f8c40e992685812170f3db796256b7e620934..21c4ebe29b9a2be839fd6399845f777e09ebe790 100644 --- a/arch/s390/purgatory/Makefile +++ b/arch/s390/purgatory/Makefile @@ -24,6 +24,7 @@ KBUILD_CFLAGS := -fno-strict-aliasing -Wall -Wstrict-prototypes KBUILD_CFLAGS += -Wno-pointer-sign -Wno-sign-compare KBUILD_CFLAGS += -fno-zero-initialized-in-bss -fno-builtin -ffreestanding KBUILD_CFLAGS += -c -MD -Os -m64 -msoft-float -fno-common +KBUILD_CFLAGS += -fno-stack-protector KBUILD_CFLAGS += $(CLANG_FLAGS) KBUILD_CFLAGS += $(call cc-option,-fno-PIE) KBUILD_AFLAGS := $(filter-out -DCC_USING_EXPOLINE,$(KBUILD_AFLAGS)) diff --git a/arch/sh/kernel/smp.c b/arch/sh/kernel/smp.c index 372acdc9033eb35da2b5a610cc6221f53208e573..65924d9ec24598f81e995bee85bf4cb135b1d84b 100644 --- a/arch/sh/kernel/smp.c +++ b/arch/sh/kernel/smp.c @@ -186,8 +186,6 @@ asmlinkage void start_secondary(void) per_cpu_trap_init(); - preempt_disable(); - notify_cpu_starting(cpu); local_irq_enable(); diff --git a/arch/sparc/kernel/smp_32.c b/arch/sparc/kernel/smp_32.c index 50c127ab46d5bc810f6e874a106188f8029e6af4..22b148e5a5f88c76c46b17b87c53f7df510940c8 100644 --- a/arch/sparc/kernel/smp_32.c +++ b/arch/sparc/kernel/smp_32.c @@ -348,7 +348,6 @@ static void sparc_start_secondary(void *arg) */ arch_cpu_pre_starting(arg); - preempt_disable(); cpu = smp_processor_id(); notify_cpu_starting(cpu); diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c index e38d8bf454e866636e7091d131277e0596baebb3..ae5faa1d989d2ec7e8ef3e0f05f7d91148b25bc3 100644 --- a/arch/sparc/kernel/smp_64.c +++ b/arch/sparc/kernel/smp_64.c @@ -138,9 +138,6 @@ void smp_callin(void) set_cpu_online(cpuid, true); - /* idle thread is expected to have preempt disabled */ - preempt_disable(); - local_irq_enable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index d8845d4aac6a75be257c3b5f825fb77947edcd80..6040817c036f3fd3ecbc6d6a128b1473d24df22c 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -256,7 +256,8 @@ static int winch_tramp(int fd, struct tty_port *port, int *fd_out, goto out_close; } - if (os_set_fd_block(*fd_out, 0)) { + err = os_set_fd_block(*fd_out, 0); + if (err) { printk(UM_KERN_ERR "winch_tramp: failed to set thread_fd " "non-blocking.\n"); goto out_close; diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 482a19c5105c5c3780642bc335d542c96fbd6997..7334019c9e60a2239b922757888b022891b9dca0 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -145,7 +145,8 @@ static int slip_open(void *data) } sfd = err; - if (set_up_tty(sfd)) + err = set_up_tty(sfd); + if (err) goto out_close2; pri->slave = sfd; diff --git a/arch/x86/crypto/curve25519-x86_64.c b/arch/x86/crypto/curve25519-x86_64.c index 5af8021b98cea4e8d10b7b1ebc5a264c89ab7bd4..11b4c83c715e333d5af73a75abd1cbc7add6dd7f 100644 --- a/arch/x86/crypto/curve25519-x86_64.c +++ b/arch/x86/crypto/curve25519-x86_64.c @@ -1500,7 +1500,7 @@ static int __init curve25519_mod_init(void) static void __exit curve25519_mod_exit(void) { if (IS_REACHABLE(CONFIG_CRYPTO_KPP) && - (boot_cpu_has(X86_FEATURE_BMI2) || boot_cpu_has(X86_FEATURE_ADX))) + static_branch_likely(&curve25519_use_bmi2_adx)) crypto_unregister_kpp(&curve25519_alg); } diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c index 2e4d91f3feea4413534dfe870f1fb736d8b75639..93a3122cd15fff046d273aa3a0e9531ef7552652 100644 --- a/arch/x86/entry/common.c +++ b/arch/x86/entry/common.c @@ -127,8 +127,8 @@ static noinstr bool __do_fast_syscall_32(struct pt_regs *regs) /* User code screwed up. */ regs->ax = -EFAULT; - instrumentation_end(); local_irq_disable(); + instrumentation_end(); irqentry_exit_to_user_mode(regs); return false; } diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index cad08703c4ad774f2e473f0dcc71b53cdb579a68..f18f3932e971af15817e62979335aaab01765c0e 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S @@ -508,7 +508,7 @@ SYM_CODE_START(\asmsym) movq %rsp, %rdi /* pt_regs pointer */ - call \cfunc + call kernel_\cfunc /* * No need to switch back to the IST stack. The current stack is either @@ -519,7 +519,7 @@ SYM_CODE_START(\asmsym) /* Switch to the regular task stack */ .Lfrom_usermode_switch_stack_\@: - idtentry_body safe_stack_\cfunc, has_error_code=1 + idtentry_body user_\cfunc, has_error_code=1 _ASM_NOKPROBE(\asmsym) SYM_CODE_END(\asmsym) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index a88c94d6569315a7bd33a85cda5f0cff212d448f..e6db1a1f22d7d60d7e8e81abce3b12d5be7da997 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -45,9 +45,11 @@ #include "perf_event.h" struct x86_pmu x86_pmu __read_mostly; +static struct pmu pmu; DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, + .pmu = &pmu, }; DEFINE_STATIC_KEY_FALSE(rdpmc_never_available_key); @@ -372,10 +374,12 @@ int x86_reserve_hardware(void) if (!atomic_inc_not_zero(&pmc_refcount)) { mutex_lock(&pmc_reserve_mutex); if (atomic_read(&pmc_refcount) == 0) { - if (!reserve_pmc_hardware()) + if (!reserve_pmc_hardware()) { err = -EBUSY; - else + } else { reserve_ds_buffers(); + reserve_lbr_buffers(); + } } if (!err) atomic_inc(&pmc_refcount); @@ -710,16 +714,23 @@ void x86_pmu_enable_all(int added) } } -static struct pmu pmu; - static inline int is_x86_event(struct perf_event *event) { return event->pmu == &pmu; } -struct pmu *x86_get_pmu(void) +struct pmu *x86_get_pmu(unsigned int cpu) { - return &pmu; + struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu); + + /* + * All CPUs of the hybrid type have been offline. + * The x86_get_pmu() should not be invoked. + */ + if (WARN_ON_ONCE(!cpuc->pmu)) + return &pmu; + + return cpuc->pmu; } /* * Event scheduler state: diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index ee659b5faf71460ec7a7d1db530b6d0dd13ee64e..3b8b8eede1a8aa7862209f3f216fb2aa53cf6d16 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -4747,7 +4747,7 @@ static void update_tfa_sched(void *ignored) * and if so force schedule out for all event types all contexts */ if (test_bit(3, cpuc->active_mask)) - perf_pmu_resched(x86_get_pmu()); + perf_pmu_resched(x86_get_pmu(smp_processor_id())); } static ssize_t show_sysctl_tfa(struct device *cdev, diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index 31a7a6566d077b3af5c019f7a5fb974b134bbc0b..945d470f62d0fcc09e4fd525fcf9f067e2bb745b 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -2076,7 +2076,7 @@ void __init intel_ds_init(void) PERF_SAMPLE_TIME; x86_pmu.flags |= PMU_FL_PEBS_ALL; pebs_qual = "-baseline"; - x86_get_pmu()->capabilities |= PERF_PMU_CAP_EXTENDED_REGS; + x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_EXTENDED_REGS; } else { /* Only basic record supported */ x86_pmu.large_pebs_flags &= @@ -2091,7 +2091,7 @@ void __init intel_ds_init(void) if (x86_pmu.intel_cap.pebs_output_pt_available) { pr_cont("PEBS-via-PT, "); - x86_get_pmu()->capabilities |= PERF_PMU_CAP_AUX_OUTPUT; + x86_get_pmu(smp_processor_id())->capabilities |= PERF_PMU_CAP_AUX_OUTPUT; } break; diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c index e2b0efcba1017bb0382ef58aa0ab38cd1b736d8c..9c1a013d5682297885704ee425127db6d464b741 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -658,7 +658,6 @@ static inline bool branch_user_callstack(unsigned br_sel) void intel_pmu_lbr_add(struct perf_event *event) { - struct kmem_cache *kmem_cache = event->pmu->task_ctx_cache; struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); if (!x86_pmu.lbr_nr) @@ -696,16 +695,11 @@ void intel_pmu_lbr_add(struct perf_event *event) perf_sched_cb_inc(event->ctx->pmu); if (!cpuc->lbr_users++ && !event->total_time_running) intel_pmu_lbr_reset(); - - if (static_cpu_has(X86_FEATURE_ARCH_LBR) && - kmem_cache && !cpuc->lbr_xsave && - (cpuc->lbr_users != cpuc->lbr_pebs_users)) - cpuc->lbr_xsave = kmem_cache_alloc(kmem_cache, GFP_KERNEL); } void release_lbr_buffers(void) { - struct kmem_cache *kmem_cache = x86_get_pmu()->task_ctx_cache; + struct kmem_cache *kmem_cache; struct cpu_hw_events *cpuc; int cpu; @@ -714,6 +708,7 @@ void release_lbr_buffers(void) for_each_possible_cpu(cpu) { cpuc = per_cpu_ptr(&cpu_hw_events, cpu); + kmem_cache = x86_get_pmu(cpu)->task_ctx_cache; if (kmem_cache && cpuc->lbr_xsave) { kmem_cache_free(kmem_cache, cpuc->lbr_xsave); cpuc->lbr_xsave = NULL; @@ -721,6 +716,27 @@ void release_lbr_buffers(void) } } +void reserve_lbr_buffers(void) +{ + struct kmem_cache *kmem_cache; + struct cpu_hw_events *cpuc; + int cpu; + + if (!static_cpu_has(X86_FEATURE_ARCH_LBR)) + return; + + for_each_possible_cpu(cpu) { + cpuc = per_cpu_ptr(&cpu_hw_events, cpu); + kmem_cache = x86_get_pmu(cpu)->task_ctx_cache; + if (!kmem_cache || cpuc->lbr_xsave) + continue; + + cpuc->lbr_xsave = kmem_cache_alloc_node(kmem_cache, + GFP_KERNEL | __GFP_ZERO, + cpu_to_node(cpu)); + } +} + void intel_pmu_lbr_del(struct perf_event *event) { struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events); @@ -1609,7 +1625,7 @@ void intel_pmu_lbr_init_hsw(void) x86_pmu.lbr_sel_mask = LBR_SEL_MASK; x86_pmu.lbr_sel_map = hsw_lbr_sel_map; - x86_get_pmu()->task_ctx_cache = create_lbr_kmem_cache(size, 0); + x86_get_pmu(smp_processor_id())->task_ctx_cache = create_lbr_kmem_cache(size, 0); if (lbr_from_signext_quirk_needed()) static_branch_enable(&lbr_from_quirk_key); @@ -1629,7 +1645,7 @@ __init void intel_pmu_lbr_init_skl(void) x86_pmu.lbr_sel_mask = LBR_SEL_MASK; x86_pmu.lbr_sel_map = hsw_lbr_sel_map; - x86_get_pmu()->task_ctx_cache = create_lbr_kmem_cache(size, 0); + x86_get_pmu(smp_processor_id())->task_ctx_cache = create_lbr_kmem_cache(size, 0); /* * SW branch filter usage: @@ -1726,7 +1742,7 @@ static bool is_arch_lbr_xsave_available(void) void __init intel_pmu_arch_lbr_init(void) { - struct pmu *pmu = x86_get_pmu(); + struct pmu *pmu = x86_get_pmu(smp_processor_id()); union cpuid28_eax eax; union cpuid28_ebx ebx; union cpuid28_ecx ecx; diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h index 6a8edfe59b09c94605b412aab5e2e01db346ded7..f07d77cffb3c6ae809fa5b457a55499e404b3228 100644 --- a/arch/x86/events/perf_event.h +++ b/arch/x86/events/perf_event.h @@ -326,6 +326,8 @@ struct cpu_hw_events { int n_pair; /* Large increment events */ void *kfree_on_online[X86_PERF_KFREE_MAX]; + + struct pmu *pmu; }; #define __EVENT_CONSTRAINT_RANGE(c, e, n, m, w, o, f) { \ @@ -897,7 +899,7 @@ static struct perf_pmu_events_ht_attr event_attr_##v = { \ .event_str_ht = ht, \ } -struct pmu *x86_get_pmu(void); +struct pmu *x86_get_pmu(unsigned int cpu); extern struct x86_pmu x86_pmu __read_mostly; static __always_inline struct x86_perf_task_context_opt *task_context_opt(void *ctx) @@ -1122,6 +1124,8 @@ void reserve_ds_buffers(void); void release_lbr_buffers(void); +void reserve_lbr_buffers(void); + extern struct event_constraint bts_constraint; extern struct event_constraint vlbr_constraint; @@ -1267,6 +1271,10 @@ static inline void release_lbr_buffers(void) { } +static inline void reserve_lbr_buffers(void) +{ +} + static inline int intel_pmu_init(void) { return 0; diff --git a/arch/x86/include/asm/fpu/internal.h b/arch/x86/include/asm/fpu/internal.h index fdee23ea4e173717a3aab162bc5582167940ddf8..4e5af2b00d89ba9651d3e5a84ef754ce96b68ce1 100644 --- a/arch/x86/include/asm/fpu/internal.h +++ b/arch/x86/include/asm/fpu/internal.h @@ -103,6 +103,7 @@ static inline void fpstate_init_fxstate(struct fxregs_state *fx) } extern void fpstate_sanitize_xstate(struct fpu *fpu); +/* Returns 0 or the negated trap number, which results in -EFAULT for #PF */ #define user_insn(insn, output, input...) \ ({ \ int err; \ @@ -110,14 +111,14 @@ extern void fpstate_sanitize_xstate(struct fpu *fpu); might_fault(); \ \ asm volatile(ASM_STAC "\n" \ - "1:" #insn "\n\t" \ + "1: " #insn "\n" \ "2: " ASM_CLAC "\n" \ ".section .fixup,\"ax\"\n" \ - "3: movl $-1,%[err]\n" \ + "3: negl %%eax\n" \ " jmp 2b\n" \ ".previous\n" \ - _ASM_EXTABLE(1b, 3b) \ - : [err] "=r" (err), output \ + _ASM_EXTABLE_FAULT(1b, 3b) \ + : [err] "=a" (err), output \ : "0"(0), input); \ err; \ }) @@ -204,6 +205,14 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) asm volatile("fxsaveq %[fx]" : [fx] "=m" (fpu->state.fxsave)); } +static inline void fxsave(struct fxregs_state *fx) +{ + if (IS_ENABLED(CONFIG_X86_32)) + asm volatile( "fxsave %[fx]" : [fx] "=m" (*fx)); + else + asm volatile("fxsaveq %[fx]" : [fx] "=m" (*fx)); +} + /* These macros all use (%edi)/(%rdi) as the single memory argument. */ #define XSAVE ".byte " REX_PREFIX "0x0f,0xae,0x27" #define XSAVEOPT ".byte " REX_PREFIX "0x0f,0xae,0x37" @@ -211,16 +220,20 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) #define XRSTOR ".byte " REX_PREFIX "0x0f,0xae,0x2f" #define XRSTORS ".byte " REX_PREFIX "0x0f,0xc7,0x1f" +/* + * After this @err contains 0 on success or the negated trap number when + * the operation raises an exception. For faults this results in -EFAULT. + */ #define XSTATE_OP(op, st, lmask, hmask, err) \ asm volatile("1:" op "\n\t" \ "xor %[err], %[err]\n" \ "2:\n\t" \ ".pushsection .fixup,\"ax\"\n\t" \ - "3: movl $-2,%[err]\n\t" \ + "3: negl %%eax\n\t" \ "jmp 2b\n\t" \ ".popsection\n\t" \ - _ASM_EXTABLE(1b, 3b) \ - : [err] "=r" (err) \ + _ASM_EXTABLE_FAULT(1b, 3b) \ + : [err] "=a" (err) \ : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ : "memory") @@ -268,28 +281,6 @@ static inline void copy_fxregs_to_kernel(struct fpu *fpu) : "D" (st), "m" (*st), "a" (lmask), "d" (hmask) \ : "memory") -/* - * This function is called only during boot time when x86 caps are not set - * up and alternative can not be used yet. - */ -static inline void copy_xregs_to_kernel_booting(struct xregs_state *xstate) -{ - u64 mask = xfeatures_mask_all; - u32 lmask = mask; - u32 hmask = mask >> 32; - int err; - - WARN_ON(system_state != SYSTEM_BOOTING); - - if (boot_cpu_has(X86_FEATURE_XSAVES)) - XSTATE_OP(XSAVES, xstate, lmask, hmask, err); - else - XSTATE_OP(XSAVE, xstate, lmask, hmask, err); - - /* We should never fault when copying to a kernel buffer: */ - WARN_ON_FPU(err); -} - /* * This function is called only during boot time when x86 caps are not set * up and alternative can not be used yet. diff --git a/arch/x86/include/asm/idtentry.h b/arch/x86/include/asm/idtentry.h index 0e3325790f3a97d14a9c1b25c137c732a5fa1e69..dc2a8b1657f4ac46bbf70b8904bd21cd693c0102 100644 --- a/arch/x86/include/asm/idtentry.h +++ b/arch/x86/include/asm/idtentry.h @@ -315,8 +315,8 @@ static __always_inline void __##func(struct pt_regs *regs) */ #define DECLARE_IDTENTRY_VC(vector, func) \ DECLARE_IDTENTRY_RAW_ERRORCODE(vector, func); \ - __visible noinstr void ist_##func(struct pt_regs *regs, unsigned long error_code); \ - __visible noinstr void safe_stack_##func(struct pt_regs *regs, unsigned long error_code) + __visible noinstr void kernel_##func(struct pt_regs *regs, unsigned long error_code); \ + __visible noinstr void user_##func(struct pt_regs *regs, unsigned long error_code) /** * DEFINE_IDTENTRY_IST - Emit code for IST entry points @@ -358,33 +358,24 @@ static __always_inline void __##func(struct pt_regs *regs) DEFINE_IDTENTRY_RAW_ERRORCODE(func) /** - * DEFINE_IDTENTRY_VC_SAFE_STACK - Emit code for VMM communication handler - which runs on a safe stack. + * DEFINE_IDTENTRY_VC_KERNEL - Emit code for VMM communication handler + when raised from kernel mode * @func: Function name of the entry point * * Maps to DEFINE_IDTENTRY_RAW_ERRORCODE */ -#define DEFINE_IDTENTRY_VC_SAFE_STACK(func) \ - DEFINE_IDTENTRY_RAW_ERRORCODE(safe_stack_##func) +#define DEFINE_IDTENTRY_VC_KERNEL(func) \ + DEFINE_IDTENTRY_RAW_ERRORCODE(kernel_##func) /** - * DEFINE_IDTENTRY_VC_IST - Emit code for VMM communication handler - which runs on the VC fall-back stack + * DEFINE_IDTENTRY_VC_USER - Emit code for VMM communication handler + when raised from user mode * @func: Function name of the entry point * * Maps to DEFINE_IDTENTRY_RAW_ERRORCODE */ -#define DEFINE_IDTENTRY_VC_IST(func) \ - DEFINE_IDTENTRY_RAW_ERRORCODE(ist_##func) - -/** - * DEFINE_IDTENTRY_VC - Emit code for VMM communication handler - * @func: Function name of the entry point - * - * Maps to DEFINE_IDTENTRY_RAW_ERRORCODE - */ -#define DEFINE_IDTENTRY_VC(func) \ - DEFINE_IDTENTRY_RAW_ERRORCODE(func) +#define DEFINE_IDTENTRY_VC_USER(func) \ + DEFINE_IDTENTRY_RAW_ERRORCODE(user_##func) #else /* CONFIG_X86_64 */ diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index ef56780022c3e232654e18492cb24c6134e2164c..b1cd8334db11a7789465f31aeb4e4a9d6ee3cdee 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -84,7 +84,7 @@ #define KVM_REQ_APICV_UPDATE \ KVM_ARCH_REQ_FLAGS(25, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP) #define KVM_REQ_TLB_FLUSH_CURRENT KVM_ARCH_REQ(26) -#define KVM_REQ_HV_TLB_FLUSH \ +#define KVM_REQ_TLB_FLUSH_GUEST \ KVM_ARCH_REQ_FLAGS(27, KVM_REQUEST_NO_WAKEUP) #define KVM_REQ_APF_READY KVM_ARCH_REQ(28) #define KVM_REQ_MSR_FILTER_CHANGED KVM_ARCH_REQ(29) @@ -296,6 +296,7 @@ union kvm_mmu_extended_role { unsigned int cr4_pke:1; unsigned int cr4_smap:1; unsigned int cr4_smep:1; + unsigned int cr4_la57:1; unsigned int maxphyaddr:6; }; }; diff --git a/arch/x86/include/asm/preempt.h b/arch/x86/include/asm/preempt.h index 69485ca13665f1722a919bbf1c8345cd25e8d8ae..a334dd0d7c42c58dc587da6105b9fa87562e19da 100644 --- a/arch/x86/include/asm/preempt.h +++ b/arch/x86/include/asm/preempt.h @@ -43,7 +43,7 @@ static __always_inline void preempt_count_set(int pc) #define init_task_preempt_count(p) do { } while (0) #define init_idle_preempt_count(p, cpu) do { \ - per_cpu(__preempt_count, (cpu)) = PREEMPT_ENABLED; \ + per_cpu(__preempt_count, (cpu)) = PREEMPT_DISABLED; \ } while (0) /* diff --git a/arch/x86/include/uapi/asm/hwcap2.h b/arch/x86/include/uapi/asm/hwcap2.h index 5fdfcb47000f9bb5ac55345c92f8dc1655bac1f7..054604aba9f00927fe8f46c62ab79e45cdb68a9c 100644 --- a/arch/x86/include/uapi/asm/hwcap2.h +++ b/arch/x86/include/uapi/asm/hwcap2.h @@ -2,10 +2,12 @@ #ifndef _ASM_X86_HWCAP2_H #define _ASM_X86_HWCAP2_H +#include <linux/const.h> + /* MONITOR/MWAIT enabled in Ring 3 */ -#define HWCAP2_RING3MWAIT (1 << 0) +#define HWCAP2_RING3MWAIT _BITUL(0) /* Kernel allows FSGSBASE instructions available in Ring 3 */ -#define HWCAP2_FSGSBASE BIT(1) +#define HWCAP2_FSGSBASE _BITUL(1) #endif diff --git a/arch/x86/kernel/fpu/regset.c b/arch/x86/kernel/fpu/regset.c index c413756ba89fa0c924e8ba08d3b86e9dba02bdc0..6bb874441de8b22d0b19d911f2547463f0e63975 100644 --- a/arch/x86/kernel/fpu/regset.c +++ b/arch/x86/kernel/fpu/regset.c @@ -117,7 +117,7 @@ int xstateregs_set(struct task_struct *target, const struct user_regset *regset, /* * A whole standard-format XSAVE buffer is needed: */ - if ((pos != 0) || (count < fpu_user_xstate_size)) + if (pos != 0 || count != fpu_user_xstate_size) return -EFAULT; xsave = &fpu->state.xsave; diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c index ec3ae305479201323977467d59c1736dc398fd4f..b7b92cdf3add41063426e8897d004d424376b5af 100644 --- a/arch/x86/kernel/fpu/signal.c +++ b/arch/x86/kernel/fpu/signal.c @@ -221,28 +221,18 @@ sanitize_restored_user_xstate(union fpregs_state *state, if (use_xsave()) { /* - * Note: we don't need to zero the reserved bits in the - * xstate_header here because we either didn't copy them at all, - * or we checked earlier that they aren't set. + * Clear all feature bits which are not set in + * user_xfeatures and clear all extended features + * for fx_only mode. */ + u64 mask = fx_only ? XFEATURE_MASK_FPSSE : user_xfeatures; /* - * 'user_xfeatures' might have bits clear which are - * set in header->xfeatures. This represents features that - * were in init state prior to a signal delivery, and need - * to be reset back to the init state. Clear any user - * feature bits which are set in the kernel buffer to get - * them back to the init state. - * - * Supervisor state is unchanged by input from userspace. - * Ensure supervisor state bits stay set and supervisor - * state is not modified. + * Supervisor state has to be preserved. The sigframe + * restore can only modify user features, i.e. @mask + * cannot contain them. */ - if (fx_only) - header->xfeatures = XFEATURE_MASK_FPSSE; - else - header->xfeatures &= user_xfeatures | - xfeatures_mask_supervisor(); + header->xfeatures &= mask | xfeatures_mask_supervisor(); } if (use_fxsr()) { diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index 67f1a03b9b2356f48d25b63f137efc16fc9fd0e6..80836b94189e700c9d629529177dd447cc16fe36 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -440,6 +440,25 @@ static void __init print_xstate_offset_size(void) } } +/* + * All supported features have either init state all zeros or are + * handled in setup_init_fpu() individually. This is an explicit + * feature list and does not use XFEATURE_MASK*SUPPORTED to catch + * newly added supported features at build time and make people + * actually look at the init state for the new feature. + */ +#define XFEATURES_INIT_FPSTATE_HANDLED \ + (XFEATURE_MASK_FP | \ + XFEATURE_MASK_SSE | \ + XFEATURE_MASK_YMM | \ + XFEATURE_MASK_OPMASK | \ + XFEATURE_MASK_ZMM_Hi256 | \ + XFEATURE_MASK_Hi16_ZMM | \ + XFEATURE_MASK_PKRU | \ + XFEATURE_MASK_BNDREGS | \ + XFEATURE_MASK_BNDCSR | \ + XFEATURE_MASK_PASID) + /* * setup the xstate image representing the init state */ @@ -447,6 +466,10 @@ static void __init setup_init_fpu_buf(void) { static int on_boot_cpu __initdata = 1; + BUILD_BUG_ON((XFEATURE_MASK_USER_SUPPORTED | + XFEATURE_MASK_SUPERVISOR_SUPPORTED) != + XFEATURES_INIT_FPSTATE_HANDLED); + WARN_ON_FPU(!on_boot_cpu); on_boot_cpu = 0; @@ -466,10 +489,22 @@ static void __init setup_init_fpu_buf(void) copy_kernel_to_xregs_booting(&init_fpstate.xsave); /* - * Dump the init state again. This is to identify the init state - * of any feature which is not represented by all zero's. + * All components are now in init state. Read the state back so + * that init_fpstate contains all non-zero init state. This only + * works with XSAVE, but not with XSAVEOPT and XSAVES because + * those use the init optimization which skips writing data for + * components in init state. + * + * XSAVE could be used, but that would require to reshuffle the + * data when XSAVES is available because XSAVES uses xstate + * compaction. But doing so is a pointless exercise because most + * components have an all zeros init state except for the legacy + * ones (FP and SSE). Those can be saved with FXSAVE into the + * legacy area. Adding new features requires to ensure that init + * state is all zeroes or if not to add the necessary handling + * here. */ - copy_xregs_to_kernel_booting(&init_fpstate.xsave); + fxsave(&init_fpstate.fxsave); } static int xfeature_uncompacted_offset(int xfeature_nr) @@ -1049,20 +1084,10 @@ static inline bool xfeatures_mxcsr_quirk(u64 xfeatures) return true; } -static void fill_gap(struct membuf *to, unsigned *last, unsigned offset) -{ - if (*last >= offset) - return; - membuf_write(to, (void *)&init_fpstate.xsave + *last, offset - *last); - *last = offset; -} - -static void copy_part(struct membuf *to, unsigned *last, unsigned offset, - unsigned size, void *from) +static void copy_feature(bool from_xstate, struct membuf *to, void *xstate, + void *init_xstate, unsigned int size) { - fill_gap(to, last, offset); - membuf_write(to, from, size); - *last = offset + size; + membuf_write(to, from_xstate ? xstate : init_xstate, size); } /* @@ -1074,10 +1099,10 @@ static void copy_part(struct membuf *to, unsigned *last, unsigned offset, */ void copy_xstate_to_kernel(struct membuf to, struct xregs_state *xsave) { + const unsigned int off_mxcsr = offsetof(struct fxregs_state, mxcsr); + struct xregs_state *xinit = &init_fpstate.xsave; struct xstate_header header; - const unsigned off_mxcsr = offsetof(struct fxregs_state, mxcsr); - unsigned size = to.left; - unsigned last = 0; + unsigned int zerofrom; int i; /* @@ -1087,41 +1112,68 @@ void copy_xstate_to_kernel(struct membuf to, struct xregs_state *xsave) header.xfeatures = xsave->header.xfeatures; header.xfeatures &= xfeatures_mask_user(); - if (header.xfeatures & XFEATURE_MASK_FP) - copy_part(&to, &last, 0, off_mxcsr, &xsave->i387); - if (header.xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM)) - copy_part(&to, &last, off_mxcsr, - MXCSR_AND_FLAGS_SIZE, &xsave->i387.mxcsr); - if (header.xfeatures & XFEATURE_MASK_FP) - copy_part(&to, &last, offsetof(struct fxregs_state, st_space), - 128, &xsave->i387.st_space); - if (header.xfeatures & XFEATURE_MASK_SSE) - copy_part(&to, &last, xstate_offsets[XFEATURE_SSE], - 256, &xsave->i387.xmm_space); - /* - * Fill xsave->i387.sw_reserved value for ptrace frame: - */ - copy_part(&to, &last, offsetof(struct fxregs_state, sw_reserved), - 48, xstate_fx_sw_bytes); - /* - * Copy xregs_state->header: - */ - copy_part(&to, &last, offsetof(struct xregs_state, header), - sizeof(header), &header); + /* Copy FP state up to MXCSR */ + copy_feature(header.xfeatures & XFEATURE_MASK_FP, &to, &xsave->i387, + &xinit->i387, off_mxcsr); + + /* Copy MXCSR when SSE or YMM are set in the feature mask */ + copy_feature(header.xfeatures & (XFEATURE_MASK_SSE | XFEATURE_MASK_YMM), + &to, &xsave->i387.mxcsr, &xinit->i387.mxcsr, + MXCSR_AND_FLAGS_SIZE); + + /* Copy the remaining FP state */ + copy_feature(header.xfeatures & XFEATURE_MASK_FP, + &to, &xsave->i387.st_space, &xinit->i387.st_space, + sizeof(xsave->i387.st_space)); + + /* Copy the SSE state - shared with YMM, but independently managed */ + copy_feature(header.xfeatures & XFEATURE_MASK_SSE, + &to, &xsave->i387.xmm_space, &xinit->i387.xmm_space, + sizeof(xsave->i387.xmm_space)); + + /* Zero the padding area */ + membuf_zero(&to, sizeof(xsave->i387.padding)); + + /* Copy xsave->i387.sw_reserved */ + membuf_write(&to, xstate_fx_sw_bytes, sizeof(xsave->i387.sw_reserved)); + + /* Copy the user space relevant state of @xsave->header */ + membuf_write(&to, &header, sizeof(header)); + + zerofrom = offsetof(struct xregs_state, extended_state_area); for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) { /* - * Copy only in-use xstates: + * The ptrace buffer is in non-compacted XSAVE format. + * In non-compacted format disabled features still occupy + * state space, but there is no state to copy from in the + * compacted init_fpstate. The gap tracking will zero this + * later. + */ + if (!(xfeatures_mask_user() & BIT_ULL(i))) + continue; + + /* + * If there was a feature or alignment gap, zero the space + * in the destination buffer. */ - if ((header.xfeatures >> i) & 1) { - void *src = __raw_xsave_addr(xsave, i); + if (zerofrom < xstate_offsets[i]) + membuf_zero(&to, xstate_offsets[i] - zerofrom); - copy_part(&to, &last, xstate_offsets[i], - xstate_sizes[i], src); - } + copy_feature(header.xfeatures & BIT_ULL(i), &to, + __raw_xsave_addr(xsave, i), + __raw_xsave_addr(xinit, i), + xstate_sizes[i]); + /* + * Keep track of the last copied state in the non-compacted + * target buffer for gap zeroing. + */ + zerofrom = xstate_offsets[i] + xstate_sizes[i]; } - fill_gap(&to, &last, size); + + if (to.left) + membuf_zero(&to, to.left); } /* diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c index e0cdab7cb632b3ccc8c25d2411ec9590147a558d..f3202b2e3c1579f2371361dd3065e7afc6cc8592 100644 --- a/arch/x86/kernel/sev-es.c +++ b/arch/x86/kernel/sev-es.c @@ -12,7 +12,6 @@ #include <linux/sched/debug.h> /* For show_regs() */ #include <linux/percpu-defs.h> #include <linux/mem_encrypt.h> -#include <linux/lockdep.h> #include <linux/printk.h> #include <linux/mm_types.h> #include <linux/set_memory.h> @@ -180,11 +179,19 @@ void noinstr __sev_es_ist_exit(void) this_cpu_write(cpu_tss_rw.x86_tss.ist[IST_INDEX_VC], *(unsigned long *)ist); } -static __always_inline struct ghcb *sev_es_get_ghcb(struct ghcb_state *state) +/* + * Nothing shall interrupt this code path while holding the per-CPU + * GHCB. The backup GHCB is only for NMIs interrupting this path. + * + * Callers must disable local interrupts around it. + */ +static noinstr struct ghcb *__sev_get_ghcb(struct ghcb_state *state) { struct sev_es_runtime_data *data; struct ghcb *ghcb; + WARN_ON(!irqs_disabled()); + data = this_cpu_read(runtime_data); ghcb = &data->ghcb_page; @@ -201,7 +208,9 @@ static __always_inline struct ghcb *sev_es_get_ghcb(struct ghcb_state *state) data->ghcb_active = false; data->backup_ghcb_active = false; + instrumentation_begin(); panic("Unable to handle #VC exception! GHCB and Backup GHCB are already in use"); + instrumentation_end(); } /* Mark backup_ghcb active before writing to it */ @@ -452,11 +461,13 @@ static enum es_result vc_slow_virt_to_phys(struct ghcb *ghcb, struct es_em_ctxt /* Include code shared with pre-decompression boot stage */ #include "sev-es-shared.c" -static __always_inline void sev_es_put_ghcb(struct ghcb_state *state) +static noinstr void __sev_put_ghcb(struct ghcb_state *state) { struct sev_es_runtime_data *data; struct ghcb *ghcb; + WARN_ON(!irqs_disabled()); + data = this_cpu_read(runtime_data); ghcb = &data->ghcb_page; @@ -480,7 +491,7 @@ void noinstr __sev_es_nmi_complete(void) struct ghcb_state state; struct ghcb *ghcb; - ghcb = sev_es_get_ghcb(&state); + ghcb = __sev_get_ghcb(&state); vc_ghcb_invalidate(ghcb); ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_NMI_COMPLETE); @@ -490,7 +501,7 @@ void noinstr __sev_es_nmi_complete(void) sev_es_wr_ghcb_msr(__pa_nodebug(ghcb)); VMGEXIT(); - sev_es_put_ghcb(&state); + __sev_put_ghcb(&state); } static u64 get_jump_table_addr(void) @@ -502,7 +513,7 @@ static u64 get_jump_table_addr(void) local_irq_save(flags); - ghcb = sev_es_get_ghcb(&state); + ghcb = __sev_get_ghcb(&state); vc_ghcb_invalidate(ghcb); ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_JUMP_TABLE); @@ -516,7 +527,7 @@ static u64 get_jump_table_addr(void) ghcb_sw_exit_info_2_is_valid(ghcb)) ret = ghcb->save.sw_exit_info_2; - sev_es_put_ghcb(&state); + __sev_put_ghcb(&state); local_irq_restore(flags); @@ -641,7 +652,7 @@ static void sev_es_ap_hlt_loop(void) struct ghcb_state state; struct ghcb *ghcb; - ghcb = sev_es_get_ghcb(&state); + ghcb = __sev_get_ghcb(&state); while (true) { vc_ghcb_invalidate(ghcb); @@ -658,7 +669,7 @@ static void sev_es_ap_hlt_loop(void) break; } - sev_es_put_ghcb(&state); + __sev_put_ghcb(&state); } /* @@ -748,7 +759,7 @@ void __init sev_es_init_vc_handling(void) sev_es_setup_play_dead(); /* Secondary CPUs use the runtime #VC handler */ - initial_vc_handler = (unsigned long)safe_stack_exc_vmm_communication; + initial_vc_handler = (unsigned long)kernel_exc_vmm_communication; } static void __init vc_early_forward_exception(struct es_em_ctxt *ctxt) @@ -1186,14 +1197,6 @@ static enum es_result vc_handle_trap_ac(struct ghcb *ghcb, return ES_EXCEPTION; } -static __always_inline void vc_handle_trap_db(struct pt_regs *regs) -{ - if (user_mode(regs)) - noist_exc_debug(regs); - else - exc_debug(regs); -} - static enum es_result vc_handle_exitcode(struct es_em_ctxt *ctxt, struct ghcb *ghcb, unsigned long exit_code) @@ -1289,44 +1292,15 @@ static __always_inline bool on_vc_fallback_stack(struct pt_regs *regs) return (sp >= __this_cpu_ist_bottom_va(VC2) && sp < __this_cpu_ist_top_va(VC2)); } -/* - * Main #VC exception handler. It is called when the entry code was able to - * switch off the IST to a safe kernel stack. - * - * With the current implementation it is always possible to switch to a safe - * stack because #VC exceptions only happen at known places, like intercepted - * instructions or accesses to MMIO areas/IO ports. They can also happen with - * code instrumentation when the hypervisor intercepts #DB, but the critical - * paths are forbidden to be instrumented, so #DB exceptions currently also - * only happen in safe places. - */ -DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication) +static bool vc_raw_handle_exception(struct pt_regs *regs, unsigned long error_code) { - irqentry_state_t irq_state; struct ghcb_state state; struct es_em_ctxt ctxt; enum es_result result; struct ghcb *ghcb; + bool ret = true; - /* - * Handle #DB before calling into !noinstr code to avoid recursive #DB. - */ - if (error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB) { - vc_handle_trap_db(regs); - return; - } - - irq_state = irqentry_nmi_enter(regs); - lockdep_assert_irqs_disabled(); - instrumentation_begin(); - - /* - * This is invoked through an interrupt gate, so IRQs are disabled. The - * code below might walk page-tables for user or kernel addresses, so - * keep the IRQs disabled to protect us against concurrent TLB flushes. - */ - - ghcb = sev_es_get_ghcb(&state); + ghcb = __sev_get_ghcb(&state); vc_ghcb_invalidate(ghcb); result = vc_init_em_ctxt(&ctxt, regs, error_code); @@ -1334,7 +1308,7 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication) if (result == ES_OK) result = vc_handle_exitcode(&ctxt, ghcb, error_code); - sev_es_put_ghcb(&state); + __sev_put_ghcb(&state); /* Done - now check the result */ switch (result) { @@ -1344,15 +1318,18 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication) case ES_UNSUPPORTED: pr_err_ratelimited("Unsupported exit-code 0x%02lx in early #VC exception (IP: 0x%lx)\n", error_code, regs->ip); - goto fail; + ret = false; + break; case ES_VMM_ERROR: pr_err_ratelimited("Failure in communication with VMM (exit-code 0x%02lx IP: 0x%lx)\n", error_code, regs->ip); - goto fail; + ret = false; + break; case ES_DECODE_FAILED: pr_err_ratelimited("Failed to decode instruction (exit-code 0x%02lx IP: 0x%lx)\n", error_code, regs->ip); - goto fail; + ret = false; + break; case ES_EXCEPTION: vc_forward_exception(&ctxt); break; @@ -1368,24 +1345,52 @@ DEFINE_IDTENTRY_VC_SAFE_STACK(exc_vmm_communication) BUG(); } -out: - instrumentation_end(); - irqentry_nmi_exit(regs, irq_state); + return ret; +} - return; +static __always_inline bool vc_is_db(unsigned long error_code) +{ + return error_code == SVM_EXIT_EXCP_BASE + X86_TRAP_DB; +} -fail: - if (user_mode(regs)) { - /* - * Do not kill the machine if user-space triggered the - * exception. Send SIGBUS instead and let user-space deal with - * it. - */ - force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)0); - } else { - pr_emerg("PANIC: Unhandled #VC exception in kernel space (result=%d)\n", - result); +/* + * Runtime #VC exception handler when raised from kernel mode. Runs in NMI mode + * and will panic when an error happens. + */ +DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication) +{ + irqentry_state_t irq_state; + /* + * With the current implementation it is always possible to switch to a + * safe stack because #VC exceptions only happen at known places, like + * intercepted instructions or accesses to MMIO areas/IO ports. They can + * also happen with code instrumentation when the hypervisor intercepts + * #DB, but the critical paths are forbidden to be instrumented, so #DB + * exceptions currently also only happen in safe places. + * + * But keep this here in case the noinstr annotations are violated due + * to bug elsewhere. + */ + if (unlikely(on_vc_fallback_stack(regs))) { + instrumentation_begin(); + panic("Can't handle #VC exception from unsupported context\n"); + instrumentation_end(); + } + + /* + * Handle #DB before calling into !noinstr code to avoid recursive #DB. + */ + if (vc_is_db(error_code)) { + exc_debug(regs); + return; + } + + irq_state = irqentry_nmi_enter(regs); + + instrumentation_begin(); + + if (!vc_raw_handle_exception(regs, error_code)) { /* Show some debug info */ show_regs(regs); @@ -1396,23 +1401,38 @@ fail: panic("Returned from Terminate-Request to Hypervisor\n"); } - goto out; + instrumentation_end(); + irqentry_nmi_exit(regs, irq_state); } -/* This handler runs on the #VC fall-back stack. It can cause further #VC exceptions */ -DEFINE_IDTENTRY_VC_IST(exc_vmm_communication) +/* + * Runtime #VC exception handler when raised from user mode. Runs in IRQ mode + * and will kill the current task with SIGBUS when an error happens. + */ +DEFINE_IDTENTRY_VC_USER(exc_vmm_communication) { + /* + * Handle #DB before calling into !noinstr code to avoid recursive #DB. + */ + if (vc_is_db(error_code)) { + noist_exc_debug(regs); + return; + } + + irqentry_enter_from_user_mode(regs); instrumentation_begin(); - panic("Can't handle #VC exception from unsupported context\n"); - instrumentation_end(); -} -DEFINE_IDTENTRY_VC(exc_vmm_communication) -{ - if (likely(!on_vc_fallback_stack(regs))) - safe_stack_exc_vmm_communication(regs, error_code); - else - ist_exc_vmm_communication(regs, error_code); + if (!vc_raw_handle_exception(regs, error_code)) { + /* + * Do not kill the machine if user-space triggered the + * exception. Send SIGBUS instead and let user-space deal with + * it. + */ + force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)0); + } + + instrumentation_end(); + irqentry_exit_to_user_mode(regs); } bool __init handle_vc_boot_ghcb(struct pt_regs *regs) diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index f51cab3e983d8fa4897de31f1bc63e01684967ae..b001ba811cabbe716c5d9ba46ca4e258acd0570a 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -234,10 +234,11 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, void __user **fpstate) { /* Default to using normal stack */ + bool nested_altstack = on_sig_stack(regs->sp); + bool entering_altstack = false; unsigned long math_size = 0; unsigned long sp = regs->sp; unsigned long buf_fx = 0; - int onsigstack = on_sig_stack(sp); int ret; /* redzone */ @@ -246,15 +247,23 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, /* This is the X/Open sanctioned signal stack switching. */ if (ka->sa.sa_flags & SA_ONSTACK) { - if (sas_ss_flags(sp) == 0) + /* + * This checks nested_altstack via sas_ss_flags(). Sensible + * programs use SS_AUTODISARM, which disables that check, and + * programs that don't use SS_AUTODISARM get compatible. + */ + if (sas_ss_flags(sp) == 0) { sp = current->sas_ss_sp + current->sas_ss_size; + entering_altstack = true; + } } else if (IS_ENABLED(CONFIG_X86_32) && - !onsigstack && + !nested_altstack && regs->ss != __USER_DS && !(ka->sa.sa_flags & SA_RESTORER) && ka->sa.sa_restorer) { /* This is the legacy signal stack switching. */ sp = (unsigned long) ka->sa.sa_restorer; + entering_altstack = true; } sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32), @@ -267,8 +276,15 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size, * If we are on the alternate signal stack and would overflow it, don't. * Return an always-bogus address instead so we will die with SIGSEGV. */ - if (onsigstack && !likely(on_sig_stack(sp))) + if (unlikely((nested_altstack || entering_altstack) && + !__on_sig_stack(sp))) { + + if (show_unhandled_signals && printk_ratelimit()) + pr_info("%s[%d] overflowed sigaltstack\n", + current->comm, task_pid_nr(current)); + return (void __user *)-1L; + } /* save i387 and extended state */ ret = copy_fpstate_to_sigframe(*fpstate, (void __user *)buf_fx, math_size); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 582387fc939f409ffa78c48a1f2c7b73fdf9986e..8baff500914ea12f0e0f0310171a9d2f257edb83 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -230,7 +230,6 @@ static void notrace start_secondary(void *unused) cpu_init_exception_handling(); cpu_init(); x86_cpuinit.early_percpu_clock_init(); - preempt_disable(); smp_callin(); enable_start_cpu0 = 0; diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c index f70dffc2771f53d5f2b924126150d244463c09ee..56289170753c580c59f96fe1030b0c3a68ebbc8c 100644 --- a/arch/x86/kernel/tsc.c +++ b/arch/x86/kernel/tsc.c @@ -1151,7 +1151,8 @@ static struct clocksource clocksource_tsc = { .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_VALID_FOR_HRES | - CLOCK_SOURCE_MUST_VERIFY, + CLOCK_SOURCE_MUST_VERIFY | + CLOCK_SOURCE_VERIFY_PERCPU, .vdso_clock_mode = VDSO_CLOCKMODE_TSC, .enable = tsc_cs_enable, .resume = tsc_resume, diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c index 56a62d555e924a6daf91a1e332ff448934dbd19a..7a3fbf3b796e6aacaa5720dbbc2d78ab6b4aaed4 100644 --- a/arch/x86/kvm/cpuid.c +++ b/arch/x86/kvm/cpuid.c @@ -827,8 +827,14 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function) unsigned virt_as = max((entry->eax >> 8) & 0xff, 48U); unsigned phys_as = entry->eax & 0xff; - if (!g_phys_as) + /* + * Use bare metal's MAXPHADDR if the CPU doesn't report guest + * MAXPHYADDR separately, or if TDP (NPT) is disabled, as the + * guest version "applies only to guests using nested paging". + */ + if (!g_phys_as || !tdp_enabled) g_phys_as = phys_as; + entry->eax = g_phys_as | (virt_as << 8); entry->edx = 0; cpuid_entry_override(entry, CPUID_8000_0008_EBX); diff --git a/arch/x86/kvm/hyperv.c b/arch/x86/kvm/hyperv.c index 5c7c4060b45cbb58b8c7e76e528a9df246f0363a..bb39f493447cf8c1aa96bd2185e81b0b2f7aab72 100644 --- a/arch/x86/kvm/hyperv.c +++ b/arch/x86/kvm/hyperv.c @@ -1564,7 +1564,7 @@ static u64 kvm_hv_flush_tlb(struct kvm_vcpu *current_vcpu, u64 ingpa, * vcpu->arch.cr3 may not be up-to-date for running vCPUs so we can't * analyze it here, flush TLB regardless of the specified address space. */ - kvm_make_vcpus_request_mask(kvm, KVM_REQ_HV_TLB_FLUSH, + kvm_make_vcpus_request_mask(kvm, KVM_REQ_TLB_FLUSH_GUEST, NULL, vcpu_mask, &hv_vcpu->tlb_flush); ret_success: diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 6b794344c02dbd7de80505f8b4dcf0fb76f587b7..7ca2da9028298a4c04af6ad0077880324f12640e 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -52,6 +52,8 @@ #include <asm/kvm_page_track.h> #include "trace.h" +#include "paging.h" + extern bool itlb_multihit_kvm_mitigation; static int __read_mostly nx_huge_pages = -1; @@ -4133,7 +4135,15 @@ static void reset_rsvds_bits_mask_ept(struct kvm_vcpu *vcpu, void reset_shadow_zero_bits_mask(struct kvm_vcpu *vcpu, struct kvm_mmu *context) { - bool uses_nx = context->nx || + /* + * KVM uses NX when TDP is disabled to handle a variety of scenarios, + * notably for huge SPTEs if iTLB multi-hit mitigation is enabled and + * to generate correct permissions for CR0.WP=0/CR4.SMEP=1/EFER.NX=0. + * The iTLB multi-hit workaround can be toggled at any time, so assume + * NX can be used by any non-nested shadow MMU to avoid having to reset + * MMU contexts. Note, KVM forces EFER.NX=1 when TDP is disabled. + */ + bool uses_nx = context->nx || !tdp_enabled || context->mmu_role.base.smep_andnot_wp; struct rsvd_bits_validate *shadow_zero_check; int i; @@ -4442,6 +4452,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu) ext.cr4_smap = !!kvm_read_cr4_bits(vcpu, X86_CR4_SMAP); ext.cr4_pse = !!is_pse(vcpu); ext.cr4_pke = !!kvm_read_cr4_bits(vcpu, X86_CR4_PKE); + ext.cr4_la57 = !!kvm_read_cr4_bits(vcpu, X86_CR4_LA57); ext.maxphyaddr = cpuid_maxphyaddr(vcpu); ext.valid = 1; diff --git a/arch/x86/kvm/mmu/paging.h b/arch/x86/kvm/mmu/paging.h new file mode 100644 index 0000000000000000000000000000000000000000..de8ab323bb7076dd7b854d34ffc1a80a74d069d3 --- /dev/null +++ b/arch/x86/kvm/mmu/paging.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* Shadow paging constants/helpers that don't need to be #undef'd. */ +#ifndef __KVM_X86_PAGING_H +#define __KVM_X86_PAGING_H + +#define GUEST_PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1)) +#define PT64_LVL_ADDR_MASK(level) \ + (GUEST_PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + (((level) - 1) \ + * PT64_LEVEL_BITS))) - 1)) +#define PT64_LVL_OFFSET_MASK(level) \ + (GUEST_PT64_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \ + * PT64_LEVEL_BITS))) - 1)) +#endif /* __KVM_X86_PAGING_H */ + diff --git a/arch/x86/kvm/mmu/paging_tmpl.h b/arch/x86/kvm/mmu/paging_tmpl.h index 00a0bfaed6e86f72150ecf1cd2cc3c9e6a93ebe7..f8829134bf3413c8141e1c74cabb888853a90a15 100644 --- a/arch/x86/kvm/mmu/paging_tmpl.h +++ b/arch/x86/kvm/mmu/paging_tmpl.h @@ -24,7 +24,7 @@ #define pt_element_t u64 #define guest_walker guest_walker64 #define FNAME(name) paging##64_##name - #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK + #define PT_BASE_ADDR_MASK GUEST_PT64_BASE_ADDR_MASK #define PT_LVL_ADDR_MASK(lvl) PT64_LVL_ADDR_MASK(lvl) #define PT_LVL_OFFSET_MASK(lvl) PT64_LVL_OFFSET_MASK(lvl) #define PT_INDEX(addr, level) PT64_INDEX(addr, level) @@ -57,7 +57,7 @@ #define pt_element_t u64 #define guest_walker guest_walkerEPT #define FNAME(name) ept_##name - #define PT_BASE_ADDR_MASK PT64_BASE_ADDR_MASK + #define PT_BASE_ADDR_MASK GUEST_PT64_BASE_ADDR_MASK #define PT_LVL_ADDR_MASK(lvl) PT64_LVL_ADDR_MASK(lvl) #define PT_LVL_OFFSET_MASK(lvl) PT64_LVL_OFFSET_MASK(lvl) #define PT_INDEX(addr, level) PT64_INDEX(addr, level) @@ -471,8 +471,7 @@ retry_walk: error: errcode |= write_fault | user_fault; - if (fetch_fault && (mmu->nx || - kvm_read_cr4_bits(vcpu, X86_CR4_SMEP))) + if (fetch_fault && (mmu->nx || mmu->mmu_role.ext.cr4_smep)) errcode |= PFERR_FETCH_MASK; walker->fault.vector = PF_VECTOR; diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h index 2b3a30bd38b07e2e27882a108a28c931c36f1d95..667f207d3d099fda6493f10b50787aefb25ec400 100644 --- a/arch/x86/kvm/mmu/spte.h +++ b/arch/x86/kvm/mmu/spte.h @@ -23,12 +23,6 @@ #else #define PT64_BASE_ADDR_MASK (((1ULL << 52) - 1) & ~(u64)(PAGE_SIZE-1)) #endif -#define PT64_LVL_ADDR_MASK(level) \ - (PT64_BASE_ADDR_MASK & ~((1ULL << (PAGE_SHIFT + (((level) - 1) \ - * PT64_LEVEL_BITS))) - 1)) -#define PT64_LVL_OFFSET_MASK(level) \ - (PT64_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \ - * PT64_LEVEL_BITS))) - 1)) #define PT64_PERM_MASK (PT_PRESENT_MASK | PT_WRITABLE_MASK | shadow_user_mask \ | shadow_x_mask | shadow_nx_mask | shadow_me_mask) diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index 61c00f8631f1ad9d56a5b21464d045165bf280f7..f2ddf663e72e92a0f871522dc97e776ac283fc29 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -527,7 +527,7 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu, int write, kvm_pfn_t pfn, bool prefault) { u64 new_spte; - int ret = 0; + int ret = RET_PF_FIXED; int make_spte_ret = 0; if (unlikely(is_noslot_pfn(pfn))) { diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 16b10b9436dc59e4456da07487d83ef49f5298b0..01547bdbfb061c867b1a7c7ec22fb0a482168c17 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -130,9 +130,25 @@ static void sev_asid_free(int asid) mutex_unlock(&sev_bitmap_lock); } -static void sev_unbind_asid(struct kvm *kvm, unsigned int handle) +static void sev_decommission(unsigned int handle) { struct sev_data_decommission *decommission; + + if (!handle) + return; + + decommission = kzalloc(sizeof(*decommission), GFP_KERNEL); + if (!decommission) + return; + + decommission->handle = handle; + sev_guest_decommission(decommission, NULL); + + kfree(decommission); +} + +static void sev_unbind_asid(struct kvm *kvm, unsigned int handle) +{ struct sev_data_deactivate *data; if (!handle) @@ -152,15 +168,7 @@ static void sev_unbind_asid(struct kvm *kvm, unsigned int handle) kfree(data); - decommission = kzalloc(sizeof(*decommission), GFP_KERNEL); - if (!decommission) - return; - - /* decommission handle */ - decommission->handle = handle; - sev_guest_decommission(decommission, NULL); - - kfree(decommission); + sev_decommission(handle); } static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp) @@ -288,8 +296,10 @@ static int sev_launch_start(struct kvm *kvm, struct kvm_sev_cmd *argp) /* Bind ASID to this guest */ ret = sev_bind_asid(kvm, start->handle, error); - if (ret) + if (ret) { + sev_decommission(start->handle); goto e_free_session; + } /* return handle to userspace */ params.handle = start->handle; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 41d44fb5f753d84cef2ae7ea94744125d0bb76d6..1c9226cd6cdecf7d29e4f08092786ff33bf74f14 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2745,7 +2745,16 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) svm_disable_lbrv(vcpu); break; case MSR_VM_HSAVE_PA: - svm->nested.hsave_msr = data; + /* + * Old kernels did not validate the value written to + * MSR_VM_HSAVE_PA. Allow KVM_SET_MSR to set an invalid + * value to allow live migrating buggy or malicious guests + * originating from those kernels. + */ + if (!msr->host_initiated && !page_address_valid(vcpu, data)) + return 1; + + svm->nested.hsave_msr = data & PAGE_MASK; break; case MSR_VM_CR: return svm_set_vm_cr(vcpu, data); diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 32e6f33c2c45b94a51c2b8a97274701f7f031b27..67554bc7adb2606f905ab83221621c0914c96e6c 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -1142,12 +1142,19 @@ static int nested_vmx_load_cr3(struct kvm_vcpu *vcpu, unsigned long cr3, bool ne /* * Unconditionally skip the TLB flush on fast CR3 switch, all TLB - * flushes are handled by nested_vmx_transition_tlb_flush(). See - * nested_vmx_transition_mmu_sync for details on skipping the MMU sync. + * flushes are handled by nested_vmx_transition_tlb_flush(). */ - if (!nested_ept) - kvm_mmu_new_pgd(vcpu, cr3, true, - !nested_vmx_transition_mmu_sync(vcpu)); + if (!nested_ept) { + kvm_mmu_new_pgd(vcpu, cr3, true, true); + + /* + * A TLB flush on VM-Enter/VM-Exit flushes all linear mappings + * across all PCIDs, i.e. all PGDs need to be synchronized. + * See nested_vmx_transition_mmu_sync() for more details. + */ + if (nested_vmx_transition_mmu_sync(vcpu)) + kvm_make_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu); + } vcpu->arch.cr3 = cr3; kvm_register_mark_available(vcpu, VCPU_EXREG_CR3); @@ -5477,8 +5484,6 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu, { u32 index = kvm_rcx_read(vcpu); u64 new_eptp; - bool accessed_dirty; - struct kvm_mmu *mmu = vcpu->arch.walk_mmu; if (!nested_cpu_has_eptp_switching(vmcs12) || !nested_cpu_has_ept(vmcs12)) @@ -5487,13 +5492,10 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu, if (index >= VMFUNC_EPTP_ENTRIES) return 1; - if (kvm_vcpu_read_guest_page(vcpu, vmcs12->eptp_list_address >> PAGE_SHIFT, &new_eptp, index * 8, 8)) return 1; - accessed_dirty = !!(new_eptp & VMX_EPTP_AD_ENABLE_BIT); - /* * If the (L2) guest does a vmfunc to the currently * active ept pointer, we don't have to do anything else @@ -5502,8 +5504,6 @@ static int nested_vmx_eptp_switching(struct kvm_vcpu *vcpu, if (!nested_vmx_check_eptp(vcpu, new_eptp)) return 1; - mmu->ept_ad = accessed_dirty; - mmu->mmu_role.base.ad_disabled = !accessed_dirty; vmcs12->ept_pointer = new_eptp; kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu); @@ -5529,7 +5529,7 @@ static int handle_vmfunc(struct kvm_vcpu *vcpu) } vmcs12 = get_vmcs12(vcpu); - if ((vmcs12->vm_function_control & (1 << function)) == 0) + if (!(vmcs12->vm_function_control & BIT_ULL(function))) goto fail; switch (function) { @@ -5787,6 +5787,9 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu, else if (is_breakpoint(intr_info) && vcpu->guest_debug & KVM_GUESTDBG_USE_SW_BP) return true; + else if (is_alignment_check(intr_info) && + !vmx_guest_inject_ac(vcpu)) + return true; return false; case EXIT_REASON_EXTERNAL_INTERRUPT: return true; diff --git a/arch/x86/kvm/vmx/vmcs.h b/arch/x86/kvm/vmx/vmcs.h index 1472c6c376f74a661d053c616f648556019da64a..571d9ad80a59ebac719f3937c07d3c7b8f5a90bc 100644 --- a/arch/x86/kvm/vmx/vmcs.h +++ b/arch/x86/kvm/vmx/vmcs.h @@ -117,6 +117,11 @@ static inline bool is_gp_fault(u32 intr_info) return is_exception_n(intr_info, GP_VECTOR); } +static inline bool is_alignment_check(u32 intr_info) +{ + return is_exception_n(intr_info, AC_VECTOR); +} + static inline bool is_machine_check(u32 intr_info) { return is_exception_n(intr_info, MC_VECTOR); diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 45877364e6829168af0b94910d7319c80393f0c6..de24d3826788af8aec7a56e51e45b6112c354635 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -4755,7 +4755,7 @@ static int handle_machine_check(struct kvm_vcpu *vcpu) * - Guest has #AC detection enabled in CR0 * - Guest EFLAGS has AC bit set */ -static inline bool guest_inject_ac(struct kvm_vcpu *vcpu) +bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu) { if (!boot_cpu_has(X86_FEATURE_SPLIT_LOCK_DETECT)) return true; @@ -4864,7 +4864,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu) kvm_run->debug.arch.exception = ex_no; break; case AC_VECTOR: - if (guest_inject_ac(vcpu)) { + if (vmx_guest_inject_ac(vcpu)) { kvm_queue_exception_e(vcpu, AC_VECTOR, error_code); return 1; } diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index ae3a89ac0600d4f420a192bb74abf2806232b765..73d87d44b65782a772b10ef29ee07058ba957215 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -352,6 +352,7 @@ void vmx_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); u64 construct_eptp(struct kvm_vcpu *vcpu, unsigned long root_hpa, int root_level); +bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu); void update_exception_bitmap(struct kvm_vcpu *vcpu); void vmx_update_msr_bitmap(struct kvm_vcpu *vcpu); bool vmx_nmi_blocked(struct kvm_vcpu *vcpu); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index d3372cb973079e05cdb9bffeb314b8b46ccf68dd..800914e9e12b9b4f1a3475e200c3df9498929a65 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -8852,7 +8852,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) } if (kvm_check_request(KVM_REQ_TLB_FLUSH_CURRENT, vcpu)) kvm_vcpu_flush_tlb_current(vcpu); - if (kvm_check_request(KVM_REQ_HV_TLB_FLUSH, vcpu)) + if (kvm_check_request(KVM_REQ_TLB_FLUSH_GUEST, vcpu)) kvm_vcpu_flush_tlb_guest(vcpu); if (kvm_check_request(KVM_REQ_REPORT_TPR_ACCESS, vcpu)) { @@ -9020,6 +9020,8 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) set_debugreg(vcpu->arch.eff_db[3], 3); set_debugreg(vcpu->arch.dr6, 6); vcpu->arch.switch_db_regs &= ~KVM_DEBUGREG_RELOAD; + } else if (unlikely(hw_breakpoint_active())) { + set_debugreg(0, 7); } exit_fastpath = kvm_x86_ops.run(vcpu); diff --git a/arch/x86/pci/fixup.c b/arch/x86/pci/fixup.c index 0a0e168be1cbec0da9bad7cf2266d11118eae977..9b0e771302ceed06c1ed0fd7ffe10272fd3b79b0 100644 --- a/arch/x86/pci/fixup.c +++ b/arch/x86/pci/fixup.c @@ -779,4 +779,48 @@ DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1571, pci_amd_enable_64bit_bar); DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x15b1, pci_amd_enable_64bit_bar); DECLARE_PCI_FIXUP_RESUME(PCI_VENDOR_ID_AMD, 0x1601, pci_amd_enable_64bit_bar); +#define RS690_LOWER_TOP_OF_DRAM2 0x30 +#define RS690_LOWER_TOP_OF_DRAM2_VALID 0x1 +#define RS690_UPPER_TOP_OF_DRAM2 0x31 +#define RS690_HTIU_NB_INDEX 0xA8 +#define RS690_HTIU_NB_INDEX_WR_ENABLE 0x100 +#define RS690_HTIU_NB_DATA 0xAC + +/* + * Some BIOS implementations support RAM above 4GB, but do not configure the + * PCI host to respond to bus master accesses for these addresses. These + * implementations set the TOP_OF_DRAM_SLOT1 register correctly, so PCI DMA + * works as expected for addresses below 4GB. + * + * Reference: "AMD RS690 ASIC Family Register Reference Guide" (pg. 2-57) + * https://www.amd.com/system/files/TechDocs/43372_rs690_rrg_3.00o.pdf + */ +static void rs690_fix_64bit_dma(struct pci_dev *pdev) +{ + u32 val = 0; + phys_addr_t top_of_dram = __pa(high_memory - 1) + 1; + + if (top_of_dram <= (1ULL << 32)) + return; + + pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX, + RS690_LOWER_TOP_OF_DRAM2); + pci_read_config_dword(pdev, RS690_HTIU_NB_DATA, &val); + + if (val) + return; + + pci_info(pdev, "Adjusting top of DRAM to %pa for 64-bit DMA support\n", &top_of_dram); + + pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX, + RS690_UPPER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE); + pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, top_of_dram >> 32); + + pci_write_config_dword(pdev, RS690_HTIU_NB_INDEX, + RS690_LOWER_TOP_OF_DRAM2 | RS690_HTIU_NB_INDEX_WR_ENABLE); + pci_write_config_dword(pdev, RS690_HTIU_NB_DATA, + top_of_dram | RS690_LOWER_TOP_OF_DRAM2_VALID); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ATI, 0x7910, rs690_fix_64bit_dma); + #endif diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 8064df6382227004533b8264511cb57317ce4a26..d3cdf467d91fa4bcc1c47993538b511f2151696b 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -586,8 +586,10 @@ DEFINE_IDTENTRY_RAW(xenpv_exc_debug) DEFINE_IDTENTRY_RAW(exc_xen_unknown_trap) { /* This should never happen and there is no way to handle it. */ + instrumentation_begin(); pr_err("Unknown trap in Xen PV mode."); BUG(); + instrumentation_end(); } struct trap_array_entry { diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c index cd85a7a2722ba4f4f101957c8cbc7665deda12ac..1254da07ead1f42712918b90c54b45ebf83cb5bb 100644 --- a/arch/xtensa/kernel/smp.c +++ b/arch/xtensa/kernel/smp.c @@ -145,7 +145,6 @@ void secondary_start_kernel(void) cpumask_set_cpu(cpu, mm_cpumask(mm)); enter_lazy_tlb(mm, current); - preempt_disable(); trace_hardirqs_off(); calibrate_delay(); diff --git a/block/blk-flush.c b/block/blk-flush.c index fd5cee9f1a3bec1b6b3a8a80171d02a15960f8fd..7ee7e5e8905d5f0f0c71a0b002af895a43acff28 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -220,8 +220,6 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) unsigned long flags = 0; struct blk_flush_queue *fq = blk_get_flush_queue(q, flush_rq->mq_ctx); - blk_account_io_flush(flush_rq); - /* release the tag's ownership to the req cloned from */ spin_lock_irqsave(&fq->mq_flush_lock, flags); @@ -231,6 +229,7 @@ static void flush_end_io(struct request *flush_rq, blk_status_t error) return; } + blk_account_io_flush(flush_rq); /* * Flush request has to be marked as IDLE when it is really ended * because its .end_io() is called from timeout code path too for diff --git a/block/blk-merge.c b/block/blk-merge.c index 7cdd566966473158e4da8eefae62a10e0f67f772..349cd7d3af815b1343149915e9e55fbff14e715f 100644 --- a/block/blk-merge.c +++ b/block/blk-merge.c @@ -552,10 +552,14 @@ static inline unsigned int blk_rq_get_max_segments(struct request *rq) static inline int ll_new_hw_segment(struct request *req, struct bio *bio, unsigned int nr_phys_segs) { - if (req->nr_phys_segments + nr_phys_segs > blk_rq_get_max_segments(req)) + if (blk_integrity_merge_bio(req->q, req, bio) == false) goto no_merge; - if (blk_integrity_merge_bio(req->q, req, bio) == false) + /* discard request merge won't add new segment */ + if (req_op(req) == REQ_OP_DISCARD) + return 1; + + if (req->nr_phys_segments + nr_phys_segs > blk_rq_get_max_segments(req)) goto no_merge; /* diff --git a/block/blk-mq-tag.c b/block/blk-mq-tag.c index 9c92053e704dc105312a01e5f063a5643cc7fde7..c4f2f6c123aedd3b52fae84a76c72ce7e5f63668 100644 --- a/block/blk-mq-tag.c +++ b/block/blk-mq-tag.c @@ -199,6 +199,20 @@ struct bt_iter_data { bool reserved; }; +static struct request *blk_mq_find_and_get_req(struct blk_mq_tags *tags, + unsigned int bitnr) +{ + struct request *rq; + unsigned long flags; + + spin_lock_irqsave(&tags->lock, flags); + rq = tags->rqs[bitnr]; + if (!rq || !refcount_inc_not_zero(&rq->ref)) + rq = NULL; + spin_unlock_irqrestore(&tags->lock, flags); + return rq; +} + static bool bt_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data) { struct bt_iter_data *iter_data = data; @@ -206,18 +220,22 @@ static bool bt_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data) struct blk_mq_tags *tags = hctx->tags; bool reserved = iter_data->reserved; struct request *rq; + bool ret = true; if (!reserved) bitnr += tags->nr_reserved_tags; - rq = tags->rqs[bitnr]; - /* * We can hit rq == NULL here, because the tagging functions * test and set the bit before assigning ->rqs[]. */ - if (rq && rq->q == hctx->queue && rq->mq_hctx == hctx) - return iter_data->fn(hctx, rq, iter_data->data, reserved); - return true; + rq = blk_mq_find_and_get_req(tags, bitnr); + if (!rq) + return true; + + if (rq->q == hctx->queue && rq->mq_hctx == hctx) + ret = iter_data->fn(hctx, rq, iter_data->data, reserved); + blk_mq_put_rq_ref(rq); + return ret; } /** @@ -264,6 +282,8 @@ static bool bt_tags_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data) struct blk_mq_tags *tags = iter_data->tags; bool reserved = iter_data->flags & BT_TAG_ITER_RESERVED; struct request *rq; + bool ret = true; + bool iter_static_rqs = !!(iter_data->flags & BT_TAG_ITER_STATIC_RQS); if (!reserved) bitnr += tags->nr_reserved_tags; @@ -272,16 +292,19 @@ static bool bt_tags_iter(struct sbitmap *bitmap, unsigned int bitnr, void *data) * We can hit rq == NULL here, because the tagging functions * test and set the bit before assigning ->rqs[]. */ - if (iter_data->flags & BT_TAG_ITER_STATIC_RQS) + if (iter_static_rqs) rq = tags->static_rqs[bitnr]; else - rq = tags->rqs[bitnr]; + rq = blk_mq_find_and_get_req(tags, bitnr); if (!rq) return true; - if ((iter_data->flags & BT_TAG_ITER_STARTED) && - !blk_mq_request_started(rq)) - return true; - return iter_data->fn(rq, iter_data->data, reserved); + + if (!(iter_data->flags & BT_TAG_ITER_STARTED) || + blk_mq_request_started(rq)) + ret = iter_data->fn(rq, iter_data->data, reserved); + if (!iter_static_rqs) + blk_mq_put_rq_ref(rq); + return ret; } /** @@ -348,6 +371,9 @@ void blk_mq_all_tag_iter(struct blk_mq_tags *tags, busy_tag_iter_fn *fn, * indicates whether or not @rq is a reserved request. Return * true to continue iterating tags, false to stop. * @priv: Will be passed as second argument to @fn. + * + * We grab one request reference before calling @fn and release it after + * @fn returns. */ void blk_mq_tagset_busy_iter(struct blk_mq_tag_set *tagset, busy_tag_iter_fn *fn, void *priv) @@ -516,6 +542,7 @@ struct blk_mq_tags *blk_mq_init_tags(unsigned int total_tags, tags->nr_tags = total_tags; tags->nr_reserved_tags = reserved_tags; + spin_lock_init(&tags->lock); if (flags & BLK_MQ_F_TAG_HCTX_SHARED) return tags; diff --git a/block/blk-mq-tag.h b/block/blk-mq-tag.h index 7d3e6b333a4a97b88969de12e7032f77ca4b57a0..f887988e5ef60339a0f62f190cc9dee8a1d5c921 100644 --- a/block/blk-mq-tag.h +++ b/block/blk-mq-tag.h @@ -20,6 +20,12 @@ struct blk_mq_tags { struct request **rqs; struct request **static_rqs; struct list_head page_list; + + /* + * used to clear request reference in rqs[] before freeing one + * request pool + */ + spinlock_t lock; }; extern struct blk_mq_tags *blk_mq_init_tags(unsigned int nr_tags, diff --git a/block/blk-mq.c b/block/blk-mq.c index 4bf9449b45868691535699b3e0cdcee3c4de993f..a368eb6dc64709a7472649042898d814890f5166 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -927,6 +927,14 @@ static bool blk_mq_req_expired(struct request *rq, unsigned long *next) return false; } +void blk_mq_put_rq_ref(struct request *rq) +{ + if (is_flush_rq(rq, rq->mq_hctx)) + rq->end_io(rq, 0); + else if (refcount_dec_and_test(&rq->ref)) + __blk_mq_free_request(rq); +} + static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx, struct request *rq, void *priv, bool reserved) { @@ -960,11 +968,7 @@ static bool blk_mq_check_expired(struct blk_mq_hw_ctx *hctx, if (blk_mq_req_expired(rq, next)) blk_mq_rq_timed_out(rq, reserved); - if (is_flush_rq(rq, hctx)) - rq->end_io(rq, 0); - else if (refcount_dec_and_test(&rq->ref)) - __blk_mq_free_request(rq); - + blk_mq_put_rq_ref(rq); return true; } @@ -1238,9 +1242,6 @@ static void blk_mq_update_dispatch_busy(struct blk_mq_hw_ctx *hctx, bool busy) { unsigned int ewma; - if (hctx->queue->elevator) - return; - ewma = hctx->dispatch_busy; if (!ewma && !busy) @@ -2272,6 +2273,45 @@ queue_exit: return BLK_QC_T_NONE; } +static size_t order_to_size(unsigned int order) +{ + return (size_t)PAGE_SIZE << order; +} + +/* called before freeing request pool in @tags */ +static void blk_mq_clear_rq_mapping(struct blk_mq_tag_set *set, + struct blk_mq_tags *tags, unsigned int hctx_idx) +{ + struct blk_mq_tags *drv_tags = set->tags[hctx_idx]; + struct page *page; + unsigned long flags; + + list_for_each_entry(page, &tags->page_list, lru) { + unsigned long start = (unsigned long)page_address(page); + unsigned long end = start + order_to_size(page->private); + int i; + + for (i = 0; i < set->queue_depth; i++) { + struct request *rq = drv_tags->rqs[i]; + unsigned long rq_addr = (unsigned long)rq; + + if (rq_addr >= start && rq_addr < end) { + WARN_ON_ONCE(refcount_read(&rq->ref) != 0); + cmpxchg(&drv_tags->rqs[i], rq, NULL); + } + } + } + + /* + * Wait until all pending iteration is done. + * + * Request reference is cleared and it is guaranteed to be observed + * after the ->lock is released. + */ + spin_lock_irqsave(&drv_tags->lock, flags); + spin_unlock_irqrestore(&drv_tags->lock, flags); +} + void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, unsigned int hctx_idx) { @@ -2290,6 +2330,8 @@ void blk_mq_free_rqs(struct blk_mq_tag_set *set, struct blk_mq_tags *tags, } } + blk_mq_clear_rq_mapping(set, tags, hctx_idx); + while (!list_empty(&tags->page_list)) { page = list_first_entry(&tags->page_list, struct page, lru); list_del_init(&page->lru); @@ -2349,11 +2391,6 @@ struct blk_mq_tags *blk_mq_alloc_rq_map(struct blk_mq_tag_set *set, return tags; } -static size_t order_to_size(unsigned int order) -{ - return (size_t)PAGE_SIZE << order; -} - static int blk_mq_init_request(struct blk_mq_tag_set *set, struct request *rq, unsigned int hctx_idx, int node) { diff --git a/block/blk-mq.h b/block/blk-mq.h index d2359f7cfd5f2e8d154c0e6f7561383542f2a697..f792a0920ebb13e3857e6a5d3397e13775c67e53 100644 --- a/block/blk-mq.h +++ b/block/blk-mq.h @@ -47,6 +47,7 @@ void blk_mq_add_to_requeue_list(struct request *rq, bool at_head, void blk_mq_flush_busy_ctxs(struct blk_mq_hw_ctx *hctx, struct list_head *list); struct request *blk_mq_dequeue_from_ctx(struct blk_mq_hw_ctx *hctx, struct blk_mq_ctx *start); +void blk_mq_put_rq_ref(struct request *rq); /* * Internal helpers for allocating/freeing the request map diff --git a/block/blk-rq-qos.c b/block/blk-rq-qos.c index 656460636ad34a176297bfb991aba977b3c0e9ca..e83af7bc759194126a645bea59eef2b841603961 100644 --- a/block/blk-rq-qos.c +++ b/block/blk-rq-qos.c @@ -266,8 +266,8 @@ void rq_qos_wait(struct rq_wait *rqw, void *private_data, if (!has_sleeper && acquire_inflight_cb(rqw, private_data)) return; - prepare_to_wait_exclusive(&rqw->wait, &data.wq, TASK_UNINTERRUPTIBLE); - has_sleeper = !wq_has_single_sleeper(&rqw->wait); + has_sleeper = !prepare_to_wait_exclusive(&rqw->wait, &data.wq, + TASK_UNINTERRUPTIBLE); do { /* The memory barrier in set_task_state saves us here. */ if (data.got_token) diff --git a/block/blk-rq-qos.h b/block/blk-rq-qos.h index 2bc43e94f4c407582087e328d892f0c5d1e4da86..2bcb3495e376b5b63c56b4a0501532fec80996fe 100644 --- a/block/blk-rq-qos.h +++ b/block/blk-rq-qos.h @@ -7,6 +7,7 @@ #include <linux/blk_types.h> #include <linux/atomic.h> #include <linux/wait.h> +#include <linux/blk-mq.h> #include "blk-mq-debugfs.h" @@ -99,8 +100,21 @@ static inline void rq_wait_init(struct rq_wait *rq_wait) static inline void rq_qos_add(struct request_queue *q, struct rq_qos *rqos) { + /* + * No IO can be in-flight when adding rqos, so freeze queue, which + * is fine since we only support rq_qos for blk-mq queue. + * + * Reuse ->queue_lock for protecting against other concurrent + * rq_qos adding/deleting + */ + blk_mq_freeze_queue(q); + + spin_lock_irq(&q->queue_lock); rqos->next = q->rq_qos; q->rq_qos = rqos; + spin_unlock_irq(&q->queue_lock); + + blk_mq_unfreeze_queue(q); if (rqos->ops->debugfs_attrs) blk_mq_debugfs_register_rqos(rqos); @@ -110,12 +124,22 @@ static inline void rq_qos_del(struct request_queue *q, struct rq_qos *rqos) { struct rq_qos **cur; + /* + * See comment in rq_qos_add() about freezing queue & using + * ->queue_lock. + */ + blk_mq_freeze_queue(q); + + spin_lock_irq(&q->queue_lock); for (cur = &q->rq_qos; *cur; cur = &(*cur)->next) { if (*cur == rqos) { *cur = rqos->next; break; } } + spin_unlock_irq(&q->queue_lock); + + blk_mq_unfreeze_queue(q); blk_mq_debugfs_unregister_rqos(rqos); } diff --git a/block/blk-wbt.c b/block/blk-wbt.c index fd410086fe1de59b02e926dd364b9253a05a6311..35d81b5deae1c821da2f8a937dcc4eb60bbec834 100644 --- a/block/blk-wbt.c +++ b/block/blk-wbt.c @@ -77,7 +77,8 @@ enum { static inline bool rwb_enabled(struct rq_wb *rwb) { - return rwb && rwb->wb_normal != 0; + return rwb && rwb->enable_state != WBT_STATE_OFF_DEFAULT && + rwb->wb_normal != 0; } static void wb_timestamp(struct rq_wb *rwb, unsigned long *var) @@ -636,9 +637,13 @@ void wbt_set_write_cache(struct request_queue *q, bool write_cache_on) void wbt_enable_default(struct request_queue *q) { struct rq_qos *rqos = wbt_rq_qos(q); + /* Throttling already enabled? */ - if (rqos) + if (rqos) { + if (RQWB(rqos)->enable_state == WBT_STATE_OFF_DEFAULT) + RQWB(rqos)->enable_state = WBT_STATE_ON_DEFAULT; return; + } /* Queue not registered? Maybe shutting down... */ if (!blk_queue_registered(q)) @@ -702,7 +707,7 @@ void wbt_disable_default(struct request_queue *q) rwb = RQWB(rqos); if (rwb->enable_state == WBT_STATE_ON_DEFAULT) { blk_stat_deactivate(rwb->cb); - rwb->wb_normal = 0; + rwb->enable_state = WBT_STATE_OFF_DEFAULT; } } EXPORT_SYMBOL_GPL(wbt_disable_default); diff --git a/block/blk-wbt.h b/block/blk-wbt.h index 16bdc85b8df92eba6a94250d83fd0e3e7ab4a837..2eb01becde8c412c11a7ffedd8a04bd8e41521ac 100644 --- a/block/blk-wbt.h +++ b/block/blk-wbt.h @@ -34,6 +34,7 @@ enum { enum { WBT_STATE_ON_DEFAULT = 1, WBT_STATE_ON_MANUAL = 2, + WBT_STATE_OFF_DEFAULT }; struct rq_wb { diff --git a/block/partitions/ldm.c b/block/partitions/ldm.c index d333786b5c7ebe655eec420277762d74094c2f2a..cc86534c80ad9822ce301dd910155b7887e61561 100644 --- a/block/partitions/ldm.c +++ b/block/partitions/ldm.c @@ -510,7 +510,7 @@ static bool ldm_validate_partition_table(struct parsed_partitions *state) p = (struct msdos_partition *)(data + 0x01BE); for (i = 0; i < 4; i++, p++) - if (SYS_IND (p) == LDM_PARTITION) { + if (p->sys_ind == LDM_PARTITION) { result = true; break; } diff --git a/block/partitions/ldm.h b/block/partitions/ldm.h index d8d6beaa72c4d78dab7a602b1ee3637585880e79..8693704dcf5e99b150c878ade086a67506cf4b6e 100644 --- a/block/partitions/ldm.h +++ b/block/partitions/ldm.h @@ -84,9 +84,6 @@ struct parsed_partitions; #define TOC_BITMAP1 "config" /* Names of the two defined */ #define TOC_BITMAP2 "log" /* bitmaps in the TOCBLOCK. */ -/* Borrowed from msdos.c */ -#define SYS_IND(p) (get_unaligned(&(p)->sys_ind)) - struct frag { /* VBLK Fragment handling */ struct list_head list; u32 group; diff --git a/block/partitions/msdos.c b/block/partitions/msdos.c index 8f2fcc0802642bec8edaaaea963d9a7be954d9bb..c94de377c5025e012289c0d8fb583cf717e0fe00 100644 --- a/block/partitions/msdos.c +++ b/block/partitions/msdos.c @@ -38,8 +38,6 @@ */ #include <asm/unaligned.h> -#define SYS_IND(p) get_unaligned(&p->sys_ind) - static inline sector_t nr_sects(struct msdos_partition *p) { return (sector_t)get_unaligned_le32(&p->nr_sects); @@ -52,9 +50,9 @@ static inline sector_t start_sect(struct msdos_partition *p) static inline int is_extended_partition(struct msdos_partition *p) { - return (SYS_IND(p) == DOS_EXTENDED_PARTITION || - SYS_IND(p) == WIN98_EXTENDED_PARTITION || - SYS_IND(p) == LINUX_EXTENDED_PARTITION); + return (p->sys_ind == DOS_EXTENDED_PARTITION || + p->sys_ind == WIN98_EXTENDED_PARTITION || + p->sys_ind == LINUX_EXTENDED_PARTITION); } #define MSDOS_LABEL_MAGIC1 0x55 @@ -193,7 +191,7 @@ static void parse_extended(struct parsed_partitions *state, put_partition(state, state->next, next, size); set_info(state, state->next, disksig); - if (SYS_IND(p) == LINUX_RAID_PARTITION) + if (p->sys_ind == LINUX_RAID_PARTITION) state->parts[state->next].flags = ADDPART_FLAG_RAID; loopct = 0; if (++state->next == state->limit) @@ -546,7 +544,7 @@ static void parse_minix(struct parsed_partitions *state, * a secondary MBR describing its subpartitions, or * the normal boot sector. */ if (msdos_magic_present(data + 510) && - SYS_IND(p) == MINIX_PARTITION) { /* subpartition table present */ + p->sys_ind == MINIX_PARTITION) { /* subpartition table present */ char tmp[1 + BDEVNAME_SIZE + 10 + 9 + 1]; snprintf(tmp, sizeof(tmp), " %s%d: <minix:", state->name, origin); @@ -555,7 +553,7 @@ static void parse_minix(struct parsed_partitions *state, if (state->next == state->limit) break; /* add each partition in use */ - if (SYS_IND(p) == MINIX_PARTITION) + if (p->sys_ind == MINIX_PARTITION) put_partition(state, state->next++, start_sect(p), nr_sects(p)); } @@ -643,7 +641,7 @@ int msdos_partition(struct parsed_partitions *state) p = (struct msdos_partition *) (data + 0x1be); for (slot = 1 ; slot <= 4 ; slot++, p++) { /* If this is an EFI GPT disk, msdos should ignore it. */ - if (SYS_IND(p) == EFI_PMBR_OSTYPE_EFI_GPT) { + if (p->sys_ind == EFI_PMBR_OSTYPE_EFI_GPT) { put_dev_sector(sect); return 0; } @@ -685,11 +683,11 @@ int msdos_partition(struct parsed_partitions *state) } put_partition(state, slot, start, size); set_info(state, slot, disksig); - if (SYS_IND(p) == LINUX_RAID_PARTITION) + if (p->sys_ind == LINUX_RAID_PARTITION) state->parts[slot].flags = ADDPART_FLAG_RAID; - if (SYS_IND(p) == DM6_PARTITION) + if (p->sys_ind == DM6_PARTITION) strlcat(state->pp_buf, "[DM]", PAGE_SIZE); - if (SYS_IND(p) == EZD_PARTITION) + if (p->sys_ind == EZD_PARTITION) strlcat(state->pp_buf, "[EZD]", PAGE_SIZE); } @@ -698,7 +696,7 @@ int msdos_partition(struct parsed_partitions *state) /* second pass - output for each on a separate line */ p = (struct msdos_partition *) (0x1be + data); for (slot = 1 ; slot <= 4 ; slot++, p++) { - unsigned char id = SYS_IND(p); + unsigned char id = p->sys_ind; int n; if (!nr_sects(p)) diff --git a/certs/.gitignore b/certs/.gitignore index 2a248399068635ff51a8c66f4081f1816e3e25ff..6cbd1f1a5837b2b61552a5084e08873abab5cb34 100644 --- a/certs/.gitignore +++ b/certs/.gitignore @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only x509_certificate_list +x509_revocation_list diff --git a/certs/Kconfig b/certs/Kconfig index c94e93d8bccf038f4684c4cce93d558d9e7269ff..ab88d2a7f3c7fb38526b334562cd7b283ca5ea62 100644 --- a/certs/Kconfig +++ b/certs/Kconfig @@ -83,4 +83,21 @@ config SYSTEM_BLACKLIST_HASH_LIST wrapper to incorporate the list into the kernel. Each <hash> should be a string of hex digits. +config SYSTEM_REVOCATION_LIST + bool "Provide system-wide ring of revocation certificates" + depends on SYSTEM_BLACKLIST_KEYRING + depends on PKCS7_MESSAGE_PARSER=y + help + If set, this allows revocation certificates to be stored in the + blacklist keyring and implements a hook whereby a PKCS#7 message can + be checked to see if it matches such a certificate. + +config SYSTEM_REVOCATION_KEYS + string "X.509 certificates to be preloaded into the system blacklist keyring" + depends on SYSTEM_REVOCATION_LIST + help + If set, this option should be the filename of a PEM-formatted file + containing X.509 certificates to be included in the default blacklist + keyring. + endmenu diff --git a/certs/Makefile b/certs/Makefile index f4c25b67aad90b5833f1e390e2cf0ae303412fbd..b6db52ebf0beb166f290899519515fccc72e4786 100644 --- a/certs/Makefile +++ b/certs/Makefile @@ -3,8 +3,9 @@ # Makefile for the linux kernel signature checking certificates. # -obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o -obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o +obj-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += system_keyring.o system_certificates.o common.o +obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist.o common.o +obj-$(CONFIG_SYSTEM_REVOCATION_LIST) += revocation_certificates.o ifneq ($(CONFIG_SYSTEM_BLACKLIST_HASH_LIST),"") obj-$(CONFIG_SYSTEM_BLACKLIST_KEYRING) += blacklist_hashes.o else @@ -29,7 +30,7 @@ $(obj)/x509_certificate_list: scripts/extract-cert $(SYSTEM_TRUSTED_KEYS_SRCPREF $(call if_changed,extract_certs,$(SYSTEM_TRUSTED_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_TRUSTED_KEYS)) endif # CONFIG_SYSTEM_TRUSTED_KEYRING -clean-files := x509_certificate_list .x509.list +clean-files := x509_certificate_list .x509.list x509_revocation_list ifeq ($(CONFIG_MODULE_SIG),y) ############################################################################### @@ -104,3 +105,17 @@ targets += signing_key.x509 $(obj)/signing_key.x509: scripts/extract-cert $(X509_DEP) FORCE $(call if_changed,extract_certs,$(MODULE_SIG_KEY_SRCPREFIX)$(CONFIG_MODULE_SIG_KEY)) endif # CONFIG_MODULE_SIG + +ifeq ($(CONFIG_SYSTEM_REVOCATION_LIST),y) + +$(eval $(call config_filename,SYSTEM_REVOCATION_KEYS)) + +$(obj)/revocation_certificates.o: $(obj)/x509_revocation_list + +quiet_cmd_extract_certs = EXTRACT_CERTS $(patsubst "%",%,$(2)) + cmd_extract_certs = scripts/extract-cert $(2) $@ + +targets += x509_revocation_list +$(obj)/x509_revocation_list: scripts/extract-cert $(SYSTEM_REVOCATION_KEYS_SRCPREFIX)$(SYSTEM_REVOCATION_KEYS_FILENAME) FORCE + $(call if_changed,extract_certs,$(SYSTEM_REVOCATION_KEYS_SRCPREFIX)$(CONFIG_SYSTEM_REVOCATION_KEYS)) +endif diff --git a/certs/blacklist.c b/certs/blacklist.c index f1c434b04b5e46afd1b41f013c40ee37c49e4027..c973de883cf02c7e226152d3433623f75b22255a 100644 --- a/certs/blacklist.c +++ b/certs/blacklist.c @@ -16,9 +16,15 @@ #include <linux/seq_file.h> #include <keys/system_keyring.h> #include "blacklist.h" +#include "common.h" static struct key *blacklist_keyring; +#ifdef CONFIG_SYSTEM_REVOCATION_LIST +extern __initconst const u8 revocation_certificate_list[]; +extern __initconst const unsigned long revocation_certificate_list_size; +#endif + /* * The description must be a type prefix, a colon and then an even number of * hex digits. The hash is kept in the description. @@ -144,6 +150,49 @@ int is_binary_blacklisted(const u8 *hash, size_t hash_len) } EXPORT_SYMBOL_GPL(is_binary_blacklisted); +#ifdef CONFIG_SYSTEM_REVOCATION_LIST +/** + * add_key_to_revocation_list - Add a revocation certificate to the blacklist + * @data: The data blob containing the certificate + * @size: The size of data blob + */ +int add_key_to_revocation_list(const char *data, size_t size) +{ + key_ref_t key; + + key = key_create_or_update(make_key_ref(blacklist_keyring, true), + "asymmetric", + NULL, + data, + size, + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW), + KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN); + + if (IS_ERR(key)) { + pr_err("Problem with revocation key (%ld)\n", PTR_ERR(key)); + return PTR_ERR(key); + } + + return 0; +} + +/** + * is_key_on_revocation_list - Determine if the key for a PKCS#7 message is revoked + * @pkcs7: The PKCS#7 message to check + */ +int is_key_on_revocation_list(struct pkcs7_message *pkcs7) +{ + int ret; + + ret = pkcs7_validate_trust(pkcs7, blacklist_keyring); + + if (ret == 0) + return -EKEYREJECTED; + + return -ENOKEY; +} +#endif + /* * Initialise the blacklist */ @@ -177,3 +226,18 @@ static int __init blacklist_init(void) * Must be initialised before we try and load the keys into the keyring. */ device_initcall(blacklist_init); + +#ifdef CONFIG_SYSTEM_REVOCATION_LIST +/* + * Load the compiled-in list of revocation X.509 certificates. + */ +static __init int load_revocation_certificate_list(void) +{ + if (revocation_certificate_list_size) + pr_notice("Loading compiled-in revocation X.509 certificates\n"); + + return load_certificate_list(revocation_certificate_list, revocation_certificate_list_size, + blacklist_keyring); +} +late_initcall(load_revocation_certificate_list); +#endif diff --git a/certs/blacklist.h b/certs/blacklist.h index 1efd6fa0dc608c2a3d598b56c798f3e772a2bdbc..51b320cf85749e7a82788ed54a301b8a63243f1e 100644 --- a/certs/blacklist.h +++ b/certs/blacklist.h @@ -1,3 +1,5 @@ #include <linux/kernel.h> +#include <linux/errno.h> +#include <crypto/pkcs7.h> extern const char __initconst *const blacklist_hashes[]; diff --git a/certs/common.c b/certs/common.c new file mode 100644 index 0000000000000000000000000000000000000000..16a220887a53e8d74cb80c4e9f534a013e313c14 --- /dev/null +++ b/certs/common.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <linux/kernel.h> +#include <linux/key.h> +#include "common.h" + +int load_certificate_list(const u8 cert_list[], + const unsigned long list_size, + const struct key *keyring) +{ + key_ref_t key; + const u8 *p, *end; + size_t plen; + + p = cert_list; + end = p + list_size; + while (p < end) { + /* Each cert begins with an ASN.1 SEQUENCE tag and must be more + * than 256 bytes in size. + */ + if (end - p < 4) + goto dodgy_cert; + if (p[0] != 0x30 && + p[1] != 0x82) + goto dodgy_cert; + plen = (p[2] << 8) | p[3]; + plen += 4; + if (plen > end - p) + goto dodgy_cert; + + key = key_create_or_update(make_key_ref(keyring, 1), + "asymmetric", + NULL, + p, + plen, + ((KEY_POS_ALL & ~KEY_POS_SETATTR) | + KEY_USR_VIEW | KEY_USR_READ), + KEY_ALLOC_NOT_IN_QUOTA | + KEY_ALLOC_BUILT_IN | + KEY_ALLOC_BYPASS_RESTRICTION); + if (IS_ERR(key)) { + pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", + PTR_ERR(key)); + } else { + pr_notice("Loaded X.509 cert '%s'\n", + key_ref_to_ptr(key)->description); + key_ref_put(key); + } + p += plen; + } + + return 0; + +dodgy_cert: + pr_err("Problem parsing in-kernel X.509 certificate list\n"); + return 0; +} diff --git a/certs/common.h b/certs/common.h new file mode 100644 index 0000000000000000000000000000000000000000..abdb5795936b76f6ed5f958eec9b0918a7cac0d6 --- /dev/null +++ b/certs/common.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _CERT_COMMON_H +#define _CERT_COMMON_H + +int load_certificate_list(const u8 cert_list[], const unsigned long list_size, + const struct key *keyring); + +#endif diff --git a/certs/revocation_certificates.S b/certs/revocation_certificates.S new file mode 100644 index 0000000000000000000000000000000000000000..f21aae8a8f0ef76fd79f3276e40a6a591b49357a --- /dev/null +++ b/certs/revocation_certificates.S @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#include <linux/export.h> +#include <linux/init.h> + + __INITRODATA + + .align 8 + .globl revocation_certificate_list +revocation_certificate_list: +__revocation_list_start: + .incbin "certs/x509_revocation_list" +__revocation_list_end: + + .align 8 + .globl revocation_certificate_list_size +revocation_certificate_list_size: +#ifdef CONFIG_64BIT + .quad __revocation_list_end - __revocation_list_start +#else + .long __revocation_list_end - __revocation_list_start +#endif diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 798291177186c361ffdb6797096bdb0f219228ae..a44a8915c94cfa356be24879fec8058fa78698c1 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -15,6 +15,7 @@ #include <keys/asymmetric-type.h> #include <keys/system_keyring.h> #include <crypto/pkcs7.h> +#include "common.h" static struct key *builtin_trusted_keys; #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING @@ -136,54 +137,10 @@ device_initcall(system_trusted_keyring_init); */ static __init int load_system_certificate_list(void) { - key_ref_t key; - const u8 *p, *end; - size_t plen; - pr_notice("Loading compiled-in X.509 certificates\n"); - p = system_certificate_list; - end = p + system_certificate_list_size; - while (p < end) { - /* Each cert begins with an ASN.1 SEQUENCE tag and must be more - * than 256 bytes in size. - */ - if (end - p < 4) - goto dodgy_cert; - if (p[0] != 0x30 && - p[1] != 0x82) - goto dodgy_cert; - plen = (p[2] << 8) | p[3]; - plen += 4; - if (plen > end - p) - goto dodgy_cert; - - key = key_create_or_update(make_key_ref(builtin_trusted_keys, 1), - "asymmetric", - NULL, - p, - plen, - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | - KEY_USR_VIEW | KEY_USR_READ), - KEY_ALLOC_NOT_IN_QUOTA | - KEY_ALLOC_BUILT_IN | - KEY_ALLOC_BYPASS_RESTRICTION); - if (IS_ERR(key)) { - pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", - PTR_ERR(key)); - } else { - pr_notice("Loaded X.509 cert '%s'\n", - key_ref_to_ptr(key)->description); - key_ref_put(key); - } - p += plen; - } - - return 0; - -dodgy_cert: - pr_err("Problem parsing in-kernel X.509 certificate list\n"); - return 0; + return load_certificate_list(system_certificate_list, system_certificate_list_size, + builtin_trusted_keys); } late_initcall(load_system_certificate_list); @@ -241,6 +198,12 @@ int verify_pkcs7_message_sig(const void *data, size_t len, pr_devel("PKCS#7 platform keyring is not available\n"); goto error; } + + ret = is_key_on_revocation_list(pkcs7); + if (ret != -ENOKEY) { + pr_devel("PKCS#7 platform key is on revocation list\n"); + goto error; + } } ret = pkcs7_validate_trust(pkcs7, trusted_keys); if (ret < 0) { diff --git a/crypto/shash.c b/crypto/shash.c index 2e3433ad97629741727126988b8a91edae7c1495..0a0a50cb694f0ebb1fa7a27cca5ec6225f86ec60 100644 --- a/crypto/shash.c +++ b/crypto/shash.c @@ -20,12 +20,24 @@ static const struct crypto_type crypto_shash_type; -int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, - unsigned int keylen) +static int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, + unsigned int keylen) { return -ENOSYS; } -EXPORT_SYMBOL_GPL(shash_no_setkey); + +/* + * Check whether an shash algorithm has a setkey function. + * + * For CFI compatibility, this must not be an inline function. This is because + * when CFI is enabled, modules won't get the same address for shash_no_setkey + * (if it were exported, which inlining would require) as the core kernel will. + */ +bool crypto_shash_alg_has_setkey(struct shash_alg *alg) +{ + return alg->setkey != shash_no_setkey; +} +EXPORT_SYMBOL_GPL(crypto_shash_alg_has_setkey); static int shash_setkey_unaligned(struct crypto_shash *tfm, const u8 *key, unsigned int keylen) diff --git a/crypto/sm2.c b/crypto/sm2.c index 767e160333f6e96f6d903e30441b075753a65ac3..db8a4a265669d9e85b6f56f7305b419b5c9c80a7 100644 --- a/crypto/sm2.c +++ b/crypto/sm2.c @@ -79,10 +79,17 @@ static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec) goto free; rc = -ENOMEM; + + ec->Q = mpi_point_new(0); + if (!ec->Q) + goto free; + /* mpi_ec_setup_elliptic_curve */ ec->G = mpi_point_new(0); - if (!ec->G) + if (!ec->G) { + mpi_point_release(ec->Q); goto free; + } mpi_set(ec->G->x, x); mpi_set(ec->G->y, y); @@ -91,6 +98,7 @@ static int sm2_ec_ctx_init(struct mpi_ec_ctx *ec) rc = -EINVAL; ec->n = mpi_scanval(ecp->n); if (!ec->n) { + mpi_point_release(ec->Q); mpi_point_release(ec->G); goto free; } @@ -119,12 +127,6 @@ static void sm2_ec_ctx_deinit(struct mpi_ec_ctx *ec) memset(ec, 0, sizeof(*ec)); } -static int sm2_ec_ctx_reset(struct mpi_ec_ctx *ec) -{ - sm2_ec_ctx_deinit(ec); - return sm2_ec_ctx_init(ec); -} - /* RESULT must have been initialized and is set on success to the * point given by VALUE. */ @@ -132,55 +134,48 @@ static int sm2_ecc_os2ec(MPI_POINT result, MPI value) { int rc; size_t n; - const unsigned char *buf; - unsigned char *buf_memory; + unsigned char *buf; MPI x, y; - n = (mpi_get_nbits(value)+7)/8; - buf_memory = kmalloc(n, GFP_KERNEL); - rc = mpi_print(GCRYMPI_FMT_USG, buf_memory, n, &n, value); - if (rc) { - kfree(buf_memory); - return rc; - } - buf = buf_memory; + n = MPI_NBYTES(value); + buf = kmalloc(n, GFP_KERNEL); + if (!buf) + return -ENOMEM; - if (n < 1) { - kfree(buf_memory); - return -EINVAL; - } - if (*buf != 4) { - kfree(buf_memory); - return -EINVAL; /* No support for point compression. */ - } - if (((n-1)%2)) { - kfree(buf_memory); - return -EINVAL; - } - n = (n-1)/2; + rc = mpi_print(GCRYMPI_FMT_USG, buf, n, &n, value); + if (rc) + goto err_freebuf; + + rc = -EINVAL; + if (n < 1 || ((n - 1) % 2)) + goto err_freebuf; + /* No support for point compression */ + if (*buf != 0x4) + goto err_freebuf; + + rc = -ENOMEM; + n = (n - 1) / 2; x = mpi_read_raw_data(buf + 1, n); - if (!x) { - kfree(buf_memory); - return -ENOMEM; - } + if (!x) + goto err_freebuf; y = mpi_read_raw_data(buf + 1 + n, n); - kfree(buf_memory); - if (!y) { - mpi_free(x); - return -ENOMEM; - } + if (!y) + goto err_freex; mpi_normalize(x); mpi_normalize(y); - mpi_set(result->x, x); mpi_set(result->y, y); mpi_set_ui(result->z, 1); - mpi_free(x); - mpi_free(y); + rc = 0; - return 0; + mpi_free(y); +err_freex: + mpi_free(x); +err_freebuf: + kfree(buf); + return rc; } struct sm2_signature_ctx { @@ -399,31 +394,15 @@ static int sm2_set_pub_key(struct crypto_akcipher *tfm, MPI a; int rc; - rc = sm2_ec_ctx_reset(ec); - if (rc) - return rc; - - ec->Q = mpi_point_new(0); - if (!ec->Q) - return -ENOMEM; - /* include the uncompressed flag '0x04' */ - rc = -ENOMEM; a = mpi_read_raw_data(key, keylen); if (!a) - goto error; + return -ENOMEM; mpi_normalize(a); rc = sm2_ecc_os2ec(ec->Q, a); mpi_free(a); - if (rc) - goto error; - return 0; - -error: - mpi_point_release(ec->Q); - ec->Q = NULL; return rc; } diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile index 44e41250631786693c61009d1983ca75fd9b197f..4466156474eefd3aa18550752978b0cf3914cfda 100644 --- a/drivers/acpi/Makefile +++ b/drivers/acpi/Makefile @@ -8,6 +8,11 @@ ccflags-$(CONFIG_ACPI_DEBUG) += -DACPI_DEBUG_OUTPUT # # ACPI Boot-Time Table Parsing # +ifeq ($(CONFIG_ACPI_CUSTOM_DSDT),y) +tables.o: $(src)/../../include/$(subst $\",,$(CONFIG_ACPI_CUSTOM_DSDT_FILE)) ; + +endif + obj-$(CONFIG_ACPI) += tables.o obj-$(CONFIG_X86) += blacklist.o diff --git a/drivers/acpi/acpi_amba.c b/drivers/acpi/acpi_amba.c index 49b781a9cd97974dab36ac6971e82a5271cb4d0f..ab8a4e0191b19c9ff5a87e8cb9c47b11cc51bc59 100644 --- a/drivers/acpi/acpi_amba.c +++ b/drivers/acpi/acpi_amba.c @@ -76,6 +76,7 @@ static int amba_handler_attach(struct acpi_device *adev, case IORESOURCE_MEM: if (!address_found) { dev->res = *rentry->res; + dev->res.name = dev_name(&dev->dev); address_found = true; } break; diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index b8745ce48a47b21044dd0f189d30835698378dee..b84ab722feb444a9fecca65f76ae3a7e7cc67a89 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c @@ -261,7 +261,7 @@ static uint32_t acpi_pad_idle_cpus_num(void) return ps_tsk_num; } -static ssize_t acpi_pad_rrtime_store(struct device *dev, +static ssize_t rrtime_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long num; @@ -275,16 +275,14 @@ static ssize_t acpi_pad_rrtime_store(struct device *dev, return count; } -static ssize_t acpi_pad_rrtime_show(struct device *dev, +static ssize_t rrtime_show(struct device *dev, struct device_attribute *attr, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time); } -static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR, - acpi_pad_rrtime_show, - acpi_pad_rrtime_store); +static DEVICE_ATTR_RW(rrtime); -static ssize_t acpi_pad_idlepct_store(struct device *dev, +static ssize_t idlepct_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long num; @@ -298,16 +296,14 @@ static ssize_t acpi_pad_idlepct_store(struct device *dev, return count; } -static ssize_t acpi_pad_idlepct_show(struct device *dev, +static ssize_t idlepct_show(struct device *dev, struct device_attribute *attr, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct); } -static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR, - acpi_pad_idlepct_show, - acpi_pad_idlepct_store); +static DEVICE_ATTR_RW(idlepct); -static ssize_t acpi_pad_idlecpus_store(struct device *dev, +static ssize_t idlecpus_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long num; @@ -319,16 +315,14 @@ static ssize_t acpi_pad_idlecpus_store(struct device *dev, return count; } -static ssize_t acpi_pad_idlecpus_show(struct device *dev, +static ssize_t idlecpus_show(struct device *dev, struct device_attribute *attr, char *buf) { return cpumap_print_to_pagebuf(false, buf, to_cpumask(pad_busy_cpus_bits)); } -static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR, - acpi_pad_idlecpus_show, - acpi_pad_idlecpus_store); +static DEVICE_ATTR_RW(idlecpus); static int acpi_pad_add_sysfs(struct acpi_device *device) { diff --git a/drivers/acpi/acpi_tad.c b/drivers/acpi/acpi_tad.c index 7d45cce0c3c187ffc33e4f7d3526d181acf1088b..e9b8e8305e23e6086a84096ff6b09d24d97a88b8 100644 --- a/drivers/acpi/acpi_tad.c +++ b/drivers/acpi/acpi_tad.c @@ -237,7 +237,7 @@ static ssize_t time_show(struct device *dev, struct device_attribute *attr, rt.tz, rt.daylight); } -static DEVICE_ATTR(time, S_IRUSR | S_IWUSR, time_show, time_store); +static DEVICE_ATTR_RW(time); static struct attribute *acpi_tad_time_attrs[] = { &dev_attr_time.attr, @@ -446,7 +446,7 @@ static ssize_t ac_alarm_show(struct device *dev, struct device_attribute *attr, return acpi_tad_alarm_read(dev, buf, ACPI_TAD_AC_TIMER); } -static DEVICE_ATTR(ac_alarm, S_IRUSR | S_IWUSR, ac_alarm_show, ac_alarm_store); +static DEVICE_ATTR_RW(ac_alarm); static ssize_t ac_policy_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -462,7 +462,7 @@ static ssize_t ac_policy_show(struct device *dev, struct device_attribute *attr, return acpi_tad_policy_read(dev, buf, ACPI_TAD_AC_TIMER); } -static DEVICE_ATTR(ac_policy, S_IRUSR | S_IWUSR, ac_policy_show, ac_policy_store); +static DEVICE_ATTR_RW(ac_policy); static ssize_t ac_status_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -478,7 +478,7 @@ static ssize_t ac_status_show(struct device *dev, struct device_attribute *attr, return acpi_tad_status_read(dev, buf, ACPI_TAD_AC_TIMER); } -static DEVICE_ATTR(ac_status, S_IRUSR | S_IWUSR, ac_status_show, ac_status_store); +static DEVICE_ATTR_RW(ac_status); static struct attribute *acpi_tad_attrs[] = { &dev_attr_caps.attr, @@ -505,7 +505,7 @@ static ssize_t dc_alarm_show(struct device *dev, struct device_attribute *attr, return acpi_tad_alarm_read(dev, buf, ACPI_TAD_DC_TIMER); } -static DEVICE_ATTR(dc_alarm, S_IRUSR | S_IWUSR, dc_alarm_show, dc_alarm_store); +static DEVICE_ATTR_RW(dc_alarm); static ssize_t dc_policy_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -521,7 +521,7 @@ static ssize_t dc_policy_show(struct device *dev, struct device_attribute *attr, return acpi_tad_policy_read(dev, buf, ACPI_TAD_DC_TIMER); } -static DEVICE_ATTR(dc_policy, S_IRUSR | S_IWUSR, dc_policy_show, dc_policy_store); +static DEVICE_ATTR_RW(dc_policy); static ssize_t dc_status_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -537,7 +537,7 @@ static ssize_t dc_status_show(struct device *dev, struct device_attribute *attr, return acpi_tad_status_read(dev, buf, ACPI_TAD_DC_TIMER); } -static DEVICE_ATTR(dc_status, S_IRUSR | S_IWUSR, dc_status_show, dc_status_store); +static DEVICE_ATTR_RW(dc_status); static struct attribute *acpi_tad_dc_attrs[] = { &dev_attr_dc_alarm.attr, diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index a322a7bd286ba6a05b484a23358e5ee19622033b..eb04b2f828eef470c4116dae8f41aba1473e35d7 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -543,6 +543,15 @@ static const struct dmi_system_id video_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Vostro V131"), }, }, + { + .callback = video_set_report_key_events, + .driver_data = (void *)((uintptr_t)REPORT_BRIGHTNESS_KEY_EVENTS), + .ident = "Dell Vostro 3350", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Vostro 3350"), + }, + }, /* * Some machines change the brightness themselves when a brightness * hotkey gets pressed, despite us telling them not to. In this case diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 125143c41bb8100bb4f5953ba1070bf400c22414..8768594c79e58524f32e7852266123f4900a5a30 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -375,6 +375,13 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info, (*element_ptr)->common.reference_count = original_ref_count; + + /* + * The original_element holds a reference from the package object + * that represents _HID. Since a new element was created by _HID, + * remove the reference from the _CID package. + */ + acpi_ut_remove_reference(original_element); } element_ptr++; diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index fce7ade2aba92f8ec2a9398ce948d365700f54a6..0c8330ed1ffd5c80c6774687b60970f07822e17f 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -441,28 +441,35 @@ static void ghes_kick_task_work(struct callback_head *head) gen_pool_free(ghes_estatus_pool, (unsigned long)estatus_node, node_len); } -static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, - int sev) +static bool ghes_do_memory_failure(u64 physical_addr, int flags) { unsigned long pfn; - int flags = -1; - int sec_sev = ghes_severity(gdata->error_severity); - struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); if (!IS_ENABLED(CONFIG_ACPI_APEI_MEMORY_FAILURE)) return false; - if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) - return false; - - pfn = mem_err->physical_addr >> PAGE_SHIFT; + pfn = PHYS_PFN(physical_addr); if (!pfn_valid(pfn)) { pr_warn_ratelimited(FW_WARN GHES_PFX "Invalid address in generic error data: %#llx\n", - mem_err->physical_addr); + physical_addr); return false; } + memory_failure_queue(pfn, flags); + return true; +} + +static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, + int sev) +{ + int flags = -1; + int sec_sev = ghes_severity(gdata->error_severity); + struct cper_sec_mem_err *mem_err = acpi_hest_get_payload(gdata); + + if (!(mem_err->validation_bits & CPER_MEM_VALID_PA)) + return false; + /* iff following two events can be handled properly by now */ if (sec_sev == GHES_SEV_CORRECTED && (gdata->flags & CPER_SEC_ERROR_THRESHOLD_EXCEEDED)) @@ -470,14 +477,56 @@ static bool ghes_handle_memory_failure(struct acpi_hest_generic_data *gdata, if (sev == GHES_SEV_RECOVERABLE && sec_sev == GHES_SEV_RECOVERABLE) flags = 0; - if (flags != -1) { - memory_failure_queue(pfn, flags); - return true; - } + if (flags != -1) + return ghes_do_memory_failure(mem_err->physical_addr, flags); return false; } +static bool ghes_handle_arm_hw_error(struct acpi_hest_generic_data *gdata, int sev) +{ + struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); + bool queued = false; + int sec_sev, i; + char *p; + + log_arm_hw_error(err); + + sec_sev = ghes_severity(gdata->error_severity); + if (sev != GHES_SEV_RECOVERABLE || sec_sev != GHES_SEV_RECOVERABLE) + return false; + + p = (char *)(err + 1); + for (i = 0; i < err->err_info_num; i++) { + struct cper_arm_err_info *err_info = (struct cper_arm_err_info *)p; + bool is_cache = (err_info->type == CPER_ARM_CACHE_ERROR); + bool has_pa = (err_info->validation_bits & CPER_ARM_INFO_VALID_PHYSICAL_ADDR); + const char *error_type = "unknown error"; + + /* + * The field (err_info->error_info & BIT(26)) is fixed to set to + * 1 in some old firmware of HiSilicon Kunpeng920. We assume that + * firmware won't mix corrected errors in an uncorrected section, + * and don't filter out 'corrected' error here. + */ + if (is_cache && has_pa) { + queued = ghes_do_memory_failure(err_info->physical_fault_addr, 0); + p += err_info->length; + continue; + } + + if (err_info->type < ARRAY_SIZE(cper_proc_error_type_strs)) + error_type = cper_proc_error_type_strs[err_info->type]; + + pr_warn_ratelimited(FW_WARN GHES_PFX + "Unhandled processor error type: %s\n", + error_type); + p += err_info->length; + } + + return queued; +} + /* * PCIe AER errors need to be sent to the AER driver for reporting and * recovery. The GHES severities map to the following AER severities and @@ -605,9 +654,7 @@ static bool ghes_do_proc(struct ghes *ghes, ghes_handle_aer(gdata); } else if (guid_equal(sec_type, &CPER_SEC_PROC_ARM)) { - struct cper_sec_proc_arm *err = acpi_hest_get_payload(gdata); - - log_arm_hw_error(err); + queued = ghes_handle_arm_hw_error(gdata, sev); } else { void *err = acpi_hest_get_payload(gdata); diff --git a/drivers/acpi/bgrt.c b/drivers/acpi/bgrt.c index 251f961c28cc4c3cbe5883d987977edd84676a98..e0d14017706eabdf9217c594774f2e2fbcdab9c0 100644 --- a/drivers/acpi/bgrt.c +++ b/drivers/acpi/bgrt.c @@ -15,40 +15,19 @@ static void *bgrt_image; static struct kobject *bgrt_kobj; -static ssize_t show_version(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.version); -} -static DEVICE_ATTR(version, S_IRUGO, show_version, NULL); - -static ssize_t show_status(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.status); -} -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - -static ssize_t show_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_type); -} -static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); - -static ssize_t show_xoffset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_x); -} -static DEVICE_ATTR(xoffset, S_IRUGO, show_xoffset, NULL); - -static ssize_t show_yoffset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab.image_offset_y); -} -static DEVICE_ATTR(yoffset, S_IRUGO, show_yoffset, NULL); +#define BGRT_SHOW(_name, _member) \ + static ssize_t _name##_show(struct kobject *kobj, \ + struct kobj_attribute *attr, char *buf) \ + { \ + return snprintf(buf, PAGE_SIZE, "%d\n", bgrt_tab._member); \ + } \ + struct kobj_attribute bgrt_attr_##_name = __ATTR_RO(_name) + +BGRT_SHOW(version, version); +BGRT_SHOW(status, status); +BGRT_SHOW(type, image_type); +BGRT_SHOW(xoffset, image_offset_x); +BGRT_SHOW(yoffset, image_offset_y); static ssize_t image_read(struct file *file, struct kobject *kobj, struct bin_attribute *attr, char *buf, loff_t off, size_t count) @@ -60,11 +39,11 @@ static ssize_t image_read(struct file *file, struct kobject *kobj, static BIN_ATTR_RO(image, 0); /* size gets filled in later */ static struct attribute *bgrt_attributes[] = { - &dev_attr_version.attr, - &dev_attr_status.attr, - &dev_attr_type.attr, - &dev_attr_xoffset.attr, - &dev_attr_yoffset.attr, + &bgrt_attr_version.attr, + &bgrt_attr_status.attr, + &bgrt_attr_type.attr, + &bgrt_attr_xoffset.attr, + &bgrt_attr_yoffset.attr, NULL, }; diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 1682f8b454a2e6ed545f05ad9d6993f5c0fba23a..e317214aabec5570fcc1b5bbe1a89211fabe0198 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1245,6 +1245,7 @@ static int __init acpi_init(void) result = acpi_bus_init(); if (result) { + kobject_put(acpi_kobj); disable_acpi(); return result; } diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c index 48ff6821a83d40262c2325886e7b24ccb2afcc5d..ecd2ddc2215f5e9da8799b73641928b1582f4d45 100644 --- a/drivers/acpi/device_pm.c +++ b/drivers/acpi/device_pm.c @@ -18,6 +18,7 @@ #include <linux/pm_runtime.h> #include <linux/suspend.h> +#include "fan.h" #include "internal.h" #define _COMPONENT ACPI_POWER_COMPONENT @@ -1298,10 +1299,7 @@ int acpi_dev_pm_attach(struct device *dev, bool power_on) * with the generic ACPI PM domain. */ static const struct acpi_device_id special_pm_ids[] = { - {"PNP0C0B", }, /* Generic ACPI fan */ - {"INT3404", }, /* Fan */ - {"INTC1044", }, /* Fan for Tiger Lake generation */ - {"INTC1048", }, /* Fan for Alder Lake generation */ + ACPI_FAN_DEVICE_IDS, {} }; struct acpi_device *adev = ACPI_COMPANION(dev); diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index bfca116482b8bb5d22defaf301cca48384700740..fe8c7e79f4726f10d7ef9cff6507706adec0d938 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c @@ -325,11 +325,11 @@ int acpi_device_modalias(struct device *dev, char *buf, int size) EXPORT_SYMBOL_GPL(acpi_device_modalias); static ssize_t -acpi_device_modalias_show(struct device *dev, struct device_attribute *attr, char *buf) +modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { return __acpi_device_modalias(to_acpi_device(dev), buf, 1024); } -static DEVICE_ATTR(modalias, 0444, acpi_device_modalias_show, NULL); +static DEVICE_ATTR_RO(modalias); static ssize_t real_power_state_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -358,8 +358,8 @@ static ssize_t power_state_show(struct device *dev, static DEVICE_ATTR_RO(power_state); static ssize_t -acpi_eject_store(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) +eject_store(struct device *d, struct device_attribute *attr, + const char *buf, size_t count) { struct acpi_device *acpi_device = to_acpi_device(d); acpi_object_type not_used; @@ -387,28 +387,28 @@ acpi_eject_store(struct device *d, struct device_attribute *attr, return status == AE_NO_MEMORY ? -ENOMEM : -EAGAIN; } -static DEVICE_ATTR(eject, 0200, NULL, acpi_eject_store); +static DEVICE_ATTR_WO(eject); static ssize_t -acpi_device_hid_show(struct device *dev, struct device_attribute *attr, char *buf) +hid_show(struct device *dev, struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); return sprintf(buf, "%s\n", acpi_device_hid(acpi_dev)); } -static DEVICE_ATTR(hid, 0444, acpi_device_hid_show, NULL); +static DEVICE_ATTR_RO(hid); -static ssize_t acpi_device_uid_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t uid_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); return sprintf(buf, "%s\n", acpi_dev->pnp.unique_id); } -static DEVICE_ATTR(uid, 0444, acpi_device_uid_show, NULL); +static DEVICE_ATTR_RO(uid); -static ssize_t acpi_device_adr_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t adr_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); @@ -417,16 +417,16 @@ static ssize_t acpi_device_adr_show(struct device *dev, else return sprintf(buf, "0x%08llx\n", acpi_dev->pnp.bus_address); } -static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL); +static DEVICE_ATTR_RO(adr); -static ssize_t acpi_device_path_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t path_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); return acpi_object_path(acpi_dev->handle, buf); } -static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); +static DEVICE_ATTR_RO(path); /* sysfs file that shows description text from the ACPI _STR method */ static ssize_t description_show(struct device *dev, @@ -446,7 +446,7 @@ static ssize_t description_show(struct device *dev, (wchar_t *)acpi_dev->pnp.str_obj->buffer.pointer, acpi_dev->pnp.str_obj->buffer.length, UTF16_LITTLE_ENDIAN, buf, - PAGE_SIZE); + PAGE_SIZE - 1); buf[result++] = '\n'; @@ -455,8 +455,8 @@ static ssize_t description_show(struct device *dev, static DEVICE_ATTR_RO(description); static ssize_t -acpi_device_sun_show(struct device *dev, struct device_attribute *attr, - char *buf) { +sun_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); acpi_status status; unsigned long long sun; @@ -467,11 +467,11 @@ acpi_device_sun_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%llu\n", sun); } -static DEVICE_ATTR(sun, 0444, acpi_device_sun_show, NULL); +static DEVICE_ATTR_RO(sun); static ssize_t -acpi_device_hrv_show(struct device *dev, struct device_attribute *attr, - char *buf) { +hrv_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct acpi_device *acpi_dev = to_acpi_device(dev); acpi_status status; unsigned long long hrv; @@ -482,7 +482,7 @@ acpi_device_hrv_show(struct device *dev, struct device_attribute *attr, return sprintf(buf, "%llu\n", hrv); } -static DEVICE_ATTR(hrv, 0444, acpi_device_hrv_show, NULL); +static DEVICE_ATTR_RO(hrv); static ssize_t status_show(struct device *dev, struct device_attribute *attr, char *buf) { diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 24e076f44d23827874c4d476ba8323d55dfa993c..0937ceab052e89f90009c519339354f6a8a7d0ae 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -484,7 +484,7 @@ int dock_notify(struct acpi_device *adev, u32 event) /* * show_docked - read method for "docked" file in sysfs */ -static ssize_t show_docked(struct device *dev, +static ssize_t docked_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dock_station *dock_station = dev->platform_data; @@ -493,25 +493,25 @@ static ssize_t show_docked(struct device *dev, acpi_bus_get_device(dock_station->handle, &adev); return snprintf(buf, PAGE_SIZE, "%u\n", acpi_device_enumerated(adev)); } -static DEVICE_ATTR(docked, S_IRUGO, show_docked, NULL); +static DEVICE_ATTR_RO(docked); /* * show_flags - read method for flags file in sysfs */ -static ssize_t show_flags(struct device *dev, +static ssize_t flags_show(struct device *dev, struct device_attribute *attr, char *buf) { struct dock_station *dock_station = dev->platform_data; return snprintf(buf, PAGE_SIZE, "%d\n", dock_station->flags); } -static DEVICE_ATTR(flags, S_IRUGO, show_flags, NULL); +static DEVICE_ATTR_RO(flags); /* * write_undock - write method for "undock" file in sysfs */ -static ssize_t write_undock(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t undock_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { int ret; struct dock_station *dock_station = dev->platform_data; @@ -525,13 +525,13 @@ static ssize_t write_undock(struct device *dev, struct device_attribute *attr, acpi_scan_lock_release(); return ret ? ret: count; } -static DEVICE_ATTR(undock, S_IWUSR, NULL, write_undock); +static DEVICE_ATTR_WO(undock); /* * show_dock_uid - read method for "uid" file in sysfs */ -static ssize_t show_dock_uid(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t uid_show(struct device *dev, + struct device_attribute *attr, char *buf) { unsigned long long lbuf; struct dock_station *dock_station = dev->platform_data; @@ -542,10 +542,10 @@ static ssize_t show_dock_uid(struct device *dev, return snprintf(buf, PAGE_SIZE, "%llx\n", lbuf); } -static DEVICE_ATTR(uid, S_IRUGO, show_dock_uid, NULL); +static DEVICE_ATTR_RO(uid); -static ssize_t show_dock_type(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t type_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct dock_station *dock_station = dev->platform_data; char *type; @@ -561,7 +561,7 @@ static ssize_t show_dock_type(struct device *dev, return snprintf(buf, PAGE_SIZE, "%s\n", type); } -static DEVICE_ATTR(type, S_IRUGO, show_dock_type, NULL); +static DEVICE_ATTR_RO(type); static struct attribute *dock_attributes[] = { &dev_attr_docked.attr, diff --git a/drivers/acpi/ec.c b/drivers/acpi/ec.c index e0cb1bcfffb293b64a97ea2586718bf08763aaee..be3e0921a6c006f820d2cfa1fea47e995e3c8fa7 100644 --- a/drivers/acpi/ec.c +++ b/drivers/acpi/ec.c @@ -183,6 +183,7 @@ static struct workqueue_struct *ec_query_wq; static int EC_FLAGS_CORRECT_ECDT; /* Needs ECDT port address correction */ static int EC_FLAGS_IGNORE_DSDT_GPE; /* Needs ECDT GPE as correction setting */ +static int EC_FLAGS_TRUST_DSDT_GPE; /* Needs DSDT GPE as correction setting */ static int EC_FLAGS_CLEAR_ON_RESUME; /* Needs acpi_ec_clear() on boot/resume */ /* -------------------------------------------------------------------------- @@ -1606,7 +1607,8 @@ static int acpi_ec_add(struct acpi_device *device) } if (boot_ec && ec->command_addr == boot_ec->command_addr && - ec->data_addr == boot_ec->data_addr) { + ec->data_addr == boot_ec->data_addr && + !EC_FLAGS_TRUST_DSDT_GPE) { /* * Trust PNP0C09 namespace location rather than * ECDT ID. But trust ECDT GPE rather than _GPE @@ -1829,6 +1831,18 @@ static int ec_correct_ecdt(const struct dmi_system_id *id) return 0; } +/* + * Some ECDTs contain wrong GPE setting, but they share the same port addresses + * with DSDT EC, don't duplicate the DSDT EC with ECDT EC in this case. + * https://bugzilla.kernel.org/show_bug.cgi?id=209989 + */ +static int ec_honor_dsdt_gpe(const struct dmi_system_id *id) +{ + pr_debug("Detected system needing DSDT GPE setting.\n"); + EC_FLAGS_TRUST_DSDT_GPE = 1; + return 0; +} + /* * Some DSDTs contain wrong GPE setting. * Asus FX502VD/VE, GL702VMK, X550VXK, X580VD @@ -1859,6 +1873,22 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "GL702VMK"),}, NULL}, { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BA", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X505BA"),}, NULL}, + { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X505BP", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X505BP"),}, NULL}, + { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BA", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X542BA"),}, NULL}, + { + ec_honor_ecdt_gpe, "ASUSTeK COMPUTER INC. X542BP", { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "X542BP"),}, NULL}, + { ec_honor_ecdt_gpe, "ASUS X550VXK", { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X550VXK"),}, NULL}, @@ -1867,6 +1897,11 @@ static const struct dmi_system_id ec_dmi_table[] __initconst = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_PRODUCT_NAME, "X580VD"),}, NULL}, { + /* https://bugzilla.kernel.org/show_bug.cgi?id=209989 */ + ec_honor_dsdt_gpe, "HP Pavilion Gaming Laptop 15-cx0xxx", { + DMI_MATCH(DMI_SYS_VENDOR, "HP"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion Gaming Laptop 15-cx0xxx"),}, NULL}, + { ec_clear_on_resume, "Samsung hardware", { DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD.")}, NULL}, {}, diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c index 66c3983f0ccca7aacb83feb63c34c5b9e4e36cab..5cd0ceb50bc8a4d88aaa452755e4ea49657cc52c 100644 --- a/drivers/acpi/fan.c +++ b/drivers/acpi/fan.c @@ -16,6 +16,8 @@ #include <linux/platform_device.h> #include <linux/sort.h> +#include "fan.h" + MODULE_AUTHOR("Paul Diefenbaugh"); MODULE_DESCRIPTION("ACPI Fan Driver"); MODULE_LICENSE("GPL"); @@ -24,10 +26,7 @@ static int acpi_fan_probe(struct platform_device *pdev); static int acpi_fan_remove(struct platform_device *pdev); static const struct acpi_device_id fan_device_ids[] = { - {"PNP0C0B", 0}, - {"INT3404", 0}, - {"INTC1044", 0}, - {"INTC1048", 0}, + ACPI_FAN_DEVICE_IDS, {"", 0}, }; MODULE_DEVICE_TABLE(acpi, fan_device_ids); diff --git a/drivers/acpi/fan.h b/drivers/acpi/fan.h new file mode 100644 index 0000000000000000000000000000000000000000..dc9a6efa514b0378a5c72d96f1d55e44746ec441 --- /dev/null +++ b/drivers/acpi/fan.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +/* + * ACPI fan device IDs are shared between the fan driver and the device power + * management code. + * + * Add new device IDs before the generic ACPI fan one. + */ +#define ACPI_FAN_DEVICE_IDS \ + {"INT3404", }, /* Fan */ \ + {"INTC1044", }, /* Fan for Tiger Lake generation */ \ + {"INTC1048", }, /* Fan for Alder Lake generation */ \ + {"PNP0C0B", } /* Generic ACPI fan */ diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 8048da85b7e0787b340086200776a35f6310f06b..61115ed8b93fb1c386c79a23281c58ddd9e0526d 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -886,15 +886,16 @@ static void acpi_release_power_resource(struct device *dev) kfree(resource); } -static ssize_t acpi_power_in_use_show(struct device *dev, - struct device_attribute *attr, - char *buf) { +static ssize_t resource_in_use_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ struct acpi_power_resource *resource; resource = to_power_resource(to_acpi_device(dev)); return sprintf(buf, "%u\n", !!resource->ref_count); } -static DEVICE_ATTR(resource_in_use, 0444, acpi_power_in_use_show, NULL); +static DEVICE_ATTR_RO(resource_in_use); static void acpi_power_sysfs_remove(struct acpi_device *device) { diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index fb161a21d0aecc549511089886987859f3e6c7fe..8377c3ed10ffa148cdb852e0cec8f3bf89932645 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -16,6 +16,7 @@ #include <linux/acpi.h> #include <linux/dmi.h> #include <linux/sched.h> /* need_resched() */ +#include <linux/sort.h> #include <linux/tick.h> #include <linux/cpuidle.h> #include <linux/cpu.h> @@ -389,10 +390,37 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr, return; } +static int acpi_cst_latency_cmp(const void *a, const void *b) +{ + const struct acpi_processor_cx *x = a, *y = b; + + if (!(x->valid && y->valid)) + return 0; + if (x->latency > y->latency) + return 1; + if (x->latency < y->latency) + return -1; + return 0; +} +static void acpi_cst_latency_swap(void *a, void *b, int n) +{ + struct acpi_processor_cx *x = a, *y = b; + u32 tmp; + + if (!(x->valid && y->valid)) + return; + tmp = x->latency; + x->latency = y->latency; + y->latency = tmp; +} + static int acpi_processor_power_verify(struct acpi_processor *pr) { unsigned int i; unsigned int working = 0; + unsigned int last_latency = 0; + unsigned int last_type = 0; + bool buggy_latency = false; pr->power.timer_broadcast_on_state = INT_MAX; @@ -416,12 +444,24 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) } if (!cx->valid) continue; + if (cx->type >= last_type && cx->latency < last_latency) + buggy_latency = true; + last_latency = cx->latency; + last_type = cx->type; lapic_timer_check_state(i, pr, cx); tsc_check_state(cx->type); working++; } + if (buggy_latency) { + pr_notice("FW issue: working around C-state latencies out of order\n"); + sort(&pr->power.states[1], max_cstate, + sizeof(struct acpi_processor_cx), + acpi_cst_latency_cmp, + acpi_cst_latency_swap); + } + lapic_timer_propagate_broadcast(pr); return (working); diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c index f2f5f1dc7c61d64f5804cc1095687fc343e92b32..9d82440a1d75bf114126a2b3e9a43ba61785f264 100644 --- a/drivers/acpi/resource.c +++ b/drivers/acpi/resource.c @@ -430,6 +430,13 @@ static void acpi_dev_get_irqresource(struct resource *res, u32 gsi, } } +static bool irq_is_legacy(struct acpi_resource_irq *irq) +{ + return irq->triggering == ACPI_EDGE_SENSITIVE && + irq->polarity == ACPI_ACTIVE_HIGH && + irq->shareable == ACPI_EXCLUSIVE; +} + /** * acpi_dev_resource_interrupt - Extract ACPI interrupt resource information. * @ares: Input ACPI resource object. @@ -468,7 +475,7 @@ bool acpi_dev_resource_interrupt(struct acpi_resource *ares, int index, } acpi_dev_get_irqresource(res, irq->interrupts[index], irq->triggering, irq->polarity, - irq->shareable, true); + irq->shareable, irq_is_legacy(irq)); break; case ACPI_RESOURCE_TYPE_EXTENDED_IRQ: ext_irq = &ares->data.extended_irq; diff --git a/drivers/acpi/video_detect.c b/drivers/acpi/video_detect.c index 83cd4c95faf0da8acec49d1104542c61cd218f5e..33474fd969913c513d1acfd1577a0135f1c8a8d9 100644 --- a/drivers/acpi/video_detect.c +++ b/drivers/acpi/video_detect.c @@ -385,6 +385,30 @@ static const struct dmi_system_id video_detect_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "BA51_MV"), }, }, + { + .callback = video_detect_force_native, + .ident = "ASUSTeK COMPUTER INC. GA401", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA401"), + }, + }, + { + .callback = video_detect_force_native, + .ident = "ASUSTeK COMPUTER INC. GA502", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA502"), + }, + }, + { + .callback = video_detect_force_native, + .ident = "ASUSTeK COMPUTER INC. GA503", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "GA503"), + }, + }, /* * Desktops which falsely report a backlight and which our heuristics diff --git a/drivers/ata/ahci_sunxi.c b/drivers/ata/ahci_sunxi.c index cb69b737cb4996c9b1ca1643522b82b87c73f0fd..56b695136977ab728e3ed6771f8d392ccbe4f270 100644 --- a/drivers/ata/ahci_sunxi.c +++ b/drivers/ata/ahci_sunxi.c @@ -200,7 +200,7 @@ static void ahci_sunxi_start_engine(struct ata_port *ap) } static const struct ata_port_info ahci_sunxi_port_info = { - .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ, + .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ | ATA_FLAG_NO_DIPM, .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_platform_ops, diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c index badab67088935e8b8bbcff3a625762bb9bb3230b..46208ececbb6acd6e723cc9b8331a49d72e27bb2 100644 --- a/drivers/ata/pata_ep93xx.c +++ b/drivers/ata/pata_ep93xx.c @@ -928,7 +928,7 @@ static int ep93xx_pata_probe(struct platform_device *pdev) /* INT[3] (IRQ_EP93XX_EXT3) line connected as pull down */ irq = platform_get_irq(pdev, 0); if (irq < 0) { - err = -ENXIO; + err = irq; goto err_rel_gpio; } diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index bd87476ab48136f19286a94a21d0735b1a944ff5..b5a3f710d76de1f6b5e439023792fcd89c90adc3 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -898,10 +898,11 @@ static int octeon_cf_probe(struct platform_device *pdev) return -EINVAL; } - irq_handler = octeon_cf_interrupt; i = platform_get_irq(dma_dev, 0); - if (i > 0) + if (i > 0) { irq = i; + irq_handler = octeon_cf_interrupt; + } } of_node_put(dma_node); } diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 479c4b29b856261200740be36c1bd72a57027b81..303f8c375b3afbe63e13dc527ff5a99991ba49e1 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -115,10 +115,12 @@ static int rb532_pata_driver_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { + if (irq < 0) { dev_err(&pdev->dev, "no IRQ resource found\n"); - return -ENOENT; + return irq; } + if (!irq) + return -EINVAL; gpiod = devm_gpiod_get(&pdev->dev, NULL, GPIOD_IN); if (IS_ERR(gpiod)) { diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c index 64b2ef15ec191d7a95adaabdf79064333365c915..8440203e835edf9d59b51be7adbc203cb72ec7d0 100644 --- a/drivers/ata/sata_highbank.c +++ b/drivers/ata/sata_highbank.c @@ -469,10 +469,12 @@ static int ahci_highbank_probe(struct platform_device *pdev) } irq = platform_get_irq(pdev, 0); - if (irq <= 0) { + if (irq < 0) { dev_err(dev, "no irq\n"); - return -EINVAL; + return irq; } + if (!irq) + return -EINVAL; hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); if (!hpriv) { diff --git a/drivers/atm/iphase.c b/drivers/atm/iphase.c index eef637fd90b323ce182e4a5298d3eb9fefb89f36..a59554e5b8b0fe23cf99d7c1d091422799b63c05 100644 --- a/drivers/atm/iphase.c +++ b/drivers/atm/iphase.c @@ -3279,7 +3279,7 @@ static void __exit ia_module_exit(void) { pci_unregister_driver(&ia_driver); - del_timer(&ia_timer); + del_timer_sync(&ia_timer); } module_init(ia_module_init); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 09ad73361879e1a7b84944382e8927a01d4d00e4..6eb4ed256a7e2306ed64fe4194a1a6dbb88f6c72 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -297,7 +297,7 @@ static void __exit nicstar_cleanup(void) { XPRINTK("nicstar: nicstar_cleanup() called.\n"); - del_timer(&ns_timer); + del_timer_sync(&ns_timer); pci_unregister_driver(&nicstar_driver); @@ -525,6 +525,15 @@ static int ns_init_card(int i, struct pci_dev *pcidev) /* Set the VPI/VCI MSb mask to zero so we can receive OAM cells */ writel(0x00000000, card->membase + VPM); + card->intcnt = 0; + if (request_irq + (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) { + pr_err("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); + error = 9; + ns_init_card_error(card, error); + return error; + } + /* Initialize TSQ */ card->tsq.org = dma_alloc_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT, @@ -751,15 +760,6 @@ static int ns_init_card(int i, struct pci_dev *pcidev) card->efbie = 1; - card->intcnt = 0; - if (request_irq - (pcidev->irq, &ns_irq_handler, IRQF_SHARED, "nicstar", card) != 0) { - printk("nicstar%d: can't allocate IRQ %d.\n", i, pcidev->irq); - error = 9; - ns_init_card_error(card, error); - return error; - } - /* Register device */ card->atmdev = atm_dev_register("nicstar", &card->pcidev->dev, &atm_ops, -1, NULL); @@ -837,10 +837,12 @@ static void ns_init_card_error(ns_dev *card, int error) dev_kfree_skb_any(hb); } if (error >= 12) { - kfree(card->rsq.org); + dma_free_coherent(&card->pcidev->dev, NS_RSQSIZE + NS_RSQ_ALIGNMENT, + card->rsq.org, card->rsq.dma); } if (error >= 11) { - kfree(card->tsq.org); + dma_free_coherent(&card->pcidev->dev, NS_TSQSIZE + NS_TSQ_ALIGNMENT, + card->tsq.org, card->tsq.dma); } if (error >= 10) { free_irq(card->pcidev->irq, card); diff --git a/drivers/block/loop.c b/drivers/block/loop.c index a58084c2ed7ceb128ea9de08e7cda190d627b591..f0fa0c8e7ec60c151c0562bba147e8553dcd11f2 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -1161,6 +1161,7 @@ static int loop_configure(struct loop_device *lo, fmode_t mode, blk_queue_physical_block_size(lo->lo_queue, bsize); blk_queue_io_min(lo->lo_queue, bsize); + loop_config_discard(lo); loop_update_rotational(lo); loop_update_dio(lo); loop_sysfs_init(lo); @@ -1223,6 +1224,9 @@ static int __loop_clr_fd(struct loop_device *lo, bool release) goto out_unlock; } + if (test_bit(QUEUE_FLAG_WC, &lo->lo_queue->queue_flags)) + blk_queue_write_cache(lo->lo_queue, false, false); + /* freeze request queue during the transition */ blk_mq_freeze_queue(lo->lo_queue); diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index a314b9382442b6411d5bd78b52103573287ee0d3..42acf9587ef38947a68485dd884f5c2507b6cc45 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -946,6 +946,8 @@ static int virtblk_freeze(struct virtio_device *vdev) blk_mq_quiesce_queue(vblk->disk->queue); vdev->config->del_vqs(vdev); + kfree(vblk->vqs); + return 0; } diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c index ce9dcffdc5bfd6edd75cd478b6892db3f26be3b8..7551cac3fd7a954c50862cb0802009c9cf77c87f 100644 --- a/drivers/bluetooth/btqca.c +++ b/drivers/bluetooth/btqca.c @@ -143,7 +143,7 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev) EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd); static void qca_tlv_check_data(struct qca_fw_config *config, - const struct firmware *fw, enum qca_btsoc_type soc_type) + u8 *fw_data, enum qca_btsoc_type soc_type) { const u8 *data; u32 type_len; @@ -154,7 +154,7 @@ static void qca_tlv_check_data(struct qca_fw_config *config, struct tlv_type_nvm *tlv_nvm; uint8_t nvm_baud_rate = config->user_baud_rate; - tlv = (struct tlv_type_hdr *)fw->data; + tlv = (struct tlv_type_hdr *)fw_data; type_len = le32_to_cpu(tlv->type_len); length = (type_len >> 8) & 0x00ffffff; @@ -350,8 +350,9 @@ static int qca_download_firmware(struct hci_dev *hdev, enum qca_btsoc_type soc_type) { const struct firmware *fw; + u8 *data; const u8 *segment; - int ret, remain, i = 0; + int ret, size, remain, i = 0; bt_dev_info(hdev, "QCA Downloading %s", config->fwname); @@ -362,10 +363,22 @@ static int qca_download_firmware(struct hci_dev *hdev, return ret; } - qca_tlv_check_data(config, fw, soc_type); + size = fw->size; + data = vmalloc(fw->size); + if (!data) { + bt_dev_err(hdev, "QCA Failed to allocate memory for file: %s", + config->fwname); + release_firmware(fw); + return -ENOMEM; + } + + memcpy(data, fw->data, size); + release_firmware(fw); + + qca_tlv_check_data(config, data, soc_type); - segment = fw->data; - remain = fw->size; + segment = data; + remain = size; while (remain > 0) { int segsize = min(MAX_SIZE_PER_TLV_SEGMENT, remain); @@ -395,7 +408,7 @@ static int qca_download_firmware(struct hci_dev *hdev, ret = qca_inject_cmd_complete_event(hdev); out: - release_firmware(fw); + vfree(data); return ret; } diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index b1f0b13cc8bc6f166e5244611135f28c7c8c293f..afd2b1f12d49db66c9d70fc3602a91796cc3b126 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -269,6 +269,8 @@ static const struct usb_device_id blacklist_table[] = { BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME | BTUSB_WIDEBAND_SPEECH }, + { USB_DEVICE(0x0cf3, 0xe500), .driver_info = BTUSB_QCA_ROME | + BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME | BTUSB_WIDEBAND_SPEECH }, { USB_DEVICE(0x0489, 0xe09f), .driver_info = BTUSB_QCA_ROME | @@ -1719,6 +1721,13 @@ static void btusb_work(struct work_struct *work) * which work with WBS at all. */ new_alts = btusb_find_altsetting(data, 6) ? 6 : 1; + /* Because mSBC frames do not need to be aligned to the + * SCO packet boundary. If support the Alt 3, use the + * Alt 3 for HCI payload >= 60 Bytes let air packet + * data satisfy 60 bytes. + */ + if (new_alts == 1 && btusb_find_altsetting(data, 3)) + new_alts = 3; } if (btusb_switch_alt_setting(hdev, new_alts) < 0) @@ -2963,11 +2972,6 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, struct btmtk_wmt_hdr *hdr; int err; - /* Submit control IN URB on demand to process the WMT event */ - err = btusb_mtk_submit_wmt_recv_urb(hdev); - if (err < 0) - return err; - /* Send the WMT command and wait until the WMT event returns */ hlen = sizeof(*hdr) + wmt_params->dlen; if (hlen > 255) @@ -2989,6 +2993,11 @@ static int btusb_mtk_hci_wmt_sync(struct hci_dev *hdev, return err; } + /* Submit control IN URB on demand to process the WMT event */ + err = btusb_mtk_submit_wmt_recv_urb(hdev); + if (err < 0) + return err; + /* The vendor specific WMT commands are all answered by a vendor * specific event and will have the Command Status or Command * Complete as with usual HCI command flow control. @@ -3549,6 +3558,11 @@ static int btusb_setup_qca_download_fw(struct hci_dev *hdev, sent += size; count -= size; + /* ep2 need time to switch from function acl to function dfu, + * so we add 20ms delay here. + */ + msleep(20); + while (count) { size = min_t(size_t, count, QCA_DFU_PACKET_LEN); diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c index ad47ff0d55c2e28d341bf86fe87d6e64a01031b0..4184faef9f169b9defdfede96734f9486487a40d 100644 --- a/drivers/bluetooth/hci_qca.c +++ b/drivers/bluetooth/hci_qca.c @@ -1809,8 +1809,6 @@ static void qca_power_shutdown(struct hci_uart *hu) unsigned long flags; enum qca_btsoc_type soc_type = qca_soc_type(hu); - qcadev = serdev_device_get_drvdata(hu->serdev); - /* From this point we go into power off state. But serial port is * still open, stop queueing the IBS data and flush all the buffered * data in skb's. @@ -1826,6 +1824,8 @@ static void qca_power_shutdown(struct hci_uart *hu) if (!hu->serdev) return; + qcadev = serdev_device_get_drvdata(hu->serdev); + if (qca_is_wcn399x(soc_type)) { host_set_baudrate(hu, 2400); qca_send_power_pulse(hu, false); diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/core/pm.c index aeb895c084607d0ac218a7307d12e69f35336721..044dcdd723a707bb95dfc77086e7a6f5a2849fa3 100644 --- a/drivers/bus/mhi/core/pm.c +++ b/drivers/bus/mhi/core/pm.c @@ -809,6 +809,7 @@ int mhi_pm_resume(struct mhi_controller *mhi_cntrl) ret = wait_event_timeout(mhi_cntrl->state_event, mhi_cntrl->dev_state == MHI_STATE_M0 || + mhi_cntrl->dev_state == MHI_STATE_M2 || MHI_PM_IN_ERROR_STATE(mhi_cntrl->pm_state), msecs_to_jiffies(mhi_cntrl->timeout_ms)); diff --git a/drivers/char/hw_random/exynos-trng.c b/drivers/char/hw_random/exynos-trng.c index 8e1fe3f8dd2df6c232ac462e017b0817fb3cfaf5..c8db62bc5ff7205ff15949bcb08e627412088346 100644 --- a/drivers/char/hw_random/exynos-trng.c +++ b/drivers/char/hw_random/exynos-trng.c @@ -132,7 +132,7 @@ static int exynos_trng_probe(struct platform_device *pdev) return PTR_ERR(trng->mem); pm_runtime_enable(&pdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "Could not get runtime PM.\n"); goto err_pm_get; @@ -165,7 +165,7 @@ err_register: clk_disable_unprepare(trng->clk); err_clock: - pm_runtime_put_sync(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); err_pm_get: pm_runtime_disable(&pdev->dev); diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index f78156d93c3f241adbdf614971bac72281052deb..6384510c48d6b167aa9978a2473a7e9fc4555381 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c @@ -371,16 +371,18 @@ static int __ipmi_set_timeout(struct ipmi_smi_msg *smi_msg, data[0] = 0; WDOG_SET_TIMER_USE(data[0], WDOG_TIMER_USE_SMS_OS); - if ((ipmi_version_major > 1) - || ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) { - /* This is an IPMI 1.5-only feature. */ - data[0] |= WDOG_DONT_STOP_ON_SET; - } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { - /* - * In ipmi 1.0, setting the timer stops the watchdog, we - * need to start it back up again. - */ - hbnow = 1; + if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { + if ((ipmi_version_major > 1) || + ((ipmi_version_major == 1) && (ipmi_version_minor >= 5))) { + /* This is an IPMI 1.5-only feature. */ + data[0] |= WDOG_DONT_STOP_ON_SET; + } else { + /* + * In ipmi 1.0, setting the timer stops the watchdog, we + * need to start it back up again. + */ + hbnow = 1; + } } data[1] = 0; diff --git a/drivers/char/pcmcia/cm4000_cs.c b/drivers/char/pcmcia/cm4000_cs.c index 89681f07bc787297fa1aae10afc7f500aea8a4bd..9468e9520cee00da4090cb6551f27acd69bec9c9 100644 --- a/drivers/char/pcmcia/cm4000_cs.c +++ b/drivers/char/pcmcia/cm4000_cs.c @@ -544,6 +544,10 @@ static int set_protocol(struct cm4000_dev *dev, struct ptsreq *ptsreq) io_read_num_rec_bytes(iobase, &num_bytes_read); if (num_bytes_read >= 4) { DEBUGP(2, dev, "NumRecBytes = %i\n", num_bytes_read); + if (num_bytes_read > 4) { + rc = -EIO; + goto exit_setprotocol; + } break; } usleep_range(10000, 11000); diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index 55b9d3965ae1b3b9135065db1690bb97771b6a07..69579efb247b3b7508df00d5796cb9d429db3889 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -196,13 +196,24 @@ static u8 tpm_tis_status(struct tpm_chip *chip) return 0; if (unlikely((status & TPM_STS_READ_ZERO) != 0)) { - /* - * If this trips, the chances are the read is - * returning 0xff because the locality hasn't been - * acquired. Usually because tpm_try_get_ops() hasn't - * been called before doing a TPM operation. - */ - WARN_ONCE(1, "TPM returned invalid status\n"); + if (!test_and_set_bit(TPM_TIS_INVALID_STATUS, &priv->flags)) { + /* + * If this trips, the chances are the read is + * returning 0xff because the locality hasn't been + * acquired. Usually because tpm_try_get_ops() hasn't + * been called before doing a TPM operation. + */ + dev_err(&chip->dev, "invalid TPM_STS.x 0x%02x, dumping stack for forensics\n", + status); + + /* + * Dump stack for forensics, as invalid TPM_STS.x could be + * potentially triggered by impaired tpm_try_get_ops() or + * tpm_find_get_ops(). + */ + dump_stack(); + } + return 0; } diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index 9b2d32a59f6704645d13bef82b5d265e020eee03..b2a3c6c72882d48feada725f9e3bcda3ca53010e 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -83,6 +83,7 @@ enum tis_defaults { enum tpm_tis_flags { TPM_TIS_ITPM_WORKAROUND = BIT(0), + TPM_TIS_INVALID_STATUS = BIT(1), }; struct tpm_tis_data { @@ -90,7 +91,7 @@ struct tpm_tis_data { int locality; int irq; bool irq_tested; - unsigned int flags; + unsigned long flags; void __iomem *ilb_base_addr; u16 clkrun_enabled; wait_queue_head_t int_queue; diff --git a/drivers/char/tpm/tpm_tis_spi_main.c b/drivers/char/tpm/tpm_tis_spi_main.c index 3856f6ebcb34f712ff983cc3e15c9fc804f6c870..de4209003a448ea0e141538d51f8b67bf2aad0a9 100644 --- a/drivers/char/tpm/tpm_tis_spi_main.c +++ b/drivers/char/tpm/tpm_tis_spi_main.c @@ -260,6 +260,8 @@ static int tpm_tis_spi_remove(struct spi_device *dev) } static const struct spi_device_id tpm_tis_spi_id[] = { + { "st33htpm-spi", (unsigned long)tpm_tis_spi_probe }, + { "slb9670", (unsigned long)tpm_tis_spi_probe }, { "tpm_tis_spi", (unsigned long)tpm_tis_spi_probe }, { "cr50", (unsigned long)cr50_spi_probe }, {} diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 1836cc56e357b7b428808e5a0d32163e68f2e491..673522874cec43e6e502b83c9795978671c0ef96 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -475,7 +475,7 @@ static struct port_buffer *get_inbuf(struct port *port) buf = virtqueue_get_buf(port->in_vq, &len); if (buf) { - buf->len = len; + buf->len = min_t(size_t, len, buf->size); buf->offset = 0; port->stats.bytes_received += len; } @@ -1712,7 +1712,7 @@ static void control_work_handler(struct work_struct *work) while ((buf = virtqueue_get_buf(vq, &len))) { spin_unlock(&portdev->c_ivq_lock); - buf->len = len; + buf->len = min_t(size_t, len, buf->size); buf->offset = 0; handle_control_message(vq->vdev, portdev, buf); diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c index 61bb224f633093c5f247116a0a8b460764817543..cbeb51c804eb50aecf26f7d8b1b4d12422029504 100644 --- a/drivers/clk/actions/owl-s500.c +++ b/drivers/clk/actions/owl-s500.c @@ -127,8 +127,7 @@ static struct clk_factor_table sd_factor_table[] = { { 12, 1, 13 }, { 13, 1, 14 }, { 14, 1, 15 }, { 15, 1, 16 }, { 16, 1, 17 }, { 17, 1, 18 }, { 18, 1, 19 }, { 19, 1, 20 }, { 20, 1, 21 }, { 21, 1, 22 }, { 22, 1, 23 }, { 23, 1, 24 }, - { 24, 1, 25 }, { 25, 1, 26 }, { 26, 1, 27 }, { 27, 1, 28 }, - { 28, 1, 29 }, { 29, 1, 30 }, { 30, 1, 31 }, { 31, 1, 32 }, + { 24, 1, 25 }, /* bit8: /128 */ { 256, 1, 1 * 128 }, { 257, 1, 2 * 128 }, { 258, 1, 3 * 128 }, { 259, 1, 4 * 128 }, @@ -137,19 +136,20 @@ static struct clk_factor_table sd_factor_table[] = { { 268, 1, 13 * 128 }, { 269, 1, 14 * 128 }, { 270, 1, 15 * 128 }, { 271, 1, 16 * 128 }, { 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 }, { 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 }, - { 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 }, - { 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 }, + { 280, 1, 25 * 128 }, { 0, 0, 0 }, }; -static struct clk_factor_table bisp_factor_table[] = { - { 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 }, - { 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 }, +static struct clk_factor_table de_factor_table[] = { + { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, + { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, + { 8, 1, 12 }, { 0, 0, 0 }, }; -static struct clk_factor_table ahb_factor_table[] = { - { 1, 1, 2 }, { 2, 1, 3 }, +static struct clk_factor_table hde_factor_table[] = { + { 0, 1, 1 }, { 1, 2, 3 }, { 2, 1, 2 }, { 3, 2, 5 }, + { 4, 1, 3 }, { 5, 1, 4 }, { 6, 1, 6 }, { 7, 1, 8 }, { 0, 0, 0 }, }; @@ -158,6 +158,13 @@ static struct clk_div_table rmii_ref_div_table[] = { { 0, 0 }, }; +static struct clk_div_table std12rate_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, + { 4, 5 }, { 5, 6 }, { 6, 7 }, { 7, 8 }, + { 8, 9 }, { 9, 10 }, { 10, 11 }, { 11, 12 }, + { 0, 0 }, +}; + static struct clk_div_table i2s_div_table[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 }, @@ -174,7 +181,6 @@ static struct clk_div_table nand_div_table[] = { /* mux clock */ static OWL_MUX(dev_clk, "dev_clk", dev_clk_mux_p, CMU_DEVPLL, 12, 1, CLK_SET_RATE_PARENT); -static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT); /* gate clocks */ static OWL_GATE(gpio_clk, "gpio_clk", "apb_clk", CMU_DEVCLKEN0, 18, 0, 0); @@ -187,45 +193,54 @@ static OWL_GATE(timer_clk, "timer_clk", "hosc", CMU_DEVCLKEN1, 27, 0, 0); static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0); /* divider clocks */ -static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0); +static OWL_DIVIDER(h_clk, "h_clk", "ahbprediv_clk", CMU_BUSCLK1, 2, 2, NULL, 0, 0); static OWL_DIVIDER(apb_clk, "apb_clk", "ahb_clk", CMU_BUSCLK1, 14, 2, NULL, 0, 0); static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0); /* factor clocks */ -static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0); -static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 3, bisp_factor_table, 0, 0); -static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 3, bisp_factor_table, 0, 0); +static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 4, de_factor_table, 0, 0); +static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 4, de_factor_table, 0, 0); /* composite clocks */ +static OWL_COMP_DIV(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, + OWL_MUX_HW(CMU_BUSCLK1, 8, 3), + { 0 }, + OWL_DIVIDER_HW(CMU_BUSCLK1, 12, 2, 0, NULL), + CLK_SET_RATE_PARENT); + +static OWL_COMP_FIXED_FACTOR(ahb_clk, "ahb_clk", "h_clk", + { 0 }, + 1, 1, 0); + static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VCECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0), - OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, bisp_factor_table), + OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, hde_factor_table), 0); static OWL_COMP_FACTOR(vde_clk, "vde_clk", hde_clk_mux_p, OWL_MUX_HW(CMU_VDECLK, 4, 2), OWL_GATE_HW(CMU_DEVCLKEN0, 25, 0), - OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, bisp_factor_table), + OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, hde_factor_table), 0); -static OWL_COMP_FACTOR(bisp_clk, "bisp_clk", bisp_clk_mux_p, +static OWL_COMP_DIV(bisp_clk, "bisp_clk", bisp_clk_mux_p, OWL_MUX_HW(CMU_BISPCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_BISPCLK, 0, 3, 0, bisp_factor_table), + OWL_DIVIDER_HW(CMU_BISPCLK, 0, 4, 0, std12rate_div_table), 0); -static OWL_COMP_FACTOR(sensor0_clk, "sensor0_clk", sensor_clk_mux_p, +static OWL_COMP_DIV(sensor0_clk, "sensor0_clk", sensor_clk_mux_p, OWL_MUX_HW(CMU_SENSORCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_SENSORCLK, 0, 3, 0, bisp_factor_table), - CLK_IGNORE_UNUSED); + OWL_DIVIDER_HW(CMU_SENSORCLK, 0, 4, 0, std12rate_div_table), + 0); -static OWL_COMP_FACTOR(sensor1_clk, "sensor1_clk", sensor_clk_mux_p, +static OWL_COMP_DIV(sensor1_clk, "sensor1_clk", sensor_clk_mux_p, OWL_MUX_HW(CMU_SENSORCLK, 4, 1), OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0), - OWL_FACTOR_HW(CMU_SENSORCLK, 8, 3, 0, bisp_factor_table), - CLK_IGNORE_UNUSED); + OWL_DIVIDER_HW(CMU_SENSORCLK, 8, 4, 0, std12rate_div_table), + 0); static OWL_COMP_FACTOR(sd0_clk, "sd0_clk", sd_clk_mux_p, OWL_MUX_HW(CMU_SD0CLK, 9, 1), @@ -305,7 +320,7 @@ static OWL_COMP_FIXED_FACTOR(i2c3_clk, "i2c3_clk", "ethernet_pll_clk", static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART0CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART0CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p, @@ -317,31 +332,31 @@ static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p, static OWL_COMP_DIV(uart2_clk, "uart2_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART2CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 8, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART2CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart3_clk, "uart3_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART3CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 19, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART3CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart4_clk, "uart4_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART4CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 20, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART4CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart5_clk, "uart5_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART5CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 21, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART5CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(uart6_clk, "uart6_clk", uart_clk_mux_p, OWL_MUX_HW(CMU_UART6CLK, 16, 1), OWL_GATE_HW(CMU_DEVCLKEN1, 18, 0), - OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), + OWL_DIVIDER_HW(CMU_UART6CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL), CLK_IGNORE_UNUSED); static OWL_COMP_DIV(i2srx_clk, "i2srx_clk", i2s_clk_mux_p, diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index e0446e66fa6450d0d62e410883d24bbd0be89b61..eb22f4fdbc6b42c2f3384bafdc33ef93c8c8375e 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -92,12 +92,22 @@ struct clk_si5341_output_config { #define SI5341_PN_BASE 0x0002 #define SI5341_DEVICE_REV 0x0005 #define SI5341_STATUS 0x000C +#define SI5341_LOS 0x000D +#define SI5341_STATUS_STICKY 0x0011 +#define SI5341_LOS_STICKY 0x0012 #define SI5341_SOFT_RST 0x001C #define SI5341_IN_SEL 0x0021 +#define SI5341_DEVICE_READY 0x00FE #define SI5341_XAXB_CFG 0x090E #define SI5341_IN_EN 0x0949 #define SI5341_INX_TO_PFD_EN 0x094A +/* Status bits */ +#define SI5341_STATUS_SYSINCAL BIT(0) +#define SI5341_STATUS_LOSXAXB BIT(1) +#define SI5341_STATUS_LOSREF BIT(2) +#define SI5341_STATUS_LOL BIT(3) + /* Input selection */ #define SI5341_IN_SEL_MASK 0x06 #define SI5341_IN_SEL_SHIFT 1 @@ -340,6 +350,8 @@ static const struct si5341_reg_default si5341_reg_defaults[] = { { 0x094A, 0x00 }, /* INx_TO_PFD_EN (disabled) */ { 0x0A02, 0x00 }, /* Not in datasheet */ { 0x0B44, 0x0F }, /* PDIV_ENB (datasheet does not mention what it is) */ + { 0x0B57, 0x10 }, /* VCO_RESET_CALCODE (not described in datasheet) */ + { 0x0B58, 0x05 }, /* VCO_RESET_CALCODE (not described in datasheet) */ }; /* Read and interpret a 44-bit followed by a 32-bit value in the regmap */ @@ -623,6 +635,9 @@ static unsigned long si5341_synth_clk_recalc_rate(struct clk_hw *hw, SI5341_SYNTH_N_NUM(synth->index), &n_num, &n_den); if (err < 0) return err; + /* Check for bogus/uninitialized settings */ + if (!n_num || !n_den) + return 0; /* * n_num and n_den are shifted left as much as possible, so to prevent @@ -806,6 +821,9 @@ static long si5341_output_clk_round_rate(struct clk_hw *hw, unsigned long rate, { unsigned long r; + if (!rate) + return 0; + r = *parent_rate >> 1; /* If rate is an even divisor, no changes to parent required */ @@ -834,11 +852,16 @@ static int si5341_output_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { struct clk_si5341_output *output = to_clk_si5341_output(hw); - /* Frequency divider is (r_div + 1) * 2 */ - u32 r_div = (parent_rate / rate) >> 1; + u32 r_div; int err; u8 r[3]; + if (!rate) + return -EINVAL; + + /* Frequency divider is (r_div + 1) * 2 */ + r_div = (parent_rate / rate) >> 1; + if (r_div <= 1) r_div = 0; else if (r_div >= BIT(24)) @@ -1083,7 +1106,7 @@ static const struct si5341_reg_default si5341_preamble[] = { { 0x0B25, 0x00 }, { 0x0502, 0x01 }, { 0x0505, 0x03 }, - { 0x0957, 0x1F }, + { 0x0957, 0x17 }, { 0x0B4E, 0x1A }, }; @@ -1189,6 +1212,32 @@ static const struct regmap_range_cfg si5341_regmap_ranges[] = { }, }; +static int si5341_wait_device_ready(struct i2c_client *client) +{ + int count; + + /* Datasheet warns: Any attempt to read or write any register other + * than DEVICE_READY before DEVICE_READY reads as 0x0F may corrupt the + * NVM programming and may corrupt the register contents, as they are + * read from NVM. Note that this includes accesses to the PAGE register. + * Also: DEVICE_READY is available on every register page, so no page + * change is needed to read it. + * Do this outside regmap to avoid automatic PAGE register access. + * May take up to 300ms to complete. + */ + for (count = 0; count < 15; ++count) { + s32 result = i2c_smbus_read_byte_data(client, + SI5341_DEVICE_READY); + if (result < 0) + return result; + if (result == 0x0F) + return 0; + msleep(20); + } + dev_err(&client->dev, "timeout waiting for DEVICE_READY\n"); + return -EIO; +} + static const struct regmap_config si5341_regmap_config = { .reg_bits = 8, .val_bits = 8, @@ -1378,6 +1427,7 @@ static int si5341_probe(struct i2c_client *client, unsigned int i; struct clk_si5341_output_config config[SI5341_MAX_NUM_OUTPUTS]; bool initialization_required; + u32 status; data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -1385,6 +1435,11 @@ static int si5341_probe(struct i2c_client *client, data->i2c_client = client; + /* Must be done before otherwise touching hardware */ + err = si5341_wait_device_ready(client); + if (err) + return err; + for (i = 0; i < SI5341_NUM_INPUTS; ++i) { input = devm_clk_get(&client->dev, si5341_input_clock_names[i]); if (IS_ERR(input)) { @@ -1540,6 +1595,22 @@ static int si5341_probe(struct i2c_client *client, return err; } + /* wait for device to report input clock present and PLL lock */ + err = regmap_read_poll_timeout(data->regmap, SI5341_STATUS, status, + !(status & (SI5341_STATUS_LOSREF | SI5341_STATUS_LOL)), + 10000, 250000); + if (err) { + dev_err(&client->dev, "Error waiting for input clock or PLL lock\n"); + return err; + } + + /* clear sticky alarm bits from initialization */ + err = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0); + if (err) { + dev_err(&client->dev, "unable to clear sticky status\n"); + return err; + } + /* Free the names, clk framework makes copies */ for (i = 0; i < data->num_synth; ++i) devm_kfree(&client->dev, (void *)synth_clock_names[i]); diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index 43db67337bc0682475c467de2ba2b05b76c106b7..4e741f94baf02adf3b379892364f04433bb038bf 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -69,7 +69,10 @@ #define VC5_FEEDBACK_FRAC_DIV(n) (0x19 + (n)) #define VC5_RC_CONTROL0 0x1e #define VC5_RC_CONTROL1 0x1f -/* Register 0x20 is factory reserved */ + +/* These registers are named "Unused Factory Reserved Registers" */ +#define VC5_RESERVED_X0(idx) (0x20 + ((idx) * 0x10)) +#define VC5_RESERVED_X0_BYPASS_SYNC BIT(7) /* bypass_sync<idx> bit */ /* Output divider control for divider 1,2,3,4 */ #define VC5_OUT_DIV_CONTROL(idx) (0x21 + ((idx) * 0x10)) @@ -87,7 +90,6 @@ #define VC5_OUT_DIV_SKEW_INT(idx, n) (0x2b + ((idx) * 0x10) + (n)) #define VC5_OUT_DIV_INT(idx, n) (0x2d + ((idx) * 0x10) + (n)) #define VC5_OUT_DIV_SKEW_FRAC(idx) (0x2f + ((idx) * 0x10)) -/* Registers 0x30, 0x40, 0x50 are factory reserved */ /* Clock control register for clock 1,2 */ #define VC5_CLK_OUTPUT_CFG(idx, n) (0x60 + ((idx) * 0x2) + (n)) @@ -140,6 +142,8 @@ #define VC5_HAS_INTERNAL_XTAL BIT(0) /* chip has PFD requency doubler */ #define VC5_HAS_PFD_FREQ_DBL BIT(1) +/* chip has bits to disable FOD sync */ +#define VC5_HAS_BYPASS_SYNC_BIT BIT(2) /* Supported IDT VC5 models. */ enum vc5_model { @@ -581,6 +585,23 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) unsigned int src; int ret; + /* + * When enabling a FOD, all currently enabled FODs are briefly + * stopped in order to synchronize all of them. This causes a clock + * disruption to any unrelated chips that might be already using + * other clock outputs. Bypass the sync feature to avoid the issue, + * which is possible on the VersaClock 6E family via reserved + * registers. + */ + if (vc5->chip_info->flags & VC5_HAS_BYPASS_SYNC_BIT) { + ret = regmap_update_bits(vc5->regmap, + VC5_RESERVED_X0(hwdata->num), + VC5_RESERVED_X0_BYPASS_SYNC, + VC5_RESERVED_X0_BYPASS_SYNC); + if (ret) + return ret; + } + /* * If the input mux is disabled, enable it first and * select source from matching FOD. @@ -1102,7 +1123,7 @@ static const struct vc5_chip_info idt_5p49v6965_info = { .model = IDT_VC6_5P49V6965, .clk_fod_cnt = 4, .clk_out_cnt = 5, - .flags = 0, + .flags = VC5_HAS_BYPASS_SYNC_BIT, }; static const struct i2c_device_id vc5_id[] = { diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 9137dee9410bfd5c3867b21558c0d0c062ce03ca..73cc228cac336e598928df6638bcb354074d8d05 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -391,7 +391,6 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_VIDEO2_PLL_OUT] = imx_clk_hw_sscg_pll("video2_pll_out", video2_pll_out_sels, ARRAY_SIZE(video2_pll_out_sels), 0, 0, 0, base + 0x54, 0); /* SYS PLL1 fixed output */ - hws[IMX8MQ_SYS1_PLL_40M] = imx_clk_hw_fixed_factor("sys1_pll_40m", "sys1_pll_out", 1, 20); hws[IMX8MQ_SYS1_PLL_80M] = imx_clk_hw_fixed_factor("sys1_pll_80m", "sys1_pll_out", 1, 10); hws[IMX8MQ_SYS1_PLL_100M] = imx_clk_hw_fixed_factor("sys1_pll_100m", "sys1_pll_out", 1, 8); @@ -403,7 +402,6 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_SYS1_PLL_800M] = imx_clk_hw_fixed_factor("sys1_pll_800m", "sys1_pll_out", 1, 1); /* SYS PLL2 fixed output */ - hws[IMX8MQ_SYS2_PLL_50M] = imx_clk_hw_fixed_factor("sys2_pll_50m", "sys2_pll_out", 1, 20); hws[IMX8MQ_SYS2_PLL_100M] = imx_clk_hw_fixed_factor("sys2_pll_100m", "sys2_pll_out", 1, 10); hws[IMX8MQ_SYS2_PLL_125M] = imx_clk_hw_fixed_factor("sys2_pll_125m", "sys2_pll_out", 1, 8); diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index b814d44917a5db9d471da8c9086afd5e17aa08cd..2876bb83d9d0edc1b7c8c728b8b6f1846a4701da 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -1602,7 +1602,7 @@ static struct clk_regmap g12b_cpub_clk_trace = { }; static const struct pll_mult_range g12a_gp0_pll_mult_range = { - .min = 55, + .min = 125, .max = 255, }; diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 564431130a760de60ec440cb3285c3908bd0da50..1a571c04a76cbf4f494a4d4c0e9d80d9ab6e476f 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1214,7 +1214,7 @@ static int alpha_pll_fabia_prepare(struct clk_hw *hw) return -EINVAL; /* Setup PLL for calibration frequency */ - regmap_write(pll->clkr.regmap, PLL_ALPHA_VAL(pll), cal_l); + regmap_write(pll->clkr.regmap, PLL_CAL_L_VAL(pll), cal_l); /* Bringup the PLL at calibration frequency */ ret = clk_alpha_pll_enable(hw); diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 5b4691117b470556dbb71f79993dc703bf3a9747..026e2612c33cac890f0baf781b7d8042a7520281 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -75,6 +75,7 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { DEF_RATE(".oco", CLK_OCO, 8 * 1000 * 1000), /* Core Clock Outputs */ + DEF_FIXED("za2", R8A77995_CLK_ZA2, CLK_PLL0D3, 2, 1), DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1), DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1), DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1), diff --git a/drivers/clk/renesas/rcar-usb2-clock-sel.c b/drivers/clk/renesas/rcar-usb2-clock-sel.c index d4c02986c34e9347d1317b318453028206055320..0ccc6e709a385f3a75eb94ddbae4c621b84c4d84 100644 --- a/drivers/clk/renesas/rcar-usb2-clock-sel.c +++ b/drivers/clk/renesas/rcar-usb2-clock-sel.c @@ -128,10 +128,8 @@ static int rcar_usb2_clock_sel_resume(struct device *dev) static int rcar_usb2_clock_sel_remove(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev); of_clk_del_provider(dev->of_node); - clk_hw_unregister(&priv->hw); pm_runtime_put(dev); pm_runtime_disable(dev); @@ -164,9 +162,6 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) if (IS_ERR(priv->rsts)) return PTR_ERR(priv->rsts); - pm_runtime_enable(dev); - pm_runtime_get_sync(dev); - clk = devm_clk_get(dev, "usb_extal"); if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { priv->extal = !!clk_get_rate(clk); @@ -183,6 +178,8 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) return -ENOENT; } + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); platform_set_drvdata(pdev, priv); dev_set_drvdata(dev, priv); @@ -193,11 +190,20 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) init.num_parents = 0; priv->hw.init = &init; - clk = clk_register(NULL, &priv->hw); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ret = devm_clk_hw_register(NULL, &priv->hw); + if (ret) + goto pm_put; + + ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); + if (ret) + goto pm_put; + + return 0; - return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); +pm_put: + pm_runtime_put(dev); + pm_runtime_disable(dev); + return ret; } static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = { diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index bb3e80928ebe84460ccf44b8ab12be13bb96a4bf..438075a50b9f277b0938ab7245cdbea808987667 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -186,6 +186,41 @@ static const struct clk_parent_data noc_mux[] = { .name = "boot_clk", }, }; +static const struct clk_parent_data sdmmc_mux[] = { + { .fw_name = "sdmmc_free_clk", + .name = "sdmmc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_user1_mux[] = { + { .fw_name = "s2f_user1_free_clk", + .name = "s2f_user1_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_mux[] = { + { .fw_name = "psi_ref_free_clk", + .name = "psi_ref_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_mux[] = { + { .fw_name = "gpio_db_free_clk", + .name = "gpio_db_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_mux[] = { + { .fw_name = "emac_ptp_free_clk", + .name = "emac_ptp_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock agilex_pll_clks[] = { { AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, @@ -211,11 +246,9 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { { AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 0, 0x3C, 0, 0, 0}, { AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), - 0, 0x40, 0, 0, 1}, - { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, - 0, 4, 0, 0}, - { AGILEX_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), - 0, 0, 0, 0x30, 1}, + 0, 0x40, 0, 0, 0}, + { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, + 0, 4, 0x30, 1}, { AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 0, 0xD4, 0, 0x88, 0}, { AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), @@ -225,7 +258,7 @@ static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { { AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux, ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3}, { AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux, - ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0x88, 4}, + ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0, 0}, { AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux, ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0}, { AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux, @@ -241,24 +274,24 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 0, 0, 0, 0, 0, 0, 4}, { AGILEX_MPU_CCU_CLK, "mpu_ccu_clk", "mpu_clk", NULL, 1, 0, 0x24, 0, 0, 0, 0, 0, 0, 2}, - { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24, - 1, 0x44, 0, 2, 0, 0, 0}, - { AGILEX_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x24, - 2, 0x44, 8, 2, 0, 0, 0}, + { AGILEX_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 1, 0x44, 0, 2, 0x30, 1, 0}, + { AGILEX_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 2, 0x44, 8, 2, 0x30, 1, 0}, /* * The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them * being the SP timers, thus cannot get gated. */ - { AGILEX_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x24, - 3, 0x44, 16, 2, 0, 0, 0}, - { AGILEX_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x24, - 4, 0x44, 24, 2, 0, 0, 0}, - { AGILEX_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x24, - 4, 0x44, 26, 2, 0, 0, 0}, + { AGILEX_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x24, + 3, 0x44, 16, 2, 0x30, 1, 0}, + { AGILEX_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 4, 0x44, 24, 2, 0x30, 1, 0}, + { AGILEX_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 4, 0x44, 26, 2, 0x30, 1, 0}, { AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24, 4, 0x44, 28, 1, 0, 0, 0}, - { AGILEX_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x24, - 5, 0, 0, 0, 0, 0, 0}, + { AGILEX_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x24, + 5, 0, 0, 0, 0x30, 1, 0}, { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24, 6, 0, 0, 0, 0, 0, 0}, { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, @@ -267,16 +300,16 @@ static const struct stratix10_gate_clock agilex_gate_clks[] = { 1, 0, 0, 0, 0x94, 27, 0}, { AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, 2, 0, 0, 0, 0x94, 28, 0}, - { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0x7C, - 3, 0, 0, 0, 0, 0, 0}, - { AGILEX_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0x7C, - 4, 0x98, 0, 16, 0, 0, 0}, - { AGILEX_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0x7C, - 5, 0, 0, 0, 0, 0, 4}, - { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0x7C, - 6, 0, 0, 0, 0, 0, 0}, - { AGILEX_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0x7C, - 7, 0, 0, 0, 0, 0, 0}, + { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0x7C, + 3, 0, 0, 0, 0x88, 2, 0}, + { AGILEX_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0x7C, + 4, 0x98, 0, 16, 0x88, 3, 0}, + { AGILEX_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0x7C, + 5, 0, 0, 0, 0x88, 4, 4}, + { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0x7C, + 6, 0, 0, 0, 0x88, 5, 0}, + { AGILEX_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0x7C, + 7, 0, 0, 0, 0x88, 6, 0}, { AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, 8, 0, 0, 0, 0, 0, 0}, { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index 397b77b89b166eabd43b4a5ec41f098a06fc39a7..bae595f17061f30d4dfda18faf9712d8ff43f11b 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -49,16 +49,21 @@ static u8 clk_periclk_get_parent(struct clk_hw *hwclk) { struct socfpga_periph_clk *socfpgaclk = to_periph_clk(hwclk); u32 clk_src, mask; - u8 parent; + u8 parent = 0; + /* handle the bypass first */ if (socfpgaclk->bypass_reg) { mask = (0x1 << socfpgaclk->bypass_shift); parent = ((readl(socfpgaclk->bypass_reg) & mask) >> socfpgaclk->bypass_shift); - } else { + if (parent) + return parent; + } + + if (socfpgaclk->hw.reg) { clk_src = readl(socfpgaclk->hw.reg); parent = (clk_src >> CLK_MGR_FREE_SHIFT) & - CLK_MGR_FREE_MASK; + CLK_MGR_FREE_MASK; } return parent; } diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index 661a8e9bfb9bd230f878f83d78cdb0b5045c7a05..aaf69058b1dca85bac6a8c955e9d79be0554731a 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -144,6 +144,41 @@ static const struct clk_parent_data mpu_free_mux[] = { .name = "f2s-free-clk", }, }; +static const struct clk_parent_data sdmmc_mux[] = { + { .fw_name = "sdmmc_free_clk", + .name = "sdmmc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_user1_mux[] = { + { .fw_name = "s2f_user1_free_clk", + .name = "s2f_user1_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_mux[] = { + { .fw_name = "psi_ref_free_clk", + .name = "psi_ref_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_mux[] = { + { .fw_name = "gpio_db_free_clk", + .name = "gpio_db_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_mux[] = { + { .fw_name = "emac_ptp_free_clk", + .name = "emac_ptp_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock s10_pll_clks[] = { { STRATIX10_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, @@ -167,7 +202,7 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = { { STRATIX10_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), 0, 0x48, 0, 0, 0}, { STRATIX10_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), - 0, 0x4C, 0, 0, 0}, + 0, 0x4C, 0, 0x3C, 1}, { STRATIX10_MAIN_EMACA_CLK, "main_emaca_clk", "main_noc_base_clk", NULL, 1, 0, 0x50, 0, 0, 0}, { STRATIX10_MAIN_EMACB_CLK, "main_emacb_clk", "main_noc_base_clk", NULL, 1, 0, @@ -200,10 +235,8 @@ static const struct stratix10_perip_cnt_clock s10_main_perip_cnt_clks[] = { 0, 0xD4, 0, 0, 0}, { STRATIX10_PERI_PSI_REF_CLK, "peri_psi_ref_clk", "peri_noc_base_clk", NULL, 1, 0, 0xD8, 0, 0, 0}, - { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, - 0, 4, 0, 0}, - { STRATIX10_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), - 0, 0, 0, 0x3C, 1}, + { STRATIX10_L4_SYS_FREE_CLK, "l4_sys_free_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, + 0, 4, 0x3C, 1}, { STRATIX10_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), 0, 0, 2, 0xB0, 0}, { STRATIX10_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), @@ -227,20 +260,20 @@ static const struct stratix10_gate_clock s10_gate_clks[] = { 0, 0, 0, 0, 0, 0, 4}, { STRATIX10_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 2}, - { STRATIX10_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x30, - 1, 0x70, 0, 2, 0, 0, 0}, - { STRATIX10_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x30, - 2, 0x70, 8, 2, 0, 0, 0}, - { STRATIX10_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x30, - 3, 0x70, 16, 2, 0, 0, 0}, - { STRATIX10_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x30, - 4, 0x70, 24, 2, 0, 0, 0}, - { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x30, - 4, 0x70, 26, 2, 0, 0, 0}, + { STRATIX10_L4_MAIN_CLK, "l4_main_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 1, 0x70, 0, 2, 0x3C, 1, 0}, + { STRATIX10_L4_MP_CLK, "l4_mp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 2, 0x70, 8, 2, 0x3C, 1, 0}, + { STRATIX10_L4_SP_CLK, "l4_sp_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), CLK_IS_CRITICAL, 0x30, + 3, 0x70, 16, 2, 0x3C, 1, 0}, + { STRATIX10_CS_AT_CLK, "cs_at_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 4, 0x70, 24, 2, 0x3C, 1, 0}, + { STRATIX10_CS_TRACE_CLK, "cs_trace_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 4, 0x70, 26, 2, 0x3C, 1, 0}, { STRATIX10_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x30, 4, 0x70, 28, 1, 0, 0, 0}, - { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x30, - 5, 0, 0, 0, 0, 0, 0}, + { STRATIX10_CS_TIMER_CLK, "cs_timer_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), 0, 0x30, + 5, 0, 0, 0, 0x3C, 1, 0}, { STRATIX10_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x30, 6, 0, 0, 0, 0, 0, 0}, { STRATIX10_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4, @@ -249,16 +282,16 @@ static const struct stratix10_gate_clock s10_gate_clks[] = { 1, 0, 0, 0, 0xDC, 27, 0}, { STRATIX10_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0xA4, 2, 0, 0, 0, 0xDC, 28, 0}, - { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0xA4, - 3, 0, 0, 0, 0, 0, 0}, - { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0xA4, - 4, 0xE0, 0, 16, 0, 0, 0}, - { STRATIX10_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0xA4, - 5, 0, 0, 0, 0, 0, 4}, - { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0xA4, - 6, 0, 0, 0, 0, 0, 0}, - { STRATIX10_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0xA4, - 7, 0, 0, 0, 0, 0, 0}, + { STRATIX10_EMAC_PTP_CLK, "emac_ptp_clk", NULL, emac_ptp_mux, ARRAY_SIZE(emac_ptp_mux), 0, 0xA4, + 3, 0, 0, 0, 0xB0, 2, 0}, + { STRATIX10_GPIO_DB_CLK, "gpio_db_clk", NULL, gpio_db_mux, ARRAY_SIZE(gpio_db_mux), 0, 0xA4, + 4, 0xE0, 0, 16, 0xB0, 3, 0}, + { STRATIX10_SDMMC_CLK, "sdmmc_clk", NULL, sdmmc_mux, ARRAY_SIZE(sdmmc_mux), 0, 0xA4, + 5, 0, 0, 0, 0xB0, 4, 4}, + { STRATIX10_S2F_USER1_CLK, "s2f_user1_clk", NULL, s2f_user1_mux, ARRAY_SIZE(s2f_user1_mux), 0, 0xA4, + 6, 0, 0, 0, 0xB0, 5, 0}, + { STRATIX10_PSI_REF_CLK, "psi_ref_clk", NULL, psi_mux, ARRAY_SIZE(psi_mux), 0, 0xA4, + 7, 0, 0, 0, 0xB0, 6, 0}, { STRATIX10_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0xA4, 8, 0, 0, 0, 0, 0, 0}, { STRATIX10_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0xA4, diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index 4b31beefc9fc2da723ab7bb4108e4d286ea3dbcd..dc3f92678407be30c6e65f8da9841984a930f29d 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c @@ -48,18 +48,9 @@ static int clk_periph_is_enabled(struct clk_hw *hw) return state; } -static int clk_periph_enable(struct clk_hw *hw) +static void clk_periph_enable_locked(struct clk_hw *hw) { struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); - unsigned long flags = 0; - - spin_lock_irqsave(&periph_ref_lock, flags); - - gate->enable_refcnt[gate->clk_num]++; - if (gate->enable_refcnt[gate->clk_num] > 1) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return 0; - } write_enb_set(periph_clk_to_bit(gate), gate); udelay(2); @@ -78,6 +69,32 @@ static int clk_periph_enable(struct clk_hw *hw) udelay(1); writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); } +} + +static void clk_periph_disable_locked(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + + /* + * If peripheral is in the APB bus then read the APB bus to + * flush the write operation in apb bus. This will avoid the + * peripheral access after disabling clock + */ + if (gate->flags & TEGRA_PERIPH_ON_APB) + tegra_read_chipid(); + + write_enb_clr(periph_clk_to_bit(gate), gate); +} + +static int clk_periph_enable(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); + + if (!gate->enable_refcnt[gate->clk_num]++) + clk_periph_enable_locked(hw); spin_unlock_irqrestore(&periph_ref_lock, flags); @@ -91,21 +108,28 @@ static void clk_periph_disable(struct clk_hw *hw) spin_lock_irqsave(&periph_ref_lock, flags); - gate->enable_refcnt[gate->clk_num]--; - if (gate->enable_refcnt[gate->clk_num] > 0) { - spin_unlock_irqrestore(&periph_ref_lock, flags); - return; - } + WARN_ON(!gate->enable_refcnt[gate->clk_num]); + + if (--gate->enable_refcnt[gate->clk_num] == 0) + clk_periph_disable_locked(hw); + + spin_unlock_irqrestore(&periph_ref_lock, flags); +} + +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw); + unsigned long flags = 0; + + spin_lock_irqsave(&periph_ref_lock, flags); /* - * If peripheral is in the APB bus then read the APB bus to - * flush the write operation in apb bus. This will avoid the - * peripheral access after disabling clock + * Some clocks are duplicated and some of them are marked as critical, + * like fuse and fuse_burn for example, thus the enable_refcnt will + * be non-zero here if the "unused" duplicate is disabled by CCF. */ - if (gate->flags & TEGRA_PERIPH_ON_APB) - tegra_read_chipid(); - - write_enb_clr(periph_clk_to_bit(gate), gate); + if (!gate->enable_refcnt[gate->clk_num]) + clk_periph_disable_locked(hw); spin_unlock_irqrestore(&periph_ref_lock, flags); } @@ -114,6 +138,7 @@ const struct clk_ops tegra_clk_periph_gate_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, }; struct clk *tegra_clk_register_periph_gate(const char *name, @@ -148,9 +173,6 @@ struct clk *tegra_clk_register_periph_gate(const char *name, gate->enable_refcnt = enable_refcnt; gate->regs = pregs; - if (read_enb(gate) & periph_clk_to_bit(gate)) - enable_refcnt[clk_num]++; - /* Data in .init is copied by clk_register(), so stack variable OK */ gate->hw.init = &init; diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 67620c7ecd9ee299b274d9784fa5e675e08e4e8e..79ca3aa072b70747f8304c8aa7164fbd30fe1662 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c @@ -100,6 +100,15 @@ static void clk_periph_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); } +static void clk_periph_disable_unused(struct clk_hw *hw) +{ + struct tegra_clk_periph *periph = to_clk_periph(hw); + const struct clk_ops *gate_ops = periph->gate_ops; + struct clk_hw *gate_hw = &periph->gate.hw; + + gate_ops->disable_unused(gate_hw); +} + static void clk_periph_restore_context(struct clk_hw *hw) { struct tegra_clk_periph *periph = to_clk_periph(hw); @@ -126,6 +135,7 @@ const struct clk_ops tegra_clk_periph_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, }; @@ -135,6 +145,7 @@ static const struct clk_ops tegra_clk_periph_nodiv_ops = { .is_enabled = clk_periph_is_enabled, .enable = clk_periph_enable, .disable = clk_periph_disable, + .disable_unused = clk_periph_disable_unused, .restore_context = clk_periph_restore_context, }; diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index c5cc0a2dac6ff880de18824553701c9d06c5ee5e..d709ecb7d8d7e6ab46c0f68058b8adefbba681d6 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c @@ -1131,7 +1131,8 @@ static int clk_pllu_enable(struct clk_hw *hw) if (pll->lock) spin_lock_irqsave(pll->lock, flags); - _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (ret < 0) @@ -1748,15 +1749,13 @@ static int clk_pllu_tegra114_enable(struct clk_hw *hw) return -EINVAL; } - if (clk_pll_is_enabled(hw)) - return 0; - input_rate = clk_hw_get_rate(__clk_get_hw(osc)); if (pll->lock) spin_lock_irqsave(pll->lock, flags); - _clk_pll_enable(hw); + if (!clk_pll_is_enabled(hw)) + _clk_pll_enable(hw); ret = clk_pll_wait_for_lock(pll); if (ret < 0) diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 9cf249c344d9e415877c2f1a8b89ad1fa4d5f958..31e752318a10433f5786bbe923a92b3bdb76a073 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1248,7 +1248,7 @@ static struct tegra_clk_init_table init_table[] __initdata = { { TEGRA30_CLK_GR3D, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_GR3D2, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_PLL_U, TEGRA30_CLK_CLK_MAX, 480000000, 0 }, - { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 600000000, 0 }, + { TEGRA30_CLK_VDE, TEGRA30_CLK_PLL_C, 300000000, 0 }, { TEGRA30_CLK_SPDIF_IN_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S0_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, { TEGRA30_CLK_I2S1_SYNC, TEGRA30_CLK_CLK_MAX, 24000000, 0 }, diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c index d0177824c518b88daa749d2f8d3d4b9ac183b8d0..f4881764bf8f4f6658b27d2146de48b3bac0376b 100644 --- a/drivers/clocksource/arm_arch_timer.c +++ b/drivers/clocksource/arm_arch_timer.c @@ -352,7 +352,7 @@ static u64 notrace arm64_858921_read_cntvct_el0(void) do { \ _val = read_sysreg(reg); \ _retries--; \ - } while (((_val + 1) & GENMASK(9, 0)) <= 1 && _retries); \ + } while (((_val + 1) & GENMASK(8, 0)) <= 1 && _retries); \ \ WARN_ON_ONCE(!_retries); \ _val; \ diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c index 33eeabf9c3d12bd2c6220d49d0ab26612f41daf6..e5c631f1b5cbe49a9a098f32790ee2a552a3ffc3 100644 --- a/drivers/clocksource/timer-ti-dm.c +++ b/drivers/clocksource/timer-ti-dm.c @@ -78,6 +78,9 @@ static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg, static void omap_timer_restore_context(struct omap_dm_timer *timer) { + __omap_dm_timer_write(timer, OMAP_TIMER_OCP_CFG_OFFSET, + timer->context.ocp_cfg, 0); + omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, timer->context.twer); omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, @@ -95,6 +98,9 @@ static void omap_timer_restore_context(struct omap_dm_timer *timer) static void omap_timer_save_context(struct omap_dm_timer *timer) { + timer->context.ocp_cfg = + __omap_dm_timer_read(timer, OMAP_TIMER_OCP_CFG_OFFSET, 0); + timer->context.tclr = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG); timer->context.twer = diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1e7e3f2ff09f0d6236491bb2f380a2b3ad2d6273..ebee0ad559fad31131aa1e02ad2cec713ebb4522 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1368,9 +1368,14 @@ static int cpufreq_online(unsigned int cpu) goto out_free_policy; } + /* + * The initialization has succeeded and the policy is online. + * If there is a problem with its frequency table, take it + * offline and drop it. + */ ret = cpufreq_table_validate_and_sort(policy); if (ret) - goto out_exit_policy; + goto out_offline_policy; /* related_cpus should at least include policy->cpus. */ cpumask_copy(policy->related_cpus, policy->cpus); @@ -1513,6 +1518,10 @@ out_destroy_policy: up_write(&policy->rwsem); +out_offline_policy: + if (cpufreq_driver->offline) + cpufreq_driver->offline(policy); + out_exit_policy: if (cpufreq_driver->exit) cpufreq_driver->exit(policy); diff --git a/drivers/crypto/cavium/nitrox/nitrox_isr.c b/drivers/crypto/cavium/nitrox/nitrox_isr.c index 3dec570a190ad5efca0696831a281307f1f185a3..10e3408bf704cede60ca0de7745e86b4c9d248c7 100644 --- a/drivers/crypto/cavium/nitrox/nitrox_isr.c +++ b/drivers/crypto/cavium/nitrox/nitrox_isr.c @@ -306,6 +306,10 @@ int nitrox_register_interrupts(struct nitrox_device *ndev) * Entry 192: NPS_CORE_INT_ACTIVE */ nr_vecs = pci_msix_vec_count(pdev); + if (nr_vecs < 0) { + dev_err(DEV(ndev), "Error in getting vec count %d\n", nr_vecs); + return nr_vecs; + } /* Enable MSI-X */ ret = pci_alloc_irq_vectors(pdev, nr_vecs, nr_vecs, PCI_IRQ_MSIX); diff --git a/drivers/crypto/ccp/sev-dev.c b/drivers/crypto/ccp/sev-dev.c index 21caed429cc52ffa7e0c9a5516d913990a2e6007..d0018794e92e8e10e87cbe5d750c72cbad8708c2 100644 --- a/drivers/crypto/ccp/sev-dev.c +++ b/drivers/crypto/ccp/sev-dev.c @@ -42,6 +42,10 @@ static int psp_probe_timeout = 5; module_param(psp_probe_timeout, int, 0644); MODULE_PARM_DESC(psp_probe_timeout, " default timeout value, in seconds, during PSP device probe"); +MODULE_FIRMWARE("amd/amd_sev_fam17h_model0xh.sbin"); /* 1st gen EPYC */ +MODULE_FIRMWARE("amd/amd_sev_fam17h_model3xh.sbin"); /* 2nd gen EPYC */ +MODULE_FIRMWARE("amd/amd_sev_fam19h_model0xh.sbin"); /* 3rd gen EPYC */ + static bool psp_dead; static int psp_timeout; diff --git a/drivers/crypto/ccp/sp-pci.c b/drivers/crypto/ccp/sp-pci.c index f471dbaef1fbc35e4bd9d40c38b5fdda4c74047e..7d346d842a39ee1d5f19af2284d8b3ded0c447ff 100644 --- a/drivers/crypto/ccp/sp-pci.c +++ b/drivers/crypto/ccp/sp-pci.c @@ -222,7 +222,7 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) { dev_err(dev, "dma_set_mask_and_coherent failed (%d)\n", ret); - goto e_err; + goto free_irqs; } } @@ -230,10 +230,12 @@ static int sp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = sp_init(sp); if (ret) - goto e_err; + goto free_irqs; return 0; +free_irqs: + sp_free_irqs(sp); e_err: dev_notice(dev, "initialization failed\n"); return ret; diff --git a/drivers/crypto/hisilicon/sec2/sec_crypto.c b/drivers/crypto/hisilicon/sec2/sec_crypto.c index 41f1fcacb2809bc37b090ebd0143eb1414b6623f..630dcb59ad56974df34587c58a2941eab5368bd2 100644 --- a/drivers/crypto/hisilicon/sec2/sec_crypto.c +++ b/drivers/crypto/hisilicon/sec2/sec_crypto.c @@ -1515,11 +1515,11 @@ static struct skcipher_alg sec_skciphers[] = { AES_BLOCK_SIZE, AES_BLOCK_SIZE) SEC_SKCIPHER_ALG("ecb(des3_ede)", sec_setkey_3des_ecb, - SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE, + SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE, DES3_EDE_BLOCK_SIZE, 0) SEC_SKCIPHER_ALG("cbc(des3_ede)", sec_setkey_3des_cbc, - SEC_DES3_2KEY_SIZE, SEC_DES3_3KEY_SIZE, + SEC_DES3_3KEY_SIZE, SEC_DES3_3KEY_SIZE, DES3_EDE_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE) SEC_SKCIPHER_ALG("xts(sm4)", sec_setkey_sm4_xts, diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 276012e7c482fae284f620740a7dbff219781f53..5e474a7a1912c2d4c326ae30ee651d02f7d96c67 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -149,6 +149,8 @@ struct crypt_ctl { struct ablk_ctx { struct buffer_desc *src; struct buffer_desc *dst; + u8 iv[MAX_IVLEN]; + bool encrypt; }; struct aead_ctx { @@ -330,7 +332,7 @@ static void free_buf_chain(struct device *dev, struct buffer_desc *buf, buf1 = buf->next; phys1 = buf->phys_next; - dma_unmap_single(dev, buf->phys_next, buf->buf_len, buf->dir); + dma_unmap_single(dev, buf->phys_addr, buf->buf_len, buf->dir); dma_pool_free(buffer_pool, buf, phys); buf = buf1; phys = phys1; @@ -381,6 +383,20 @@ static void one_packet(dma_addr_t phys) case CTL_FLAG_PERFORM_ABLK: { struct skcipher_request *req = crypt->data.ablk_req; struct ablk_ctx *req_ctx = skcipher_request_ctx(req); + struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); + unsigned int ivsize = crypto_skcipher_ivsize(tfm); + unsigned int offset; + + if (ivsize > 0) { + offset = req->cryptlen - ivsize; + if (req_ctx->encrypt) { + scatterwalk_map_and_copy(req->iv, req->dst, + offset, ivsize, 0); + } else { + memcpy(req->iv, req_ctx->iv, ivsize); + memzero_explicit(req_ctx->iv, ivsize); + } + } if (req_ctx->dst) { free_buf_chain(dev, req_ctx->dst, crypt->dst_buf); @@ -876,6 +892,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) struct ablk_ctx *req_ctx = skcipher_request_ctx(req); struct buffer_desc src_hook; struct device *dev = &pdev->dev; + unsigned int offset; gfp_t flags = req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP ? GFP_KERNEL : GFP_ATOMIC; @@ -885,6 +902,7 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) return -EAGAIN; dir = encrypt ? &ctx->encrypt : &ctx->decrypt; + req_ctx->encrypt = encrypt; crypt = get_crypt_desc(); if (!crypt) @@ -900,6 +918,10 @@ static int ablk_perform(struct skcipher_request *req, int encrypt) BUG_ON(ivsize && !req->iv); memcpy(crypt->iv, req->iv, ivsize); + if (ivsize > 0 && !encrypt) { + offset = req->cryptlen - ivsize; + scatterwalk_map_and_copy(req_ctx->iv, req->src, offset, ivsize, 0); + } if (req->src != req->dst) { struct buffer_desc dst_hook; crypt->mode |= NPE_OP_NOT_IN_PLACE; diff --git a/drivers/crypto/nx/nx-842-pseries.c b/drivers/crypto/nx/nx-842-pseries.c index 2de5e3672e4233e0ab3673c04627146129ff5d64..c5ec50a28f30dda36e9e2f6fe346a92bc594be70 100644 --- a/drivers/crypto/nx/nx-842-pseries.c +++ b/drivers/crypto/nx/nx-842-pseries.c @@ -538,13 +538,15 @@ static int nx842_OF_set_defaults(struct nx842_devdata *devdata) * The status field indicates if the device is enabled when the status * is 'okay'. Otherwise the device driver will be disabled. * - * @prop - struct property point containing the maxsyncop for the update + * @devdata: struct nx842_devdata to use for dev_info + * @prop: struct property point containing the maxsyncop for the update * * Returns: * 0 - Device is available * -ENODEV - Device is not available */ -static int nx842_OF_upd_status(struct property *prop) +static int nx842_OF_upd_status(struct nx842_devdata *devdata, + struct property *prop) { const char *status = (const char *)prop->value; @@ -758,7 +760,7 @@ static int nx842_OF_upd(struct property *new_prop) goto out; /* Perform property updates */ - ret = nx842_OF_upd_status(status); + ret = nx842_OF_upd_status(new_devdata, status); if (ret) goto error_out; @@ -1071,6 +1073,7 @@ static const struct vio_device_id nx842_vio_driver_ids[] = { {"ibm,compression-v1", "ibm,compression"}, {"", ""}, }; +MODULE_DEVICE_TABLE(vio, nx842_vio_driver_ids); static struct vio_driver nx842_vio_driver = { .name = KBUILD_MODNAME, diff --git a/drivers/crypto/nx/nx-aes-ctr.c b/drivers/crypto/nx/nx-aes-ctr.c index 6d5ce1a66f1eeb12a949652c14dd38cfe9c904c1..02ad26012c665b684bdd89174e3cc0e8b3a83df6 100644 --- a/drivers/crypto/nx/nx-aes-ctr.c +++ b/drivers/crypto/nx/nx-aes-ctr.c @@ -118,7 +118,7 @@ static int ctr3686_aes_nx_crypt(struct skcipher_request *req) struct nx_crypto_ctx *nx_ctx = crypto_skcipher_ctx(tfm); u8 iv[16]; - memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_IV_SIZE); + memcpy(iv, nx_ctx->priv.ctr.nonce, CTR_RFC3686_NONCE_SIZE); memcpy(iv + CTR_RFC3686_NONCE_SIZE, req->iv, CTR_RFC3686_IV_SIZE); iv[12] = iv[13] = iv[14] = 0; iv[15] = 1; diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c index a3b38d2c92e70b9a6edb9cc98f56553ddd12a78e..39d17ed1db2f2f7ab625131f6792592a6830b7c9 100644 --- a/drivers/crypto/omap-sham.c +++ b/drivers/crypto/omap-sham.c @@ -371,7 +371,7 @@ static int omap_sham_hw_init(struct omap_sham_dev *dd) { int err; - err = pm_runtime_get_sync(dd->dev); + err = pm_runtime_resume_and_get(dd->dev); if (err < 0) { dev_err(dd->dev, "failed to get sync: %d\n", err); return err; @@ -2243,7 +2243,7 @@ static int omap_sham_suspend(struct device *dev) static int omap_sham_resume(struct device *dev) { - int err = pm_runtime_get_sync(dev); + int err = pm_runtime_resume_and_get(dev); if (err < 0) { dev_err(dev, "failed to get sync: %d\n", err); return err; diff --git a/drivers/crypto/qat/qat_common/qat_hal.c b/drivers/crypto/qat/qat_common/qat_hal.c index 52ef80efeddc6f4ae1f1cddb68c98428e4dd1d8f..b40e81e0088f0c23e8db013f95b66a20484f6016 100644 --- a/drivers/crypto/qat/qat_common/qat_hal.c +++ b/drivers/crypto/qat/qat_common/qat_hal.c @@ -1213,7 +1213,11 @@ static int qat_hal_put_rel_wr_xfer(struct icp_qat_fw_loader_handle *handle, pr_err("QAT: bad xfrAddr=0x%x\n", xfr_addr); return -EINVAL; } - qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval); + status = qat_hal_rd_rel_reg(handle, ae, ctx, ICP_GPB_REL, gprnum, &gprval); + if (status) { + pr_err("QAT: failed to read register"); + return status; + } gpr_addr = qat_hal_get_reg_addr(ICP_GPB_REL, gprnum); data16low = 0xffff & data; data16hi = 0xffff & (data >> 0x10); diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c index 5d1f28cd6680919ac88a44b80be23bcb701ac102..6adc91fedb083c68630d749b7f5721185c1163dd 100644 --- a/drivers/crypto/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/qat/qat_common/qat_uclo.c @@ -342,7 +342,6 @@ static int qat_uclo_init_umem_seg(struct icp_qat_fw_loader_handle *handle, return 0; } -#define ICP_DH895XCC_PESRAM_BAR_SIZE 0x80000 static int qat_uclo_init_ae_memory(struct icp_qat_fw_loader_handle *handle, struct icp_qat_uof_initmem *init_mem) { diff --git a/drivers/crypto/qce/skcipher.c b/drivers/crypto/qce/skcipher.c index a2d3da0ad95f3eecc66730b92313fecdd439e6c0..d8053789c8828a6dc6ac0e0a02ead50e3eacc248 100644 --- a/drivers/crypto/qce/skcipher.c +++ b/drivers/crypto/qce/skcipher.c @@ -71,7 +71,7 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) struct scatterlist *sg; bool diff_dst; gfp_t gfp; - int ret; + int dst_nents, src_nents, ret; rctx->iv = req->iv; rctx->ivsize = crypto_skcipher_ivsize(skcipher); @@ -122,21 +122,26 @@ qce_skcipher_async_req_handle(struct crypto_async_request *async_req) sg_mark_end(sg); rctx->dst_sg = rctx->dst_tbl.sgl; - ret = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); - if (ret < 0) + dst_nents = dma_map_sg(qce->dev, rctx->dst_sg, rctx->dst_nents, dir_dst); + if (dst_nents < 0) { + ret = dst_nents; goto error_free; + } if (diff_dst) { - ret = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); - if (ret < 0) + src_nents = dma_map_sg(qce->dev, req->src, rctx->src_nents, dir_src); + if (src_nents < 0) { + ret = src_nents; goto error_unmap_dst; + } rctx->src_sg = req->src; } else { rctx->src_sg = rctx->dst_sg; + src_nents = dst_nents - 1; } - ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, rctx->src_nents, - rctx->dst_sg, rctx->dst_nents, + ret = qce_dma_prep_sgs(&qce->dma, rctx->src_sg, src_nents, + rctx->dst_sg, dst_nents, qce_skcipher_done, async_req); if (ret) goto error_unmap_src; diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c index 4640fe0c1f221b90768fbd032d802656fd84f2a5..f15fc1fb370794ec590620cb490b1e917a1283cf 100644 --- a/drivers/crypto/sa2ul.c +++ b/drivers/crypto/sa2ul.c @@ -2270,9 +2270,9 @@ static int sa_dma_init(struct sa_crypto_data *dd) dd->dma_rx2 = dma_request_chan(dd->dev, "rx2"); if (IS_ERR(dd->dma_rx2)) { - dma_release_channel(dd->dma_rx1); - return dev_err_probe(dd->dev, PTR_ERR(dd->dma_rx2), - "Unable to request rx2 DMA channel\n"); + ret = dev_err_probe(dd->dev, PTR_ERR(dd->dma_rx2), + "Unable to request rx2 DMA channel\n"); + goto err_dma_rx2; } dd->dma_tx = dma_request_chan(dd->dev, "tx"); @@ -2293,28 +2293,31 @@ static int sa_dma_init(struct sa_crypto_data *dd) if (ret) { dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n", ret); - return ret; + goto err_dma_config; } ret = dmaengine_slave_config(dd->dma_rx2, &cfg); if (ret) { dev_err(dd->dev, "can't configure IN dmaengine slave: %d\n", ret); - return ret; + goto err_dma_config; } ret = dmaengine_slave_config(dd->dma_tx, &cfg); if (ret) { dev_err(dd->dev, "can't configure OUT dmaengine slave: %d\n", ret); - return ret; + goto err_dma_config; } return 0; +err_dma_config: + dma_release_channel(dd->dma_tx); err_dma_tx: - dma_release_channel(dd->dma_rx1); dma_release_channel(dd->dma_rx2); +err_dma_rx2: + dma_release_channel(dd->dma_rx1); return ret; } @@ -2353,13 +2356,14 @@ static int sa_ul_probe(struct platform_device *pdev) if (ret < 0) { dev_err(&pdev->dev, "%s: failed to get sync: %d\n", __func__, ret); + pm_runtime_disable(dev); return ret; } sa_init_mem(dev_data); ret = sa_dma_init(dev_data); if (ret) - goto disable_pm_runtime; + goto destroy_dma_pool; spin_lock_init(&dev_data->scid_lock); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -2389,9 +2393,9 @@ release_dma: dma_release_channel(dev_data->dma_rx1); dma_release_channel(dev_data->dma_tx); +destroy_dma_pool: dma_pool_destroy(dev_data->sc_pool); -disable_pm_runtime: pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); diff --git a/drivers/crypto/ux500/hash/hash_core.c b/drivers/crypto/ux500/hash/hash_core.c index 3d407eebb2babc816294e588e5575fac63735d11..1e2daf403032717ff5646ea00eca204a44fb712f 100644 --- a/drivers/crypto/ux500/hash/hash_core.c +++ b/drivers/crypto/ux500/hash/hash_core.c @@ -1009,6 +1009,7 @@ static int hash_hw_final(struct ahash_request *req) goto out; } } else if (req->nbytes == 0 && ctx->keylen > 0) { + ret = -EPERM; dev_err(device_data->dev, "%s: Empty message with keylength > 0, NOT supported\n", __func__); goto out; diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 98f03a02d11221c19c97674f2f86b7ad94003c10..829128c0cc68c4d968b4af63a9ae370564e85809 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -789,6 +789,7 @@ struct devfreq *devfreq_add_device(struct device *dev, if (devfreq->profile->timer < 0 || devfreq->profile->timer >= DEVFREQ_TIMER_NUM) { mutex_unlock(&devfreq->lock); + err = -EINVAL; goto err_dev; } diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index a3fc6aa159b41ea86d79c1732f872d9937d657a1..c76ae8884c802f0db24d58711a610e0c5af6d9db 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -724,6 +724,7 @@ config XILINX_ZYNQMP_DMA config XILINX_ZYNQMP_DPDMA tristate "Xilinx DPDMA Engine" + depends on HAS_IOMEM && OF select DMA_ENGINE select DMA_VIRTUAL_CHANNELS help diff --git a/drivers/dma/mediatek/mtk-uart-apdma.c b/drivers/dma/mediatek/mtk-uart-apdma.c index 27c07350971dd5d636c2c12eeea3ce917b9d54c0..375e7e647df6b5093b156c2cd88e7f7f0e6798d3 100644 --- a/drivers/dma/mediatek/mtk-uart-apdma.c +++ b/drivers/dma/mediatek/mtk-uart-apdma.c @@ -131,10 +131,7 @@ static unsigned int mtk_uart_apdma_read(struct mtk_chan *c, unsigned int reg) static void mtk_uart_apdma_desc_free(struct virt_dma_desc *vd) { - struct dma_chan *chan = vd->tx.chan; - struct mtk_chan *c = to_mtk_uart_apdma_chan(chan); - - kfree(c->desc); + kfree(container_of(vd, struct mtk_uart_apdma_desc, vd)); } static void mtk_uart_apdma_start_tx(struct mtk_chan *c) @@ -207,14 +204,9 @@ static void mtk_uart_apdma_start_rx(struct mtk_chan *c) static void mtk_uart_apdma_tx_handler(struct mtk_chan *c) { - struct mtk_uart_apdma_desc *d = c->desc; - mtk_uart_apdma_write(c, VFF_INT_FLAG, VFF_TX_INT_CLR_B); mtk_uart_apdma_write(c, VFF_INT_EN, VFF_INT_EN_CLR_B); mtk_uart_apdma_write(c, VFF_EN, VFF_EN_CLR_B); - - list_del(&d->vd.node); - vchan_cookie_complete(&d->vd); } static void mtk_uart_apdma_rx_handler(struct mtk_chan *c) @@ -245,9 +237,17 @@ static void mtk_uart_apdma_rx_handler(struct mtk_chan *c) c->rx_status = d->avail_len - cnt; mtk_uart_apdma_write(c, VFF_RPT, wg); +} - list_del(&d->vd.node); - vchan_cookie_complete(&d->vd); +static void mtk_uart_apdma_chan_complete_handler(struct mtk_chan *c) +{ + struct mtk_uart_apdma_desc *d = c->desc; + + if (d) { + list_del(&d->vd.node); + vchan_cookie_complete(&d->vd); + c->desc = NULL; + } } static irqreturn_t mtk_uart_apdma_irq_handler(int irq, void *dev_id) @@ -261,6 +261,7 @@ static irqreturn_t mtk_uart_apdma_irq_handler(int irq, void *dev_id) mtk_uart_apdma_rx_handler(c); else if (c->dir == DMA_MEM_TO_DEV) mtk_uart_apdma_tx_handler(c); + mtk_uart_apdma_chan_complete_handler(c); spin_unlock_irqrestore(&c->vc.lock, flags); return IRQ_HANDLED; @@ -348,7 +349,7 @@ static struct dma_async_tx_descriptor *mtk_uart_apdma_prep_slave_sg return NULL; /* Now allocate and setup the descriptor */ - d = kzalloc(sizeof(*d), GFP_ATOMIC); + d = kzalloc(sizeof(*d), GFP_NOWAIT); if (!d) return NULL; @@ -366,7 +367,7 @@ static void mtk_uart_apdma_issue_pending(struct dma_chan *chan) unsigned long flags; spin_lock_irqsave(&c->vc.lock, flags); - if (vchan_issue_pending(&c->vc)) { + if (vchan_issue_pending(&c->vc) && !c->desc) { vd = vchan_next_desc(&c->vc); c->desc = to_mtk_uart_apdma_desc(&vd->tx); diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c index a57705356e8bb796a3a375540afe5e7e4030777c..991a7b5da29f085625356abf60344f4e8be8fc20 100644 --- a/drivers/dma/sh/rcar-dmac.c +++ b/drivers/dma/sh/rcar-dmac.c @@ -1874,7 +1874,7 @@ static int rcar_dmac_probe(struct platform_device *pdev) /* Enable runtime PM and initialize the device. */ pm_runtime_enable(&pdev->dev); - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "runtime PM get sync failed (%d)\n", ret); return ret; diff --git a/drivers/dma/stm32-mdma.c b/drivers/dma/stm32-mdma.c index 08cfbfab837bb29b697a2eb46ec234e9e6aae811..9d473923712adab957e8dcbc200d496b2c786c37 100644 --- a/drivers/dma/stm32-mdma.c +++ b/drivers/dma/stm32-mdma.c @@ -1448,7 +1448,7 @@ static int stm32_mdma_alloc_chan_resources(struct dma_chan *c) return -ENOMEM; } - ret = pm_runtime_get_sync(dmadev->ddev.dev); + ret = pm_runtime_resume_and_get(dmadev->ddev.dev); if (ret < 0) return ret; @@ -1714,7 +1714,7 @@ static int stm32_mdma_pm_suspend(struct device *dev) u32 ccr, id; int ret; - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index ff7dfb3fdeb475205833b2f768c73b819c27fcbb..6c709803203ad9c251d0523a2729c6662a074ece 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -113,6 +113,7 @@ #define XILINX_DPDMA_CH_VDO 0x020 #define XILINX_DPDMA_CH_PYLD_SZ 0x024 #define XILINX_DPDMA_CH_DESC_ID 0x028 +#define XILINX_DPDMA_CH_DESC_ID_MASK GENMASK(15, 0) /* DPDMA descriptor fields */ #define XILINX_DPDMA_DESC_CONTROL_PREEMBLE 0xa5 @@ -866,7 +867,8 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan) * will be used, but it should be enough. */ list_for_each_entry(sw_desc, &desc->descriptors, node) - sw_desc->hw.desc_id = desc->vdesc.tx.cookie; + sw_desc->hw.desc_id = desc->vdesc.tx.cookie + & XILINX_DPDMA_CH_DESC_ID_MASK; sw_desc = list_first_entry(&desc->descriptors, struct xilinx_dpdma_sw_desc, node); @@ -1086,7 +1088,8 @@ static void xilinx_dpdma_chan_vsync_irq(struct xilinx_dpdma_chan *chan) if (!chan->running || !pending) goto out; - desc_id = dpdma_read(chan->reg, XILINX_DPDMA_CH_DESC_ID); + desc_id = dpdma_read(chan->reg, XILINX_DPDMA_CH_DESC_ID) + & XILINX_DPDMA_CH_DESC_ID_MASK; /* If the retrigger raced with vsync, retry at the next frame. */ sw_desc = list_first_entry(&pending->descriptors, diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index d8419565b92ccda520202cb6a40ddab8e6c4717f..5fecf5aa6e85899b0180ed0db76b2edb3ea88b64 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -468,7 +468,7 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) struct zynqmp_dma_desc_sw *desc; int i, ret; - ret = pm_runtime_get_sync(chan->dev); + ret = pm_runtime_resume_and_get(chan->dev); if (ret < 0) return ret; diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c index 7b52691c45d26c938526b872da376caadfed4be1..4912a7b8838010e6b303cb3ff83b78c8f426587b 100644 --- a/drivers/edac/i10nm_base.c +++ b/drivers/edac/i10nm_base.c @@ -263,6 +263,9 @@ static int __init i10nm_init(void) if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) return -EBUSY; + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) + return -ENODEV; + id = x86_match_cpu(i10nm_cpuids); if (!id) return -ENODEV; diff --git a/drivers/edac/pnd2_edac.c b/drivers/edac/pnd2_edac.c index 928f63a374c78cdc98d89ceefa5e543ce368351a..c94ca1f790c4371ee1fc1821c57a96f958b92a49 100644 --- a/drivers/edac/pnd2_edac.c +++ b/drivers/edac/pnd2_edac.c @@ -1554,6 +1554,9 @@ static int __init pnd2_init(void) if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) return -EBUSY; + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) + return -ENODEV; + id = x86_match_cpu(pnd2_cpuids); if (!id) return -ENODEV; diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index 93daa4297f2e0596d9999613edf54c017491d86f..4c626fcd4dcbb5f43f1aa40749e9d561d8815116 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c @@ -3510,6 +3510,9 @@ static int __init sbridge_init(void) if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) return -EBUSY; + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) + return -ENODEV; + id = x86_match_cpu(sbridge_cpuids); if (!id) return -ENODEV; diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c index 2c7db95df32631edbb10f417e431296d70973c0b..f887e31666510514709166b585329553f752e08d 100644 --- a/drivers/edac/skx_base.c +++ b/drivers/edac/skx_base.c @@ -656,6 +656,9 @@ static int __init skx_init(void) if (owner && strncmp(owner, EDAC_MOD_STR, sizeof(EDAC_MOD_STR))) return -EBUSY; + if (cpu_feature_enabled(X86_FEATURE_HYPERVISOR)) + return -ENODEV; + id = x86_match_cpu(skx_cpuids); if (!id) return -ENODEV; diff --git a/drivers/edac/ti_edac.c b/drivers/edac/ti_edac.c index e7eae20f83d1d03875bb3ef30b3d7eae2c201272..169f96e51c2933722e4cb457b0101f1cf9d197e2 100644 --- a/drivers/edac/ti_edac.c +++ b/drivers/edac/ti_edac.c @@ -197,6 +197,7 @@ static const struct of_device_id ti_edac_of_match[] = { { .compatible = "ti,emif-dra7xx", .data = (void *)EMIF_TYPE_DRA7 }, {}, }; +MODULE_DEVICE_TABLE(of, ti_edac_of_match); static int _emif_get_id(struct device_node *node) { diff --git a/drivers/extcon/extcon-intel-mrfld.c b/drivers/extcon/extcon-intel-mrfld.c index f47016fb28a8457b4301a2ffbfd4107c7fbad21c..cd1a5f230077ca0de266b9b75b2557f10f2bdfc0 100644 --- a/drivers/extcon/extcon-intel-mrfld.c +++ b/drivers/extcon/extcon-intel-mrfld.c @@ -197,6 +197,7 @@ static int mrfld_extcon_probe(struct platform_device *pdev) struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent); struct regmap *regmap = pmic->regmap; struct mrfld_extcon_data *data; + unsigned int status; unsigned int id; int irq, ret; @@ -244,6 +245,14 @@ static int mrfld_extcon_probe(struct platform_device *pdev) /* Get initial state */ mrfld_extcon_role_detect(data); + /* + * Cached status value is used for cable detection, see comments + * in mrfld_extcon_cable_detect(), we need to sync cached value + * with a real state of the hardware. + */ + regmap_read(regmap, BCOVE_SCHGRIRQ1, &status); + data->status = status; + mrfld_extcon_clear(data, BCOVE_MIRQLVL1, BCOVE_LVL1_CHGR); mrfld_extcon_clear(data, BCOVE_MCHGRIRQ1, BCOVE_CHGRIRQ_ALL); diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index 337b0eea4e629ea00dd55e96a75299e663a1a67c..64008808675ef990e17ebd0ef4f76270d58bf835 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c @@ -729,7 +729,7 @@ static int max8997_muic_probe(struct platform_device *pdev) 2, info->status); if (ret) { dev_err(info->dev, "failed to read MUIC register\n"); - return ret; + goto err_irq; } cable_type = max8997_muic_get_cable_type(info, MAX8997_CABLE_GROUP_ADC, &attached); @@ -784,3 +784,4 @@ module_platform_driver(max8997_muic_driver); MODULE_DESCRIPTION("Maxim MAX8997 Extcon driver"); MODULE_AUTHOR("Donggeun Kim <dg77.kim@samsung.com>"); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:max8997-muic"); diff --git a/drivers/extcon/extcon-sm5502.c b/drivers/extcon/extcon-sm5502.c index 106d4da647bd9097d93ce05f6381402274be6ebb..5e0718dee03bc1b63225a0f2a2a25952c7a0c450 100644 --- a/drivers/extcon/extcon-sm5502.c +++ b/drivers/extcon/extcon-sm5502.c @@ -88,7 +88,6 @@ static struct reg_data sm5502_reg_data[] = { | SM5502_REG_INTM2_MHL_MASK, .invert = true, }, - { } }; /* List of detectable cables */ diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c index 3e748e57deab3d862386771895ba121534d64fc0..02352e9e0f1c3b6a95db9b4fcc8d6297a3a90fa0 100644 --- a/drivers/firmware/arm_scmi/driver.c +++ b/drivers/firmware/arm_scmi/driver.c @@ -268,6 +268,10 @@ static void scmi_handle_response(struct scmi_chan_info *cinfo, return; } + /* rx.len could be shrunk in the sync do_xfer, so reset to maxsz */ + if (msg_type == MSG_TYPE_DELAYED_RESP) + xfer->rx.len = info->desc->max_msg_size; + scmi_dump_header_dbg(dev, &xfer->hdr); info->desc->ops->fetch_response(cinfo, xfer); diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 0078260fbabeaf3e1f4969cb70accbceb0255744..172c751a4f6c24acc1e5e8cb04b594b1843a5b86 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -299,15 +299,13 @@ static int fw_cfg_do_platform_probe(struct platform_device *pdev) return 0; } -static ssize_t fw_cfg_showrev(struct kobject *k, struct attribute *a, char *buf) +static ssize_t fw_cfg_showrev(struct kobject *k, struct kobj_attribute *a, + char *buf) { return sprintf(buf, "%u\n", fw_cfg_rev); } -static const struct { - struct attribute attr; - ssize_t (*show)(struct kobject *k, struct attribute *a, char *buf); -} fw_cfg_rev_attr = { +static const struct kobj_attribute fw_cfg_rev_attr = { .attr = { .name = "rev", .mode = S_IRUSR }, .show = fw_cfg_showrev, }; diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c index 3aa489dba30a741501fd459be1070ed9ff30b332..2a7687911c097c964bed2444d45262441f2872e3 100644 --- a/drivers/firmware/stratix10-svc.c +++ b/drivers/firmware/stratix10-svc.c @@ -1034,24 +1034,32 @@ static int stratix10_svc_drv_probe(struct platform_device *pdev) /* add svc client device(s) */ svc = devm_kzalloc(dev, sizeof(*svc), GFP_KERNEL); - if (!svc) - return -ENOMEM; + if (!svc) { + ret = -ENOMEM; + goto err_free_kfifo; + } svc->stratix10_svc_rsu = platform_device_alloc(STRATIX10_RSU, 0); if (!svc->stratix10_svc_rsu) { dev_err(dev, "failed to allocate %s device\n", STRATIX10_RSU); - return -ENOMEM; + ret = -ENOMEM; + goto err_free_kfifo; } ret = platform_device_add(svc->stratix10_svc_rsu); - if (ret) { - platform_device_put(svc->stratix10_svc_rsu); - return ret; - } + if (ret) + goto err_put_device; + dev_set_drvdata(dev, svc); pr_info("Intel Service Layer Driver Initialized\n"); + return 0; + +err_put_device: + platform_device_put(svc->stratix10_svc_rsu); +err_free_kfifo: + kfifo_free(&controller->svc_fifo); return ret; } diff --git a/drivers/firmware/tegra/bpmp-tegra210.c b/drivers/firmware/tegra/bpmp-tegra210.c index ae15940a078e3e5076121e17480472b06b13dd65..c32754055c60bf44e89a5d8d8b4fe2931db47ceb 100644 --- a/drivers/firmware/tegra/bpmp-tegra210.c +++ b/drivers/firmware/tegra/bpmp-tegra210.c @@ -210,7 +210,7 @@ static int tegra210_bpmp_init(struct tegra_bpmp *bpmp) priv->tx_irq_data = irq_get_irq_data(err); if (!priv->tx_irq_data) { dev_err(&pdev->dev, "failed to get IRQ data for TX IRQ\n"); - return err; + return -ENOENT; } err = platform_get_irq_byname(pdev, "rx"); diff --git a/drivers/firmware/turris-mox-rwtm.c b/drivers/firmware/turris-mox-rwtm.c index 50bb2a6d6ccf79a7986da30f56c1604804230d92..03f1eac9ad69b32f3692247ae149666ebf96967a 100644 --- a/drivers/firmware/turris-mox-rwtm.c +++ b/drivers/firmware/turris-mox-rwtm.c @@ -147,11 +147,14 @@ MOX_ATTR_RO(pubkey, "%s\n", pubkey); static int mox_get_status(enum mbox_cmd cmd, u32 retval) { - if (MBOX_STS_CMD(retval) != cmd || - MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS) + if (MBOX_STS_CMD(retval) != cmd) return -EIO; else if (MBOX_STS_ERROR(retval) == MBOX_STS_FAIL) return -(int)MBOX_STS_VALUE(retval); + else if (MBOX_STS_ERROR(retval) == MBOX_STS_BADCMD) + return -ENOSYS; + else if (MBOX_STS_ERROR(retval) != MBOX_STS_SUCCESS) + return -EIO; else return MBOX_STS_VALUE(retval); } @@ -201,11 +204,14 @@ static int mox_get_board_info(struct mox_rwtm *rwtm) return ret; ret = mox_get_status(MBOX_CMD_BOARD_INFO, reply->retval); - if (ret < 0 && ret != -ENODATA) { - return ret; - } else if (ret == -ENODATA) { + if (ret == -ENODATA) { dev_warn(rwtm->dev, "Board does not have manufacturing information burned!\n"); + } else if (ret == -ENOSYS) { + dev_notice(rwtm->dev, + "Firmware does not support the BOARD_INFO command\n"); + } else if (ret < 0) { + return ret; } else { rwtm->serial_number = reply->status[1]; rwtm->serial_number <<= 32; @@ -234,10 +240,13 @@ static int mox_get_board_info(struct mox_rwtm *rwtm) return ret; ret = mox_get_status(MBOX_CMD_ECDSA_PUB_KEY, reply->retval); - if (ret < 0 && ret != -ENODATA) { - return ret; - } else if (ret == -ENODATA) { + if (ret == -ENODATA) { dev_warn(rwtm->dev, "Board has no public key burned!\n"); + } else if (ret == -ENOSYS) { + dev_notice(rwtm->dev, + "Firmware does not support the ECDSA_PUB_KEY command\n"); + } else if (ret < 0) { + return ret; } else { u32 *s = reply->status; @@ -251,6 +260,27 @@ static int mox_get_board_info(struct mox_rwtm *rwtm) return 0; } +static int check_get_random_support(struct mox_rwtm *rwtm) +{ + struct armada_37xx_rwtm_tx_msg msg; + int ret; + + msg.command = MBOX_CMD_GET_RANDOM; + msg.args[0] = 1; + msg.args[1] = rwtm->buf_phys; + msg.args[2] = 4; + + ret = mbox_send_message(rwtm->mbox, &msg); + if (ret < 0) + return ret; + + ret = wait_for_completion_timeout(&rwtm->cmd_done, HZ / 2); + if (ret < 0) + return ret; + + return mox_get_status(MBOX_CMD_GET_RANDOM, rwtm->reply.retval); +} + static int mox_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) { struct mox_rwtm *rwtm = (struct mox_rwtm *) rng->priv; @@ -488,6 +518,13 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev) if (ret < 0) dev_warn(dev, "Cannot read board information: %i\n", ret); + ret = check_get_random_support(rwtm); + if (ret < 0) { + dev_notice(dev, + "Firmware does not support the GET_RANDOM command\n"); + goto free_channel; + } + rwtm->hwrng.name = DRIVER_NAME "_hwrng"; rwtm->hwrng.read = mox_hwrng_read; rwtm->hwrng.priv = (unsigned long) rwtm; @@ -505,6 +542,8 @@ static int turris_mox_rwtm_probe(struct platform_device *pdev) goto free_channel; } + dev_info(dev, "HWRNG successfully registered\n"); + return 0; free_channel: diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c index 657a70c5fc996980abe7591ece16755f54be5ea0..9e34bbbce26e2afbf66eda52743888fb299269c7 100644 --- a/drivers/fpga/stratix10-soc.c +++ b/drivers/fpga/stratix10-soc.c @@ -454,6 +454,7 @@ static int s10_remove(struct platform_device *pdev) struct s10_priv *priv = mgr->priv; fpga_mgr_unregister(mgr); + fpga_mgr_free(mgr); stratix10_svc_free_channel(priv->chan); return 0; diff --git a/drivers/fsi/fsi-core.c b/drivers/fsi/fsi-core.c index 4e60e84cd17a553c5dca6c3aee930501c0108c5e..59ddc9fd5bca47cdf6f997c3ac72e08a7d215e6e 100644 --- a/drivers/fsi/fsi-core.c +++ b/drivers/fsi/fsi-core.c @@ -724,7 +724,7 @@ static ssize_t cfam_read(struct file *filep, char __user *buf, size_t count, rc = count; fail: *offset = off; - return count; + return rc; } static ssize_t cfam_write(struct file *filep, const char __user *buf, @@ -761,7 +761,7 @@ static ssize_t cfam_write(struct file *filep, const char __user *buf, rc = count; fail: *offset = off; - return count; + return rc; } static loff_t cfam_llseek(struct file *file, loff_t offset, int whence) diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c index 90dbe58ca1edca5c204732b616412a802309d884..dbad73162c8333bf5161b688d9a53a4eb4ae71b4 100644 --- a/drivers/fsi/fsi-master-aspeed.c +++ b/drivers/fsi/fsi-master-aspeed.c @@ -645,6 +645,7 @@ static const struct of_device_id fsi_master_aspeed_match[] = { { .compatible = "aspeed,ast2600-fsi-master" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_aspeed_match); static struct platform_driver fsi_master_aspeed_driver = { .driver = { diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c index 57a779a89b07339f2d7dd56695389a85827eb161..70c03e304d6c880ca68e549e22e552d676fa3974 100644 --- a/drivers/fsi/fsi-master-ast-cf.c +++ b/drivers/fsi/fsi-master-ast-cf.c @@ -1427,6 +1427,7 @@ static const struct of_device_id fsi_master_acf_match[] = { { .compatible = "aspeed,ast2500-cf-fsi-master" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_acf_match); static struct platform_driver fsi_master_acf = { .driver = { diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c index aa97c4a250cb41663e6fcca42d2c8b299bab5409..7d5f29b4b595d24ae48cd9dd0d0f69bc2209de2d 100644 --- a/drivers/fsi/fsi-master-gpio.c +++ b/drivers/fsi/fsi-master-gpio.c @@ -882,6 +882,7 @@ static const struct of_device_id fsi_master_gpio_match[] = { { .compatible = "fsi-master-gpio" }, { }, }; +MODULE_DEVICE_TABLE(of, fsi_master_gpio_match); static struct platform_driver fsi_master_gpio_driver = { .driver = { diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c index 9eeb856c8905e49c74f07e7212a4804a0eaf019a..a9beef2ae5a09f0d23bbdd8df8233f23de7f1009 100644 --- a/drivers/fsi/fsi-occ.c +++ b/drivers/fsi/fsi-occ.c @@ -445,6 +445,7 @@ int fsi_occ_submit(struct device *dev, const void *request, size_t req_len, goto done; if (resp->return_status == OCC_RESP_CMD_IN_PRG || + resp->return_status == OCC_RESP_CRIT_INIT || resp->seq_no != seq_no) { rc = -ETIMEDOUT; @@ -578,6 +579,7 @@ static const struct of_device_id occ_match[] = { { .compatible = "ibm,p9-occ" }, { }, }; +MODULE_DEVICE_TABLE(of, occ_match); static struct platform_driver occ_driver = { .driver = { diff --git a/drivers/fsi/fsi-sbefifo.c b/drivers/fsi/fsi-sbefifo.c index bfd5e5da80209dc0f98b880aaf21df8d22103545..84cb965bfed5c92061ee825d1cd9acf89ccfad0c 100644 --- a/drivers/fsi/fsi-sbefifo.c +++ b/drivers/fsi/fsi-sbefifo.c @@ -325,7 +325,8 @@ static int sbefifo_up_write(struct sbefifo *sbefifo, __be32 word) static int sbefifo_request_reset(struct sbefifo *sbefifo) { struct device *dev = &sbefifo->fsi_dev->dev; - u32 status, timeout; + unsigned long end_time; + u32 status; int rc; dev_dbg(dev, "Requesting FIFO reset\n"); @@ -341,7 +342,8 @@ static int sbefifo_request_reset(struct sbefifo *sbefifo) } /* Wait for it to complete */ - for (timeout = 0; timeout < SBEFIFO_RESET_TIMEOUT; timeout++) { + end_time = jiffies + msecs_to_jiffies(SBEFIFO_RESET_TIMEOUT); + while (!time_after(jiffies, end_time)) { rc = sbefifo_regr(sbefifo, SBEFIFO_UP | SBEFIFO_STS, &status); if (rc) { dev_err(dev, "Failed to read UP fifo status during reset" @@ -355,7 +357,7 @@ static int sbefifo_request_reset(struct sbefifo *sbefifo) return 0; } - msleep(1); + cond_resched(); } dev_err(dev, "FIFO reset timed out\n"); @@ -400,7 +402,7 @@ static int sbefifo_cleanup_hw(struct sbefifo *sbefifo) /* The FIFO already contains a reset request from the SBE ? */ if (down_status & SBEFIFO_STS_RESET_REQ) { dev_info(dev, "Cleanup: FIFO reset request set, resetting\n"); - rc = sbefifo_regw(sbefifo, SBEFIFO_UP, SBEFIFO_PERFORM_RESET); + rc = sbefifo_regw(sbefifo, SBEFIFO_DOWN, SBEFIFO_PERFORM_RESET); if (rc) { sbefifo->broken = true; dev_err(dev, "Cleanup: Reset reg write failed, rc=%d\n", rc); diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c index b45bfab7b7f55a60c82311739678c12404df8808..75d1389e2626da1418cee72da488963645e3d35e 100644 --- a/drivers/fsi/fsi-scom.c +++ b/drivers/fsi/fsi-scom.c @@ -38,9 +38,10 @@ #define SCOM_STATUS_PIB_RESP_MASK 0x00007000 #define SCOM_STATUS_PIB_RESP_SHIFT 12 -#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_PROTECTION | \ - SCOM_STATUS_PARITY | \ - SCOM_STATUS_PIB_ABORT | \ +#define SCOM_STATUS_FSI2PIB_ERROR (SCOM_STATUS_PROTECTION | \ + SCOM_STATUS_PARITY | \ + SCOM_STATUS_PIB_ABORT) +#define SCOM_STATUS_ANY_ERR (SCOM_STATUS_FSI2PIB_ERROR | \ SCOM_STATUS_PIB_RESP_MASK) /* SCOM address encodings */ #define XSCOM_ADDR_IND_FLAG BIT_ULL(63) @@ -240,13 +241,14 @@ static int handle_fsi2pib_status(struct scom_device *scom, uint32_t status) { uint32_t dummy = -1; - if (status & SCOM_STATUS_PROTECTION) - return -EPERM; - if (status & SCOM_STATUS_PARITY) { + if (status & SCOM_STATUS_FSI2PIB_ERROR) fsi_device_write(scom->fsi_dev, SCOM_FSI2PIB_RESET_REG, &dummy, sizeof(uint32_t)); + + if (status & SCOM_STATUS_PROTECTION) + return -EPERM; + if (status & SCOM_STATUS_PARITY) return -EIO; - } /* Return -EBUSY on PIB abort to force a retry */ if (status & SCOM_STATUS_PIB_ABORT) return -EBUSY; diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index e006f76103f5afee0fc6d26c1aac8a10ba5807a7..374539e6e12a33a2417e9b54c58b3e60524f5a6e 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -1356,6 +1356,7 @@ config GPIO_TPS68470 config GPIO_TQMX86 tristate "TQ-Systems QTMX86 GPIO" depends on MFD_TQMX86 || COMPILE_TEST + depends on HAS_IOPORT_MAP select GPIOLIB_IRQCHIP help This driver supports GPIO on the TQMX86 IO controller. @@ -1423,6 +1424,7 @@ menu "PCI GPIO expanders" config GPIO_AMD8111 tristate "AMD 8111 GPIO driver" depends on X86 || COMPILE_TEST + depends on HAS_IOPORT_MAP help The AMD 8111 south bridge contains 32 GPIO pins which can be used. diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 1dfe513f8fcf4994ce76aafe5edac2b98edcd963..cd167ce3bb9b094d42a8d7199b18128df9fa27cd 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -513,7 +513,7 @@ static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base, ct->chip.irq_set_wake = gpio_set_wake_irq; ct->chip.irq_request_resources = mxc_gpio_irq_reqres; ct->chip.irq_release_resources = mxc_gpio_irq_relres, - ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND; + ct->chip.flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_ENABLE_WAKEUP_ON_SUSPEND; ct->regs.ack = GPIO_ISR; ct->regs.mask = GPIO_IMR; diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c index a172657b2615b8f2c5e0cd647c1e42e0c10634c9..4902ef4dd39834a3485f5aa727bfda77b4914bb7 100644 --- a/drivers/gpio/gpio-pca953x.c +++ b/drivers/gpio/gpio-pca953x.c @@ -1258,6 +1258,7 @@ static const struct of_device_id pca953x_dt_ids[] = { { .compatible = "onnn,cat9554", .data = OF_953X( 8, PCA_INT), }, { .compatible = "onnn,pca9654", .data = OF_953X( 8, PCA_INT), }, + { .compatible = "onnn,pca9655", .data = OF_953X(16, PCA_INT), }, { .compatible = "exar,xra1202", .data = OF_953X( 8, 0), }, { } diff --git a/drivers/gpio/gpio-zynq.c b/drivers/gpio/gpio-zynq.c index 3521c1dc3ac00bef2408796a8f45bd5e646bf680..c288a7502de25313afaa984731233a6b5c501b9c 100644 --- a/drivers/gpio/gpio-zynq.c +++ b/drivers/gpio/gpio-zynq.c @@ -736,6 +736,11 @@ static int __maybe_unused zynq_gpio_suspend(struct device *dev) struct zynq_gpio *gpio = dev_get_drvdata(dev); struct irq_data *data = irq_get_irq_data(gpio->irq); + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) disable_irq(gpio->irq); @@ -753,6 +758,11 @@ static int __maybe_unused zynq_gpio_resume(struct device *dev) struct irq_data *data = irq_get_irq_data(gpio->irq); int ret; + if (!data) { + dev_err(dev, "irq_get_irq_data() failed\n"); + return -EINVAL; + } + if (!device_may_wakeup(dev)) enable_irq(gpio->irq); @@ -1001,8 +1011,11 @@ err_pm_dis: static int zynq_gpio_remove(struct platform_device *pdev) { struct zynq_gpio *gpio = platform_get_drvdata(pdev); + int ret; - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) + dev_warn(&pdev->dev, "pm_runtime_get_sync() Failed\n"); gpiochip_remove(&gpio->chip); clk_disable_unprepare(gpio->clk); device_set_wakeup_capable(&pdev->dev, 0); diff --git a/drivers/gpio/gpiolib-cdev.c b/drivers/gpio/gpiolib-cdev.c index ade3ecf2ee49522453bab67391c2b8997b91852b..2613881a66e662beccd0b8b51f98133ea52114ca 100644 --- a/drivers/gpio/gpiolib-cdev.c +++ b/drivers/gpio/gpiolib-cdev.c @@ -1865,6 +1865,7 @@ static void gpio_v2_line_info_changed_to_v1( struct gpio_v2_line_info_changed *lic_v2, struct gpioline_info_changed *lic_v1) { + memset(lic_v1, 0, sizeof(*lic_v1)); gpio_v2_line_info_to_v1(&lic_v2->info, &lic_v1->info); lic_v1->timestamp = lic_v2->timestamp_ns; lic_v1->event_type = lic_v2->event_type; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 5da487b64a668a4590d85bd2123cd523c0ced8bd..26f8a21383774337ca09128072cc05ec170de53f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -48,12 +48,6 @@ static struct { spinlock_t mem_limit_lock; } kfd_mem_limit; -/* Struct used for amdgpu_amdkfd_bo_validate */ -struct amdgpu_vm_parser { - uint32_t domain; - bool wait; -}; - static const char * const domain_bit_to_string[] = { "CPU", "GTT", @@ -337,11 +331,9 @@ validate_fail: return ret; } -static int amdgpu_amdkfd_validate(void *param, struct amdgpu_bo *bo) +static int amdgpu_amdkfd_validate_vm_bo(void *_unused, struct amdgpu_bo *bo) { - struct amdgpu_vm_parser *p = param; - - return amdgpu_amdkfd_bo_validate(bo, p->domain, p->wait); + return amdgpu_amdkfd_bo_validate(bo, bo->allowed_domains, false); } /* vm_validate_pt_pd_bos - Validate page table and directory BOs @@ -355,20 +347,15 @@ static int vm_validate_pt_pd_bos(struct amdgpu_vm *vm) { struct amdgpu_bo *pd = vm->root.base.bo; struct amdgpu_device *adev = amdgpu_ttm_adev(pd->tbo.bdev); - struct amdgpu_vm_parser param; int ret; - param.domain = AMDGPU_GEM_DOMAIN_VRAM; - param.wait = false; - - ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate, - ¶m); + ret = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_amdkfd_validate_vm_bo, NULL); if (ret) { pr_err("failed to validate PT BOs\n"); return ret; } - ret = amdgpu_amdkfd_validate(¶m, pd); + ret = amdgpu_amdkfd_validate_vm_bo(NULL, pd); if (ret) { pr_err("failed to validate PD\n"); return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 87c7c45f1bb73454abac4e97eb916c5b43f5fcdd..6948ab3c0d998dbe1a59c8f07b4abf7094214aa7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2760,7 +2760,7 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev) AMD_IP_BLOCK_TYPE_IH, }; - for (i = 0; i < ARRAY_SIZE(ip_order); i++) { + for (i = 0; i < adev->num_ip_blocks; i++) { int j; struct amdgpu_ip_block *block; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 1b56dbc1f304e626c697a18f4a33cc6a6769944b..e93ccdc5faf4ec12ca8e14db07bec0f036ef0c88 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -238,9 +238,21 @@ static int amdgpu_dma_buf_pin(struct dma_buf_attachment *attach) { struct drm_gem_object *obj = attach->dmabuf->priv; struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); + int r; /* pin buffer into GTT */ - return amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT); + r = amdgpu_bo_pin(bo, AMDGPU_GEM_DOMAIN_GTT); + if (r) + return r; + + if (bo->tbo.moving) { + r = dma_fence_wait(bo->tbo.moving, true); + if (r) { + amdgpu_bo_unpin(bo); + return r; + } + } + return 0; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c index 28f20f0b722f54f3e03d045cc1a0899fe73d02e6..163188ce02bd45dbba9579c68048d5f69d112b90 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c @@ -128,7 +128,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, struct amdgpu_device *adev = ring->adev; struct amdgpu_ib *ib = &ibs[0]; struct dma_fence *tmp = NULL; - bool skip_preamble, need_ctx_switch; + bool need_ctx_switch; unsigned patch_offset = ~0; struct amdgpu_vm *vm; uint64_t fence_ctx; @@ -221,7 +221,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, if (need_ctx_switch) status |= AMDGPU_HAVE_CTX_SWITCH; - skip_preamble = ring->current_ctx == fence_ctx; if (job && ring->funcs->emit_cntxcntl) { status |= job->preamble_status; status |= job->preemption_status; @@ -239,14 +238,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs, for (i = 0; i < num_ibs; ++i) { ib = &ibs[i]; - /* drop preamble IBs if we don't have a context switch */ - if ((ib->flags & AMDGPU_IB_FLAG_PREAMBLE) && - skip_preamble && - !(status & AMDGPU_PREAMBLE_IB_PRESENT_FIRST) && - !amdgpu_mcbp && - !amdgpu_sriov_vf(adev)) /* for SRIOV preemption, Preamble CE ib must be inserted anyway */ - continue; - if (job && ring->funcs->emit_frame_cntl) { if (secure != !!(ib->flags & AMDGPU_IB_FLAGS_SECURE)) { amdgpu_ring_emit_frame_cntl(ring, false, secure); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h index 18381449365800c70ca8e5855c85af2da94f8454..bda4438c39256c00ce6de749471462af7f1db7fc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_umc.h @@ -21,6 +21,11 @@ #ifndef __AMDGPU_UMC_H__ #define __AMDGPU_UMC_H__ +/* + * (addr / 256) * 4096, the higher 26 bits in ErrorAddr + * is the index of 4KB block + */ +#define ADDR_OF_4KB_BLOCK(addr) (((addr) & ~0xffULL) << 4) /* * (addr / 256) * 8192, the higher 26 bits in ErrorAddr * is the index of 8KB block diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 3c92dacbc24ad88d915314286e4206d9bde680f9..fc8da5fed779b5841d5d3fd930e3f9bf5a2e41b7 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -6590,12 +6590,8 @@ static int gfx_v10_0_kiq_init_register(struct amdgpu_ring *ring) if (ring->use_doorbell) { WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (adev->doorbell_index.kiq * 2) << 2); - /* If GC has entered CGPG, ringing doorbell > first page doesn't - * wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround - * this issue. - */ WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, - (adev->doorbell.size - 4)); + (adev->doorbell_index.userqueue_end * 2) << 2); } WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 1859d293ef712e70bd529cfd941e457c2e5b9cc8..fb15e8b5af32fc0a39b4afb70760706e94796adf 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -3619,12 +3619,8 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring) if (ring->use_doorbell) { WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER, (adev->doorbell_index.kiq * 2) << 2); - /* If GC has entered CGPG, ringing doorbell > first page doesn't - * wakeup GC. Enlarge CP_MEC_DOORBELL_RANGE_UPPER to workaround - * this issue. - */ WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER, - (adev->doorbell.size - 4)); + (adev->doorbell_index.userqueue_end * 2) << 2); } WREG32_SOC15_RLC(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index e82f49f62f6e6d81525197cb817323c0d960cd03..1f2e2460e121ee134a72d423baeea06184474750 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -143,7 +143,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_1[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_IB_CNTL, 0x800f0111, 0x00000100), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000) }; @@ -269,7 +269,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4_3[] = { SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_POWER_CNTL, 0x003fff07, 0x40000051), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC0_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0xfffffff7, 0x00403000), - SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0), + SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003e0), SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x03fbe1fe) }; diff --git a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c index 5665c77a9d5874a1c0bda1d1ee2123813d7708bf..afbbe9f05d5ea7ca6dc1f0d2ee05dd0a0c00612e 100644 --- a/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c +++ b/drivers/gpu/drm/amd/amdgpu/umc_v8_7.c @@ -233,7 +233,7 @@ static void umc_v8_7_query_error_address(struct amdgpu_device *adev, err_addr &= ~((0x1ULL << lsb) - 1); /* translate umc channel address to soc pa, 3 parts are included */ - retired_page = ADDR_OF_8KB_BLOCK(err_addr) | + retired_page = ADDR_OF_4KB_BLOCK(err_addr) | ADDR_OF_256B_BLOCK(channel_index) | OFFSET_IN_256B_BLOCK(err_addr); 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 6ea8a4b6efde3debc000d2b917ccbd7c8124d0f2..352a32dc609b2026a039caef5a4e40688f9291fb 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -486,9 +486,6 @@ static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, if (retval == -ETIME) qpd->reset_wavefronts = true; - - mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); - list_del(&q->list); if (list_empty(&qpd->queues_list)) { if (qpd->reset_wavefronts) { @@ -523,6 +520,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, int retval; uint64_t sdma_val = 0; struct kfd_process_device *pdd = qpd_to_pdd(qpd); + struct mqd_manager *mqd_mgr = + dqm->mqd_mgrs[get_mqd_type_from_queue_type(q->properties.type)]; /* Get the SDMA queue stats */ if ((q->properties.type == KFD_QUEUE_TYPE_SDMA) || @@ -540,6 +539,8 @@ static int destroy_queue_nocpsch(struct device_queue_manager *dqm, pdd->sdma_past_activity_counter += sdma_val; dqm_unlock(dqm); + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + return retval; } @@ -1632,7 +1633,7 @@ static int set_trap_handler(struct device_queue_manager *dqm, static int process_termination_nocpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { - struct queue *q, *next; + struct queue *q; struct device_process_node *cur, *next_dpn; int retval = 0; bool found = false; @@ -1640,12 +1641,19 @@ static int process_termination_nocpsch(struct device_queue_manager *dqm, dqm_lock(dqm); /* Clear all user mode queues */ - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + while (!list_empty(&qpd->queues_list)) { + struct mqd_manager *mqd_mgr; int ret; + q = list_first_entry(&qpd->queues_list, struct queue, list); + mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( + q->properties.type)]; ret = destroy_queue_nocpsch_locked(dqm, qpd, q); if (ret) retval = ret; + dqm_unlock(dqm); + mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + dqm_lock(dqm); } /* Unregister process */ @@ -1677,36 +1685,34 @@ static int get_wave_state(struct device_queue_manager *dqm, u32 *save_area_used_size) { struct mqd_manager *mqd_mgr; - int r; dqm_lock(dqm); - if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || - q->properties.is_active || !q->device->cwsr_enabled) { - r = -EINVAL; - goto dqm_unlock; - } - mqd_mgr = dqm->mqd_mgrs[KFD_MQD_TYPE_CP]; - if (!mqd_mgr->get_wave_state) { - r = -EINVAL; - goto dqm_unlock; + if (q->properties.type != KFD_QUEUE_TYPE_COMPUTE || + q->properties.is_active || !q->device->cwsr_enabled || + !mqd_mgr->get_wave_state) { + dqm_unlock(dqm); + return -EINVAL; } - r = mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, - ctl_stack_used_size, save_area_used_size); - -dqm_unlock: dqm_unlock(dqm); - return r; + + /* + * get_wave_state is outside the dqm lock to prevent circular locking + * and the queue should be protected against destruction by the process + * lock. + */ + return mqd_mgr->get_wave_state(mqd_mgr, q->mqd, ctl_stack, + ctl_stack_used_size, save_area_used_size); } static int process_termination_cpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { int retval; - struct queue *q, *next; + struct queue *q; struct kernel_queue *kq, *kq_next; struct mqd_manager *mqd_mgr; struct device_process_node *cur, *next_dpn; @@ -1763,24 +1769,26 @@ static int process_termination_cpsch(struct device_queue_manager *dqm, qpd->reset_wavefronts = false; } - dqm_unlock(dqm); - - /* Outside the DQM lock because under the DQM lock we can't do - * reclaim or take other locks that others hold while reclaiming. - */ - if (found) - kfd_dec_compute_active(dqm->dev); - /* Lastly, free mqd resources. * Do free_mqd() after dqm_unlock to avoid circular locking. */ - list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + while (!list_empty(&qpd->queues_list)) { + q = list_first_entry(&qpd->queues_list, struct queue, list); mqd_mgr = dqm->mqd_mgrs[get_mqd_type_from_queue_type( q->properties.type)]; list_del(&q->list); qpd->queue_count--; + dqm_unlock(dqm); mqd_mgr->free_mqd(mqd_mgr, q->mqd, q->mqd_mem_obj); + dqm_lock(dqm); } + dqm_unlock(dqm); + + /* Outside the DQM lock because under the DQM lock we can't do + * reclaim or take other locks that others hold while reclaiming. + */ + if (found) + kfd_dec_compute_active(dqm->dev); return retval; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 65803e153a223d1536522042503c45dd5251ee8b..d243e60c6eef779c216d8b591f3535c442952829 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -452,13 +452,9 @@ static const struct sysfs_ops procfs_stats_ops = { .show = kfd_procfs_stats_show, }; -static struct attribute *procfs_stats_attrs[] = { - NULL -}; - static struct kobj_type procfs_stats_type = { .sysfs_ops = &procfs_stats_ops, - .default_attrs = procfs_stats_attrs, + .release = kfd_procfs_kobj_release, }; int kfd_procfs_add_queue(struct queue *q) @@ -973,9 +969,11 @@ static void kfd_process_wq_release(struct work_struct *work) list_for_each_entry(pdd, &p->per_device_data, per_device_list) { sysfs_remove_file(p->kobj, &pdd->attr_vram); sysfs_remove_file(p->kobj, &pdd->attr_sdma); - sysfs_remove_file(p->kobj, &pdd->attr_evict); - if (pdd->dev->kfd2kgd->get_cu_occupancy != NULL) - sysfs_remove_file(p->kobj, &pdd->attr_cu_occupancy); + + sysfs_remove_file(pdd->kobj_stats, &pdd->attr_evict); + if (pdd->dev->kfd2kgd->get_cu_occupancy) + sysfs_remove_file(pdd->kobj_stats, + &pdd->attr_cu_occupancy); kobject_del(pdd->kobj_stats); kobject_put(pdd->kobj_stats); pdd->kobj_stats = NULL; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index eb1635ac89887c18534e1ce1e969469386fcbf45..43c07ac2c6fce4056b1328c1f0dc9574190b8d14 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -153,6 +153,7 @@ void pqm_uninit(struct process_queue_manager *pqm) if (pqn->q && pqn->q->gws) amdgpu_amdkfd_remove_gws_from_process(pqm->process->kgd_process_info, pqn->q->gws); + kfd_procfs_del_queue(pqn->q); uninit_queue(pqn->q); list_del(&pqn->process_queue_list); kfree(pqn); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index df26c07cb9120aa49589578f79bcf564495edd4a..6eb308670f48772990b5564896f343872cf20ec9 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -3685,6 +3685,23 @@ static int fill_dc_scaling_info(const struct drm_plane_state *state, scaling_info->src_rect.x = state->src_x >> 16; scaling_info->src_rect.y = state->src_y >> 16; + /* + * For reasons we don't (yet) fully understand a non-zero + * src_y coordinate into an NV12 buffer can cause a + * system hang. To avoid hangs (and maybe be overly cautious) + * let's reject both non-zero src_x and src_y. + * + * We currently know of only one use-case to reproduce a + * scenario with non-zero src_x and src_y for NV12, which + * is to gesture the YouTube Android app into full screen + * on ChromeOS. + */ + if (state->fb && + state->fb->format->format == DRM_FORMAT_NV12 && + (scaling_info->src_rect.x != 0 || + scaling_info->src_rect.y != 0)) + return -EINVAL; + /* * For reasons we don't (yet) fully understand a non-zero * src_y coordinate into an NV12 buffer can cause a @@ -8291,7 +8308,8 @@ skip_modeset: BUG_ON(dm_new_crtc_state->stream == NULL); /* Scaling or underscan settings */ - if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state)) + if (is_scaling_state_different(dm_old_conn_state, dm_new_conn_state) || + drm_atomic_crtc_needs_modeset(new_crtc_state)) update_stream_scaling_settings( &new_crtc_state->mode, dm_new_conn_state, dm_new_crtc_state->stream); @@ -8744,6 +8762,10 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev, old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled) continue; + ret = amdgpu_dm_verify_lut_sizes(new_crtc_state); + if (ret) + goto fail; + if (!new_crtc_state->enable) continue; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index 1df7f1b180496bb7a776834b49d98e7a47c8a332..6c7235bb2f41b8177bdfab838e939ce92860d204 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -498,6 +498,7 @@ void amdgpu_dm_trigger_timing_sync(struct drm_device *dev); #define MAX_COLOR_LEGACY_LUT_ENTRIES 256 void amdgpu_dm_init_color_mod(void); +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state); int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc); int amdgpu_dm_update_plane_color_mgmt(struct dm_crtc_state *crtc, struct dc_plane_state *dc_plane_state); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c index 5df05f0d18bc9cca6b81e08c29cc46378441bf5c..179ff4b42f20089ac9f5bad990e5f0f61a91bba8 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_color.c @@ -284,6 +284,37 @@ static int __set_input_tf(struct dc_transfer_func *func, return res ? 0 : -ENOMEM; } +/** + * Verifies that the Degamma and Gamma LUTs attached to the |crtc_state| are of + * the expected size. + * Returns 0 on success. + */ +int amdgpu_dm_verify_lut_sizes(const struct drm_crtc_state *crtc_state) +{ + const struct drm_color_lut *lut = NULL; + uint32_t size = 0; + + lut = __extract_blob_lut(crtc_state->degamma_lut, &size); + if (lut && size != MAX_COLOR_LUT_ENTRIES) { + DRM_DEBUG_DRIVER( + "Invalid Degamma LUT size. Should be %u but got %u.\n", + MAX_COLOR_LUT_ENTRIES, size); + return -EINVAL; + } + + lut = __extract_blob_lut(crtc_state->gamma_lut, &size); + if (lut && size != MAX_COLOR_LUT_ENTRIES && + size != MAX_COLOR_LEGACY_LUT_ENTRIES) { + DRM_DEBUG_DRIVER( + "Invalid Gamma LUT size. Should be %u (or %u for legacy) but got %u.\n", + MAX_COLOR_LUT_ENTRIES, MAX_COLOR_LEGACY_LUT_ENTRIES, + size); + return -EINVAL; + } + + return 0; +} + /** * amdgpu_dm_update_crtc_color_mgmt: Maps DRM color management to DC stream. * @crtc: amdgpu_dm crtc state @@ -317,14 +348,12 @@ int amdgpu_dm_update_crtc_color_mgmt(struct dm_crtc_state *crtc) bool is_legacy; int r; - degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); - if (degamma_lut && degamma_size != MAX_COLOR_LUT_ENTRIES) - return -EINVAL; + r = amdgpu_dm_verify_lut_sizes(&crtc->base); + if (r) + return r; + degamma_lut = __extract_blob_lut(crtc->base.degamma_lut, °amma_size); regamma_lut = __extract_blob_lut(crtc->base.gamma_lut, ®amma_size); - if (regamma_lut && regamma_size != MAX_COLOR_LUT_ENTRIES && - regamma_size != MAX_COLOR_LEGACY_LUT_ENTRIES) - return -EINVAL; has_degamma = degamma_lut && !__is_lut_linear(degamma_lut, degamma_size); diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 1e448f1b39a1862589dacce3b91ed7cf366edd14..955a055bd9800f738a466f7840e9c8226034ba19 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -268,6 +268,9 @@ dm_dp_mst_detect(struct drm_connector *connector, struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); struct amdgpu_dm_connector *master = aconnector->mst_port; + if (drm_connector_is_unregistered(connector)) + return connector_status_disconnected; + return drm_dp_mst_detect_port(connector, ctx, &master->mst_mgr, aconnector->port); } diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c index 32b73ea866737cfefca8917c538f98c36a3061b4..a7f8caf1086b95a62f15aa39b08c2ca807eb306c 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link_dp.c @@ -1704,6 +1704,8 @@ static void set_dp_mst_mode(struct dc_link *link, bool mst_enable) link->type = dc_connection_single; link->local_sink = link->remote_sinks[0]; link->local_sink->sink_signal = SIGNAL_TYPE_DISPLAY_PORT; + dc_sink_retain(link->local_sink); + dm_helpers_dp_mst_stop_top_mgr(link->ctx, link); } else if (mst_enable == true && link->type == dc_connection_single && link->remote_sinks[0] != NULL) { diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c index fce37c527a0b96f27b65eb96e482f5231d9f5cbf..8bb5912d837d4e50c91725a9edee49011fba0e9c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_dpp_dscl.c @@ -482,10 +482,13 @@ static enum lb_memory_config dpp1_dscl_find_lb_memory_config(struct dcn10_dpp *d int vtaps_c = scl_data->taps.v_taps_c; int ceil_vratio = dc_fixpt_ceil(scl_data->ratios.vert); int ceil_vratio_c = dc_fixpt_ceil(scl_data->ratios.vert_c); - enum lb_memory_config mem_cfg = LB_MEMORY_CONFIG_0; - if (dpp->base.ctx->dc->debug.use_max_lb) - return mem_cfg; + if (dpp->base.ctx->dc->debug.use_max_lb) { + if (scl_data->format == PIXEL_FORMAT_420BPP8 + || scl_data->format == PIXEL_FORMAT_420BPP10) + return LB_MEMORY_CONFIG_3; + return LB_MEMORY_CONFIG_0; + } dpp->base.caps->dscl_calc_lb_num_partitions( scl_data, LB_MEMORY_CONFIG_1, &num_part_y, &num_part_c); diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index f1e9b3b06b924dcd65a591420094b8a49391e99a..9d3ccdd355825a396ae9516f7edd2715d6dfd3fe 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -243,7 +243,7 @@ void dcn20_dccg_init(struct dce_hwseq *hws) REG_WRITE(MILLISECOND_TIME_BASE_DIV, 0x1186a0); /* This value is dependent on the hardware pipeline delay so set once per SOC */ - REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0x801003c); + REG_WRITE(DISPCLK_FREQ_CHANGE_CNTL, 0xe01003c); } void dcn20_disable_vga( diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c index 9e0ae18e71fac83f1cb94e51b33286c2efe2c898..2663f1b318420fe8058b613973b3c198c404ac5f 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn30/display_mode_vba_30.c @@ -64,6 +64,7 @@ typedef struct { #define BPP_INVALID 0 #define BPP_BLENDED_PIPE 0xffffffff #define DCN30_MAX_DSC_IMAGE_WIDTH 5184 +#define DCN30_MAX_FMT_420_BUFFER_WIDTH 4096 static void DisplayPipeConfiguration(struct display_mode_lib *mode_lib); static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerformanceCalculation( @@ -2052,7 +2053,7 @@ static void DISPCLKDPPCLKDCFCLKDeepSleepPrefetchParametersWatermarksAndPerforman v->DISPCLKWithoutRamping, v->DISPCLKDPPCLKVCOSpeed); v->MaxDispclkRoundedToDFSGranularity = RoundToDFSGranularityDown( - v->soc.clock_limits[mode_lib->soc.num_states].dispclk_mhz, + v->soc.clock_limits[mode_lib->soc.num_states - 1].dispclk_mhz, v->DISPCLKDPPCLKVCOSpeed); if (v->DISPCLKWithoutRampingRoundedToDFSGranularity > v->MaxDispclkRoundedToDFSGranularity) { @@ -3957,20 +3958,20 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { v->PlaneRequiredDISPCLKWithoutODMCombine = v->PixelClock[k] * (1.0 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1.0 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithoutODMCombine >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithoutODMCombine >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithoutODMCombine = v->PixelClock[k] * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } v->PlaneRequiredDISPCLKWithODMCombine2To1 = v->PixelClock[k] / 2 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithODMCombine2To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithODMCombine2To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithODMCombine2To1 = v->PixelClock[k] / 2 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } v->PlaneRequiredDISPCLKWithODMCombine4To1 = v->PixelClock[k] / 4 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * (1 + v->DISPCLKRampingMargin / 100.0); - if ((v->PlaneRequiredDISPCLKWithODMCombine4To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states] - && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states])) { + if ((v->PlaneRequiredDISPCLKWithODMCombine4To1 >= v->MaxDispclk[i] && v->MaxDispclk[i] == v->MaxDispclk[mode_lib->soc.num_states - 1] + && v->MaxDppclk[i] == v->MaxDppclk[mode_lib->soc.num_states - 1])) { v->PlaneRequiredDISPCLKWithODMCombine4To1 = v->PixelClock[k] / 4 * (1 + v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0); } @@ -3987,19 +3988,30 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } else if (v->PlaneRequiredDISPCLKWithoutODMCombine > v->MaxDispclkRoundedDownToDFSGranularity) { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; - } else if (v->DSCEnabled[k] && (v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH)) { - v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; - v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_disabled; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithoutODMCombine; - /*420 format workaround*/ - if (v->HActive[k] > 4096 && v->OutputFormat[k] == dm_420) { + } + if (v->DSCEnabled[k] && v->HActive[k] > DCN30_MAX_DSC_IMAGE_WIDTH + && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) { + if (v->HActive[k] / 2 > DCN30_MAX_DSC_IMAGE_WIDTH) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1; + } else { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; + } + } + if (v->OutputFormat[k] == dm_420 && v->HActive[k] > DCN30_MAX_FMT_420_BUFFER_WIDTH + && v->ODMCombineEnablePerState[i][k] != dm_odm_combine_mode_4to1) { + if (v->HActive[k] / 2 > DCN30_MAX_FMT_420_BUFFER_WIDTH) { + v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_4to1; + v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine4To1; + } else { v->ODMCombineEnablePerState[i][k] = dm_odm_combine_mode_2to1; v->PlaneRequiredDISPCLK = v->PlaneRequiredDISPCLKWithODMCombine2To1; } } - if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_4to1) { v->MPCCombine[i][j][k] = false; v->NoOfDPP[i][j][k] = 4; @@ -4281,42 +4293,8 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l } } - for (i = 0; i < v->soc.num_states; i++) { - v->DSCCLKRequiredMoreThanSupported[i] = false; - for (k = 0; k <= v->NumberOfActivePlanes - 1; k++) { - if (v->BlendingAndTiming[k] == k) { - if (v->Output[k] == dm_dp || v->Output[k] == dm_edp) { - if (v->OutputFormat[k] == dm_420) { - v->DSCFormatFactor = 2; - } else if (v->OutputFormat[k] == dm_444) { - v->DSCFormatFactor = 1; - } else if (v->OutputFormat[k] == dm_n422) { - v->DSCFormatFactor = 2; - } else { - v->DSCFormatFactor = 1; - } - if (v->RequiresDSC[i][k] == true) { - if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_4to1) { - if (v->PixelClockBackEnd[k] / 12.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } else if (v->ODMCombineEnablePerState[i][k] == dm_odm_combine_mode_2to1) { - if (v->PixelClockBackEnd[k] / 6.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } else { - if (v->PixelClockBackEnd[k] / 3.0 / v->DSCFormatFactor - > (1.0 - v->DISPCLKDPPCLKDSCCLKDownSpreading / 100.0) * v->MaxDSCCLK[i]) { - v->DSCCLKRequiredMoreThanSupported[i] = true; - } - } - } - } - } - } - } + /* Skip dscclk validation: as long as dispclk is supported, dscclk is also implicitly supported */ + for (i = 0; i < v->soc.num_states; i++) { v->NotEnoughDSCUnits[i] = false; v->TotalDSCUnitsRequired = 0.0; @@ -5319,7 +5297,7 @@ void dml30_ModeSupportAndSystemConfigurationFull(struct display_mode_lib *mode_l for (j = 0; j < 2; j++) { if (v->ScaleRatioAndTapsSupport == 1 && v->SourceFormatPixelAndScanSupport == 1 && v->ViewportSizeSupport[i][j] == 1 && v->DIOSupport[i] == 1 && v->ODMCombine4To1SupportCheckOK[i] == 1 - && v->NotEnoughDSCUnits[i] == 0 && v->DSCCLKRequiredMoreThanSupported[i] == 0 + && v->NotEnoughDSCUnits[i] == 0 && v->DTBCLKRequiredMoreThanSupported[i] == 0 && v->ROBSupport[i][j] == 1 && v->DISPCLK_DPPCLK_Support[i][j] == 1 && v->TotalAvailablePipesSupport[i][j] == 1 && EnoughWritebackUnits == 1 && WritebackModeSupport == 1 diff --git a/drivers/gpu/drm/amd/display/dc/irq_types.h b/drivers/gpu/drm/amd/display/dc/irq_types.h index d0ccd81ad5b4d8f04c297665bc963cd97677df7f..ad3e5621a17446d01e43c7704f4b1607ef706df6 100644 --- a/drivers/gpu/drm/amd/display/dc/irq_types.h +++ b/drivers/gpu/drm/amd/display/dc/irq_types.h @@ -163,7 +163,7 @@ enum irq_type }; #define DAL_VALID_IRQ_SRC_NUM(src) \ - ((src) <= DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) + ((src) < DAL_IRQ_SOURCES_NUMBER && (src) > DC_IRQ_SOURCE_INVALID) /* Number of Page Flip IRQ Sources. */ #define DAL_PFLIP_IRQ_SRC_NUM \ diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 20e554e771d1634ba2c2cb14124447adbfe70405..fa8aeec304ef4b5d37ab8c779115e87b64df7590 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -260,7 +260,6 @@ enum mod_hdcp_status mod_hdcp_setup(struct mod_hdcp *hdcp, struct mod_hdcp_output output; enum mod_hdcp_status status = MOD_HDCP_STATUS_SUCCESS; - memset(hdcp, 0, sizeof(struct mod_hdcp)); memset(&output, 0, sizeof(output)); hdcp->config = *config; HDCP_TOP_INTERFACE_TRACE(hdcp); diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c index f244b72e74e06969a47abab0096948795fa3bc38..53eab2b8e2c8ac582a9e3f8513b223e7f79dadd7 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp1_execution.c @@ -29,8 +29,10 @@ static inline enum mod_hdcp_status validate_bksv(struct mod_hdcp *hdcp) { uint64_t n = 0; uint8_t count = 0; + u8 bksv[sizeof(n)] = { }; - memcpy(&n, hdcp->auth.msg.hdcp1.bksv, sizeof(uint64_t)); + memcpy(bksv, hdcp->auth.msg.hdcp1.bksv, sizeof(hdcp->auth.msg.hdcp1.bksv)); + n = *(uint64_t *)bksv; while (n) { count++; diff --git a/drivers/gpu/drm/amd/include/navi10_enum.h b/drivers/gpu/drm/amd/include/navi10_enum.h index d5ead9680c6ed10ccee33bb5bd4f32c4178453b8..84bcb96f76ea4ba32cf6ba3a030a097957e37082 100644 --- a/drivers/gpu/drm/amd/include/navi10_enum.h +++ b/drivers/gpu/drm/amd/include/navi10_enum.h @@ -430,7 +430,7 @@ ARRAY_2D_DEPTH = 0x00000001, */ typedef enum ENUM_NUM_SIMD_PER_CU { -NUM_SIMD_PER_CU = 0x00000004, +NUM_SIMD_PER_CU = 0x00000002, } ENUM_NUM_SIMD_PER_CU; /* diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 351a85088d0ecc4b9f02183066bc97546edd5530..f1e8bc39b16d31748f582e425a2ea8dc087f5a2c 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -922,6 +922,11 @@ static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = { .atomic_disable = malidp_de_plane_disable, }; +static const uint64_t linear_only_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + int malidp_de_planes_init(struct drm_device *drm) { struct malidp_drm *malidp = drm->dev_private; @@ -985,8 +990,8 @@ int malidp_de_planes_init(struct drm_device *drm) */ ret = drm_universal_plane_init(drm, &plane->base, crtcs, &malidp_de_plane_funcs, formats, n, - (id == DE_SMART) ? NULL : modifiers, plane_type, - NULL); + (id == DE_SMART) ? linear_only_modifiers : modifiers, + plane_type, NULL); if (ret < 0) goto cleanup; diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 88121c0e0d05c4a0dcb4a936712e4f0a1637b5d6..cd93c44f26627e4f81fdeb9c34578e462d278227 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -189,6 +189,9 @@ bool ast_backup_fw(struct drm_device *dev, u8 *addr, u32 size) u32 i, data; u32 boot_address; + if (ast->config_mode != ast_use_p2a) + return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (data) { boot_address = get_fw_base(ast); @@ -207,6 +210,9 @@ static bool ast_launch_m68k(struct drm_device *dev) u8 *fw_addr = NULL; u8 jreg; + if (ast->config_mode != ast_use_p2a) + return false; + data = ast_mindwm(ast, 0x1e6e2100) & 0x01; if (!data) { @@ -271,25 +277,55 @@ u8 ast_get_dp501_max_clk(struct drm_device *dev) struct ast_private *ast = to_ast_private(dev); u32 boot_address, offset, data; u8 linkcap[4], linkrate, linklanes, maxclk = 0xff; + u32 *plinkcap; - boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) /* version: 1x */ - return maxclk; - - /* Read Link Capability */ - offset = 0xf014; - *(u32 *)linkcap = ast_mindwm(ast, boot_address + offset); - if (linkcap[2] == 0) { - linkrate = linkcap[0]; - linklanes = linkcap[1]; - data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); - if (data > 0xff) - data = 0xff; - maxclk = (u8)data; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = ast_mindwm(ast, boot_address + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = AST_DP501_LINKRATE; + plinkcap = (u32 *)linkcap; + *plinkcap = ast_mindwm(ast, boot_address + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } + } else { + if (!ast->dp501_fw_buf) + return AST_DP501_DEFAULT_DCLK; /* 1024x768 as default */ + + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) /* version: 1x */ + return maxclk; + + /* Read Link Capability */ + offset = AST_DP501_LINKRATE; + plinkcap = (u32 *)linkcap; + *plinkcap = readl(ast->dp501_fw_buf + offset); + if (linkcap[2] == 0) { + linkrate = linkcap[0]; + linklanes = linkcap[1]; + data = (linkrate == 0x0a) ? (90 * linklanes) : (54 * linklanes); + if (data > 0xff) + data = 0xff; + maxclk = (u8)data; + } } return maxclk; } @@ -298,26 +334,57 @@ bool ast_dp501_read_edid(struct drm_device *dev, u8 *ediddata) { struct ast_private *ast = to_ast_private(dev); u32 i, boot_address, offset, data; + u32 *pEDIDidx; - boot_address = get_fw_base(ast); - - /* validate FW version */ - offset = 0xf000; - data = ast_mindwm(ast, boot_address + offset); - if ((data & 0xf0) != 0x10) - return false; - - /* validate PnP Monitor */ - offset = 0xf010; - data = ast_mindwm(ast, boot_address + offset); - if (!(data & 0x01)) - return false; + if (ast->config_mode == ast_use_p2a) { + boot_address = get_fw_base(ast); - /* Read EDID */ - offset = 0xf020; - for (i = 0; i < 128; i += 4) { - data = ast_mindwm(ast, boot_address + offset + i); - *(u32 *)(ediddata + i) = data; + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = ast_mindwm(ast, boot_address + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) + return false; + + /* validate PnP Monitor */ + offset = AST_DP501_PNPMONITOR; + data = ast_mindwm(ast, boot_address + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) + return false; + + /* Read EDID */ + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = ast_mindwm(ast, boot_address + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; + } + } else { + if (!ast->dp501_fw_buf) + return false; + + /* dummy read */ + offset = 0x0000; + data = readl(ast->dp501_fw_buf + offset); + + /* validate FW version */ + offset = AST_DP501_GBL_VERSION; + data = readl(ast->dp501_fw_buf + offset); + if ((data & AST_DP501_FW_VERSION_MASK) != AST_DP501_FW_VERSION_1) + return false; + + /* validate PnP Monitor */ + offset = AST_DP501_PNPMONITOR; + data = readl(ast->dp501_fw_buf + offset); + if (!(data & AST_DP501_PNP_CONNECTED)) + return false; + + /* Read EDID */ + offset = AST_DP501_EDID_DATA; + for (i = 0; i < 128; i += 4) { + data = readl(ast->dp501_fw_buf + offset + i); + pEDIDidx = (u32 *)(ediddata + i); + *pEDIDidx = data; + } } return true; diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 467049ca8430a13121d4c5f533c29f443fdeb159..b68b1ddfecb7af66d95ebee087c275063c901a26 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -120,6 +120,7 @@ struct ast_private { void __iomem *regs; void __iomem *ioregs; + void __iomem *dp501_fw_buf; enum ast_chip chip; bool vga2_clone; @@ -298,6 +299,17 @@ int ast_mode_config_init(struct ast_private *ast); #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) +#define AST_DP501_FW_VERSION_MASK GENMASK(7, 4) +#define AST_DP501_FW_VERSION_1 BIT(4) +#define AST_DP501_PNP_CONNECTED BIT(1) + +#define AST_DP501_DEFAULT_DCLK 65 + +#define AST_DP501_GBL_VERSION 0xf000 +#define AST_DP501_PNPMONITOR 0xf010 +#define AST_DP501_LINKRATE 0xf014 +#define AST_DP501_EDID_DATA 0xf020 + int ast_mm_init(struct ast_private *ast); /* ast post */ diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 77066bca87939f180d80f4ae25571e1e269bbd88..0d163511564e7f1346914a9d9da35e67313db502 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -98,7 +98,7 @@ static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev) if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) { /* Double check it's actually working */ data = ast_read32(ast, 0xf004); - if (data != 0xFFFFFFFF) { + if ((data != 0xFFFFFFFF) && (data != 0x00)) { /* P2A works, grab silicon revision */ ast->config_mode = ast_use_p2a; @@ -409,7 +409,7 @@ struct ast_private *ast_device_create(struct drm_driver *drv, dev->pdev = pdev; pci_set_drvdata(pdev, dev); - ast->regs = pci_iomap(dev->pdev, 1, 0); + ast->regs = pcim_iomap(pdev, 1, 0); if (!ast->regs) return ERR_PTR(-EIO); @@ -425,7 +425,7 @@ struct ast_private *ast_device_create(struct drm_driver *drv, /* "map" IO regs if the above hasn't done so already */ if (!ast->ioregs) { - ast->ioregs = pci_iomap(dev->pdev, 2, 0); + ast->ioregs = pcim_iomap(pdev, 2, 0); if (!ast->ioregs) return ERR_PTR(-EIO); } @@ -446,6 +446,14 @@ struct ast_private *ast_device_create(struct drm_driver *drv, if (ret) return ERR_PTR(ret); + /* map reserved buffer */ + ast->dp501_fw_buf = NULL; + if (dev->vram_mm->vram_size < pci_resource_len(dev->pdev, 0)) { + ast->dp501_fw_buf = pci_iomap_range(dev->pdev, 0, dev->vram_mm->vram_size, 0); + if (!ast->dp501_fw_buf) + drm_info(dev, "failed to map reserved buffer!\n"); + } + ret = ast_mode_config_init(ast); if (ret) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 0d6a6aa8f8c4b19e913bb06c5ba019997dd00cdc..1dd8b0f6f4b338e042082a03f60098ab4273d0a2 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -153,7 +153,7 @@ config DRM_SIL_SII8620 tristate "Silicon Image SII8620 HDMI/MHL bridge" depends on OF select DRM_KMS_HELPER - imply EXTCON + select EXTCON depends on RC_CORE || !RC_CORE help Silicon Image SII8620 HDMI/MHL bridge chip driver. diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c index d0c65610ebb5c3633a61f34890e855ba9180d4e4..f56ff97c989901acd5ccf152226771680cfbc0d4 100644 --- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c +++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c @@ -2369,9 +2369,9 @@ static int cdns_mhdp_probe(struct platform_device *pdev) clk_prepare_enable(clk); pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { - dev_err(dev, "pm_runtime_get_sync failed\n"); + dev_err(dev, "pm_runtime_resume_and_get failed\n"); pm_runtime_disable(dev); goto clk_disable; } diff --git a/drivers/gpu/drm/bridge/cdns-dsi.c b/drivers/gpu/drm/bridge/cdns-dsi.c index 76373e31df92dc444b82733b7b7c6730f27efade..b31281f76117c02335393fc9b447a6e166b2570b 100644 --- a/drivers/gpu/drm/bridge/cdns-dsi.c +++ b/drivers/gpu/drm/bridge/cdns-dsi.c @@ -1028,7 +1028,7 @@ static ssize_t cdns_dsi_transfer(struct mipi_dsi_host *host, struct mipi_dsi_packet packet; int ret, i, tx_len, rx_len; - ret = pm_runtime_get_sync(host->dev); + ret = pm_runtime_resume_and_get(host->dev); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/bridge/lontium-lt9611.c b/drivers/gpu/drm/bridge/lontium-lt9611.c index d734d9402c350fff9bf85a074201ed95e34cd0c1..c1926154eda84384cacb9ae75fbe7cc93b81fa39 100644 --- a/drivers/gpu/drm/bridge/lontium-lt9611.c +++ b/drivers/gpu/drm/bridge/lontium-lt9611.c @@ -1209,6 +1209,7 @@ static struct i2c_device_id lt9611_id[] = { { "lontium,lt9611", 0 }, {} }; +MODULE_DEVICE_TABLE(i2c, lt9611_id); static const struct of_device_id lt9611_match_table[] = { { .compatible = "lontium,lt9611" }, diff --git a/drivers/gpu/drm/drm_bridge.c b/drivers/gpu/drm/drm_bridge.c index 64f0effb52ac1210dd54da79640c3361da3a825f..044acd07c15387a612946d821bec9701478b7196 100644 --- a/drivers/gpu/drm/drm_bridge.c +++ b/drivers/gpu/drm/drm_bridge.c @@ -522,6 +522,9 @@ void drm_bridge_chain_pre_enable(struct drm_bridge *bridge) list_for_each_entry_reverse(iter, &encoder->bridge_chain, chain_node) { if (iter->funcs->pre_enable) iter->funcs->pre_enable(iter); + + if (iter == bridge) + break; } } EXPORT_SYMBOL(drm_bridge_chain_pre_enable); diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index deeed73f4ed6924d92a9f66668a1249a6f144f4d..3c55753bab161d80dbaf403cf4177ee52ed3a056 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -602,7 +602,14 @@ int drm_dp_read_downstream_info(struct drm_dp_aux *aux, !(dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DWN_STRM_PORT_PRESENT)) return 0; + /* Some branches advertise having 0 downstream ports, despite also advertising they have a + * downstream port present. The DP spec isn't clear on if this is allowed or not, but since + * some branches do it we need to handle it regardless. + */ len = drm_dp_downstream_port_count(dpcd); + if (!len) + return 0; + if (dpcd[DP_DOWNSTREAMPORT_PRESENT] & DP_DETAILED_CAP_INFO_AVAILABLE) len *= 4; diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index a08cc6b53bc2f01c6e27f58c64c8359a6307550c..861f16dfd1a3dad0107e592417aa29a406ef98cc 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -94,6 +94,9 @@ static int drm_dp_mst_register_i2c_bus(struct drm_dp_mst_port *port); static void drm_dp_mst_unregister_i2c_bus(struct drm_dp_mst_port *port); static void drm_dp_mst_kick_tx(struct drm_dp_mst_topology_mgr *mgr); +static bool drm_dp_mst_port_downstream_of_branch(struct drm_dp_mst_port *port, + struct drm_dp_mst_branch *branch); + #define DBG_PREFIX "[dp_mst]" #define DP_STR(x) [DP_ ## x] = #x @@ -2499,7 +2502,7 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, { struct drm_dp_mst_topology_mgr *mgr = mstb->mgr; struct drm_dp_mst_port *port; - int old_ddps, old_input, ret, i; + int old_ddps, ret; u8 new_pdt; bool new_mcs; bool dowork = false, create_connector = false; @@ -2531,7 +2534,6 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, } old_ddps = port->ddps; - old_input = port->input; port->input = conn_stat->input_port; port->ldps = conn_stat->legacy_device_plug_status; port->ddps = conn_stat->displayport_device_plug_status; @@ -2554,28 +2556,6 @@ drm_dp_mst_handle_conn_stat(struct drm_dp_mst_branch *mstb, dowork = false; } - if (!old_input && old_ddps != port->ddps && !port->ddps) { - for (i = 0; i < mgr->max_payloads; i++) { - struct drm_dp_vcpi *vcpi = mgr->proposed_vcpis[i]; - struct drm_dp_mst_port *port_validated; - - if (!vcpi) - continue; - - port_validated = - container_of(vcpi, struct drm_dp_mst_port, vcpi); - port_validated = - drm_dp_mst_topology_get_port_validated(mgr, port_validated); - if (!port_validated) { - mutex_lock(&mgr->payload_lock); - vcpi->num_slots = 0; - mutex_unlock(&mgr->payload_lock); - } else { - drm_dp_mst_topology_put_port(port_validated); - } - } - } - if (port->connector) drm_modeset_unlock(&mgr->base.lock); else if (create_connector) @@ -3385,6 +3365,7 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) struct drm_dp_mst_port *port; int i, j; int cur_slots = 1; + bool skip; mutex_lock(&mgr->payload_lock); for (i = 0; i < mgr->max_payloads; i++) { @@ -3399,6 +3380,16 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) port = container_of(vcpi, struct drm_dp_mst_port, vcpi); + mutex_lock(&mgr->lock); + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (skip) { + drm_dbg_kms(mgr->dev, + "Virtual channel %d is not in current topology\n", + i); + continue; + } /* Validated ports don't matter if we're releasing * VCPI */ @@ -3406,8 +3397,16 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr) port = drm_dp_mst_topology_get_port_validated( mgr, port); if (!port) { - mutex_unlock(&mgr->payload_lock); - return -EINVAL; + if (vcpi->num_slots == payload->num_slots) { + cur_slots += vcpi->num_slots; + payload->start_slot = req_payload.start_slot; + continue; + } else { + drm_dbg_kms(mgr->dev, + "Fail:set payload to invalid sink"); + mutex_unlock(&mgr->payload_lock); + return -EINVAL; + } } put_port = true; } @@ -3491,6 +3490,7 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) struct drm_dp_mst_port *port; int i; int ret = 0; + bool skip; mutex_lock(&mgr->payload_lock); for (i = 0; i < mgr->max_payloads; i++) { @@ -3500,6 +3500,13 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); + mutex_lock(&mgr->lock); + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (skip) + continue; + DRM_DEBUG_KMS("payload %d %d\n", i, mgr->payloads[i].payload_state); if (mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL) { ret = drm_dp_create_payload_step2(mgr, port, mgr->proposed_vcpis[i]->vcpi, &mgr->payloads[i]); @@ -4581,9 +4588,18 @@ EXPORT_SYMBOL(drm_dp_mst_reset_vcpi_slots); void drm_dp_mst_deallocate_vcpi(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port) { + bool skip; + if (!port->vcpi.vcpi) return; + mutex_lock(&mgr->lock); + skip = !drm_dp_mst_port_downstream_of_branch(port, mgr->mst_primary); + mutex_unlock(&mgr->lock); + + if (skip) + return; + drm_dp_mst_put_payload_id(mgr, port->vcpi.vcpi); port->vcpi.num_slots = 0; port->vcpi.pbn = 0; diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 54d9876b5305a475de62e4b219c77437787809b1..6ef4ea07d1bb857b022c5bd1d91249165564ea3b 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -435,6 +435,7 @@ static struct drm_framebuffer *psb_user_framebuffer_create const struct drm_mode_fb_cmd2 *cmd) { struct drm_gem_object *obj; + struct drm_framebuffer *fb; /* * Find the GEM object and thus the gtt range object that is @@ -445,7 +446,11 @@ static struct drm_framebuffer *psb_user_framebuffer_create return ERR_PTR(-ENOENT); /* Let the core code do all the work */ - return psb_framebuffer_create(dev, cmd, obj); + fb = psb_framebuffer_create(dev, cmd, obj); + if (IS_ERR(fb)) + drm_gem_object_put(obj); + + return fb; } static int psbfb_probe(struct drm_fb_helper *fb_helper, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index eb02ecb6e345a508ece7d94115c2babbbec76970..65d73eb5e155c84bc441e2d14161218a45355485 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5080,7 +5080,7 @@ static int intel_dp_vsc_sdp_unpack(struct drm_dp_vsc_sdp *vsc, if (size < sizeof(struct dp_sdp)) return -EINVAL; - memset(vsc, 0, size); + memset(vsc, 0, sizeof(*vsc)); if (sdp->sdp_header.HB0 != 0) return -EINVAL; diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index f08e25e95746e1e38ccee14782d2a64569cec6b4..be27f9889431eabeda812d5249fe60d06ef21273 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -299,10 +299,7 @@ static void __gen8_ppgtt_alloc(struct i915_address_space * const vm, __i915_gem_object_pin_pages(pt->base); i915_gem_object_make_unshrinkable(pt->base); - if (lvl || - gen8_pt_count(*start, end) < I915_PDES || - intel_vgpu_active(vm->i915)) - fill_px(pt, vm->scratch[lvl]->encode); + fill_px(pt, vm->scratch[lvl]->encode); spin_lock(&pd->lock); if (likely(!pd->entry[idx])) { diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index b5937b39145a4ed9676005a9fd6c460cdd8b9f07..cd71631bef0caab16928ab8278d715dce9fee850 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -348,7 +348,7 @@ static struct i915_fence_reg *fence_find(struct i915_ggtt *ggtt) if (intel_has_pending_fb_unpin(ggtt->vm.i915)) return ERR_PTR(-EAGAIN); - return ERR_PTR(-EDEADLK); + return ERR_PTR(-ENOBUFS); } int __i915_vma_pin_fence(struct i915_vma *vma) diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c index a3d1617d7c67e0d45e564be8697cc3ffc647c339..b6bb5fc7d183e82f076a4211db117eb1f030f021 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c @@ -347,7 +347,7 @@ static void ingenic_drm_plane_enable(struct ingenic_drm *priv, unsigned int en_bit; if (priv->soc_info->has_osd) { - if (plane->type == DRM_PLANE_TYPE_PRIMARY) + if (plane != &priv->f0) en_bit = JZ_LCD_OSDC_F1EN; else en_bit = JZ_LCD_OSDC_F0EN; @@ -362,7 +362,7 @@ void ingenic_drm_plane_disable(struct device *dev, struct drm_plane *plane) unsigned int en_bit; if (priv->soc_info->has_osd) { - if (plane->type == DRM_PLANE_TYPE_PRIMARY) + if (plane != &priv->f0) en_bit = JZ_LCD_OSDC_F1EN; else en_bit = JZ_LCD_OSDC_F0EN; @@ -389,8 +389,7 @@ void ingenic_drm_plane_config(struct device *dev, ingenic_drm_plane_enable(priv, plane); - if (priv->soc_info->has_osd && - plane->type == DRM_PLANE_TYPE_PRIMARY) { + if (priv->soc_info->has_osd && plane != &priv->f0) { switch (fourcc) { case DRM_FORMAT_XRGB1555: ctrl |= JZ_LCD_OSDCTRL_RGB555; @@ -423,7 +422,7 @@ void ingenic_drm_plane_config(struct device *dev, } if (priv->soc_info->has_osd) { - if (plane->type == DRM_PLANE_TYPE_PRIMARY) { + if (plane != &priv->f0) { xy_reg = JZ_REG_LCD_XYP1; size_reg = JZ_REG_LCD_SIZE1; } else { @@ -455,7 +454,7 @@ static void ingenic_drm_plane_atomic_update(struct drm_plane *plane, height = state->src_h >> 16; cpp = state->fb->format->cpp[0]; - if (priv->soc_info->has_osd && plane->type == DRM_PLANE_TYPE_OVERLAY) + if (!priv->soc_info->has_osd || plane == &priv->f0) hwdesc = priv->dma_hwdesc_f0; else hwdesc = priv->dma_hwdesc_f1; @@ -692,6 +691,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) const struct jz_soc_info *soc_info; struct ingenic_drm *priv; struct clk *parent_clk; + struct drm_plane *primary; struct drm_bridge *bridge; struct drm_panel *panel; struct drm_encoder *encoder; @@ -784,9 +784,11 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) if (soc_info->has_osd) priv->ipu_plane = drm_plane_from_index(drm, 0); - drm_plane_helper_add(&priv->f1, &ingenic_drm_plane_helper_funcs); + primary = priv->soc_info->has_osd ? &priv->f1 : &priv->f0; + + drm_plane_helper_add(primary, &ingenic_drm_plane_helper_funcs); - ret = drm_universal_plane_init(drm, &priv->f1, 1, + ret = drm_universal_plane_init(drm, primary, 1, &ingenic_drm_primary_plane_funcs, ingenic_drm_primary_formats, ARRAY_SIZE(ingenic_drm_primary_formats), @@ -798,7 +800,7 @@ static int ingenic_drm_bind(struct device *dev, bool has_components) drm_crtc_helper_add(&priv->crtc, &ingenic_drm_crtc_helper_funcs); - ret = drm_crtc_init_with_planes(drm, &priv->crtc, &priv->f1, + ret = drm_crtc_init_with_planes(drm, &priv->crtc, primary, NULL, &ingenic_drm_crtc_funcs, NULL); if (ret) { dev_err(dev, "Failed to init CRTC: %i\n", ret); diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c index fc8c6e970ee3133a785c6a67c537d183bb22099b..06fd118b1444da167f5adf94bb7303ba5a41b8a0 100644 --- a/drivers/gpu/drm/ingenic/ingenic-ipu.c +++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c @@ -753,7 +753,7 @@ static int ingenic_ipu_bind(struct device *dev, struct device *master, void *d) err = drm_universal_plane_init(drm, plane, 1, &ingenic_ipu_plane_funcs, soc_info->formats, soc_info->num_formats, - NULL, DRM_PLANE_TYPE_PRIMARY, NULL); + NULL, DRM_PLANE_TYPE_OVERLAY, NULL); if (err) { dev_err(dev, "Failed to init plane: %i\n", err); return err; diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index ac038572164d3c961413af59dd35658a31c67a57..dfd5ed15a7f4a7125833d7fc4c99cbe02ab05563 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -274,7 +274,7 @@ static int mtk_crtc_ddp_hw_init(struct mtk_drm_crtc *mtk_crtc) drm_connector_list_iter_end(&conn_iter); } - ret = pm_runtime_get_sync(crtc->dev->dev); + ret = pm_runtime_resume_and_get(crtc->dev->dev); if (ret < 0) { DRM_ERROR("Failed to enable power domain: %d\n", ret); return ret; diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c index 3416e9617ee9a3ab0d415198086db0f1a3ff2cca..96f3908e4c5b98baf31b581f513be37ad5a0844d 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_mdss.c @@ -222,7 +222,7 @@ int dpu_mdss_init(struct drm_device *dev) struct msm_drm_private *priv = dev->dev_private; struct dpu_mdss *dpu_mdss; struct dss_module_power *mp; - int ret = 0; + int ret; int irq; dpu_mdss = devm_kzalloc(dev->dev, sizeof(*dpu_mdss), GFP_KERNEL); @@ -250,8 +250,10 @@ int dpu_mdss_init(struct drm_device *dev) goto irq_domain_error; irq = platform_get_irq(pdev, 0); - if (irq < 0) + if (irq < 0) { + ret = irq; goto irq_error; + } irq_set_chained_handler_and_data(irq, dpu_mdss_irq, dpu_mdss); @@ -260,7 +262,7 @@ int dpu_mdss_init(struct drm_device *dev) pm_runtime_enable(dev->dev); - return ret; + return 0; irq_error: _dpu_mdss_irq_domain_fini(dpu_mdss); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c index dbf8d429223e4c686047589ffaa8f8d3656e1721..2f75e39052022635b5d18d4811ad891ab1b7eecb 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c @@ -88,8 +88,6 @@ static int mdp4_hw_init(struct msm_kms *kms) if (mdp4_kms->rev > 1) mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1); - dev->mode_config.allow_fb_modifiers = true; - out: pm_runtime_put_sync(dev->dev); diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c index da3cc1d8c33125882e924309497a4446dbca7d88..ee1dbb2b84af4994f9f76c4dc983010db55ebfd5 100644 --- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_plane.c @@ -347,6 +347,12 @@ enum mdp4_pipe mdp4_plane_pipe(struct drm_plane *plane) return mdp4_plane->pipe; } +static const uint64_t supported_format_modifiers[] = { + DRM_FORMAT_MOD_SAMSUNG_64_32_TILE, + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + /* initialize plane */ struct drm_plane *mdp4_plane_init(struct drm_device *dev, enum mdp4_pipe pipe_id, bool private_plane) @@ -375,7 +381,7 @@ struct drm_plane *mdp4_plane_init(struct drm_device *dev, type = private_plane ? DRM_PLANE_TYPE_PRIMARY : DRM_PLANE_TYPE_OVERLAY; ret = drm_universal_plane_init(dev, plane, 0xff, &mdp4_plane_funcs, mdp4_plane->formats, mdp4_plane->nformats, - NULL, type, NULL); + supported_format_modifiers, type, NULL); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 0aacc43faefa30a8e08ccc235a6f5e52c5922b42..edee4c2a76ce4af37558134902d5976f5ff31905 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -505,6 +505,7 @@ static int msm_drm_init(struct device *dev, struct drm_driver *drv) priv->event_thread[i].worker = kthread_create_worker(0, "crtc_event:%d", priv->event_thread[i].crtc_id); if (IS_ERR(priv->event_thread[i].worker)) { + ret = PTR_ERR(priv->event_thread[i].worker); DRM_DEV_ERROR(dev, "failed to create crtc_event kthread\n"); goto err_msm_uninit; } diff --git a/drivers/gpu/drm/mxsfb/Kconfig b/drivers/gpu/drm/mxsfb/Kconfig index 0143d539f8f8298601bb1fdf167c47ee7dd33bbc..ee22cd25d3e3d72f42526587668c146c5a68d87c 100644 --- a/drivers/gpu/drm/mxsfb/Kconfig +++ b/drivers/gpu/drm/mxsfb/Kconfig @@ -10,7 +10,6 @@ config DRM_MXSFB depends on COMMON_CLK select DRM_MXS select DRM_KMS_HELPER - select DRM_KMS_FB_HELPER select DRM_KMS_CMA_HELPER select DRM_PANEL select DRM_PANEL_BRIDGE diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 7daa12eec01bb3fdb9d8e6c10c2eeb7fd1804b86..b4946b595d86efb161dc7a22c0ce5d94a69a3dc1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -590,7 +590,7 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm; int i; - if (!ttm_dma) + if (!ttm_dma || !ttm_dma->dma_address) return; /* Don't waste time looping if the object is coherent */ @@ -610,7 +610,7 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm; int i; - if (!ttm_dma) + if (!ttm_dma || !ttm_dma->dma_address) return; /* Don't waste time looping if the object is coherent */ diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index bceb48a2dfca6ba30c89fe28716250d7284c7b6d..f2ad6f49fb72efe4cc4b3f9114b7594b89922db6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -700,7 +700,6 @@ nouveau_display_create(struct drm_device *dev) dev->mode_config.preferred_depth = 24; dev->mode_config.prefer_shadow = 1; - dev->mode_config.allow_fb_modifiers = true; if (drm->client.device.info.chipset < 0x11) dev->mode_config.async_page_flip = false; diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index b2ecb91f8ddc0357e74e6dbec2c9aeed8eae1abe..5f5b87f99546832e53d4e678bb9faeb30d9cba3d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -111,7 +111,22 @@ int nouveau_gem_prime_pin(struct drm_gem_object *obj) if (ret) return -EINVAL; - return 0; + ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); + if (ret) + goto error; + + if (nvbo->bo.moving) + ret = dma_fence_wait(nvbo->bo.moving, true); + + ttm_bo_unreserve(&nvbo->bo); + if (ret) + goto error; + + return ret; + +error: + nouveau_bo_unpin(nvbo); + return ret; } void nouveau_gem_prime_unpin(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/pl111/Kconfig b/drivers/gpu/drm/pl111/Kconfig index 80f6748055e3675a9807c7afaccebe7aa47b8881..3aae387a96af298ddb35cc8bd211558ba25c3c39 100644 --- a/drivers/gpu/drm/pl111/Kconfig +++ b/drivers/gpu/drm/pl111/Kconfig @@ -3,6 +3,7 @@ config DRM_PL111 tristate "DRM Support for PL111 CLCD Controller" depends on DRM depends on ARM || ARM64 || COMPILE_TEST + depends on VEXPRESS_CONFIG || VEXPRESS_CONFIG=n depends on COMMON_CLK select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c index c04cd5a2553ce96cc52bce4e7d0ba65209037ee1..e377bdbff90ddfcab5d06233e250008b04cb3f06 100644 --- a/drivers/gpu/drm/qxl/qxl_dumb.c +++ b/drivers/gpu/drm/qxl/qxl_dumb.c @@ -58,6 +58,8 @@ int qxl_mode_dumb_create(struct drm_file *file_priv, surf.height = args->height; surf.stride = pitch; surf.format = format; + surf.data = 0; + r = qxl_gem_object_create_with_handle(qdev, file_priv, QXL_GEM_DOMAIN_SURFACE, args->size, &surf, &qobj, diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index e0ae911ef427dd028ad3c606dae0f1d61d1c7b7a..71bdafac9210daa134a8d0af093ccba890eeeba6 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -1334,6 +1334,7 @@ radeon_user_framebuffer_create(struct drm_device *dev, /* Handle is imported dma-buf, so cannot be migrated to VRAM for scanout */ if (obj->import_attach) { DRM_DEBUG_KMS("Cannot create framebuffer from imported dma_buf\n"); + drm_gem_object_put(obj); return ERR_PTR(-EINVAL); } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4cd30613fa1dd2ca5115b841a928cd57ced9eb88..e9df5e8ef0a5bb79435d7358d350cbe1b123f943 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -416,13 +416,13 @@ radeon_pci_shutdown(struct pci_dev *pdev) if (radeon_device_is_virtual()) radeon_pci_remove(pdev); -#ifdef CONFIG_PPC64 +#if defined(CONFIG_PPC64) || defined(CONFIG_MACH_LOONGSON64) /* * Some adapters need to be suspended before a * shutdown occurs in order to prevent an error - * during kexec. - * Make this power specific becauase it breaks - * some non-power boards. + * during kexec, shutdown or reboot. + * Make this power and Loongson specific because + * it breaks some other boards. */ radeon_suspend_kms(pci_get_drvdata(pdev), true, true, false); #endif diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index b9de0e51c0be9871157d7bd7249ea43b397a32fa..cbad81578190fb3f12e0d54882c704903245ee58 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -94,9 +94,19 @@ int radeon_gem_prime_pin(struct drm_gem_object *obj) /* pin buffer into GTT */ ret = radeon_bo_pin(bo, RADEON_GEM_DOMAIN_GTT, NULL); - if (likely(ret == 0)) - bo->prime_shared_count++; - + if (unlikely(ret)) + goto error; + + if (bo->tbo.moving) { + ret = dma_fence_wait(bo->tbo.moving, false); + if (unlikely(ret)) { + radeon_bo_unpin(bo); + goto error; + } + } + + bo->prime_shared_count++; +error: radeon_bo_unreserve(bo); return ret; } diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index d256c3f2e19f697720ff5541f602d270b5e829e9..3cec866bc1d97941e9c816a45c03293f91e1393b 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -72,7 +72,8 @@ static int cdn_dp_grf_write(struct cdn_dp_device *dp, ret = regmap_write(dp->grf, reg, val); if (ret) { - DRM_DEV_ERROR(dev, "Could not write to GRF: %d\n", ret); + DRM_DEV_ERROR(dp->dev, "Could not write to GRF: %d\n", ret); + clk_disable_unprepare(dp->grf_clk); return ret; } diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index 542dcf7eddd66bbe751c7b1977bcb3b0f1674c17..d0c9610ad22025140f9e15c84a54e681eccc73ac 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -243,7 +243,6 @@ struct dw_mipi_dsi_rockchip { struct dw_mipi_dsi *dmd; const struct rockchip_dw_dsi_chip_data *cdata; struct dw_mipi_dsi_plat_data pdata; - int devcnt; }; struct dphy_pll_parameter_map { @@ -692,13 +691,8 @@ static const struct dw_mipi_dsi_phy_ops dw_mipi_dsi_rockchip_phy_ops = { .get_timing = dw_mipi_dsi_phy_get_timing, }; -static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi, - int mux) +static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi) { - if (dsi->cdata->lcdsel_grf_reg) - regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg, - mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big); - if (dsi->cdata->lanecfg1_grf_reg) regmap_write(dsi->grf_regmap, dsi->cdata->lanecfg1_grf_reg, dsi->cdata->lanecfg1); @@ -712,6 +706,13 @@ static void dw_mipi_dsi_rockchip_config(struct dw_mipi_dsi_rockchip *dsi, dsi->cdata->enable); } +static void dw_mipi_dsi_rockchip_set_lcdsel(struct dw_mipi_dsi_rockchip *dsi, + int mux) +{ + regmap_write(dsi->grf_regmap, dsi->cdata->lcdsel_grf_reg, + mux ? dsi->cdata->lcdsel_lit : dsi->cdata->lcdsel_big); +} + static int dw_mipi_dsi_encoder_atomic_check(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, @@ -767,9 +768,9 @@ static void dw_mipi_dsi_encoder_enable(struct drm_encoder *encoder) return; } - dw_mipi_dsi_rockchip_config(dsi, mux); + dw_mipi_dsi_rockchip_set_lcdsel(dsi, mux); if (dsi->slave) - dw_mipi_dsi_rockchip_config(dsi->slave, mux); + dw_mipi_dsi_rockchip_set_lcdsel(dsi->slave, mux); clk_disable_unprepare(dsi->grf_clk); } @@ -923,6 +924,24 @@ static int dw_mipi_dsi_rockchip_bind(struct device *dev, return ret; } + /* + * With the GRF clock running, write lane and dual-mode configurations + * that won't change immediately. If we waited until enable() to do + * this, things like panel preparation would not be able to send + * commands over DSI. + */ + ret = clk_prepare_enable(dsi->grf_clk); + if (ret) { + DRM_DEV_ERROR(dsi->dev, "Failed to enable grf_clk: %d\n", ret); + return ret; + } + + dw_mipi_dsi_rockchip_config(dsi); + if (dsi->slave) + dw_mipi_dsi_rockchip_config(dsi->slave); + + clk_disable_unprepare(dsi->grf_clk); + ret = rockchip_dsi_drm_create_encoder(dsi, drm_dev); if (ret) { DRM_DEV_ERROR(dev, "Failed to create drm encoder\n"); @@ -1121,9 +1140,6 @@ static int dw_mipi_dsi_rockchip_remove(struct platform_device *pdev) { struct dw_mipi_dsi_rockchip *dsi = platform_get_drvdata(pdev); - if (dsi->devcnt == 0) - component_del(dsi->dev, &dw_mipi_dsi_rockchip_ops); - dw_mipi_dsi_remove(dsi->dmd); return 0; diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c80f7d9fd13f81c4d92c00651f08a9c072643323..0f23144491e409971262f613bd36d560ac6289a4 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1013,6 +1013,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, VOP_WIN_SET(vop, win, alpha_en, 1); } else { VOP_WIN_SET(vop, win, src_alpha_ctl, SRC_ALPHA_EN(0)); + VOP_WIN_SET(vop, win, alpha_en, 0); } VOP_WIN_SET(vop, win, enable, 1); diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 41edd0a421b256cb35311156ed6bf5cb1b056847..7c20b4a24a7e2392fd13c417294ef4bc7d1f730e 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -499,11 +499,11 @@ static int px30_lvds_probe(struct platform_device *pdev, if (IS_ERR(lvds->dphy)) return PTR_ERR(lvds->dphy); - phy_init(lvds->dphy); + ret = phy_init(lvds->dphy); if (ret) return ret; - phy_set_mode(lvds->dphy, PHY_MODE_LVDS); + ret = phy_set_mode(lvds->dphy, PHY_MODE_LVDS); if (ret) return ret; diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 80053d91a301f598b473e3d708f0e6460d3965d4..a6fe03c3748aad414911cddccc6062c712940432 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -349,8 +349,8 @@ static const struct vop_win_phy rk3066_win0_data = { .nformats = ARRAY_SIZE(formats_win_full), .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 0), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 4), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 19), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 4), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 19), .act_info = VOP_REG(RK3066_WIN0_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3066_WIN0_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN0_DSP_ST, 0x1fff1fff, 0), @@ -361,13 +361,12 @@ static const struct vop_win_phy rk3066_win0_data = { }; static const struct vop_win_phy rk3066_win1_data = { - .scl = &rk3066_win_scl, .data_formats = formats_win_full, .nformats = ARRAY_SIZE(formats_win_full), .format_modifiers = format_modifiers_win_full, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 1), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 7), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 23), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 7), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 23), .act_info = VOP_REG(RK3066_WIN1_ACT_INFO, 0x1fff1fff, 0), .dsp_info = VOP_REG(RK3066_WIN1_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN1_DSP_ST, 0x1fff1fff, 0), @@ -382,8 +381,8 @@ static const struct vop_win_phy rk3066_win2_data = { .nformats = ARRAY_SIZE(formats_win_lite), .format_modifiers = format_modifiers_win_lite, .enable = VOP_REG(RK3066_SYS_CTRL1, 0x1, 2), - .format = VOP_REG(RK3066_SYS_CTRL0, 0x7, 10), - .rb_swap = VOP_REG(RK3066_SYS_CTRL0, 0x1, 27), + .format = VOP_REG(RK3066_SYS_CTRL1, 0x7, 10), + .rb_swap = VOP_REG(RK3066_SYS_CTRL1, 0x1, 27), .dsp_info = VOP_REG(RK3066_WIN2_DSP_INFO, 0x0fff0fff, 0), .dsp_st = VOP_REG(RK3066_WIN2_DSP_ST, 0x1fff1fff, 0), .yrgb_mst = VOP_REG(RK3066_WIN2_MST, 0xffffffff, 0), @@ -408,6 +407,9 @@ static const struct vop_common rk3066_common = { .dither_down_en = VOP_REG(RK3066_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3066_DSP_CTRL0, 0x1, 10), .dsp_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 24), + .dither_up = VOP_REG(RK3066_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3066_SYS_CTRL1, 0x1, 31), + .data_blank = VOP_REG(RK3066_DSP_CTRL1, 0x1, 25), }; static const struct vop_win_data rk3066_vop_win_data[] = { @@ -505,7 +507,10 @@ static const struct vop_common rk3188_common = { .dither_down_sel = VOP_REG(RK3188_DSP_CTRL0, 0x1, 27), .dither_down_en = VOP_REG(RK3188_DSP_CTRL0, 0x1, 11), .dither_down_mode = VOP_REG(RK3188_DSP_CTRL0, 0x1, 10), - .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x3, 24), + .dsp_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 24), + .dither_up = VOP_REG(RK3188_DSP_CTRL0, 0x1, 9), + .dsp_lut_en = VOP_REG(RK3188_SYS_CTRL, 0x1, 28), + .data_blank = VOP_REG(RK3188_DSP_CTRL1, 0x1, 25), }; static const struct vop_win_data rk3188_vop_win_data[] = { diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 1463801189624a571c22c84370d80c4e33fc8246..3f7f761df4cd267e42ec73a6e7ffb61f06ea3d6b 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -113,7 +113,8 @@ static bool drm_sched_entity_is_idle(struct drm_sched_entity *entity) rmb(); /* for list_empty to work without lock */ if (list_empty(&entity->list) || - spsc_queue_count(&entity->job_queue) == 0) + spsc_queue_count(&entity->job_queue) == 0 || + entity->stopped) return true; return false; @@ -218,11 +219,16 @@ static void drm_sched_entity_kill_jobs_cb(struct dma_fence *f, static void drm_sched_entity_kill_jobs(struct drm_sched_entity *entity) { struct drm_sched_job *job; + struct dma_fence *f; int r; while ((job = to_drm_sched_job(spsc_queue_pop(&entity->job_queue)))) { struct drm_sched_fence *s_fence = job->s_fence; + /* Wait for all dependencies to avoid data corruptions */ + while ((f = job->sched->ops->dependency(job, entity))) + dma_fence_wait(f, false); + drm_sched_fence_scheduled(s_fence); dma_fence_set_error(&s_fence->finished, -ESRCH); diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index 7111e0f527b0b943b1bdcb042af9e0a13972be50..b6c2757c3d83f51b075a3bbab3fc3394304eaef2 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -887,9 +887,33 @@ EXPORT_SYMBOL(drm_sched_init); */ void drm_sched_fini(struct drm_gpu_scheduler *sched) { + struct drm_sched_entity *s_entity; + int i; + if (sched->thread) kthread_stop(sched->thread); + for (i = DRM_SCHED_PRIORITY_COUNT - 1; i >= DRM_SCHED_PRIORITY_MIN; i--) { + struct drm_sched_rq *rq = &sched->sched_rq[i]; + + if (!rq) + continue; + + spin_lock(&rq->lock); + list_for_each_entry(s_entity, &rq->entities, list) + /* + * Prevents reinsertion and marks job_queue as idle, + * it will removed from rq in drm_sched_entity_fini + * eventually + */ + s_entity->stopped = true; + spin_unlock(&rq->lock); + + } + + /* Wakeup everyone stuck in drm_sched_entity_flush for this scheduler */ + wake_up_all(&sched->job_scheduled); + /* Confirm no work left behind accessing device structures */ cancel_delayed_work_sync(&sched->work_tdr); diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 3aa9a7406085439e75ebefd39716527626a9dc48..ceb86338c003913a20700909c150dee474b10807 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -947,6 +947,11 @@ static const struct drm_plane_helper_funcs tegra_cursor_plane_helper_funcs = { .atomic_disable = tegra_cursor_atomic_disable, }; +static const uint64_t linear_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, struct tegra_dc *dc) { @@ -975,7 +980,7 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, &tegra_plane_funcs, formats, - num_formats, NULL, + num_formats, linear_modifiers, DRM_PLANE_TYPE_CURSOR, NULL); if (err < 0) { kfree(plane); @@ -1094,7 +1099,8 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, err = drm_universal_plane_init(drm, &plane->base, possible_crtcs, &tegra_plane_funcs, formats, - num_formats, NULL, type, NULL); + num_formats, linear_modifiers, + type, NULL); if (err < 0) { kfree(plane); return ERR_PTR(err); diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index e4baf07992a4da636228638d2db344ea4eb4ff0a..2c6ebc328b24f6c88a713ad43d16a142191084a1 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -1127,8 +1127,6 @@ static int host1x_drm_probe(struct host1x_device *dev) drm->mode_config.max_width = 4096; drm->mode_config.max_height = 4096; - drm->mode_config.allow_fb_modifiers = true; - drm->mode_config.normalize_zpos = true; drm->mode_config.funcs = &tegra_drm_mode_config_funcs; diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 1d2416d466a360a3830d9b8486a125c0594fd015..f4ccca922e44afc7a0af61790fcded73fbf1a5f2 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -1001,7 +1001,7 @@ static const struct vc4_pv_data bcm2711_pv3_data = { .fifo_depth = 64, .pixels_per_clock = 1, .encoder_types = { - [0] = VC4_ENCODER_TYPE_VEC, + [PV_CONTROL_CLK_SELECT_VEC] = VC4_ENCODER_TYPE_VEC, }, }; @@ -1042,6 +1042,9 @@ static void vc4_set_crtc_possible_masks(struct drm_device *drm, struct vc4_encoder *vc4_encoder; int i; + if (encoder->encoder_type == DRM_MODE_ENCODER_VIRTUAL) + continue; + vc4_encoder = to_vc4_encoder(encoder); for (i = 0; i < ARRAY_SIZE(pv_data->encoder_types); i++) { if (vc4_encoder->type == encoder_types[i]) { diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index c5f2944d5bc606f25216389db01b98cf0dee0f3f..9809c3a856c67ea7431cc0cec95e752435388063 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -837,7 +837,7 @@ void vc4_crtc_destroy_state(struct drm_crtc *crtc, void vc4_crtc_reset(struct drm_crtc *crtc); void vc4_crtc_handle_vblank(struct vc4_crtc *crtc); void vc4_crtc_get_margins(struct drm_crtc_state *state, - unsigned int *right, unsigned int *left, + unsigned int *left, unsigned int *right, unsigned int *top, unsigned int *bottom); /* vc4_debugfs.c */ diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index af5f01eff872c11d51bce1d829cc6a2af5931f2e..c58b8840090abad65a3cb7c9ed5fba6f99c0d185 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -146,6 +146,8 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) struct vc4_hdmi *vc4_hdmi = connector_to_vc4_hdmi(connector); bool connected = false; + WARN_ON(pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev)); + if (vc4_hdmi->hpd_gpio) { if (gpio_get_value_cansleep(vc4_hdmi->hpd_gpio) ^ vc4_hdmi->hpd_active_low) @@ -167,10 +169,12 @@ vc4_hdmi_connector_detect(struct drm_connector *connector, bool force) } } + pm_runtime_put(&vc4_hdmi->pdev->dev); return connector_status_connected; } cec_phys_addr_invalidate(vc4_hdmi->cec_adap); + pm_runtime_put(&vc4_hdmi->pdev->dev); return connector_status_disconnected; } @@ -415,7 +419,6 @@ static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_ENABLE); clk_disable_unprepare(vc4_hdmi->pixel_bvb_clock); - clk_disable_unprepare(vc4_hdmi->hsm_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock); ret = pm_runtime_put(&vc4_hdmi->pdev->dev); @@ -624,7 +627,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) unsigned long pixel_rate, hsm_rate; int ret; - ret = pm_runtime_get_sync(&vc4_hdmi->pdev->dev); + ret = pm_runtime_resume_and_get(&vc4_hdmi->pdev->dev); if (ret < 0) { DRM_ERROR("Failed to retain power domain: %d\n", ret); return; @@ -666,13 +669,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) return; } - ret = clk_prepare_enable(vc4_hdmi->hsm_clock); - if (ret) { - DRM_ERROR("Failed to turn on HSM clock: %d\n", ret); - clk_disable_unprepare(vc4_hdmi->pixel_clock); - return; - } - vc4_hdmi_cec_update_clk_div(vc4_hdmi); /* @@ -683,7 +679,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) (hsm_rate > VC4_HSM_MID_CLOCK ? 150000000 : 75000000)); if (ret) { DRM_ERROR("Failed to set pixel bvb clock rate: %d\n", ret); - clk_disable_unprepare(vc4_hdmi->hsm_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock); return; } @@ -691,7 +686,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) ret = clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); if (ret) { DRM_ERROR("Failed to turn on pixel bvb clock: %d\n", ret); - clk_disable_unprepare(vc4_hdmi->hsm_clock); clk_disable_unprepare(vc4_hdmi->pixel_clock); return; } @@ -1724,6 +1718,29 @@ static int vc5_hdmi_init_resources(struct vc4_hdmi *vc4_hdmi) return 0; } +#ifdef CONFIG_PM +static int vc4_hdmi_runtime_suspend(struct device *dev) +{ + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + + clk_disable_unprepare(vc4_hdmi->hsm_clock); + + return 0; +} + +static int vc4_hdmi_runtime_resume(struct device *dev) +{ + struct vc4_hdmi *vc4_hdmi = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(vc4_hdmi->hsm_clock); + if (ret) + return ret; + + return 0; +} +#endif + static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) { const struct vc4_hdmi_variant *variant = of_device_get_match_data(dev); @@ -1778,7 +1795,7 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) &hpd_gpio_flags); if (vc4_hdmi->hpd_gpio < 0) { ret = vc4_hdmi->hpd_gpio; - goto err_unprepare_hsm; + goto err_put_ddc; } vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; @@ -1790,6 +1807,14 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) if (vc4_hdmi->variant->reset) vc4_hdmi->variant->reset(vc4_hdmi); + if ((of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi0") || + of_device_is_compatible(dev->of_node, "brcm,bcm2711-hdmi1")) && + HDMI_READ(HDMI_VID_CTL) & VC4_HD_VID_CTL_ENABLE) { + clk_prepare_enable(vc4_hdmi->pixel_clock); + clk_prepare_enable(vc4_hdmi->hsm_clock); + clk_prepare_enable(vc4_hdmi->pixel_bvb_clock); + } + pm_runtime_enable(dev); drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS); @@ -1819,8 +1844,8 @@ err_destroy_conn: vc4_hdmi_connector_destroy(&vc4_hdmi->connector); err_destroy_encoder: drm_encoder_cleanup(encoder); -err_unprepare_hsm: pm_runtime_disable(dev); +err_put_ddc: put_device(&vc4_hdmi->ddc->dev); return ret; @@ -1959,11 +1984,18 @@ static const struct of_device_id vc4_hdmi_dt_match[] = { {} }; +static const struct dev_pm_ops vc4_hdmi_pm_ops = { + SET_RUNTIME_PM_OPS(vc4_hdmi_runtime_suspend, + vc4_hdmi_runtime_resume, + NULL) +}; + struct platform_driver vc4_hdmi_driver = { .probe = vc4_hdmi_dev_probe, .remove = vc4_hdmi_dev_remove, .driver = { .name = "vc4_hdmi", .of_match_table = vc4_hdmi_dt_match, + .pm = &vc4_hdmi_pm_ops, }, }; diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 849dcafbfff17d127531595a43acef379b7dcc9b..d13502ae973dd1e34c7dc095b620df6e16b26c13 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -503,7 +503,7 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data) return ret; encoder = &txp->connector.encoder; - encoder->possible_crtcs |= drm_crtc_mask(crtc); + encoder->possible_crtcs = drm_crtc_mask(crtc); ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0, dev_name(dev), txp); diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index eed57a9313098d652099e98132429a8b06f6aa7f..a28b01f9279335829b7d2efbe7f9ad0c3782fbc8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -209,6 +209,7 @@ err_scanouts: err_vbufs: vgdev->vdev->config->del_vqs(vgdev->vdev); err_vqs: + dev->dev_private = NULL; kfree(vgdev); return ret; } diff --git a/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h b/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h index 4db25bd9fa22d6a1882afe5c5ec314b25ff39162..127eaf0a0a5803eb2ec5faa1631c827c669995b8 100644 --- a/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h +++ b/drivers/gpu/drm/vmwgfx/device_include/svga3d_surfacedefs.h @@ -1467,6 +1467,7 @@ struct svga3dsurface_cache { /** * struct svga3dsurface_loc - Surface location + * @sheet: The multisample sheet. * @sub_resource: Surface subresource. Defined as layer * num_mip_levels + * mip_level. * @x: X coordinate. @@ -1474,6 +1475,7 @@ struct svga3dsurface_cache { * @z: Z coordinate. */ struct svga3dsurface_loc { + u32 sheet; u32 sub_resource; u32 x, y, z; }; @@ -1566,8 +1568,8 @@ svga3dsurface_get_loc(const struct svga3dsurface_cache *cache, u32 layer; int i; - if (offset >= cache->sheet_bytes) - offset %= cache->sheet_bytes; + loc->sheet = offset / cache->sheet_bytes; + offset -= loc->sheet * cache->sheet_bytes; layer = offset / cache->mip_chain_bytes; offset -= layer * cache->mip_chain_bytes; @@ -1631,6 +1633,7 @@ svga3dsurface_min_loc(const struct svga3dsurface_cache *cache, u32 sub_resource, struct svga3dsurface_loc *loc) { + loc->sheet = 0; loc->sub_resource = sub_resource; loc->x = loc->y = loc->z = 0; } @@ -1652,6 +1655,7 @@ svga3dsurface_max_loc(const struct svga3dsurface_cache *cache, const struct drm_vmw_size *size; u32 mip; + loc->sheet = 0; loc->sub_resource = sub_resource + 1; mip = sub_resource % cache->num_mip_levels; size = &cache->mip[mip].size; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index e67e2e8f6e6fa7299c7f6057a9955ea818c5c6a5..83e1b54eb8647d0a9cc3e0d8493172ed16d12349 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2759,12 +2759,24 @@ static int vmw_cmd_dx_genmips(struct vmw_private *dev_priv, { VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXGenMips) = container_of(header, typeof(*cmd), header); - struct vmw_resource *ret; + struct vmw_resource *view; + struct vmw_res_cache_entry *rcache; - ret = vmw_view_id_val_add(sw_context, vmw_view_sr, - cmd->body.shaderResourceViewId); + view = vmw_view_id_val_add(sw_context, vmw_view_sr, + cmd->body.shaderResourceViewId); + if (IS_ERR(view)) + return PTR_ERR(view); - return PTR_ERR_OR_ZERO(ret); + /* + * Normally the shader-resource view is not gpu-dirtying, but for + * this particular command it is... + * So mark the last looked-up surface, which is the surface + * the view points to, gpu-dirty. + */ + rcache = &sw_context->res_cache[vmw_res_surface]; + vmw_validation_res_set_dirty(sw_context->ctx, rcache->private, + VMW_RES_DIRTY_SET); + return 0; } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 3914bfee0533b578a176a2de9de51ceb33a2ea82..f493b20c7a38c98b06bf1b22687b4a3164986dd5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1802,6 +1802,19 @@ static void vmw_surface_tex_dirty_range_add(struct vmw_resource *res, svga3dsurface_get_loc(cache, &loc2, end - 1); svga3dsurface_inc_loc(cache, &loc2); + if (loc1.sheet != loc2.sheet) { + u32 sub_res; + + /* + * Multiple multisample sheets. To do this in an optimized + * fashion, compute the dirty region for each sheet and the + * resulting union. Since this is not a common case, just dirty + * the whole surface. + */ + for (sub_res = 0; sub_res < dirty->num_subres; ++sub_res) + vmw_subres_dirty_full(dirty, sub_res); + return; + } if (loc1.sub_resource + 1 == loc2.sub_resource) { /* Dirty range covers a single sub-resource */ vmw_subres_dirty_add(dirty, &loc1, &loc2); diff --git a/drivers/gpu/drm/zte/Kconfig b/drivers/gpu/drm/zte/Kconfig index 90ebaedc11fdf12231bde47a99fdc14373c1be09..aa8594190b5091983f48b479ffdf13d946a3fd6a 100644 --- a/drivers/gpu/drm/zte/Kconfig +++ b/drivers/gpu/drm/zte/Kconfig @@ -3,7 +3,6 @@ config DRM_ZTE tristate "DRM Support for ZTE SoCs" depends on DRM && ARCH_ZX select DRM_KMS_CMA_HELPER - select DRM_KMS_FB_HELPER select DRM_KMS_HELPER select SND_SOC_HDMI_CODEC if SND_SOC select VIDEOMODE_HELPERS diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0f69f35f2957ec4e394b1431f78ae88d1ef3be51..5550c943f98556fa94936e86549fd403f0c3717a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2306,12 +2306,8 @@ static int hid_device_remove(struct device *dev) { struct hid_device *hdev = to_hid_device(dev); struct hid_driver *hdrv; - int ret = 0; - if (down_interruptible(&hdev->driver_input_lock)) { - ret = -EINTR; - goto end; - } + down(&hdev->driver_input_lock); hdev->io_started = false; hdrv = hdev->driver; @@ -2326,8 +2322,8 @@ static int hid_device_remove(struct device *dev) if (!hdev->io_started) up(&hdev->driver_input_lock); -end: - return ret; + + return 0; } static ssize_t modalias_show(struct device *dev, struct device_attribute *a, diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 195910dd2154e2e5471df45a17f4454ffa219787..e3835407e8d2399686121ce5f02afb708016c09b 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -122,7 +122,7 @@ #define WACOM_HID_WD_TOUCHONOFF (WACOM_HID_UP_WACOMDIGITIZER | 0x0454) #define WACOM_HID_WD_BATTERY_LEVEL (WACOM_HID_UP_WACOMDIGITIZER | 0x043b) #define WACOM_HID_WD_EXPRESSKEY00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0910) -#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0950) +#define WACOM_HID_WD_EXPRESSKEYCAP00 (WACOM_HID_UP_WACOMDIGITIZER | 0x0940) #define WACOM_HID_WD_MODE_CHANGE (WACOM_HID_UP_WACOMDIGITIZER | 0x0980) #define WACOM_HID_WD_MUTE_DEVICE (WACOM_HID_UP_WACOMDIGITIZER | 0x0981) #define WACOM_HID_WD_CONTROLPANEL (WACOM_HID_UP_WACOMDIGITIZER | 0x0982) diff --git a/drivers/hv/connection.c b/drivers/hv/connection.c index 11170d9a2e1a533b6c3a9c1bf93dd2662c92981a..bfd7f00a59ecf501edfc676ff19f0e04055dc1c5 100644 --- a/drivers/hv/connection.c +++ b/drivers/hv/connection.c @@ -229,8 +229,10 @@ int vmbus_connect(void) */ for (i = 0; ; i++) { - if (i == ARRAY_SIZE(vmbus_versions)) + if (i == ARRAY_SIZE(vmbus_versions)) { + ret = -EDOM; goto cleanup; + } version = vmbus_versions[i]; if (version > max_version) diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c index 05566ecdbe4b4b2fa0504c1d485dbfcbc8f2b083..1b914e418e41ed0a36d352535d41a0a0e47e7e87 100644 --- a/drivers/hv/hv_util.c +++ b/drivers/hv/hv_util.c @@ -696,8 +696,8 @@ static int hv_timesync_init(struct hv_util_service *srv) */ hv_ptp_clock = ptp_clock_register(&ptp_hyperv_info, NULL); if (IS_ERR_OR_NULL(hv_ptp_clock)) { - pr_err("cannot register PTP clock: %ld\n", - PTR_ERR(hv_ptp_clock)); + pr_err("cannot register PTP clock: %d\n", + PTR_ERR_OR_ZERO(hv_ptp_clock)); hv_ptp_clock = NULL; } diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index ae2b84263a4455a4ed5258e6d272adc945565f1f..6b884ea0098778e5695a19590e64fe9664569e75 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -22,10 +22,10 @@ #include <linux/hwmon.h> #include <linux/mutex.h> #include <linux/mod_devicetable.h> +#include <linux/of.h> +#include <linux/property.h> #include <linux/spi/spi.h> #include <linux/slab.h> -#include <linux/of_device.h> -#include <linux/acpi.h> #define DRVNAME "lm70" @@ -148,50 +148,17 @@ static const struct of_device_id lm70_of_ids[] = { MODULE_DEVICE_TABLE(of, lm70_of_ids); #endif -#ifdef CONFIG_ACPI -static const struct acpi_device_id lm70_acpi_ids[] = { - { - .id = "LM000070", - .driver_data = LM70_CHIP_LM70, - }, - { - .id = "TMP00121", - .driver_data = LM70_CHIP_TMP121, - }, - { - .id = "LM000071", - .driver_data = LM70_CHIP_LM71, - }, - { - .id = "LM000074", - .driver_data = LM70_CHIP_LM74, - }, - {}, -}; -MODULE_DEVICE_TABLE(acpi, lm70_acpi_ids); -#endif - static int lm70_probe(struct spi_device *spi) { - const struct of_device_id *of_match; struct device *hwmon_dev; struct lm70 *p_lm70; int chip; - of_match = of_match_device(lm70_of_ids, &spi->dev); - if (of_match) - chip = (int)(uintptr_t)of_match->data; - else { -#ifdef CONFIG_ACPI - const struct acpi_device_id *acpi_match; - - acpi_match = acpi_match_device(lm70_acpi_ids, &spi->dev); - if (acpi_match) - chip = (int)(uintptr_t)acpi_match->driver_data; - else -#endif - chip = spi_get_device_id(spi)->driver_data; - } + if (dev_fwnode(&spi->dev)) + chip = (int)(uintptr_t)device_get_match_data(&spi->dev); + else + chip = spi_get_device_id(spi)->driver_data; + /* signaling is SPI_MODE_0 */ if (spi->mode & (SPI_CPOL | SPI_CPHA)) @@ -227,7 +194,6 @@ static struct spi_driver lm70_driver = { .driver = { .name = "lm70", .of_match_table = of_match_ptr(lm70_of_ids), - .acpi_match_table = ACPI_PTR(lm70_acpi_ids), }, .id_table = lm70_ids, .probe = lm70_probe, diff --git a/drivers/hwmon/max31722.c b/drivers/hwmon/max31722.c index 062eceb7be0db3c6518c5d4856d6abe685fce0fe..613338cbcb170f478e9ea8ef18e40cf91392607e 100644 --- a/drivers/hwmon/max31722.c +++ b/drivers/hwmon/max31722.c @@ -6,7 +6,6 @@ * Copyright (c) 2016, Intel Corporation. */ -#include <linux/acpi.h> #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/kernel.h> @@ -133,20 +132,12 @@ static const struct spi_device_id max31722_spi_id[] = { {"max31723", 0}, {} }; - -static const struct acpi_device_id __maybe_unused max31722_acpi_id[] = { - {"MAX31722", 0}, - {"MAX31723", 0}, - {} -}; - MODULE_DEVICE_TABLE(spi, max31722_spi_id); static struct spi_driver max31722_driver = { .driver = { .name = "max31722", .pm = &max31722_pm_ops, - .acpi_match_table = ACPI_PTR(max31722_acpi_id), }, .probe = max31722_probe, .remove = max31722_remove, diff --git a/drivers/hwmon/max31790.c b/drivers/hwmon/max31790.c index 86e6c71db685cd9086597ce38bb799a8f42a5c86..67677c43776879721e1149ed8e04799ebac83f26 100644 --- a/drivers/hwmon/max31790.c +++ b/drivers/hwmon/max31790.c @@ -27,6 +27,7 @@ /* Fan Config register bits */ #define MAX31790_FAN_CFG_RPM_MODE 0x80 +#define MAX31790_FAN_CFG_CTRL_MON 0x10 #define MAX31790_FAN_CFG_TACH_INPUT_EN 0x08 #define MAX31790_FAN_CFG_TACH_INPUT 0x01 @@ -104,7 +105,7 @@ static struct max31790_data *max31790_update_device(struct device *dev) data->tach[NR_CHANNEL + i] = rv; } else { rv = i2c_smbus_read_word_swapped(client, - MAX31790_REG_PWMOUT(i)); + MAX31790_REG_PWM_DUTY_CYCLE(i)); if (rv < 0) goto abort; data->pwm[i] = rv; @@ -170,7 +171,7 @@ static int max31790_read_fan(struct device *dev, u32 attr, int channel, switch (attr) { case hwmon_fan_input: - sr = get_tach_period(data->fan_dynamics[channel]); + sr = get_tach_period(data->fan_dynamics[channel % NR_CHANNEL]); rpm = RPM_FROM_REG(data->tach[channel], sr); *val = rpm; return 0; @@ -271,12 +272,12 @@ static int max31790_read_pwm(struct device *dev, u32 attr, int channel, *val = data->pwm[channel] >> 8; return 0; case hwmon_pwm_enable: - if (fan_config & MAX31790_FAN_CFG_RPM_MODE) + if (fan_config & MAX31790_FAN_CFG_CTRL_MON) + *val = 0; + else if (fan_config & MAX31790_FAN_CFG_RPM_MODE) *val = 2; - else if (fan_config & MAX31790_FAN_CFG_TACH_INPUT_EN) - *val = 1; else - *val = 0; + *val = 1; return 0; default: return -EOPNOTSUPP; @@ -299,31 +300,41 @@ static int max31790_write_pwm(struct device *dev, u32 attr, int channel, err = -EINVAL; break; } - data->pwm[channel] = val << 8; + data->valid = false; err = i2c_smbus_write_word_swapped(client, MAX31790_REG_PWMOUT(channel), - data->pwm[channel]); + val << 8); break; case hwmon_pwm_enable: fan_config = data->fan_config[channel]; if (val == 0) { - fan_config &= ~(MAX31790_FAN_CFG_TACH_INPUT_EN | - MAX31790_FAN_CFG_RPM_MODE); + fan_config |= MAX31790_FAN_CFG_CTRL_MON; + /* + * Disable RPM mode; otherwise disabling fan speed + * monitoring is not possible. + */ + fan_config &= ~MAX31790_FAN_CFG_RPM_MODE; } else if (val == 1) { - fan_config = (fan_config | - MAX31790_FAN_CFG_TACH_INPUT_EN) & - ~MAX31790_FAN_CFG_RPM_MODE; + fan_config &= ~(MAX31790_FAN_CFG_CTRL_MON | MAX31790_FAN_CFG_RPM_MODE); } else if (val == 2) { - fan_config |= MAX31790_FAN_CFG_TACH_INPUT_EN | - MAX31790_FAN_CFG_RPM_MODE; + fan_config &= ~MAX31790_FAN_CFG_CTRL_MON; + /* + * The chip sets MAX31790_FAN_CFG_TACH_INPUT_EN on its + * own if MAX31790_FAN_CFG_RPM_MODE is set. + * Do it here as well to reflect the actual register + * value in the cache. + */ + fan_config |= (MAX31790_FAN_CFG_RPM_MODE | MAX31790_FAN_CFG_TACH_INPUT_EN); } else { err = -EINVAL; break; } - data->fan_config[channel] = fan_config; - err = i2c_smbus_write_byte_data(client, - MAX31790_REG_FAN_CONFIG(channel), - fan_config); + if (fan_config != data->fan_config[channel]) { + err = i2c_smbus_write_byte_data(client, MAX31790_REG_FAN_CONFIG(channel), + fan_config); + if (!err) + data->fan_config[channel] = fan_config; + } break; default: err = -EOPNOTSUPP; diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c index cc9e8025c533c018942d5fb5e9b751fb8873a228..424c296845dbb49c402d71de0012879928a8bd46 100644 --- a/drivers/hwtracing/coresight/coresight-core.c +++ b/drivers/hwtracing/coresight/coresight-core.c @@ -581,7 +581,7 @@ static struct coresight_device * coresight_find_enabled_sink(struct coresight_device *csdev) { int i; - struct coresight_device *sink; + struct coresight_device *sink = NULL; if ((csdev->type == CORESIGHT_DEV_TYPE_SINK || csdev->type == CORESIGHT_DEV_TYPE_LINKSINK) && @@ -1347,7 +1347,7 @@ static int coresight_fixup_device_conns(struct coresight_device *csdev) } } - return 0; + return ret; } static int coresight_remove_match(struct device *dev, void *data) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 989d965f3d901116febcab17cbb42ded636e2809..8978f3410bee5c05711fc700e52a747d08de284d 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -528,7 +528,7 @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, buf_ptr = buf->data_pages[cur] + offset; *buf_ptr = readl_relaxed(drvdata->base + TMC_RRD); - if (lost && *barrier) { + if (lost && i < CORESIGHT_BARRIER_PKT_SIZE) { *buf_ptr = *barrier; barrier++; } diff --git a/drivers/hwtracing/intel_th/core.c b/drivers/hwtracing/intel_th/core.c index c9ac3dc651135d156915f425ce9c232c94e568ad..9cb8c7d13d46b93b1bf66ecaa0de85cd07d9953e 100644 --- a/drivers/hwtracing/intel_th/core.c +++ b/drivers/hwtracing/intel_th/core.c @@ -215,6 +215,22 @@ static ssize_t port_show(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR_RO(port); +static void intel_th_trace_prepare(struct intel_th_device *thdev) +{ + struct intel_th_device *hub = to_intel_th_hub(thdev); + struct intel_th_driver *hubdrv = to_intel_th_driver(hub->dev.driver); + + if (hub->type != INTEL_TH_SWITCH) + return; + + if (thdev->type != INTEL_TH_OUTPUT) + return; + + pm_runtime_get_sync(&thdev->dev); + hubdrv->prepare(hub, &thdev->output); + pm_runtime_put(&thdev->dev); +} + static int intel_th_output_activate(struct intel_th_device *thdev) { struct intel_th_driver *thdrv = @@ -235,6 +251,7 @@ static int intel_th_output_activate(struct intel_th_device *thdev) if (ret) goto fail_put; + intel_th_trace_prepare(thdev); if (thdrv->activate) ret = thdrv->activate(thdev); else diff --git a/drivers/hwtracing/intel_th/gth.c b/drivers/hwtracing/intel_th/gth.c index 28509b02a0b563ab81b2229880d57a533fdbf8e3..b3308934a687dfbf8b24af75c620bfa72d5ea028 100644 --- a/drivers/hwtracing/intel_th/gth.c +++ b/drivers/hwtracing/intel_th/gth.c @@ -564,6 +564,21 @@ static void gth_tscu_resync(struct gth_device *gth) iowrite32(reg, gth->base + REG_TSCU_TSUCTRL); } +static void intel_th_gth_prepare(struct intel_th_device *thdev, + struct intel_th_output *output) +{ + struct gth_device *gth = dev_get_drvdata(&thdev->dev); + int count; + + /* + * Wait until the output port is in reset before we start + * programming it. + */ + for (count = GTH_PLE_WAITLOOP_DEPTH; + count && !(gth_output_get(gth, output->port) & BIT(5)); count--) + cpu_relax(); +} + /** * intel_th_gth_enable() - enable tracing to an output device * @thdev: GTH device @@ -815,6 +830,7 @@ static struct intel_th_driver intel_th_gth_driver = { .assign = intel_th_gth_assign, .unassign = intel_th_gth_unassign, .set_output = intel_th_gth_set_output, + .prepare = intel_th_gth_prepare, .enable = intel_th_gth_enable, .trig_switch = intel_th_gth_switch, .disable = intel_th_gth_disable, diff --git a/drivers/hwtracing/intel_th/intel_th.h b/drivers/hwtracing/intel_th/intel_th.h index 5fe694708b7a3117991900ea89028b366ae18810..595615b791086236bee35840ca7d77b5a85b98c2 100644 --- a/drivers/hwtracing/intel_th/intel_th.h +++ b/drivers/hwtracing/intel_th/intel_th.h @@ -143,6 +143,7 @@ intel_th_output_assigned(struct intel_th_device *thdev) * @remove: remove method * @assign: match a given output type device against available outputs * @unassign: deassociate an output type device from an output port + * @prepare: prepare output port for tracing * @enable: enable tracing for a given output device * @disable: disable tracing for a given output device * @irq: interrupt callback @@ -164,6 +165,8 @@ struct intel_th_driver { struct intel_th_device *othdev); void (*unassign)(struct intel_th_device *thdev, struct intel_th_device *othdev); + void (*prepare)(struct intel_th_device *thdev, + struct intel_th_output *output); void (*enable)(struct intel_th_device *thdev, struct intel_th_output *output); void (*trig_switch)(struct intel_th_device *thdev, diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index e42b87e96f74741f5d87506742474dc278f49770..eab6fd6b890ebe3e7750a2333f223c886e6d250f 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -974,6 +974,9 @@ static s32 i801_access(struct i2c_adapter *adap, u16 addr, } out: + /* Unlock the SMBus device for use by BIOS/ACPI */ + outb_p(SMBHSTSTS_INUSE_STS, SMBHSTSTS(priv)); + pm_runtime_mark_last_busy(&priv->pci_dev->dev); pm_runtime_put_autosuspend(&priv->pci_dev->dev); mutex_unlock(&priv->acpi_lock); diff --git a/drivers/i2c/busses/i2c-robotfuzz-osif.c b/drivers/i2c/busses/i2c-robotfuzz-osif.c index a39f7d09279737ff4b847a42a36809deb17bf635..66dfa211e736b1a8a7d0e9392f8dfad95eeac569 100644 --- a/drivers/i2c/busses/i2c-robotfuzz-osif.c +++ b/drivers/i2c/busses/i2c-robotfuzz-osif.c @@ -83,7 +83,7 @@ static int osif_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, } } - ret = osif_usb_read(adapter, OSIFI2C_STOP, 0, 0, NULL, 0); + ret = osif_usb_write(adapter, OSIFI2C_STOP, 0, 0, NULL, 0); if (ret) { dev_err(&adapter->dev, "failure sending STOP\n"); return -EREMOTEIO; @@ -153,7 +153,7 @@ static int osif_probe(struct usb_interface *interface, * Set bus frequency. The frequency is: * 120,000,000 / ( 16 + 2 * div * 4^prescale). * Using dev = 52, prescale = 0 give 100KHz */ - ret = osif_usb_read(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0, + ret = osif_usb_write(&priv->adapter, OSIFI2C_SET_BIT_RATE, 52, 0, NULL, 0); if (ret) { dev_err(&interface->dev, "failure sending bit rate"); diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index c13e7f107dd36cf3fc912b8ba8d8f678b11f5bbd..bdce6d3e532733339d5adca07f075b9c914988e2 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -24,6 +24,7 @@ #include <linux/i2c-smbus.h> #include <linux/idr.h> #include <linux/init.h> +#include <linux/interrupt.h> #include <linux/irqflags.h> #include <linux/jump_label.h> #include <linux/kernel.h> @@ -585,6 +586,8 @@ static void i2c_device_shutdown(struct device *dev) driver = to_i2c_driver(dev->driver); if (driver->shutdown) driver->shutdown(client); + else if (client->irq > 0) + disable_irq(client->irq); } static void i2c_client_dev_release(struct device *dev) diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c index 6b74c2b04c157dd254d5b19e8bed36c9733ea306..da56488182d0754cc6bbeeb017c28fc5b602e8cd 100644 --- a/drivers/iio/accel/bma180.c +++ b/drivers/iio/accel/bma180.c @@ -55,7 +55,7 @@ struct bma180_part_info { u8 int_reset_reg, int_reset_mask; u8 sleep_reg, sleep_mask; - u8 bw_reg, bw_mask; + u8 bw_reg, bw_mask, bw_offset; u8 scale_reg, scale_mask; u8 power_reg, power_mask, lowpower_val; u8 int_enable_reg, int_enable_mask; @@ -127,6 +127,7 @@ struct bma180_part_info { #define BMA250_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ #define BMA250_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ +#define BMA250_BW_OFFSET 8 #define BMA250_SUSPEND_MASK BIT(7) /* chip will sleep */ #define BMA250_LOWPOWER_MASK BIT(6) #define BMA250_DATA_INTEN_MASK BIT(4) @@ -143,6 +144,7 @@ struct bma180_part_info { #define BMA254_RANGE_MASK GENMASK(3, 0) /* Range of accel values */ #define BMA254_BW_MASK GENMASK(4, 0) /* Accel bandwidth */ +#define BMA254_BW_OFFSET 8 #define BMA254_SUSPEND_MASK BIT(7) /* chip will sleep */ #define BMA254_LOWPOWER_MASK BIT(6) #define BMA254_DATA_INTEN_MASK BIT(4) @@ -162,7 +164,11 @@ struct bma180_data { int scale; int bw; bool pmode; - u8 buff[16]; /* 3x 16-bit + 8-bit + padding + timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + s16 chan[4]; + s64 timestamp __aligned(8); + } scan; }; enum bma180_chan { @@ -283,7 +289,8 @@ static int bma180_set_bw(struct bma180_data *data, int val) for (i = 0; i < data->part_info->num_bw; ++i) { if (data->part_info->bw_table[i] == val) { ret = bma180_set_bits(data, data->part_info->bw_reg, - data->part_info->bw_mask, i); + data->part_info->bw_mask, + i + data->part_info->bw_offset); if (ret) { dev_err(&data->client->dev, "failed to set bandwidth\n"); @@ -876,6 +883,7 @@ static const struct bma180_part_info bma180_part_info[] = { .sleep_mask = BMA250_SUSPEND_MASK, .bw_reg = BMA250_BW_REG, .bw_mask = BMA250_BW_MASK, + .bw_offset = BMA250_BW_OFFSET, .scale_reg = BMA250_RANGE_REG, .scale_mask = BMA250_RANGE_MASK, .power_reg = BMA250_POWER_REG, @@ -905,6 +913,7 @@ static const struct bma180_part_info bma180_part_info[] = { .sleep_mask = BMA254_SUSPEND_MASK, .bw_reg = BMA254_BW_REG, .bw_mask = BMA254_BW_MASK, + .bw_offset = BMA254_BW_OFFSET, .scale_reg = BMA254_RANGE_REG, .scale_mask = BMA254_RANGE_MASK, .power_reg = BMA254_POWER_REG, @@ -938,12 +947,12 @@ static irqreturn_t bma180_trigger_handler(int irq, void *p) mutex_unlock(&data->mutex); goto err; } - ((s16 *)data->buff)[i++] = ret; + data->scan.chan[i++] = ret; } mutex_unlock(&data->mutex); - iio_push_to_buffers_with_timestamp(indio_dev, data->buff, time_ns); + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c index 3c9b0c6954e60ff7a73b0bd9a49b65283a33cb4f..e8a9db1a82ad88c76e11c5ac62ba67894ad7a36b 100644 --- a/drivers/iio/accel/bma220_spi.c +++ b/drivers/iio/accel/bma220_spi.c @@ -63,7 +63,11 @@ static const int bma220_scale_table[][2] = { struct bma220_data { struct spi_device *spi_device; struct mutex lock; - s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 8x8 timestamp */ + struct { + s8 chans[3]; + /* Ensure timestamp is naturally aligned. */ + s64 timestamp __aligned(8); + } scan; u8 tx_buf[2] ____cacheline_aligned; }; @@ -94,12 +98,12 @@ static irqreturn_t bma220_trigger_handler(int irq, void *p) mutex_lock(&data->lock); data->tx_buf[0] = BMA220_REG_ACCEL_X | BMA220_READ_MASK; - ret = spi_write_then_read(spi, data->tx_buf, 1, data->buffer, + ret = spi_write_then_read(spi, data->tx_buf, 1, &data->scan.chans, ARRAY_SIZE(bma220_channels) - 1); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: mutex_unlock(&data->lock); diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 4c5e594024f8ca0c9a0d91fda8e695446f2a5de3..f05840d17fb71fe220faf38520c7855415455c28 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -27,8 +27,11 @@ struct accel_3d_state { struct hid_sensor_hub_callbacks callbacks; struct hid_sensor_common common_attributes; struct hid_sensor_hub_attribute_info accel[ACCEL_3D_CHANNEL_MAX]; - /* Reserve for 3 channels + padding + timestamp */ - u32 accel_val[ACCEL_3D_CHANNEL_MAX + 3]; + /* Ensure timestamp is naturally aligned */ + struct { + u32 accel_val[3]; + s64 timestamp __aligned(8); + } scan; int scale_pre_decml; int scale_post_decml; int scale_precision; @@ -239,8 +242,8 @@ static int accel_3d_proc_event(struct hid_sensor_hub_device *hsdev, accel_state->timestamp = iio_get_time_ns(indio_dev); hid_sensor_push_data(indio_dev, - accel_state->accel_val, - sizeof(accel_state->accel_val), + &accel_state->scan, + sizeof(accel_state->scan), accel_state->timestamp); accel_state->timestamp = 0; @@ -265,7 +268,7 @@ static int accel_3d_capture_sample(struct hid_sensor_hub_device *hsdev, case HID_USAGE_SENSOR_ACCEL_Y_AXIS: case HID_USAGE_SENSOR_ACCEL_Z_AXIS: offset = usage_id - HID_USAGE_SENSOR_ACCEL_X_AXIS; - accel_state->accel_val[CHANNEL_SCAN_INDEX_X + offset] = + accel_state->scan.accel_val[CHANNEL_SCAN_INDEX_X + offset] = *(u32 *)raw_data; ret = 0; break; diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c index 560a3373ff20d769da08651759e2ca86c3e2c96f..c99e90469a245cc3d8e65c347a33abc17a4aa6d3 100644 --- a/drivers/iio/accel/kxcjk-1013.c +++ b/drivers/iio/accel/kxcjk-1013.c @@ -132,13 +132,24 @@ enum kx_acpi_type { ACPI_KIOX010A, }; +enum kxcjk1013_axis { + AXIS_X, + AXIS_Y, + AXIS_Z, + AXIS_MAX +}; + struct kxcjk1013_data { struct i2c_client *client; struct iio_trigger *dready_trig; struct iio_trigger *motion_trig; struct iio_mount_matrix orientation; struct mutex mutex; - s16 buffer[8]; + /* Ensure timestamp naturally aligned */ + struct { + s16 chans[AXIS_MAX]; + s64 timestamp __aligned(8); + } scan; u8 odr_bits; u8 range; int wake_thres; @@ -152,13 +163,6 @@ struct kxcjk1013_data { enum kx_acpi_type acpi_type; }; -enum kxcjk1013_axis { - AXIS_X, - AXIS_Y, - AXIS_Z, - AXIS_MAX, -}; - enum kxcjk1013_mode { STANDBY, OPERATION, @@ -1092,12 +1096,12 @@ static irqreturn_t kxcjk1013_trigger_handler(int irq, void *p) ret = i2c_smbus_read_i2c_block_data_or_emulated(data->client, KXCJK1013_REG_XOUT_L, AXIS_MAX * 2, - (u8 *)data->buffer); + (u8 *)data->scan.chans); mutex_unlock(&data->mutex); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, data->timestamp); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c index f877263dc6efbdf4535a179b5b0b8fa94136de47..5a2b0ffbb145d51fa303f9844e50cb24c571bcc2 100644 --- a/drivers/iio/accel/mxc4005.c +++ b/drivers/iio/accel/mxc4005.c @@ -56,7 +56,11 @@ struct mxc4005_data { struct mutex mutex; struct regmap *regmap; struct iio_trigger *dready_trig; - __be16 buffer[8]; + /* Ensure timestamp is naturally aligned */ + struct { + __be16 chans[3]; + s64 timestamp __aligned(8); + } scan; bool trigger_enabled; }; @@ -135,7 +139,7 @@ static int mxc4005_read_xyz(struct mxc4005_data *data) int ret; ret = regmap_bulk_read(data->regmap, MXC4005_REG_XOUT_UPPER, - data->buffer, sizeof(data->buffer)); + data->scan.chans, sizeof(data->scan.chans)); if (ret < 0) { dev_err(data->dev, "failed to read axes\n"); return ret; @@ -301,7 +305,7 @@ static irqreturn_t mxc4005_trigger_handler(int irq, void *private) if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c index 3b59887a8581bcd49a925a290ebe7cbe6d6d58a3..7d24801e8aa7c27311cc293ecc6b08ac9d1e76da 100644 --- a/drivers/iio/accel/stk8312.c +++ b/drivers/iio/accel/stk8312.c @@ -103,7 +103,11 @@ struct stk8312_data { u8 mode; struct iio_trigger *dready_trig; bool dready_trigger_on; - s8 buffer[16]; /* 3x8-bit channels + 5x8 padding + 64-bit timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + s8 chans[3]; + s64 timestamp __aligned(8); + } scan; }; static IIO_CONST_ATTR(in_accel_scale_available, STK8312_SCALE_AVAIL); @@ -438,7 +442,7 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) ret = i2c_smbus_read_i2c_block_data(data->client, STK8312_REG_XOUT, STK8312_ALL_CHANNEL_SIZE, - data->buffer); + data->scan.chans); if (ret < STK8312_ALL_CHANNEL_SIZE) { dev_err(&data->client->dev, "register read failed\n"); mutex_unlock(&data->lock); @@ -452,12 +456,12 @@ static irqreturn_t stk8312_trigger_handler(int irq, void *p) mutex_unlock(&data->lock); goto err; } - data->buffer[i++] = ret; + data->scan.chans[i++] = ret; } } mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c index 3ead378b02c9b395ffa22ed520b7a287d8763499..e8087d7ee49f9a23aeb238d90bce7fdef69295e3 100644 --- a/drivers/iio/accel/stk8ba50.c +++ b/drivers/iio/accel/stk8ba50.c @@ -91,12 +91,11 @@ struct stk8ba50_data { u8 sample_rate_idx; struct iio_trigger *dready_trig; bool dready_trigger_on; - /* - * 3 x 16-bit channels (10-bit data, 6-bit padding) + - * 1 x 16 padding + - * 4 x 16 64-bit timestamp - */ - s16 buffer[8]; + /* Ensure timestamp is naturally aligned */ + struct { + s16 chans[3]; + s64 timetamp __aligned(8); + } scan; }; #define STK8BA50_ACCEL_CHANNEL(index, reg, axis) { \ @@ -324,7 +323,7 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) ret = i2c_smbus_read_i2c_block_data(data->client, STK8BA50_REG_XOUT, STK8BA50_ALL_CHANNEL_SIZE, - (u8 *)data->buffer); + (u8 *)data->scan.chans); if (ret < STK8BA50_ALL_CHANNEL_SIZE) { dev_err(&data->client->dev, "register read failed\n"); goto err; @@ -337,10 +336,10 @@ static irqreturn_t stk8ba50_trigger_handler(int irq, void *p) if (ret < 0) goto err; - data->buffer[i++] = ret; + data->scan.chans[i++] = ret; } } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: mutex_unlock(&data->lock); diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index b917a4714a9c95e8499cbe64d3e0234d53bb49c4..b8139c435a4b0dc5d16f88393400ede3a4012024 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -403,7 +403,8 @@ struct at91_adc_state { struct at91_adc_dma dma_st; struct at91_adc_touch touch_st; struct iio_dev *indio_dev; - u16 buffer[AT91_BUFFER_MAX_HWORDS]; + /* Ensure naturally aligned timestamp */ + u16 buffer[AT91_BUFFER_MAX_HWORDS] __aligned(8); /* * lock to prevent concurrent 'single conversion' requests through * sysfs. diff --git a/drivers/iio/adc/hx711.c b/drivers/iio/adc/hx711.c index 6a173531d355bab573dd874db2cd9fdbeb3c5af1..f7ee856a6b8b6a66b319cfd7dc60ebe95899d9ba 100644 --- a/drivers/iio/adc/hx711.c +++ b/drivers/iio/adc/hx711.c @@ -86,9 +86,9 @@ struct hx711_data { struct mutex lock; /* * triggered buffer - * 2x32-bit channel + 64-bit timestamp + * 2x32-bit channel + 64-bit naturally aligned timestamp */ - u32 buffer[4]; + u32 buffer[4] __aligned(8); /* * delay after a rising edge on SCK until the data is ready DOUT * this is dependent on the hx711 where the datasheet tells a diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c index 30e29f44ebd2ee6bf3ac8bc950a8e043f44ae214..c480cb489c1a32afa80bd13a049fe08991afef3f 100644 --- a/drivers/iio/adc/mxs-lradc-adc.c +++ b/drivers/iio/adc/mxs-lradc-adc.c @@ -115,7 +115,8 @@ struct mxs_lradc_adc { struct device *dev; void __iomem *base; - u32 buffer[10]; + /* Maximum of 8 channels + 8 byte ts */ + u32 buffer[10] __aligned(8); struct iio_trigger *trig; struct completion completion; spinlock_t lock; diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index 9fef39bcf997b90be945c25942489aa6f2842333..5b828428be77c4f3090de453907633e4797a25b9 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -395,10 +395,14 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct ads1015_data *data = iio_priv(indio_dev); - s16 buf[8]; /* 1x s16 ADC val + 3x s16 padding + 4x s16 timestamp */ + /* Ensure natural alignment of timestamp */ + struct { + s16 chan; + s64 timestamp __aligned(8); + } scan; int chan, ret, res; - memset(buf, 0, sizeof(buf)); + memset(&scan, 0, sizeof(scan)); mutex_lock(&data->lock); chan = find_first_bit(indio_dev->active_scan_mask, @@ -409,10 +413,10 @@ static irqreturn_t ads1015_trigger_handler(int irq, void *p) goto err; } - buf[0] = res; + scan.chan = res; mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, buf, + iio_push_to_buffers_with_timestamp(indio_dev, &scan, iio_get_time_ns(indio_dev)); err: diff --git a/drivers/iio/adc/ti-ads8688.c b/drivers/iio/adc/ti-ads8688.c index 16bcb37eebb721236eefd6f1510267f74093d338..79c803537dc4233be7aa6c044cf2c8a63dd53879 100644 --- a/drivers/iio/adc/ti-ads8688.c +++ b/drivers/iio/adc/ti-ads8688.c @@ -383,7 +383,8 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; - u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)]; + /* Ensure naturally aligned timestamp */ + u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)] __aligned(8); int i, j = 0; for (i = 0; i < indio_dev->masklength; i++) { diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c index d14851b4b344959f3293502c3f1c1f9328307816..1d4d3cfc8965c08c27b45124f31ada2592b1a9a9 100644 --- a/drivers/iio/adc/vf610_adc.c +++ b/drivers/iio/adc/vf610_adc.c @@ -167,7 +167,11 @@ struct vf610_adc { u32 sample_freq_avail[5]; struct completion completion; - u16 buffer[8]; + /* Ensure the timestamp is naturally aligned */ + struct { + u16 chan; + s64 timestamp __aligned(8); + } scan; }; static const u32 vf610_hw_avgs[] = { 1, 4, 8, 16, 32 }; @@ -579,9 +583,9 @@ static irqreturn_t vf610_adc_isr(int irq, void *dev_id) if (coco & VF610_ADC_HS_COCO0) { info->value = vf610_adc_read_data(info); if (iio_buffer_enabled(indio_dev)) { - info->buffer[0] = info->value; + info->scan.chan = info->value; iio_push_to_buffers_with_timestamp(indio_dev, - info->buffer, + &info->scan, iio_get_time_ns(indio_dev)); iio_trigger_notify_done(indio_dev->trig); } else diff --git a/drivers/iio/chemical/atlas-sensor.c b/drivers/iio/chemical/atlas-sensor.c index cdab9d04dedd0d2dd5fd2904c9d756d6e1eb4210..0c8a50de894084c1dc0216dc2c13e7ad20e4ffd0 100644 --- a/drivers/iio/chemical/atlas-sensor.c +++ b/drivers/iio/chemical/atlas-sensor.c @@ -91,8 +91,8 @@ struct atlas_data { struct regmap *regmap; struct irq_work work; unsigned int interrupt_enabled; - - __be32 buffer[6]; /* 96-bit data + 32-bit pad + 64-bit timestamp */ + /* 96-bit data + 32-bit pad + 64-bit timestamp */ + __be32 buffer[6] __aligned(8); }; static const struct regmap_config atlas_regmap_config = { diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index 82c050a3899d9f4f2558339979fd0ec7df7c6680..8f885b0af38e5c09320c7625c27e8eea14a3703f 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c @@ -563,8 +563,10 @@ static int adf4350_probe(struct spi_device *spi) st->lock_detect_gpiod = devm_gpiod_get_optional(&spi->dev, NULL, GPIOD_IN); - if (IS_ERR(st->lock_detect_gpiod)) - return PTR_ERR(st->lock_detect_gpiod); + if (IS_ERR(st->lock_detect_gpiod)) { + ret = PTR_ERR(st->lock_detect_gpiod); + goto error_disable_reg; + } if (pdata->power_up_frequency) { ret = adf4350_set_freq(st, pdata->power_up_frequency); diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c index 8ddda96455fcb1fffaf44ae715a43cb2507c16df..39fe0b1785920c5150005a7af38a702087cdc564 100644 --- a/drivers/iio/gyro/bmg160_core.c +++ b/drivers/iio/gyro/bmg160_core.c @@ -96,7 +96,11 @@ struct bmg160_data { struct iio_trigger *motion_trig; struct iio_mount_matrix orientation; struct mutex mutex; - s16 buffer[8]; + /* Ensure naturally aligned timestamp */ + struct { + s16 chans[3]; + s64 timestamp __aligned(8); + } scan; u32 dps_range; int ev_enable_state; int slope_thres; @@ -880,12 +884,12 @@ static irqreturn_t bmg160_trigger_handler(int irq, void *p) mutex_lock(&data->mutex); ret = regmap_bulk_read(data->regmap, BMG160_REG_XOUT_L, - data->buffer, AXIS_MAX * 2); + data->scan.chans, AXIS_MAX * 2); mutex_unlock(&data->mutex); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c index b7523357d8ebae875d0b4108fcf17633f383048b..ec6bd15bd2d4c9f90c85f159d1f0ae3c20ac72bf 100644 --- a/drivers/iio/gyro/fxas21002c_core.c +++ b/drivers/iio/gyro/fxas21002c_core.c @@ -366,14 +366,7 @@ out_unlock: static int fxas21002c_pm_get(struct fxas21002c_data *data) { - struct device *dev = regmap_get_device(data->regmap); - int ret; - - ret = pm_runtime_get_sync(dev); - if (ret < 0) - pm_runtime_put_noidle(dev); - - return ret; + return pm_runtime_resume_and_get(regmap_get_device(data->regmap)); } static int fxas21002c_pm_put(struct fxas21002c_data *data) @@ -1005,7 +998,6 @@ int fxas21002c_core_probe(struct device *dev, struct regmap *regmap, int irq, pm_disable: pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); return ret; } @@ -1019,7 +1011,6 @@ void fxas21002c_core_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); } EXPORT_SYMBOL_GPL(fxas21002c_core_remove); diff --git a/drivers/iio/humidity/am2315.c b/drivers/iio/humidity/am2315.c index 02ad1767c845e8dccc26e6727881d5301cf9d5f2..3398fa413ec5cf845a605f2f622a9d171804826d 100644 --- a/drivers/iio/humidity/am2315.c +++ b/drivers/iio/humidity/am2315.c @@ -33,7 +33,11 @@ struct am2315_data { struct i2c_client *client; struct mutex lock; - s16 buffer[8]; /* 2x16-bit channels + 2x16 padding + 4x16 timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + s16 chans[2]; + s64 timestamp __aligned(8); + } scan; }; struct am2315_sensor_data { @@ -167,20 +171,20 @@ static irqreturn_t am2315_trigger_handler(int irq, void *p) mutex_lock(&data->lock); if (*(indio_dev->active_scan_mask) == AM2315_ALL_CHANNEL_MASK) { - data->buffer[0] = sensor_data.hum_data; - data->buffer[1] = sensor_data.temp_data; + data->scan.chans[0] = sensor_data.hum_data; + data->scan.chans[1] = sensor_data.temp_data; } else { i = 0; for_each_set_bit(bit, indio_dev->active_scan_mask, indio_dev->masklength) { - data->buffer[i] = (bit ? sensor_data.temp_data : - sensor_data.hum_data); + data->scan.chans[i] = (bit ? sensor_data.temp_data : + sensor_data.hum_data); i++; } } mutex_unlock(&data->lock); - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c index 785a4ce606d89a139db19741922477446b3b832e..4aff16466da02cd68a7f155785ca746601cd6244 100644 --- a/drivers/iio/imu/adis16400.c +++ b/drivers/iio/imu/adis16400.c @@ -647,9 +647,6 @@ static irqreturn_t adis16400_trigger_handler(int irq, void *p) void *buffer; int ret; - if (!adis->buffer) - return -ENOMEM; - if (!(st->variant->flags & ADIS16400_NO_BURST) && st->adis.spi->max_speed_hz > ADIS16400_SPI_BURST) { st->adis.spi->max_speed_hz = ADIS16400_SPI_BURST; diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c index 197d482409911ab34b01b1e2f5ea2e36a9acc40b..3c4e4deb8760851ae7cc24c87780b9c8e7b6a5de 100644 --- a/drivers/iio/imu/adis16475.c +++ b/drivers/iio/imu/adis16475.c @@ -990,7 +990,7 @@ static irqreturn_t adis16475_trigger_handler(int irq, void *p) ret = spi_sync(adis->spi, &adis->msg); if (ret) - return ret; + goto check_burst32; adis->spi->max_speed_hz = cached_spi_speed_hz; buffer = adis->buffer; diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c index ac354321f63a39635391958b79c10df57a37b81b..175af154e4437a1b3338934dc112e8d3a4527306 100644 --- a/drivers/iio/imu/adis_buffer.c +++ b/drivers/iio/imu/adis_buffer.c @@ -129,9 +129,6 @@ static irqreturn_t adis_trigger_handler(int irq, void *p) struct adis *adis = iio_device_get_drvdata(indio_dev); int ret; - if (!adis->buffer) - return -ENOMEM; - if (adis->data->has_paging) { mutex_lock(&adis->state_lock); if (adis->current_page != 0) { diff --git a/drivers/iio/light/isl29125.c b/drivers/iio/light/isl29125.c index b93b85dbc3a6a15e0d267ddf1634b33a855f50b8..ba53b50d711a15894d4a5d3faa1bfbb8eddc3370 100644 --- a/drivers/iio/light/isl29125.c +++ b/drivers/iio/light/isl29125.c @@ -51,7 +51,11 @@ struct isl29125_data { struct i2c_client *client; u8 conf1; - u16 buffer[8]; /* 3x 16-bit, padding, 8 bytes timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chans[3]; + s64 timestamp __aligned(8); + } scan; }; #define ISL29125_CHANNEL(_color, _si) { \ @@ -184,10 +188,10 @@ static irqreturn_t isl29125_trigger_handler(int irq, void *p) if (ret < 0) goto done; - data->buffer[j++] = ret; + data->scan.chans[j++] = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c index b4323d2db0b19b53a9405de2e3d54a875f7059e4..74ed2d88a3ed39ff10a5e1f22770fc6f17181df1 100644 --- a/drivers/iio/light/ltr501.c +++ b/drivers/iio/light/ltr501.c @@ -32,9 +32,12 @@ #define LTR501_PART_ID 0x86 #define LTR501_MANUFAC_ID 0x87 #define LTR501_ALS_DATA1 0x88 /* 16-bit, little endian */ +#define LTR501_ALS_DATA1_UPPER 0x89 /* upper 8 bits of LTR501_ALS_DATA1 */ #define LTR501_ALS_DATA0 0x8a /* 16-bit, little endian */ +#define LTR501_ALS_DATA0_UPPER 0x8b /* upper 8 bits of LTR501_ALS_DATA0 */ #define LTR501_ALS_PS_STATUS 0x8c #define LTR501_PS_DATA 0x8d /* 16-bit, little endian */ +#define LTR501_PS_DATA_UPPER 0x8e /* upper 8 bits of LTR501_PS_DATA */ #define LTR501_INTR 0x8f /* output mode, polarity, mode */ #define LTR501_PS_THRESH_UP 0x90 /* 11 bit, ps upper threshold */ #define LTR501_PS_THRESH_LOW 0x92 /* 11 bit, ps lower threshold */ @@ -406,18 +409,19 @@ static int ltr501_read_als(const struct ltr501_data *data, __le16 buf[2]) static int ltr501_read_ps(const struct ltr501_data *data) { - int ret, status; + __le16 status; + int ret; ret = ltr501_drdy(data, LTR501_STATUS_PS_RDY); if (ret < 0) return ret; ret = regmap_bulk_read(data->regmap, LTR501_PS_DATA, - &status, 2); + &status, sizeof(status)); if (ret < 0) return ret; - return status; + return le16_to_cpu(status); } static int ltr501_read_intr_prst(const struct ltr501_data *data, @@ -1205,7 +1209,7 @@ static struct ltr501_chip_info ltr501_chip_info_tbl[] = { .als_gain_tbl_size = ARRAY_SIZE(ltr559_als_gain_tbl), .ps_gain = ltr559_ps_gain_tbl, .ps_gain_tbl_size = ARRAY_SIZE(ltr559_ps_gain_tbl), - .als_mode_active = BIT(1), + .als_mode_active = BIT(0), .als_gain_mask = BIT(2) | BIT(3) | BIT(4), .als_gain_shift = 2, .info = <r501_info, @@ -1354,9 +1358,12 @@ static bool ltr501_is_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { case LTR501_ALS_DATA1: + case LTR501_ALS_DATA1_UPPER: case LTR501_ALS_DATA0: + case LTR501_ALS_DATA0_UPPER: case LTR501_ALS_PS_STATUS: case LTR501_PS_DATA: + case LTR501_PS_DATA_UPPER: return true; default: return false; diff --git a/drivers/iio/light/tcs3414.c b/drivers/iio/light/tcs3414.c index 6fe5d46f80d40126a07247a42a1c62cd05a87cca..0593abd600ec20a2966237cdf3444b31614e0655 100644 --- a/drivers/iio/light/tcs3414.c +++ b/drivers/iio/light/tcs3414.c @@ -53,7 +53,11 @@ struct tcs3414_data { u8 control; u8 gain; u8 timing; - u16 buffer[8]; /* 4x 16-bit + 8 bytes timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chans[4]; + s64 timestamp __aligned(8); + } scan; }; #define TCS3414_CHANNEL(_color, _si, _addr) { \ @@ -209,10 +213,10 @@ static irqreturn_t tcs3414_trigger_handler(int irq, void *p) if (ret < 0) goto done; - data->buffer[j++] = ret; + data->scan.chans[j++] = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c index a0dc447aeb68b1c3e3d284e11bfce0767ca1938f..371c6a39a16547751dfec2fa7792bbc0dab0fd90 100644 --- a/drivers/iio/light/tcs3472.c +++ b/drivers/iio/light/tcs3472.c @@ -64,7 +64,11 @@ struct tcs3472_data { u8 control; u8 atime; u8 apers; - u16 buffer[8]; /* 4 16-bit channels + 64-bit timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chans[4]; + s64 timestamp __aligned(8); + } scan; }; static const struct iio_event_spec tcs3472_events[] = { @@ -386,10 +390,10 @@ static irqreturn_t tcs3472_trigger_handler(int irq, void *p) if (ret < 0) goto done; - data->buffer[j++] = ret; + data->scan.chans[j++] = ret; } - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: @@ -531,7 +535,8 @@ static int tcs3472_probe(struct i2c_client *client, return 0; free_irq: - free_irq(client->irq, indio_dev); + if (client->irq) + free_irq(client->irq, indio_dev); buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); return ret; @@ -559,7 +564,8 @@ static int tcs3472_remove(struct i2c_client *client) struct iio_dev *indio_dev = i2c_get_clientdata(client); iio_device_unregister(indio_dev); - free_irq(client->irq, indio_dev); + if (client->irq) + free_irq(client->irq, indio_dev); iio_triggered_buffer_cleanup(indio_dev); tcs3472_powerdown(iio_priv(indio_dev)); diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c index fff4b36b8b58dc04cc197b52a846d9737a95648a..f4feb44903b3f1b80b970da4fc577deb4e981e33 100644 --- a/drivers/iio/light/vcnl4000.c +++ b/drivers/iio/light/vcnl4000.c @@ -910,7 +910,7 @@ static irqreturn_t vcnl4010_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct vcnl4000_data *data = iio_priv(indio_dev); const unsigned long *active_scan_mask = indio_dev->active_scan_mask; - u16 buffer[8] = {0}; /* 1x16-bit + ts */ + u16 buffer[8] __aligned(8) = {0}; /* 1x16-bit + naturally aligned ts */ bool data_read = false; unsigned long isr; int val = 0; diff --git a/drivers/iio/light/vcnl4035.c b/drivers/iio/light/vcnl4035.c index 765c44adac574f78acbfc6fb56083f76d1055d21..1bd85e21fd114821270ee20b6d672f68c399f5c0 100644 --- a/drivers/iio/light/vcnl4035.c +++ b/drivers/iio/light/vcnl4035.c @@ -102,7 +102,8 @@ static irqreturn_t vcnl4035_trigger_consumer_handler(int irq, void *p) struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; struct vcnl4035_data *data = iio_priv(indio_dev); - u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)]; + /* Ensure naturally aligned timestamp */ + u8 buffer[ALIGN(sizeof(u16), sizeof(s64)) + sizeof(s64)] __aligned(8); int ret; ret = regmap_read(data->regmap, VCNL4035_ALS_DATA, (int *)buffer); diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c index fc6840f9c1fa6a23f5c680db339d574703a20403..8eacfaf584cfd0690fb4020a6ff74cca8bb490eb 100644 --- a/drivers/iio/magnetometer/bmc150_magn.c +++ b/drivers/iio/magnetometer/bmc150_magn.c @@ -136,8 +136,11 @@ struct bmc150_magn_data { struct mutex mutex; struct regmap *regmap; struct iio_mount_matrix orientation; - /* 4 x 32 bits for x, y z, 4 bytes align, 64 bits timestamp */ - s32 buffer[6]; + /* Ensure timestamp is naturally aligned */ + struct { + s32 chans[3]; + s64 timestamp __aligned(8); + } scan; struct iio_trigger *dready_trig; bool dready_trigger_on; int max_odr; @@ -260,7 +263,7 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) int ret; if (on) { - ret = pm_runtime_get_sync(data->dev); + ret = pm_runtime_resume_and_get(data->dev); } else { pm_runtime_mark_last_busy(data->dev); ret = pm_runtime_put_autosuspend(data->dev); @@ -269,9 +272,6 @@ static int bmc150_magn_set_power_state(struct bmc150_magn_data *data, bool on) if (ret < 0) { dev_err(data->dev, "failed to change power state to %d\n", on); - if (on) - pm_runtime_put_noidle(data->dev); - return ret; } #endif @@ -673,11 +673,11 @@ static irqreturn_t bmc150_magn_trigger_handler(int irq, void *p) int ret; mutex_lock(&data->mutex); - ret = bmc150_magn_read_xyz(data, data->buffer); + ret = bmc150_magn_read_xyz(data, data->scan.chans); if (ret < 0) goto err; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, pf->timestamp); err: @@ -941,12 +941,14 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap, ret = iio_device_register(indio_dev); if (ret < 0) { dev_err(dev, "unable to register iio device\n"); - goto err_buffer_cleanup; + goto err_disable_runtime_pm; } dev_dbg(dev, "Registered device %s\n", name); return 0; +err_disable_runtime_pm: + pm_runtime_disable(dev); err_buffer_cleanup: iio_triggered_buffer_cleanup(indio_dev); err_free_irq: @@ -970,7 +972,6 @@ int bmc150_magn_remove(struct device *dev) pm_runtime_disable(dev); pm_runtime_set_suspended(dev); - pm_runtime_put_noidle(dev); iio_triggered_buffer_cleanup(indio_dev); diff --git a/drivers/iio/magnetometer/hmc5843.h b/drivers/iio/magnetometer/hmc5843.h index 3f6c0b6629415fa6794e53ac7dfb3bfa68ea9297..242f742f2643a67e696b67741188d33685adea7c 100644 --- a/drivers/iio/magnetometer/hmc5843.h +++ b/drivers/iio/magnetometer/hmc5843.h @@ -33,7 +33,8 @@ enum hmc5843_ids { * @lock: update and read regmap data * @regmap: hardware access register maps * @variant: describe chip variants - * @buffer: 3x 16-bit channels + padding + 64-bit timestamp + * @scan: buffer to pack data for passing to + * iio_push_to_buffers_with_timestamp() */ struct hmc5843_data { struct device *dev; @@ -41,7 +42,10 @@ struct hmc5843_data { struct regmap *regmap; const struct hmc5843_chip_info *variant; struct iio_mount_matrix orientation; - __be16 buffer[8]; + struct { + __be16 chans[3]; + s64 timestamp __aligned(8); + } scan; }; int hmc5843_common_probe(struct device *dev, struct regmap *regmap, diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c index 780faea61d82ed7c0d78f906987e4f6bdac17fa3..221563e0c18fdd93c09f96afa7f6d50b6bfaed45 100644 --- a/drivers/iio/magnetometer/hmc5843_core.c +++ b/drivers/iio/magnetometer/hmc5843_core.c @@ -446,13 +446,13 @@ static irqreturn_t hmc5843_trigger_handler(int irq, void *p) } ret = regmap_bulk_read(data->regmap, HMC5843_DATA_OUT_MSB_REGS, - data->buffer, 3 * sizeof(__be16)); + data->scan.chans, sizeof(data->scan.chans)); mutex_unlock(&data->lock); if (ret < 0) goto done; - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); done: diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c index 7242897a05e956ee853ebb30a7c8c862bf72722e..720234a91db11c6705b36ca2459418f2adfa1cc6 100644 --- a/drivers/iio/magnetometer/rm3100-core.c +++ b/drivers/iio/magnetometer/rm3100-core.c @@ -78,7 +78,8 @@ struct rm3100_data { bool use_interrupt; int conversion_time; int scale; - u8 buffer[RM3100_SCAN_BYTES]; + /* Ensure naturally aligned timestamp */ + u8 buffer[RM3100_SCAN_BYTES] __aligned(8); struct iio_trigger *drdy_trig; /* diff --git a/drivers/iio/potentiostat/lmp91000.c b/drivers/iio/potentiostat/lmp91000.c index f34ca769dc20de80c0d641f809f0b44bb507e683..d7ff74a798ba38d8e491abcb864f4d3339009420 100644 --- a/drivers/iio/potentiostat/lmp91000.c +++ b/drivers/iio/potentiostat/lmp91000.c @@ -71,8 +71,8 @@ struct lmp91000_data { struct completion completion; u8 chan_select; - - u32 buffer[4]; /* 64-bit data + 64-bit timestamp */ + /* 64-bit data + 64-bit naturally aligned timestamp */ + u32 buffer[4] __aligned(8); }; static const struct iio_chan_spec lmp91000_channels[] = { diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index b79ada839e0129b6a28202896569af27bc0934b2..98330e26ac3bd26fe6114ed56aa0b217ee7cf76b 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -59,7 +59,11 @@ struct as3935_state { unsigned long noise_tripped; u32 tune_cap; u32 nflwdth_reg; - u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u8 chan; + s64 timestamp __aligned(8); + } scan; u8 buf[2] ____cacheline_aligned; }; @@ -225,8 +229,8 @@ static irqreturn_t as3935_trigger_handler(int irq, void *private) if (ret) goto err_read; - st->buffer[0] = val & AS3935_DATA_MASK; - iio_push_to_buffers_with_timestamp(indio_dev, &st->buffer, + st->scan.chan = val & AS3935_DATA_MASK; + iio_push_to_buffers_with_timestamp(indio_dev, &st->scan, iio_get_time_ns(indio_dev)); err_read: iio_trigger_notify_done(indio_dev->trig); diff --git a/drivers/iio/proximity/isl29501.c b/drivers/iio/proximity/isl29501.c index 90e76451c972a8c7cba0ccd0d369ba15d90f0620..5b6ea783795d91dc0c6a40afd6c6e7058efd4454 100644 --- a/drivers/iio/proximity/isl29501.c +++ b/drivers/iio/proximity/isl29501.c @@ -938,7 +938,7 @@ static irqreturn_t isl29501_trigger_handler(int irq, void *p) struct iio_dev *indio_dev = pf->indio_dev; struct isl29501_private *isl29501 = iio_priv(indio_dev); const unsigned long *active_mask = indio_dev->active_scan_mask; - u32 buffer[4] = {}; /* 1x16-bit + ts */ + u32 buffer[4] __aligned(8) = {}; /* 1x16-bit + naturally aligned ts */ if (test_bit(ISL29501_DISTANCE_SCAN_INDEX, active_mask)) isl29501_register_read(isl29501, REG_DISTANCE, buffer); diff --git a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c index cc206bfa09c78d720f7496f94cd37c20e585de19..d854b8d5fbbaf9304f0f09ac6338a1ab39751c41 100644 --- a/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c +++ b/drivers/iio/proximity/pulsedlight-lidar-lite-v2.c @@ -44,7 +44,11 @@ struct lidar_data { int (*xfer)(struct lidar_data *data, u8 reg, u8 *val, int len); int i2c_enabled; - u16 buffer[8]; /* 2 byte distance + 8 byte timestamp */ + /* Ensure timestamp is naturally aligned */ + struct { + u16 chan; + s64 timestamp __aligned(8); + } scan; }; static const struct iio_chan_spec lidar_channels[] = { @@ -230,9 +234,9 @@ static irqreturn_t lidar_trigger_handler(int irq, void *private) struct lidar_data *data = iio_priv(indio_dev); int ret; - ret = lidar_get_measurement(data, data->buffer); + ret = lidar_get_measurement(data, &data->scan.chan); if (!ret) { - iio_push_to_buffers_with_timestamp(indio_dev, data->buffer, + iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, iio_get_time_ns(indio_dev)); } else if (ret != -EINVAL) { dev_err(&data->client->dev, "cannot read LIDAR measurement"); diff --git a/drivers/iio/proximity/srf08.c b/drivers/iio/proximity/srf08.c index 70beac5c9c1dfc72ae8a3c9aacc044cb10f0b7eb..9b0886760f76de1480b3fbc5c5dc5a72401a107b 100644 --- a/drivers/iio/proximity/srf08.c +++ b/drivers/iio/proximity/srf08.c @@ -63,11 +63,11 @@ struct srf08_data { int range_mm; struct mutex lock; - /* - * triggered buffer - * 1x16-bit channel + 3x16 padding + 4x16 timestamp - */ - s16 buffer[8]; + /* Ensure timestamp is naturally aligned */ + struct { + s16 chan; + s64 timestamp __aligned(8); + } scan; /* Sensor-Type */ enum srf08_sensor_type sensor_type; @@ -190,9 +190,9 @@ static irqreturn_t srf08_trigger_handler(int irq, void *p) mutex_lock(&data->lock); - data->buffer[0] = sensor_data; + data->scan.chan = sensor_data; iio_push_to_buffers_with_timestamp(indio_dev, - data->buffer, pf->timestamp); + &data->scan, pf->timestamp); mutex_unlock(&data->lock); err: diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index d1e94147fb1656d674f30a53d12a991e35221646..34b94e52539054be1b3f6b13654db3b935204f89 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -1856,6 +1856,7 @@ static void _destroy_id(struct rdma_id_private *id_priv, { cma_cancel_operation(id_priv, state); + rdma_restrack_del(&id_priv->res); if (id_priv->cma_dev) { if (rdma_cap_ib_cm(id_priv->id.device, 1)) { if (id_priv->cm_id.ib) @@ -1865,7 +1866,6 @@ static void _destroy_id(struct rdma_id_private *id_priv, iw_destroy_cm_id(id_priv->cm_id.iw); } cma_leave_mc_groups(id_priv); - rdma_restrack_del(&id_priv->res); cma_release_dev(id_priv); } @@ -2476,8 +2476,10 @@ static int cma_iw_listen(struct rdma_id_private *id_priv, int backlog) if (IS_ERR(id)) return PTR_ERR(id); + mutex_lock(&id_priv->qp_mutex); id->tos = id_priv->tos; id->tos_set = id_priv->tos_set; + mutex_unlock(&id_priv->qp_mutex); id_priv->cm_id.iw = id; memcpy(&id_priv->cm_id.iw->local_addr, cma_src_addr(id_priv), @@ -2537,8 +2539,10 @@ static int cma_listen_on_dev(struct rdma_id_private *id_priv, cma_id_get(id_priv); dev_id_priv->internal_id = 1; dev_id_priv->afonly = id_priv->afonly; + mutex_lock(&id_priv->qp_mutex); dev_id_priv->tos_set = id_priv->tos_set; dev_id_priv->tos = id_priv->tos; + mutex_unlock(&id_priv->qp_mutex); ret = rdma_listen(&dev_id_priv->id, id_priv->backlog); if (ret) @@ -2585,8 +2589,10 @@ void rdma_set_service_type(struct rdma_cm_id *id, int tos) struct rdma_id_private *id_priv; id_priv = container_of(id, struct rdma_id_private, id); + mutex_lock(&id_priv->qp_mutex); id_priv->tos = (u8) tos; id_priv->tos_set = true; + mutex_unlock(&id_priv->qp_mutex); } EXPORT_SYMBOL(rdma_set_service_type); @@ -2613,8 +2619,10 @@ int rdma_set_ack_timeout(struct rdma_cm_id *id, u8 timeout) return -EINVAL; id_priv = container_of(id, struct rdma_id_private, id); + mutex_lock(&id_priv->qp_mutex); id_priv->timeout = timeout; id_priv->timeout_set = true; + mutex_unlock(&id_priv->qp_mutex); return 0; } @@ -2785,7 +2793,8 @@ static int cma_resolve_ib_route(struct rdma_id_private *id_priv, cma_init_resolve_route_work(work, id_priv); - route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); + if (!route->path_rec) + route->path_rec = kmalloc(sizeof *route->path_rec, GFP_KERNEL); if (!route->path_rec) { ret = -ENOMEM; goto err1; @@ -3000,8 +3009,11 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) u8 default_roce_tos = id_priv->cma_dev->default_roce_tos[id_priv->id.port_num - rdma_start_port(id_priv->cma_dev->device)]; - u8 tos = id_priv->tos_set ? id_priv->tos : default_roce_tos; + u8 tos; + mutex_lock(&id_priv->qp_mutex); + tos = id_priv->tos_set ? id_priv->tos : default_roce_tos; + mutex_unlock(&id_priv->qp_mutex); work = kzalloc(sizeof *work, GFP_KERNEL); if (!work) @@ -3048,8 +3060,12 @@ static int cma_resolve_iboe_route(struct rdma_id_private *id_priv) * PacketLifeTime = local ACK timeout/2 * as a reasonable approximation for RoCE networks. */ - route->path_rec->packet_life_time = id_priv->timeout_set ? - id_priv->timeout - 1 : CMA_IBOE_PACKET_LIFETIME; + mutex_lock(&id_priv->qp_mutex); + if (id_priv->timeout_set && id_priv->timeout) + route->path_rec->packet_life_time = id_priv->timeout - 1; + else + route->path_rec->packet_life_time = CMA_IBOE_PACKET_LIFETIME; + mutex_unlock(&id_priv->qp_mutex); if (!route->path_rec->mtu) { ret = -EINVAL; @@ -4073,8 +4089,11 @@ static int cma_connect_iw(struct rdma_id_private *id_priv, if (IS_ERR(cm_id)) return PTR_ERR(cm_id); + mutex_lock(&id_priv->qp_mutex); cm_id->tos = id_priv->tos; cm_id->tos_set = id_priv->tos_set; + mutex_unlock(&id_priv->qp_mutex); + id_priv->cm_id.iw = cm_id; memcpy(&cm_id->local_addr, cma_src_addr(id_priv), diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index 418d133a8fb080f6ef175c59f2a1f6ccbfc6864f..466026825dd7548192a9d4a0f44d1302a8986390 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -3000,12 +3000,29 @@ static int ib_uverbs_ex_modify_wq(struct uverbs_attr_bundle *attrs) if (!wq) return -EINVAL; - wq_attr.curr_wq_state = cmd.curr_wq_state; - wq_attr.wq_state = cmd.wq_state; if (cmd.attr_mask & IB_WQ_FLAGS) { wq_attr.flags = cmd.flags; wq_attr.flags_mask = cmd.flags_mask; } + + if (cmd.attr_mask & IB_WQ_CUR_STATE) { + if (cmd.curr_wq_state > IB_WQS_ERR) + return -EINVAL; + + wq_attr.curr_wq_state = cmd.curr_wq_state; + } else { + wq_attr.curr_wq_state = wq->state; + } + + if (cmd.attr_mask & IB_WQ_STATE) { + if (cmd.wq_state > IB_WQS_ERR) + return -EINVAL; + + wq_attr.wq_state = cmd.wq_state; + } else { + wq_attr.wq_state = wq_attr.curr_wq_state; + } + ret = wq->device->ops.modify_wq(wq, &wq_attr, cmd.attr_mask, &attrs->driver_udata); rdma_lookup_put_uobject(&wq->uobject->uevent.uobject, diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 5df4bb52bb10f602913d76cdbca40d659c941a97..861e19fdfeb469fff7d75143cfbc80738ae70ecf 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c @@ -295,6 +295,7 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, if (user && (!wq->sq.bar2_pa || (need_rq && !wq->rq.bar2_pa))) { pr_warn("%s: sqid %u or rqid %u not in BAR2 range\n", pci_name(rdev->lldi.pdev), wq->sq.qid, wq->rq.qid); + ret = -EINVAL; goto free_dma; } diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index 5cb8e602294ca9ad1e89000991c307d84b3984a1..6bc0818f4b2c6f6b8ebecdc85b3bddd8348f934b 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -4244,13 +4244,8 @@ int mlx4_ib_modify_wq(struct ib_wq *ibwq, struct ib_wq_attr *wq_attr, if (wq_attr_mask & IB_WQ_FLAGS) return -EOPNOTSUPP; - cur_state = wq_attr_mask & IB_WQ_CUR_STATE ? wq_attr->curr_wq_state : - ibwq->state; - new_state = wq_attr_mask & IB_WQ_STATE ? wq_attr->wq_state : cur_state; - - if (cur_state < IB_WQS_RESET || cur_state > IB_WQS_ERR || - new_state < IB_WQS_RESET || new_state > IB_WQS_ERR) - return -EINVAL; + cur_state = wq_attr->curr_wq_state; + new_state = wq_attr->wq_state; if ((new_state == IB_WQS_RDY) && (cur_state == IB_WQS_ERR)) return -EINVAL; diff --git a/drivers/infiniband/hw/mlx5/fs.c b/drivers/infiniband/hw/mlx5/fs.c index 13d50b1781660e1380757a9824602d40aa2e0da0..b3391ecedda7e770a7e2cc8b3d6c9eaf1f5a2c5e 100644 --- a/drivers/infiniband/hw/mlx5/fs.c +++ b/drivers/infiniband/hw/mlx5/fs.c @@ -2136,6 +2136,13 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_FLOW_MATCHER_CREATE)( if (err) goto end; + if (obj->ns_type == MLX5_FLOW_NAMESPACE_FDB && + mlx5_eswitch_mode(dev->mdev->priv.eswitch) != + MLX5_ESWITCH_OFFLOADS) { + err = -EINVAL; + goto end; + } + uobj->object = obj; obj->mdev = dev->mdev; atomic_set(&obj->usecnt, 0); diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index b19506707e45cce91bdf954fee41f33a6c9e897d..eb69bec77e5d425dba2e78188a1ffae4389a0192 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -3440,8 +3440,6 @@ static void mlx5_ib_unbind_slave_port(struct mlx5_ib_dev *ibdev, port->mp.mpi = NULL; - list_add_tail(&mpi->list, &mlx5_ib_unaffiliated_port_list); - spin_unlock(&port->mp.mpi_lock); err = mlx5_nic_vport_unaffiliate_multiport(mpi->mdev); @@ -3594,6 +3592,8 @@ static void mlx5_ib_cleanup_multiport_master(struct mlx5_ib_dev *dev) dev->port[i].mp.mpi = NULL; } else { mlx5_ib_dbg(dev, "unbinding port_num: %d\n", i + 1); + list_add_tail(&dev->port[i].mp.mpi->list, + &mlx5_ib_unaffiliated_port_list); mlx5_ib_unbind_slave_port(dev, dev->port[i].mp.mpi); } } diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 6d2715f65d788e870811d00327629e891e502dd3..8beba002e5dd7da2ec7fb3ccf2d92aaea5352547 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -5236,10 +5236,8 @@ int mlx5_ib_modify_wq(struct ib_wq *wq, struct ib_wq_attr *wq_attr, rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx); - curr_wq_state = (wq_attr_mask & IB_WQ_CUR_STATE) ? - wq_attr->curr_wq_state : wq->state; - wq_state = (wq_attr_mask & IB_WQ_STATE) ? - wq_attr->wq_state : curr_wq_state; + curr_wq_state = wq_attr->curr_wq_state; + wq_state = wq_attr->wq_state; if (curr_wq_state == IB_WQS_ERR) curr_wq_state = MLX5_RQC_STATE_ERR; if (wq_state == IB_WQS_ERR) diff --git a/drivers/infiniband/sw/rxe/rxe_mr.c b/drivers/infiniband/sw/rxe/rxe_mr.c index d2ce852447c134b77cc9dc6fad13c679d88687bc..026285f7f36ac81275fd858adda05725a9a64360 100644 --- a/drivers/infiniband/sw/rxe/rxe_mr.c +++ b/drivers/infiniband/sw/rxe/rxe_mr.c @@ -139,7 +139,7 @@ int rxe_mem_init_user(struct rxe_pd *pd, u64 start, if (IS_ERR(umem)) { pr_warn("err %d from rxe_umem_get\n", (int)PTR_ERR(umem)); - err = -EINVAL; + err = PTR_ERR(umem); goto err1; } diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c index bce44502ab0eda4bc68fc8af1282a999105d60f1..c071d5b1b85a7a410189ae84c9fe141a8c9dce45 100644 --- a/drivers/infiniband/sw/rxe/rxe_net.c +++ b/drivers/infiniband/sw/rxe/rxe_net.c @@ -212,10 +212,8 @@ static struct socket *rxe_setup_udp_tunnel(struct net *net, __be16 port, /* Create UDP socket */ err = udp_sock_create(net, &udp_cfg, &sock); - if (err < 0) { - pr_err("failed to create udp socket. err = %d\n", err); + if (err < 0) return ERR_PTR(err); - } tnl_cfg.encap_type = 1; tnl_cfg.encap_rcv = rxe_udp_encap_recv; @@ -616,6 +614,12 @@ static int rxe_net_ipv6_init(void) recv_sockets.sk6 = rxe_setup_udp_tunnel(&init_net, htons(ROCE_V2_UDP_DPORT), true); + if (PTR_ERR(recv_sockets.sk6) == -EAFNOSUPPORT) { + recv_sockets.sk6 = NULL; + pr_warn("IPv6 is not supported, can not create a UDPv6 socket\n"); + return 0; + } + if (IS_ERR(recv_sockets.sk6)) { recv_sockets.sk6 = NULL; pr_err("Failed to create IPv6 UDP tunnel\n"); diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index 1e716fe7014cc565934150493fd7f66604d30f3b..a1b79015e6f22ea333e453543261eb8a7c534d08 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -125,7 +125,6 @@ static void free_rd_atomic_resources(struct rxe_qp *qp) void free_rd_atomic_resource(struct rxe_qp *qp, struct resp_res *res) { if (res->type == RXE_ATOMIC_MASK) { - rxe_drop_ref(qp); kfree_skb(res->atomic.skb); } else if (res->type == RXE_READ_MASK) { if (res->read.mr) diff --git a/drivers/infiniband/sw/rxe/rxe_resp.c b/drivers/infiniband/sw/rxe/rxe_resp.c index c7e3b6a4af38f929e9e9018465705cd75b069f34..83c03212099a21811ef708aa3f5f65d010448d8f 100644 --- a/drivers/infiniband/sw/rxe/rxe_resp.c +++ b/drivers/infiniband/sw/rxe/rxe_resp.c @@ -966,8 +966,6 @@ static int send_atomic_ack(struct rxe_qp *qp, struct rxe_pkt_info *pkt, goto out; } - rxe_add_ref(qp); - res = &qp->resp.resources[qp->resp.res_head]; free_rd_atomic_resource(qp, res); rxe_advance_resp_resource(qp); diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index e653c83f8a356229175fbc34f457c69de06359ed..edea37da8a5bd779d85bf0c76ecba146d2c8961a 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -35,10 +35,10 @@ static const struct kernel_param_ops sg_tablesize_ops = { .get = param_get_int, }; -static int isert_sg_tablesize = ISCSI_ISER_DEF_SG_TABLESIZE; +static int isert_sg_tablesize = ISCSI_ISER_MIN_SG_TABLESIZE; module_param_cb(sg_tablesize, &sg_tablesize_ops, &isert_sg_tablesize, 0644); MODULE_PARM_DESC(sg_tablesize, - "Number of gather/scatter entries in a single scsi command, should >= 128 (default: 256, max: 4096)"); + "Number of gather/scatter entries in a single scsi command, should >= 128 (default: 128, max: 4096)"); static DEFINE_MUTEX(device_list_mutex); static LIST_HEAD(device_list); diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 6c5af13db4e0d286ff718ac7bfa038e1e2ffaa8d..ca8cfebe26ca78fd18203c66eafb5c7cc6619f04 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -65,9 +65,6 @@ */ #define ISER_RX_SIZE (ISCSI_DEF_MAX_RECV_SEG_LEN + 1024) -/* Default I/O size is 1MB */ -#define ISCSI_ISER_DEF_SG_TABLESIZE 256 - /* Minimum I/O size is 512KB */ #define ISCSI_ISER_MIN_SG_TABLESIZE 128 diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index 7db550ba25d7fcb020eb2b61384c0262b451762e..46fad202a380e6043a0d94066827ccf099e953a3 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -811,6 +811,9 @@ static struct rtrs_clt_sess *get_next_path_min_inflight(struct path_it *it) int inflight; list_for_each_entry_rcu(sess, &clt->paths_list, s.entry) { + if (unlikely(READ_ONCE(sess->state) != RTRS_CLT_CONNECTED)) + continue; + if (unlikely(!list_empty(raw_cpu_ptr(sess->mp_skip_entry)))) continue; @@ -1724,7 +1727,19 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, queue_depth); return -ECONNRESET; } - if (!sess->rbufs || sess->queue_depth < queue_depth) { + if (sess->queue_depth > 0 && queue_depth != sess->queue_depth) { + rtrs_err(clt, "Error: queue depth changed\n"); + + /* + * Stop any more reconnection attempts + */ + sess->reconnect_attempts = -1; + rtrs_err(clt, + "Disabling auto-reconnect. Trigger a manual reconnect after issue is resolved\n"); + return -ECONNRESET; + } + + if (!sess->rbufs) { kfree(sess->rbufs); sess->rbufs = kcalloc(queue_depth, sizeof(*sess->rbufs), GFP_KERNEL); @@ -1738,7 +1753,7 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, sess->chunk_size = sess->max_io_size + sess->max_hdr_size; /* - * Global queue depth and IO size is always a minimum. + * Global IO size is always a minimum. * If while a reconnection server sends us a value a bit * higher - client does not care and uses cached minimum. * @@ -1746,8 +1761,7 @@ static int rtrs_rdma_conn_established(struct rtrs_clt_con *con, * connections in parallel, use lock. */ mutex_lock(&clt->paths_mutex); - clt->queue_depth = min_not_zero(sess->queue_depth, - clt->queue_depth); + clt->queue_depth = sess->queue_depth; clt->max_io_size = min_not_zero(sess->max_io_size, clt->max_io_size); mutex_unlock(&clt->paths_mutex); @@ -2692,6 +2706,8 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, if (err) { list_del_rcu(&sess->s.entry); rtrs_clt_close_conns(sess, true); + free_percpu(sess->stats->pcpu_stats); + kfree(sess->stats); free_sess(sess); goto close_all_sess; } @@ -2700,6 +2716,8 @@ struct rtrs_clt *rtrs_clt_open(struct rtrs_clt_ops *ops, if (err) { list_del_rcu(&sess->s.entry); rtrs_clt_close_conns(sess, true); + free_percpu(sess->stats->pcpu_stats); + kfree(sess->stats); free_sess(sess); goto close_all_sess; } @@ -2959,6 +2977,8 @@ int rtrs_clt_create_path_from_sysfs(struct rtrs_clt *clt, close_sess: rtrs_clt_remove_path_from_arr(sess); rtrs_clt_close_conns(sess, true); + free_percpu(sess->stats->pcpu_stats); + kfree(sess->stats); free_sess(sess); return err; diff --git a/drivers/infiniband/ulp/rtrs/rtrs-pri.h b/drivers/infiniband/ulp/rtrs/rtrs-pri.h index 8caad0a2322bfd7ee373c27e11d2d501d0e464c8..51c60f5428761cd51bcd0b66145103e858526d94 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-pri.h +++ b/drivers/infiniband/ulp/rtrs/rtrs-pri.h @@ -47,12 +47,15 @@ enum { MAX_PATHS_NUM = 128, /* - * With the size of struct rtrs_permit allocated on the client, 4K - * is the maximum number of rtrs_permits we can allocate. This number is - * also used on the client to allocate the IU for the user connection - * to receive the RDMA addresses from the server. + * Max IB immediate data size is 2^28 (MAX_IMM_PAYL_BITS) + * and the minimum chunk size is 4096 (2^12). + * So the maximum sess_queue_depth is 65536 (2^16) in theory. + * But mempool_create, create_qp and ib_post_send fail with + * "cannot allocate memory" error if sess_queue_depth is too big. + * Therefore the pratical max value of sess_queue_depth is + * somewhere between 1 and 65536 and it depends on the system. */ - MAX_SESS_QUEUE_DEPTH = 4096, + MAX_SESS_QUEUE_DEPTH = 65536, RTRS_HB_INTERVAL_MS = 5000, RTRS_HB_MISSED_MAX = 5, diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c index 39708ab4f26e56ce1b444474330c26ab3bb4c778..7c75e1459017368488a4564efd480e0a50743cfc 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv-sysfs.c @@ -214,6 +214,7 @@ rtrs_srv_destroy_once_sysfs_root_folders(struct rtrs_srv_sess *sess) device_del(&srv->dev); put_device(&srv->dev); } else { + put_device(&srv->dev); mutex_unlock(&srv->paths_mutex); } } diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c index 43806180f85ec56edd167ef8b499d2094f0b6c5c..b033bfa9f383965e3012b561887ec5027b7619c9 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c @@ -1490,6 +1490,7 @@ static void free_sess(struct rtrs_srv_sess *sess) kobject_del(&sess->kobj); kobject_put(&sess->kobj); } else { + kfree(sess->stats); kfree(sess); } } @@ -1613,7 +1614,7 @@ static int create_con(struct rtrs_srv_sess *sess, struct rtrs_sess *s = &sess->s; struct rtrs_srv_con *con; - u32 cq_size, wr_queue_size; + u32 cq_size, max_send_wr, max_recv_wr, wr_limit; int err, cq_vector; con = kzalloc(sizeof(*con), GFP_KERNEL); @@ -1634,30 +1635,42 @@ static int create_con(struct rtrs_srv_sess *sess, * All receive and all send (each requiring invalidate) * + 2 for drain and heartbeat */ - wr_queue_size = SERVICE_CON_QUEUE_DEPTH * 3 + 2; - cq_size = wr_queue_size; + max_send_wr = SERVICE_CON_QUEUE_DEPTH * 2 + 2; + max_recv_wr = SERVICE_CON_QUEUE_DEPTH + 2; + cq_size = max_send_wr + max_recv_wr; } else { - /* - * If we have all receive requests posted and - * all write requests posted and each read request - * requires an invalidate request + drain - * and qp gets into error state. - */ - cq_size = srv->queue_depth * 3 + 1; /* * In theory we might have queue_depth * 32 * outstanding requests if an unsafe global key is used * and we have queue_depth read requests each consisting * of 32 different addresses. div 3 for mlx5. */ - wr_queue_size = sess->s.dev->ib_dev->attrs.max_qp_wr / 3; + wr_limit = sess->s.dev->ib_dev->attrs.max_qp_wr / 3; + /* when always_invlaidate enalbed, we need linv+rinv+mr+imm */ + if (always_invalidate) + max_send_wr = + min_t(int, wr_limit, + srv->queue_depth * (1 + 4) + 1); + else + max_send_wr = + min_t(int, wr_limit, + srv->queue_depth * (1 + 2) + 1); + + max_recv_wr = srv->queue_depth + 1; + /* + * If we have all receive requests posted and + * all write requests posted and each read request + * requires an invalidate request + drain + * and qp gets into error state. + */ + cq_size = max_send_wr + max_recv_wr; } - atomic_set(&con->sq_wr_avail, wr_queue_size); + atomic_set(&con->sq_wr_avail, max_send_wr); cq_vector = rtrs_srv_get_next_cq_vector(sess); /* TODO: SOFTIRQ can be faster, but be careful with softirq context */ err = rtrs_cq_qp_create(&sess->s, &con->c, 1, cq_vector, cq_size, - wr_queue_size, wr_queue_size, + max_send_wr, max_recv_wr, IB_POLL_WORKQUEUE); if (err) { rtrs_err(s, "rtrs_cq_qp_create(), err: %d\n", err); diff --git a/drivers/infiniband/ulp/rtrs/rtrs.c b/drivers/infiniband/ulp/rtrs/rtrs.c index d13aff0aa816551d5a1613ddb283647e026ca9e2..4629bb758126a3c12ad486ff19905a8c0e47430f 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs.c +++ b/drivers/infiniband/ulp/rtrs/rtrs.c @@ -373,7 +373,6 @@ void rtrs_stop_hb(struct rtrs_sess *sess) { cancel_delayed_work_sync(&sess->hb_dwork); sess->hb_missed_cnt = 0; - sess->hb_missed_max = 0; } EXPORT_SYMBOL_GPL(rtrs_stop_hb); diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index a8f85993dab30c524b3c150e17643ae1e9970013..86d5c4c92b363c4fc6fb9832ca7da626496a7200 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -998,7 +998,6 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch) struct srp_device *srp_dev = target->srp_host->srp_dev; struct ib_device *ibdev = srp_dev->dev; struct srp_request *req; - void *mr_list; dma_addr_t dma_addr; int i, ret = -ENOMEM; @@ -1009,12 +1008,12 @@ static int srp_alloc_req_data(struct srp_rdma_ch *ch) for (i = 0; i < target->req_ring_size; ++i) { req = &ch->req_ring[i]; - mr_list = kmalloc_array(target->mr_per_cmd, sizeof(void *), - GFP_KERNEL); - if (!mr_list) - goto out; - if (srp_dev->use_fast_reg) - req->fr_list = mr_list; + if (srp_dev->use_fast_reg) { + req->fr_list = kmalloc_array(target->mr_per_cmd, + sizeof(void *), GFP_KERNEL); + if (!req->fr_list) + goto out; + } req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL); if (!req->indirect_desc) goto out; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 430dc69750048a88105551979b8e1640e9cf07ac..675fcd0952a2d9923e6d2010d2305d3513a09db2 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -500,7 +500,7 @@ static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, memcpy(joydev->keypam, keypam, len); for (i = 0; i < joydev->nkey; i++) - joydev->keymap[keypam[i] - BTN_MISC] = i; + joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; out: kfree(keypam); diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 260a8a2c8c01e2dfe40e38336bb87a3149be307d..42a541fbf9e28a8c973f047b33246bcac1d441dd 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -67,9 +67,6 @@ config KEYBOARD_AMIGA To compile this driver as a module, choose M here: the module will be called amikbd. -config ATARI_KBD_CORE - bool - config KEYBOARD_APPLESPI tristate "Apple SPI keyboard and trackpad" depends on ACPI && EFI diff --git a/drivers/input/keyboard/hil_kbd.c b/drivers/input/keyboard/hil_kbd.c index bb29a7c9a1c0cf51d81b338834e149ab8555d50d..54afb38601b9f1196c9143aaf4e0cb7bb79b2708 100644 --- a/drivers/input/keyboard/hil_kbd.c +++ b/drivers/input/keyboard/hil_kbd.c @@ -512,6 +512,7 @@ static int hil_dev_connect(struct serio *serio, struct serio_driver *drv) HIL_IDD_NUM_AXES_PER_SET(*idd)) { printk(KERN_INFO PREFIX "combo devices are not supported.\n"); + error = -EINVAL; goto bail1; } diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 7d37e8e35a429b08d9690c2b3b85babc42732ec9..eca8dd866a50b9fccf85b51e52cf68c587afb8ac 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -178,51 +178,6 @@ static const unsigned long goodix_irq_flags[] = { IRQ_TYPE_LEVEL_HIGH, }; -/* - * Those tablets have their coordinates origin at the bottom right - * of the tablet, as if rotated 180 degrees - */ -static const struct dmi_system_id rotated_screen[] = { -#if defined(CONFIG_DMI) && defined(CONFIG_X86) - { - .ident = "Teclast X89", - .matches = { - /* tPAD is too generic, also match on bios date */ - DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), - DMI_MATCH(DMI_BOARD_NAME, "tPAD"), - DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"), - }, - }, - { - .ident = "Teclast X98 Pro", - .matches = { - /* - * Only match BIOS date, because the manufacturers - * BIOS does not report the board name at all - * (sometimes)... - */ - DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), - DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"), - }, - }, - { - .ident = "WinBook TW100", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), - DMI_MATCH(DMI_PRODUCT_NAME, "TW100") - } - }, - { - .ident = "WinBook TW700", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), - DMI_MATCH(DMI_PRODUCT_NAME, "TW700") - }, - }, -#endif - {} -}; - static const struct dmi_system_id nine_bytes_report[] = { #if defined(CONFIG_DMI) && defined(CONFIG_X86) { @@ -1121,13 +1076,6 @@ static int goodix_configure_dev(struct goodix_ts_data *ts) ABS_MT_POSITION_Y, ts->prop.max_y); } - if (dmi_check_system(rotated_screen)) { - ts->prop.invert_x = true; - ts->prop.invert_y = true; - dev_dbg(&ts->client->dev, - "Applying '180 degrees rotated screen' quirk\n"); - } - if (dmi_check_system(nine_bytes_report)) { ts->contact_size = 9; diff --git a/drivers/input/touchscreen/hideep.c b/drivers/input/touchscreen/hideep.c index ddad4a82a5e55c28635f33f8c5f91490e5c81e96..e9547ee297564d21e3e6782304ba8a2938ae3de6 100644 --- a/drivers/input/touchscreen/hideep.c +++ b/drivers/input/touchscreen/hideep.c @@ -361,13 +361,16 @@ static int hideep_enter_pgm(struct hideep_ts *ts) return -EIO; } -static void hideep_nvm_unlock(struct hideep_ts *ts) +static int hideep_nvm_unlock(struct hideep_ts *ts) { u32 unmask_code; + int error; hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_SFR_RPAGE); - hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code); + error = hideep_pgm_r_reg(ts, 0x0000000C, &unmask_code); hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); + if (error) + return error; /* make it unprotected code */ unmask_code &= ~HIDEEP_PROT_MODE; @@ -384,6 +387,8 @@ static void hideep_nvm_unlock(struct hideep_ts *ts) NVM_W_SFR(HIDEEP_NVM_MASK_OFS, ts->nvm_mask); SET_FLASH_HWCONTROL(); hideep_pgm_w_reg(ts, HIDEEP_FLASH_CFG, HIDEEP_NVM_DEFAULT_PAGE); + + return 0; } static int hideep_check_status(struct hideep_ts *ts) @@ -462,7 +467,9 @@ static int hideep_program_nvm(struct hideep_ts *ts, u32 addr = 0; int error; - hideep_nvm_unlock(ts); + error = hideep_nvm_unlock(ts); + if (error) + return error; while (ucode_len > 0) { xfer_len = min_t(size_t, ucode_len, HIDEEP_NVM_PAGE_SIZE); diff --git a/drivers/input/touchscreen/usbtouchscreen.c b/drivers/input/touchscreen/usbtouchscreen.c index 397cb1d3f481baf16e1f298dae7653d1c83b7c54..544a8f40b81f15b4e070e13884f7e338f1562d80 100644 --- a/drivers/input/touchscreen/usbtouchscreen.c +++ b/drivers/input/touchscreen/usbtouchscreen.c @@ -251,7 +251,7 @@ static int e2i_init(struct usbtouch_usb *usbtouch) int ret; struct usb_device *udev = interface_to_usbdev(usbtouch->interface); - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x01, 0x02, 0x0000, 0x0081, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -531,7 +531,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) if (ret) return ret; - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), MTOUCHUSB_RESET, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -543,7 +543,7 @@ static int mtouch_init(struct usbtouch_usb *usbtouch) msleep(150); for (i = 0; i < 3; i++) { - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), MTOUCHUSB_ASYNC_REPORT, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 1, 1, NULL, 0, USB_CTRL_SET_TIMEOUT); @@ -722,7 +722,7 @@ static int dmc_tsc10_init(struct usbtouch_usb *usbtouch) } /* start sending data */ - ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0), + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), TSC10_CMD_DATA1, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index cc9869cc48e4113c31483512ca4908c7588287df..fa57986c2309c708b9511c37de91e4123005603d 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -1914,8 +1914,8 @@ static void print_iommu_info(void) pci_info(pdev, "Found IOMMU cap 0x%hx\n", iommu->cap_ptr); if (iommu->cap & (1 << IOMMU_CAP_EFR)) { - pci_info(pdev, "Extended features (%#llx):", - iommu->features); + pr_info("Extended features (%#llx):", iommu->features); + for (i = 0; i < ARRAY_SIZE(feat_str); ++i) { if (iommu_feature(iommu, (1ULL << i))) pr_cont(" %s", feat_str[i]); diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c index bcbacf22331d60c6e701f8ba404f87afd50ea128..df24bbe3ea4f1512876c9caba05b57a2ac88e757 100644 --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c @@ -74,7 +74,7 @@ static bool using_legacy_binding, using_generic_binding; static inline int arm_smmu_rpm_get(struct arm_smmu_device *smmu) { if (pm_runtime_enabled(smmu->dev)) - return pm_runtime_get_sync(smmu->dev); + return pm_runtime_resume_and_get(smmu->dev); return 0; } @@ -1284,6 +1284,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, u64 phys; unsigned long va, flags; int ret, idx = cfg->cbndx; + phys_addr_t addr = 0; ret = arm_smmu_rpm_get(smmu); if (ret < 0) @@ -1303,6 +1304,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, dev_err(dev, "iova to phys timed out on %pad. Falling back to software table walk.\n", &iova); + arm_smmu_rpm_put(smmu); return ops->iova_to_phys(ops, iova); } @@ -1311,12 +1313,14 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain, if (phys & ARM_SMMU_CB_PAR_F) { dev_err(dev, "translation fault!\n"); dev_err(dev, "PAR = 0x%llx\n", phys); - return 0; + goto out; } + addr = (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff); +out: arm_smmu_rpm_put(smmu); - return (phys & GENMASK_ULL(39, 12)) | (iova & 0xfff); + return addr; } static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain, diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c index 0cbcd3fc3e7e8d9c7c5633753eccff5718d3fade..d1539b7399a961f25c2cd4f40fd3cbde72b20324 100644 --- a/drivers/iommu/dma-iommu.c +++ b/drivers/iommu/dma-iommu.c @@ -216,9 +216,11 @@ resv_iova: lo = iova_pfn(iovad, start); hi = iova_pfn(iovad, end); reserve_iova(iovad, lo, hi); - } else { + } else if (end < start) { /* dma_ranges list should be sorted */ - dev_err(&dev->dev, "Failed to reserve IOVA\n"); + dev_err(&dev->dev, + "Failed to reserve IOVA [%pa-%pa]\n", + &start, &end); return -EINVAL; } diff --git a/drivers/ipack/carriers/tpci200.c b/drivers/ipack/carriers/tpci200.c index ec71063fff76a37f9913b19b0eda756e1b25518c..e1822e87ec3d2f0ec098879558a56aa589ec5491 100644 --- a/drivers/ipack/carriers/tpci200.c +++ b/drivers/ipack/carriers/tpci200.c @@ -596,8 +596,11 @@ static int tpci200_pci_probe(struct pci_dev *pdev, out_err_bus_register: tpci200_uninstall(tpci200); + /* tpci200->info->cfg_regs is unmapped in tpci200_uninstall */ + tpci200->info->cfg_regs = NULL; out_err_install: - iounmap(tpci200->info->cfg_regs); + if (tpci200->info->cfg_regs) + iounmap(tpci200->info->cfg_regs); out_err_ioremap: pci_release_region(pdev, TPCI200_CFG_MEM_BAR); out_err_pci_request: diff --git a/drivers/isdn/hardware/mISDN/hfcpci.c b/drivers/isdn/hardware/mISDN/hfcpci.c index 56bd2e9db6ed6a1bfe92173e0c987d0ca527b3b9..e501cb03f211dee02a0f32be36a7017edfaef970 100644 --- a/drivers/isdn/hardware/mISDN/hfcpci.c +++ b/drivers/isdn/hardware/mISDN/hfcpci.c @@ -2342,7 +2342,7 @@ static void __exit HFC_cleanup(void) { if (timer_pending(&hfc_tl)) - del_timer(&hfc_tl); + del_timer_sync(&hfc_tl); pci_unregister_driver(&hfc_driver); } diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 849d3c5f908e4d597f4cf0225d596549ccdee770..56e8198e13d10ed36d4f92b854c3d6f8d55c2ad1 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -199,6 +199,7 @@ config LEDS_LM3530 config LEDS_LM3532 tristate "LCD Backlight driver for LM3532" + select REGMAP_I2C depends on LEDS_CLASS depends on I2C help diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 131ca83f5fb380f05e0efd0042262a92f400623a..4365c1cc4505ffa9b7851e92aa1273c9899de293 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -286,10 +286,6 @@ struct led_classdev *__must_check devm_of_led_get(struct device *dev, if (!dev) return ERR_PTR(-EINVAL); - /* Not using device tree? */ - if (!IS_ENABLED(CONFIG_OF) || !dev->of_node) - return ERR_PTR(-ENOTSUPP); - led = of_led_get(dev->of_node, index); if (IS_ERR(led)) return led; diff --git a/drivers/leds/leds-as3645a.c b/drivers/leds/leds-as3645a.c index e8922fa03379620f4ee15896d224bd81535a589f..80411d41e802d4653b23028480f83f12ccba0b22 100644 --- a/drivers/leds/leds-as3645a.c +++ b/drivers/leds/leds-as3645a.c @@ -545,6 +545,7 @@ static int as3645a_parse_node(struct as3645a *flash, if (!flash->indicator_node) { dev_warn(&flash->client->dev, "can't find indicator node\n"); + rval = -ENODEV; goto out_err; } diff --git a/drivers/leds/leds-ktd2692.c b/drivers/leds/leds-ktd2692.c index 632f10db4b3ff5509663af940f8df43f7a11f371..f341da1503a49287aa786ca23f476b2bbf90d7b2 100644 --- a/drivers/leds/leds-ktd2692.c +++ b/drivers/leds/leds-ktd2692.c @@ -256,6 +256,17 @@ static void ktd2692_setup(struct ktd2692_context *led) | KTD2692_REG_FLASH_CURRENT_BASE); } +static void regulator_disable_action(void *_data) +{ + struct device *dev = _data; + struct ktd2692_context *led = dev_get_drvdata(dev); + int ret; + + ret = regulator_disable(led->regulator); + if (ret) + dev_err(dev, "Failed to disable supply: %d\n", ret); +} + static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev, struct ktd2692_led_config_data *cfg) { @@ -286,8 +297,14 @@ static int ktd2692_parse_dt(struct ktd2692_context *led, struct device *dev, if (led->regulator) { ret = regulator_enable(led->regulator); - if (ret) + if (ret) { dev_err(dev, "Failed to enable supply: %d\n", ret); + } else { + ret = devm_add_action_or_reset(dev, + regulator_disable_action, dev); + if (ret) + return ret; + } } child_node = of_get_next_available_child(np, NULL); @@ -377,17 +394,9 @@ static int ktd2692_probe(struct platform_device *pdev) static int ktd2692_remove(struct platform_device *pdev) { struct ktd2692_context *led = platform_get_drvdata(pdev); - int ret; led_classdev_flash_unregister(&led->fled_cdev); - if (led->regulator) { - ret = regulator_disable(led->regulator); - if (ret) - dev_err(&pdev->dev, - "Failed to disable supply: %d\n", ret); - } - mutex_destroy(&led->lock); return 0; diff --git a/drivers/leds/leds-lm36274.c b/drivers/leds/leds-lm36274.c index aadb03468a40a00e930ecb0983cd7bf6f36bbdc5..a23a9424c2f389cab46eade573d6206b2b9a7daa 100644 --- a/drivers/leds/leds-lm36274.c +++ b/drivers/leds/leds-lm36274.c @@ -127,6 +127,7 @@ static int lm36274_probe(struct platform_device *pdev) ret = lm36274_init(chip); if (ret) { + fwnode_handle_put(init_data.fwnode); dev_err(chip->dev, "Failed to init the device\n"); return ret; } diff --git a/drivers/leds/leds-lm3692x.c b/drivers/leds/leds-lm3692x.c index e945de45388ca75dcbcf6c9565a7c45bd953c57b..55e6443997ec9a42e11a61f1762e4a8d73e26e6e 100644 --- a/drivers/leds/leds-lm3692x.c +++ b/drivers/leds/leds-lm3692x.c @@ -435,6 +435,7 @@ static int lm3692x_probe_dt(struct lm3692x_led *led) ret = fwnode_property_read_u32(child, "reg", &led->led_enable); if (ret) { + fwnode_handle_put(child); dev_err(&led->client->dev, "reg DT property missing\n"); return ret; } @@ -449,12 +450,11 @@ static int lm3692x_probe_dt(struct lm3692x_led *led) ret = devm_led_classdev_register_ext(&led->client->dev, &led->led_dev, &init_data); - if (ret) { + if (ret) dev_err(&led->client->dev, "led register err: %d\n", ret); - return ret; - } - return 0; + fwnode_handle_put(init_data.fwnode); + return ret; } static int lm3692x_probe(struct i2c_client *client, diff --git a/drivers/leds/leds-lm3697.c b/drivers/leds/leds-lm3697.c index 7d216cdb91a8abe587d2d9ad1e72ff8260595f4b..912e8bb22a9953db2f8a44f9b73d9e258693bdb2 100644 --- a/drivers/leds/leds-lm3697.c +++ b/drivers/leds/leds-lm3697.c @@ -203,11 +203,9 @@ static int lm3697_probe_dt(struct lm3697 *priv) priv->enable_gpio = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW); - if (IS_ERR(priv->enable_gpio)) { - ret = PTR_ERR(priv->enable_gpio); - dev_err(dev, "Failed to get enable gpio: %d\n", ret); - return ret; - } + if (IS_ERR(priv->enable_gpio)) + return dev_err_probe(dev, PTR_ERR(priv->enable_gpio), + "Failed to get enable GPIO\n"); priv->regulator = devm_regulator_get(dev, "vled"); if (IS_ERR(priv->regulator)) diff --git a/drivers/leds/leds-lp50xx.c b/drivers/leds/leds-lp50xx.c index f13117eed976d90e792d990e55caf304765305b4..d4529082935b8a8d766bdb5e9225d05ee9e6ce61 100644 --- a/drivers/leds/leds-lp50xx.c +++ b/drivers/leds/leds-lp50xx.c @@ -496,6 +496,7 @@ static int lp50xx_probe_dt(struct lp50xx *priv) ret = fwnode_property_read_u32(led_node, "color", &color_id); if (ret) { + fwnode_handle_put(led_node); dev_err(priv->dev, "Cannot read color\n"); goto child_out; } @@ -519,7 +520,6 @@ static int lp50xx_probe_dt(struct lp50xx *priv) goto child_out; } i++; - fwnode_handle_put(child); } return 0; diff --git a/drivers/leds/leds-tlc591xx.c b/drivers/leds/leds-tlc591xx.c index 5b9dfdf743ecdc49633ad94fc7edb8d88e3c5d41..cb7bd1353f9f01e4bf67757ab89f70e19f90d471 100644 --- a/drivers/leds/leds-tlc591xx.c +++ b/drivers/leds/leds-tlc591xx.c @@ -148,16 +148,20 @@ static int tlc591xx_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct device_node *np = dev_of_node(&client->dev), *child; + struct device_node *np, *child; struct device *dev = &client->dev; const struct tlc591xx *tlc591xx; struct tlc591xx_priv *priv; int err, count, reg; - tlc591xx = device_get_match_data(dev); + np = dev_of_node(dev); if (!np) return -ENODEV; + tlc591xx = device_get_match_data(dev); + if (!tlc591xx) + return -ENODEV; + count = of_get_available_child_count(np); if (!count || count > tlc591xx->max_leds) return -EINVAL; diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c index 880fc8def530906336575f17522142b1a4572199..ec87a958f1512ef23d89bac6ecf07e364a382c4f 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -277,6 +277,7 @@ static const struct i2c_device_id omnia_id[] = { { "omnia", 0 }, { } }; +MODULE_DEVICE_TABLE(i2c, omnia_id); static struct i2c_driver omnia_leds_driver = { .probe = omnia_leds_probe, diff --git a/drivers/mailbox/qcom-apcs-ipc-mailbox.c b/drivers/mailbox/qcom-apcs-ipc-mailbox.c index 077e5c6a9ef7de7b474532c792ef2e59a747bb9e..3d100a004760fa84bf72e3f9c120e088818ddef6 100644 --- a/drivers/mailbox/qcom-apcs-ipc-mailbox.c +++ b/drivers/mailbox/qcom-apcs-ipc-mailbox.c @@ -128,7 +128,7 @@ static int qcom_apcs_ipc_probe(struct platform_device *pdev) if (apcs_data->clk_name) { apcs->clk = platform_device_register_data(&pdev->dev, apcs_data->clk_name, - PLATFORM_DEVID_NONE, + PLATFORM_DEVID_AUTO, NULL, 0); if (IS_ERR(apcs->clk)) dev_err(&pdev->dev, "failed to register APCS clk\n"); diff --git a/drivers/mailbox/qcom-ipcc.c b/drivers/mailbox/qcom-ipcc.c index 2d13c72944c6fd5d83adccb1947ca9f22f115169..584700cd15855181dfb41c9485db28e5612cdc5b 100644 --- a/drivers/mailbox/qcom-ipcc.c +++ b/drivers/mailbox/qcom-ipcc.c @@ -155,6 +155,11 @@ static int qcom_ipcc_mbox_send_data(struct mbox_chan *chan, void *data) return 0; } +static void qcom_ipcc_mbox_shutdown(struct mbox_chan *chan) +{ + chan->con_priv = NULL; +} + static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox, const struct of_phandle_args *ph) { @@ -184,6 +189,7 @@ static struct mbox_chan *qcom_ipcc_mbox_xlate(struct mbox_controller *mbox, static const struct mbox_chan_ops ipcc_mbox_chan_ops = { .send_data = qcom_ipcc_mbox_send_data, + .shutdown = qcom_ipcc_mbox_shutdown, }; static int qcom_ipcc_setup_mbox(struct qcom_ipcc *ipcc) diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c index 8628c4aa2e8541d0634b338e404dd57b4f24ce6f..9d6ae3e64285b49ac7b362e07a022290ea3b28d8 100644 --- a/drivers/md/dm-writecache.c +++ b/drivers/md/dm-writecache.c @@ -532,7 +532,7 @@ static void ssd_commit_superblock(struct dm_writecache *wc) region.bdev = wc->ssd_dev->bdev; region.sector = 0; - region.count = PAGE_SIZE >> SECTOR_SHIFT; + region.count = max(4096U, wc->block_size) >> SECTOR_SHIFT; if (unlikely(region.sector + region.count > wc->metadata_sectors)) region.count = wc->metadata_sectors - region.sector; @@ -1301,8 +1301,12 @@ static int writecache_map(struct dm_target *ti, struct bio *bio) writecache_flush(wc); if (writecache_has_error(wc)) goto unlock_error; + if (unlikely(wc->cleaner)) + goto unlock_remap_origin; goto unlock_submit; } else { + if (dm_bio_get_target_bio_nr(bio)) + goto unlock_remap_origin; writecache_offload_bio(wc, bio); goto unlock_return; } @@ -1360,14 +1364,18 @@ read_next_block: } else { do { bool found_entry = false; + bool search_used = false; if (writecache_has_error(wc)) goto unlock_error; e = writecache_find_entry(wc, bio->bi_iter.bi_sector, 0); if (e) { - if (!writecache_entry_is_committed(wc, e)) + if (!writecache_entry_is_committed(wc, e)) { + search_used = true; goto bio_copy; + } if (!WC_MODE_PMEM(wc) && !e->write_in_progress) { wc->overwrote_committed = true; + search_used = true; goto bio_copy; } found_entry = true; @@ -1377,7 +1385,7 @@ read_next_block: } e = writecache_pop_from_freelist(wc, (sector_t)-1); if (unlikely(!e)) { - if (!found_entry) { + if (!WC_MODE_PMEM(wc) && !found_entry) { direct_write: e = writecache_find_entry(wc, bio->bi_iter.bi_sector, WFE_RETURN_FOLLOWING); if (e) { @@ -1404,13 +1412,31 @@ bio_copy: sector_t current_cache_sec = start_cache_sec + (bio_size >> SECTOR_SHIFT); while (bio_size < bio->bi_iter.bi_size) { - struct wc_entry *f = writecache_pop_from_freelist(wc, current_cache_sec); - if (!f) - break; - write_original_sector_seq_count(wc, f, bio->bi_iter.bi_sector + - (bio_size >> SECTOR_SHIFT), wc->seq_count); - writecache_insert_entry(wc, f); - wc->uncommitted_blocks++; + if (!search_used) { + struct wc_entry *f = writecache_pop_from_freelist(wc, current_cache_sec); + if (!f) + break; + write_original_sector_seq_count(wc, f, bio->bi_iter.bi_sector + + (bio_size >> SECTOR_SHIFT), wc->seq_count); + writecache_insert_entry(wc, f); + wc->uncommitted_blocks++; + } else { + struct wc_entry *f; + struct rb_node *next = rb_next(&e->rb_node); + if (!next) + break; + f = container_of(next, struct wc_entry, rb_node); + if (f != e + 1) + break; + if (read_original_sector(wc, f) != + read_original_sector(wc, e) + (wc->block_size >> SECTOR_SHIFT)) + break; + if (unlikely(f->write_in_progress)) + break; + if (writecache_entry_is_committed(wc, f)) + wc->overwrote_committed = true; + e = f; + } bio_size += wc->block_size; current_cache_sec += wc->block_size >> SECTOR_SHIFT; } @@ -2465,7 +2491,7 @@ overflow: goto bad; } - ti->num_flush_bios = 1; + ti->num_flush_bios = WC_MODE_PMEM(wc) ? 1 : 2; ti->flush_supported = true; ti->num_discard_bios = 1; diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c index b298fefb022eb9062025b753d53e71fc42d73b74..5100907974612323a1479870d92e31ad4f7c713a 100644 --- a/drivers/md/dm-zoned-metadata.c +++ b/drivers/md/dm-zoned-metadata.c @@ -1390,6 +1390,13 @@ static int dmz_init_zone(struct blk_zone *blkz, unsigned int num, void *data) return -ENXIO; } + /* + * Devices that have zones with a capacity smaller than the zone size + * (e.g. NVMe zoned namespaces) are not supported. + */ + if (blkz->capacity != blkz->len) + return -ENXIO; + switch (blkz->type) { case BLK_ZONE_TYPE_CONVENTIONAL: set_bit(DMZ_RND, &zone->flags); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 638c04f9e832c73fecf7fb3b0bd22c9f06c88831..19a70f434029b53ce90161c46f14aa6a96a50cbf 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1230,8 +1230,8 @@ static int dm_dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff, /* * A target may call dm_accept_partial_bio only from the map routine. It is - * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_RESET, - * REQ_OP_ZONE_OPEN, REQ_OP_ZONE_CLOSE and REQ_OP_ZONE_FINISH. + * allowed for all bio types except REQ_PREFLUSH, REQ_OP_ZONE_* zone management + * operations and REQ_OP_ZONE_APPEND (zone append writes). * * dm_accept_partial_bio informs the dm that the target only wants to process * additional n_sectors sectors of the bio and the rest of the data should be @@ -1261,9 +1261,13 @@ void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors) { struct dm_target_io *tio = container_of(bio, struct dm_target_io, clone); unsigned bi_size = bio->bi_iter.bi_size >> SECTOR_SHIFT; + BUG_ON(bio->bi_opf & REQ_PREFLUSH); + BUG_ON(op_is_zone_mgmt(bio_op(bio))); + BUG_ON(bio_op(bio) == REQ_OP_ZONE_APPEND); BUG_ON(bi_size > *tio->len_ptr); BUG_ON(n_sectors > bi_size); + *tio->len_ptr -= bi_size - n_sectors; bio->bi_iter.bi_size = n_sectors << SECTOR_SHIFT; } diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index eff04fa23dfad46d7d43dee24cde0a1fd90f2f68..9e4d1212f4c16caefd33b51752b8bdeda0018423 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -549,7 +549,8 @@ int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, delete_at(n, index); } - *new_root = shadow_root(&spine); + if (!r) + *new_root = shadow_root(&spine); exit_shadow_spine(&spine); return r; diff --git a/drivers/md/persistent-data/dm-space-map-disk.c b/drivers/md/persistent-data/dm-space-map-disk.c index bf4c5e2ccb6ffc8d8e0fa5ba049429bdb6dc18d0..e0acae7a3815d4e026cf6b32dc0c4d868895678a 100644 --- a/drivers/md/persistent-data/dm-space-map-disk.c +++ b/drivers/md/persistent-data/dm-space-map-disk.c @@ -171,6 +171,14 @@ static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b) * Any block we allocate has to be free in both the old and current ll. */ r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, smd->begin, smd->ll.nr_blocks, b); + if (r == -ENOSPC) { + /* + * There's no free block between smd->begin and the end of the metadata device. + * We search before smd->begin in case something has been freed. + */ + r = sm_ll_find_common_free_block(&smd->old_ll, &smd->ll, 0, smd->begin, b); + } + if (r) return r; @@ -199,7 +207,6 @@ static int sm_disk_commit(struct dm_space_map *sm) return r; memcpy(&smd->old_ll, &smd->ll, sizeof(smd->old_ll)); - smd->begin = 0; smd->nr_allocated_this_transaction = 0; r = sm_disk_get_nr_free(sm, &nr_free); diff --git a/drivers/md/persistent-data/dm-space-map-metadata.c b/drivers/md/persistent-data/dm-space-map-metadata.c index 9e3c64ec2026fa66b3b1a02adcd5c3b0085f1318..da439ac85796374e1c4582c02b4a884df38564c4 100644 --- a/drivers/md/persistent-data/dm-space-map-metadata.c +++ b/drivers/md/persistent-data/dm-space-map-metadata.c @@ -452,6 +452,14 @@ static int sm_metadata_new_block_(struct dm_space_map *sm, dm_block_t *b) * Any block we allocate has to be free in both the old and current ll. */ r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, smm->begin, smm->ll.nr_blocks, b); + if (r == -ENOSPC) { + /* + * There's no free block between smm->begin and the end of the metadata device. + * We search before smm->begin in case something has been freed. + */ + r = sm_ll_find_common_free_block(&smm->old_ll, &smm->ll, 0, smm->begin, b); + } + if (r) return r; @@ -503,7 +511,6 @@ static int sm_metadata_commit(struct dm_space_map *sm) return r; memcpy(&smm->old_ll, &smm->ll, sizeof(smm->old_ll)); - smm->begin = 0; smm->allocated_this_transaction = 0; return 0; diff --git a/drivers/media/cec/platform/s5p/s5p_cec.c b/drivers/media/cec/platform/s5p/s5p_cec.c index 2a3e7ffefe0a21b7b953ea3321bf4db04357376b..028a09a7531efd986cba2bbdb63d724cca1917a1 100644 --- a/drivers/media/cec/platform/s5p/s5p_cec.c +++ b/drivers/media/cec/platform/s5p/s5p_cec.c @@ -35,10 +35,13 @@ MODULE_PARM_DESC(debug, "debug level (0-2)"); static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable) { + int ret; struct s5p_cec_dev *cec = cec_get_drvdata(adap); if (enable) { - pm_runtime_get_sync(cec->dev); + ret = pm_runtime_resume_and_get(cec->dev); + if (ret < 0) + return ret; s5p_cec_reset(cec); @@ -51,7 +54,7 @@ static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable) } else { s5p_cec_mask_tx_interrupts(cec); s5p_cec_mask_rx_interrupts(cec); - pm_runtime_disable(cec->dev); + pm_runtime_put(cec->dev); } return 0; diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c index c1511094fdc7ba9c5563be46c0655cee060231a0..b735e237013735b44ce82ec22d933dba36302918 100644 --- a/drivers/media/common/siano/smscoreapi.c +++ b/drivers/media/common/siano/smscoreapi.c @@ -908,7 +908,7 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, void *buffer, size_t size) { struct sms_firmware *firmware = (struct sms_firmware *) buffer; - struct sms_msg_data4 *msg; + struct sms_msg_data5 *msg; u32 mem_address, calc_checksum = 0; u32 i, *ptr; u8 *payload = firmware->payload; @@ -989,24 +989,20 @@ static int smscore_load_firmware_family2(struct smscore_device_t *coredev, goto exit_fw_download; if (coredev->mode == DEVICE_MODE_NONE) { - struct sms_msg_data *trigger_msg = - (struct sms_msg_data *) msg; - pr_debug("sending MSG_SMS_SWDOWNLOAD_TRIGGER_REQ\n"); SMS_INIT_MSG(&msg->x_msg_header, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, - sizeof(struct sms_msg_hdr) + - sizeof(u32) * 5); + sizeof(*msg)); - trigger_msg->msg_data[0] = firmware->start_address; + msg->msg_data[0] = firmware->start_address; /* Entry point */ - trigger_msg->msg_data[1] = 6; /* Priority */ - trigger_msg->msg_data[2] = 0x200; /* Stack size */ - trigger_msg->msg_data[3] = 0; /* Parameter */ - trigger_msg->msg_data[4] = 4; /* Task ID */ + msg->msg_data[1] = 6; /* Priority */ + msg->msg_data[2] = 0x200; /* Stack size */ + msg->msg_data[3] = 0; /* Parameter */ + msg->msg_data[4] = 4; /* Task ID */ - rc = smscore_sendrequest_and_wait(coredev, trigger_msg, - trigger_msg->x_msg_header.msg_length, + rc = smscore_sendrequest_and_wait(coredev, msg, + msg->x_msg_header.msg_length, &coredev->trigger_done); } else { SMS_INIT_MSG(&msg->x_msg_header, MSG_SW_RELOAD_EXEC_REQ, diff --git a/drivers/media/common/siano/smscoreapi.h b/drivers/media/common/siano/smscoreapi.h index b3b793b5caf358033a057ba6fe1074d4ef0d7e7e..16c45afabc530282af22d40dede6149f288170f3 100644 --- a/drivers/media/common/siano/smscoreapi.h +++ b/drivers/media/common/siano/smscoreapi.h @@ -629,9 +629,9 @@ struct sms_msg_data2 { u32 msg_data[2]; }; -struct sms_msg_data4 { +struct sms_msg_data5 { struct sms_msg_hdr x_msg_header; - u32 msg_data[4]; + u32 msg_data[5]; }; struct sms_data_download { diff --git a/drivers/media/common/siano/smsdvb-main.c b/drivers/media/common/siano/smsdvb-main.c index ae17407e477a49f1b8977d2de34e35e57a4980cd..7cc654bc52d37654efabd33f9926078019e2acae 100644 --- a/drivers/media/common/siano/smsdvb-main.c +++ b/drivers/media/common/siano/smsdvb-main.c @@ -1176,6 +1176,10 @@ static int smsdvb_hotplug(struct smscore_device_t *coredev, return 0; media_graph_error: + mutex_lock(&g_smsdvb_clientslock); + list_del(&client->entry); + mutex_unlock(&g_smsdvb_clientslock); + smsdvb_debugfs_release(client); client_error: diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c index 89620da983bab0fcb0ee8a78f3c0228e1907a3aa..dddebea644bb8426e7469fe3bf4ed1800f42a264 100644 --- a/drivers/media/dvb-core/dvb_net.c +++ b/drivers/media/dvb-core/dvb_net.c @@ -45,6 +45,7 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/netdevice.h> +#include <linux/nospec.h> #include <linux/etherdevice.h> #include <linux/dvb/net.h> #include <linux/uio.h> @@ -1462,14 +1463,20 @@ static int dvb_net_do_ioctl(struct file *file, struct net_device *netdev; struct dvb_net_priv *priv_data; struct dvb_net_if *dvbnetif = parg; + int if_num = dvbnetif->if_num; - if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || - !dvbnet->state[dvbnetif->if_num]) { + if (if_num >= DVB_NET_DEVICES_MAX) { ret = -EINVAL; goto ioctl_error; } + if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX); - netdev = dvbnet->device[dvbnetif->if_num]; + if (!dvbnet->state[if_num]) { + ret = -EINVAL; + goto ioctl_error; + } + + netdev = dvbnet->device[if_num]; priv_data = netdev_priv(netdev); dvbnetif->pid=priv_data->pid; @@ -1522,14 +1529,20 @@ static int dvb_net_do_ioctl(struct file *file, struct net_device *netdev; struct dvb_net_priv *priv_data; struct __dvb_net_if_old *dvbnetif = parg; + int if_num = dvbnetif->if_num; + + if (if_num >= DVB_NET_DEVICES_MAX) { + ret = -EINVAL; + goto ioctl_error; + } + if_num = array_index_nospec(if_num, DVB_NET_DEVICES_MAX); - if (dvbnetif->if_num >= DVB_NET_DEVICES_MAX || - !dvbnet->state[dvbnetif->if_num]) { + if (!dvbnet->state[if_num]) { ret = -EINVAL; goto ioctl_error; } - netdev = dvbnet->device[dvbnetif->if_num]; + netdev = dvbnet->device[if_num]; priv_data = netdev_priv(netdev); dvbnetif->pid=priv_data->pid; diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c index e8119ad0bc71dc38de4c719a121034e357e2c3d9..92376592455eebf2f8c0eb56a23e991e8944c255 100644 --- a/drivers/media/i2c/ir-kbd-i2c.c +++ b/drivers/media/i2c/ir-kbd-i2c.c @@ -678,8 +678,8 @@ static int zilog_tx(struct rc_dev *rcdev, unsigned int *txbuf, goto out_unlock; } - i = i2c_master_recv(ir->tx_c, buf, 1); - if (i != 1) { + ret = i2c_master_recv(ir->tx_c, buf, 1); + if (ret != 1) { dev_err(&ir->rc->dev, "i2c_master_recv failed with %d\n", ret); ret = -EIO; goto out_unlock; diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 42f64175a6dff2c0122104b0018b27a786a987b9..fb78a1cedc03b71e23e60d42c7bc3882b3e1f410 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -204,6 +204,7 @@ struct ov2659 { struct i2c_client *client; struct v4l2_ctrl_handler ctrls; struct v4l2_ctrl *link_frequency; + struct clk *clk; const struct ov2659_framesize *frame_size; struct sensor_register *format_ctrl_regs; struct ov2659_pll_ctrl pll; @@ -1270,6 +1271,8 @@ static int ov2659_power_off(struct device *dev) gpiod_set_value(ov2659->pwdn_gpio, 1); + clk_disable_unprepare(ov2659->clk); + return 0; } @@ -1278,9 +1281,17 @@ static int ov2659_power_on(struct device *dev) struct i2c_client *client = to_i2c_client(dev); struct v4l2_subdev *sd = i2c_get_clientdata(client); struct ov2659 *ov2659 = to_ov2659(sd); + int ret; dev_dbg(&client->dev, "%s:\n", __func__); + ret = clk_prepare_enable(ov2659->clk); + if (ret) { + dev_err(&client->dev, "%s: failed to enable clock\n", + __func__); + return ret; + } + gpiod_set_value(ov2659->pwdn_gpio, 0); if (ov2659->resetb_gpio) { @@ -1425,7 +1436,6 @@ static int ov2659_probe(struct i2c_client *client) const struct ov2659_platform_data *pdata = ov2659_get_pdata(client); struct v4l2_subdev *sd; struct ov2659 *ov2659; - struct clk *clk; int ret; if (!pdata) { @@ -1440,11 +1450,11 @@ static int ov2659_probe(struct i2c_client *client) ov2659->pdata = pdata; ov2659->client = client; - clk = devm_clk_get(&client->dev, "xvclk"); - if (IS_ERR(clk)) - return PTR_ERR(clk); + ov2659->clk = devm_clk_get(&client->dev, "xvclk"); + if (IS_ERR(ov2659->clk)) + return PTR_ERR(ov2659->clk); - ov2659->xvclk_frequency = clk_get_rate(clk); + ov2659->xvclk_frequency = clk_get_rate(ov2659->clk); if (ov2659->xvclk_frequency < 6000000 || ov2659->xvclk_frequency > 27000000) return -EINVAL; @@ -1506,7 +1516,9 @@ static int ov2659_probe(struct i2c_client *client) ov2659->frame_size = &ov2659_framesizes[2]; ov2659->format_ctrl_regs = ov2659_formats[0].format_ctrl_regs; - ov2659_power_on(&client->dev); + ret = ov2659_power_on(&client->dev); + if (ret < 0) + goto error; ret = ov2659_detect(sd); if (ret < 0) diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c index 5b4c4a3547c93669e4c63d632b0f0187346a3704..71804a70bc6d79bc8ddcd0aa969f92adb7e28c65 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c +++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c @@ -1386,7 +1386,7 @@ static int __s5c73m3_power_on(struct s5c73m3 *state) s5c73m3_gpio_deassert(state, STBY); usleep_range(100, 200); - s5c73m3_gpio_deassert(state, RST); + s5c73m3_gpio_deassert(state, RSET); usleep_range(50, 100); return 0; @@ -1401,7 +1401,7 @@ static int __s5c73m3_power_off(struct s5c73m3 *state) { int i, ret; - if (s5c73m3_gpio_assert(state, RST)) + if (s5c73m3_gpio_assert(state, RSET)) usleep_range(10, 50); if (s5c73m3_gpio_assert(state, STBY)) @@ -1606,7 +1606,7 @@ static int s5c73m3_get_platform_data(struct s5c73m3 *state) state->mclk_frequency = pdata->mclk_frequency; state->gpio[STBY] = pdata->gpio_stby; - state->gpio[RST] = pdata->gpio_reset; + state->gpio[RSET] = pdata->gpio_reset; return 0; } diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h index ef7e85b34263b2afabba95d9c59ab172b161862f..c3fcfdd3ea66dff0196959c5e100db75aebc2563 100644 --- a/drivers/media/i2c/s5c73m3/s5c73m3.h +++ b/drivers/media/i2c/s5c73m3/s5c73m3.h @@ -353,7 +353,7 @@ struct s5c73m3_ctrls { enum s5c73m3_gpio_id { STBY, - RST, + RSET, GPIO_NUM, }; diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c index b2d53417badf6c283c3153d9d22702b2799e9598..4e97309a67f416d1afea1abacd9bc0720ad54890 100644 --- a/drivers/media/i2c/s5k4ecgx.c +++ b/drivers/media/i2c/s5k4ecgx.c @@ -173,7 +173,7 @@ static const char * const s5k4ecgx_supply_names[] = { enum s5k4ecgx_gpio_id { STBY, - RST, + RSET, GPIO_NUM, }; @@ -476,7 +476,7 @@ static int __s5k4ecgx_power_on(struct s5k4ecgx *priv) if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level)) usleep_range(30, 50); - if (s5k4ecgx_gpio_set_value(priv, RST, priv->gpio[RST].level)) + if (s5k4ecgx_gpio_set_value(priv, RSET, priv->gpio[RSET].level)) usleep_range(30, 50); return 0; @@ -484,7 +484,7 @@ static int __s5k4ecgx_power_on(struct s5k4ecgx *priv) static int __s5k4ecgx_power_off(struct s5k4ecgx *priv) { - if (s5k4ecgx_gpio_set_value(priv, RST, !priv->gpio[RST].level)) + if (s5k4ecgx_gpio_set_value(priv, RSET, !priv->gpio[RSET].level)) usleep_range(30, 50); if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level)) @@ -872,7 +872,7 @@ static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv, int ret; priv->gpio[STBY].gpio = -EINVAL; - priv->gpio[RST].gpio = -EINVAL; + priv->gpio[RSET].gpio = -EINVAL; ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY"); @@ -891,7 +891,7 @@ static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv, s5k4ecgx_free_gpios(priv); return ret; } - priv->gpio[RST] = *gpio; + priv->gpio[RSET] = *gpio; if (gpio_is_valid(gpio->gpio)) gpio_set_value(gpio->gpio, 0); diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c index ec6f22efe19ad5cc4c2bc621ee94bcd105eba5fb..ec65a8e084c6ab3ef7d0cc35b5231569a0e537d4 100644 --- a/drivers/media/i2c/s5k5baf.c +++ b/drivers/media/i2c/s5k5baf.c @@ -235,7 +235,7 @@ struct s5k5baf_gpio { enum s5k5baf_gpio_id { STBY, - RST, + RSET, NUM_GPIOS, }; @@ -969,7 +969,7 @@ static int s5k5baf_power_on(struct s5k5baf *state) s5k5baf_gpio_deassert(state, STBY); usleep_range(50, 100); - s5k5baf_gpio_deassert(state, RST); + s5k5baf_gpio_deassert(state, RSET); return 0; err_reg_dis: @@ -987,7 +987,7 @@ static int s5k5baf_power_off(struct s5k5baf *state) state->apply_cfg = 0; state->apply_crop = 0; - s5k5baf_gpio_assert(state, RST); + s5k5baf_gpio_assert(state, RSET); s5k5baf_gpio_assert(state, STBY); if (!IS_ERR(state->clock)) diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c index 72439fae7968bdac20f0fc62e1f9344fe6b50a34..6516e205e9a3d7f0d94b651f36e03f72055b8064 100644 --- a/drivers/media/i2c/s5k6aa.c +++ b/drivers/media/i2c/s5k6aa.c @@ -177,7 +177,7 @@ static const char * const s5k6aa_supply_names[] = { enum s5k6aa_gpio_id { STBY, - RST, + RSET, GPIO_NUM, }; @@ -841,7 +841,7 @@ static int __s5k6aa_power_on(struct s5k6aa *s5k6aa) ret = s5k6aa->s_power(1); usleep_range(4000, 5000); - if (s5k6aa_gpio_deassert(s5k6aa, RST)) + if (s5k6aa_gpio_deassert(s5k6aa, RSET)) msleep(20); return ret; @@ -851,7 +851,7 @@ static int __s5k6aa_power_off(struct s5k6aa *s5k6aa) { int ret; - if (s5k6aa_gpio_assert(s5k6aa, RST)) + if (s5k6aa_gpio_assert(s5k6aa, RSET)) usleep_range(100, 150); if (s5k6aa->s_power) { @@ -1510,7 +1510,7 @@ static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa, int ret; s5k6aa->gpio[STBY].gpio = -EINVAL; - s5k6aa->gpio[RST].gpio = -EINVAL; + s5k6aa->gpio[RSET].gpio = -EINVAL; gpio = &pdata->gpio_stby; if (gpio_is_valid(gpio->gpio)) { @@ -1533,7 +1533,7 @@ static int s5k6aa_configure_gpios(struct s5k6aa *s5k6aa, if (ret < 0) return ret; - s5k6aa->gpio[RST] = *gpio; + s5k6aa->gpio[RSET] = *gpio; } return 0; diff --git a/drivers/media/i2c/saa6588.c b/drivers/media/i2c/saa6588.c index ecb491d5f2ab8a97430a8338e0b97b706e11546c..d1e0716bdfffde5e26fb61993491edd6059eed34 100644 --- a/drivers/media/i2c/saa6588.c +++ b/drivers/media/i2c/saa6588.c @@ -380,7 +380,7 @@ static void saa6588_configure(struct saa6588 *s) /* ---------------------------------------------------------------------- */ -static long saa6588_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) +static long saa6588_command(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct saa6588 *s = to_saa6588(sd); struct saa6588_command *a = arg; @@ -433,7 +433,7 @@ static int saa6588_s_tuner(struct v4l2_subdev *sd, const struct v4l2_tuner *vt) /* ----------------------------------------------------------------------- */ static const struct v4l2_subdev_core_ops saa6588_core_ops = { - .ioctl = saa6588_ioctl, + .command = saa6588_command, }; static const struct v4l2_subdev_tuner_ops saa6588_tuner_ops = { diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index 1b309bb743c7bd7452705606e831319209acf8be..f21da11caf22411456e8bb63327f071a7549d67d 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1974,6 +1974,7 @@ static int tc358743_probe_of(struct tc358743_state *state) bps_pr_lane = 2 * endpoint.link_frequencies[0]; if (bps_pr_lane < 62500000U || bps_pr_lane > 1000000000U) { dev_err(dev, "unsupported bps per lane: %u bps\n", bps_pr_lane); + ret = -EINVAL; goto disable_clk; } diff --git a/drivers/media/mc/Makefile b/drivers/media/mc/Makefile index 119037f0e686dd6daf460c5532d3ba8c0d10652d..2b7af42ba59c19670f51a5e726e707e638d3351a 100644 --- a/drivers/media/mc/Makefile +++ b/drivers/media/mc/Makefile @@ -3,7 +3,7 @@ mc-objs := mc-device.o mc-devnode.o mc-entity.o \ mc-request.o -ifeq ($(CONFIG_USB),y) +ifneq ($(CONFIG_USB),) mc-objs += mc-dev-allocator.o endif diff --git a/drivers/media/pci/bt8xx/bt878.c b/drivers/media/pci/bt8xx/bt878.c index 79ba15a9385a58dd9d61deccbb4bc9e8e2f9dfb2..0705913972c6602693dcb2df00e9f250355c8b45 100644 --- a/drivers/media/pci/bt8xx/bt878.c +++ b/drivers/media/pci/bt8xx/bt878.c @@ -300,7 +300,8 @@ static irqreturn_t bt878_irq(int irq, void *dev_id) } if (astat & BT878_ARISCI) { bt->finished_block = (stat & BT878_ARISCS) >> 28; - tasklet_schedule(&bt->tasklet); + if (bt->tasklet.callback) + tasklet_schedule(&bt->tasklet); break; } count++; @@ -477,6 +478,9 @@ static int bt878_probe(struct pci_dev *dev, const struct pci_device_id *pci_id) btwrite(0, BT878_AINT_MASK); bt878_num++; + if (!bt->tasklet.func) + tasklet_disable(&bt->tasklet); + return 0; fail2: diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index 8824dd0fb331e41184061055b2d497a34e89f2a1..35a51e9b539da194c766e72b7156225db043f9a2 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c @@ -3187,7 +3187,7 @@ static int radio_release(struct file *file) btv->radio_user--; - bttv_call_all(btv, core, ioctl, SAA6588_CMD_CLOSE, &cmd); + bttv_call_all(btv, core, command, SAA6588_CMD_CLOSE, &cmd); if (btv->radio_user == 0) btv->has_radio_tuner = 0; @@ -3268,7 +3268,7 @@ static ssize_t radio_read(struct file *file, char __user *data, cmd.result = -ENODEV; radio_enable(btv); - bttv_call_all(btv, core, ioctl, SAA6588_CMD_READ, &cmd); + bttv_call_all(btv, core, command, SAA6588_CMD_READ, &cmd); return cmd.result; } @@ -3289,7 +3289,7 @@ static __poll_t radio_poll(struct file *file, poll_table *wait) cmd.instance = file; cmd.event_list = wait; cmd.poll_mask = res; - bttv_call_all(btv, core, ioctl, SAA6588_CMD_POLL, &cmd); + bttv_call_all(btv, core, command, SAA6588_CMD_POLL, &cmd); return cmd.poll_mask; } diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c index 0695078ef81252c37eb12fa966d1c91d627279b5..1bd8bbe57a30e6ccd2c2dc66aea24ef2fc46665e 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.c +++ b/drivers/media/pci/cobalt/cobalt-driver.c @@ -667,6 +667,7 @@ static int cobalt_probe(struct pci_dev *pci_dev, return -ENOMEM; cobalt->pci_dev = pci_dev; cobalt->instance = i; + mutex_init(&cobalt->pci_lock); retval = v4l2_device_register(&pci_dev->dev, &cobalt->v4l2_dev); if (retval) { diff --git a/drivers/media/pci/cobalt/cobalt-driver.h b/drivers/media/pci/cobalt/cobalt-driver.h index bca68572b3242af74527cfc39f3c67fd6f104721..12c33e035904cac536b55968927a992e0f850066 100644 --- a/drivers/media/pci/cobalt/cobalt-driver.h +++ b/drivers/media/pci/cobalt/cobalt-driver.h @@ -251,6 +251,8 @@ struct cobalt { int instance; struct pci_dev *pci_dev; struct v4l2_device v4l2_dev; + /* serialize PCI access in cobalt_s_bit_sysctrl() */ + struct mutex pci_lock; void __iomem *bar0, *bar1; @@ -320,10 +322,13 @@ static inline u32 cobalt_g_sysctrl(struct cobalt *cobalt) static inline void cobalt_s_bit_sysctrl(struct cobalt *cobalt, int bit, int val) { - u32 ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE); + u32 ctrl; + mutex_lock(&cobalt->pci_lock); + ctrl = cobalt_read_bar1(cobalt, COBALT_SYS_CTRL_BASE); cobalt_write_bar1(cobalt, COBALT_SYS_CTRL_BASE, (ctrl & ~(1UL << bit)) | (val << bit)); + mutex_unlock(&cobalt->pci_lock); } static inline u32 cobalt_g_sysstat(struct cobalt *cobalt) diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index dcbfe8c9abc721ce0d45c8149a486a5a7255ed5b..2fe4a0bd028449602ba9daee1a5c3cd238c9b2fe 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1476,7 +1476,8 @@ static int cio2_parse_firmware(struct cio2_device *cio2) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; - struct sensor_async_subdev *s_asd = NULL; + struct sensor_async_subdev *s_asd; + struct v4l2_async_subdev *asd; struct fwnode_handle *ep; ep = fwnode_graph_get_endpoint_by_id( @@ -1490,27 +1491,23 @@ static int cio2_parse_firmware(struct cio2_device *cio2) if (ret) goto err_parse; - s_asd = kzalloc(sizeof(*s_asd), GFP_KERNEL); - if (!s_asd) { - ret = -ENOMEM; + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &cio2->notifier, ep, sizeof(*s_asd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); goto err_parse; } + s_asd = container_of(asd, struct sensor_async_subdev, asd); s_asd->csi2.port = vep.base.port; s_asd->csi2.lanes = vep.bus.mipi_csi2.num_data_lanes; - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &cio2->notifier, ep, &s_asd->asd); - if (ret) - goto err_parse; - fwnode_handle_put(ep); continue; err_parse: fwnode_handle_put(ep); - kfree(s_asd); return ret; } diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c index 9a6a6b68f8e3e179c3bd0fcc6dcf883aa3ac1924..85d082baaadc572b2a23b988bbc36e7b5f35369a 100644 --- a/drivers/media/pci/saa7134/saa7134-video.c +++ b/drivers/media/pci/saa7134/saa7134-video.c @@ -1178,7 +1178,7 @@ static int video_release(struct file *file) saa_call_all(dev, tuner, standby); if (vdev->vfl_type == VFL_TYPE_RADIO) - saa_call_all(dev, core, ioctl, SAA6588_CMD_CLOSE, &cmd); + saa_call_all(dev, core, command, SAA6588_CMD_CLOSE, &cmd); mutex_unlock(&dev->lock); return 0; @@ -1197,7 +1197,7 @@ static ssize_t radio_read(struct file *file, char __user *data, cmd.result = -ENODEV; mutex_lock(&dev->lock); - saa_call_all(dev, core, ioctl, SAA6588_CMD_READ, &cmd); + saa_call_all(dev, core, command, SAA6588_CMD_READ, &cmd); mutex_unlock(&dev->lock); return cmd.result; @@ -1213,7 +1213,7 @@ static __poll_t radio_poll(struct file *file, poll_table *wait) cmd.event_list = wait; cmd.poll_mask = 0; mutex_lock(&dev->lock); - saa_call_all(dev, core, ioctl, SAA6588_CMD_POLL, &cmd); + saa_call_all(dev, core, command, SAA6588_CMD_POLL, &cmd); mutex_unlock(&dev->lock); return rc | cmd.poll_mask; diff --git a/drivers/media/platform/am437x/am437x-vpfe.c b/drivers/media/platform/am437x/am437x-vpfe.c index 0fb9f9ba1219d3a29850696408074bcf2d7808c1..31cee69adbe1feff2590dc954f6bad4f550216c0 100644 --- a/drivers/media/platform/am437x/am437x-vpfe.c +++ b/drivers/media/platform/am437x/am437x-vpfe.c @@ -1021,7 +1021,9 @@ static int vpfe_initialize_device(struct vpfe_device *vpfe) if (ret) return ret; - pm_runtime_get_sync(vpfe->pdev); + ret = pm_runtime_resume_and_get(vpfe->pdev); + if (ret < 0) + return ret; vpfe_config_enable(&vpfe->ccdc, 1); @@ -2443,7 +2445,11 @@ static int vpfe_probe(struct platform_device *pdev) pm_runtime_enable(&pdev->dev); /* for now just enable it here instead of waiting for the open */ - pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret < 0) { + vpfe_err(vpfe, "Unable to resume device.\n"); + goto probe_out_v4l2_unregister; + } vpfe_ccdc_config_defaults(ccdc); @@ -2530,6 +2536,11 @@ static int vpfe_suspend(struct device *dev) /* only do full suspend if streaming has started */ if (vb2_start_streaming_called(&vpfe->buffer_queue)) { + /* + * ignore RPM resume errors here, as it is already too late. + * A check like that should happen earlier, either at + * open() or just before start streaming. + */ pm_runtime_get_sync(dev); vpfe_config_enable(ccdc, 1); diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c index d19bad997f30cfffe4345ac73144e2c719498b65..bf3c3e76b9213102629369988855a9322a2fc60d 100644 --- a/drivers/media/platform/davinci/vpbe_display.c +++ b/drivers/media/platform/davinci/vpbe_display.c @@ -47,7 +47,7 @@ static int venc_is_second_field(struct vpbe_display *disp_dev) ret = v4l2_subdev_call(vpbe_dev->venc, core, - ioctl, + command, VENC_GET_FLD, &val); if (ret < 0) { diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c index 8caa084e570469c6fed105a02dd442be471b03b1..bde241c26d795e5af0870af4b66b5ed0fa243d7e 100644 --- a/drivers/media/platform/davinci/vpbe_venc.c +++ b/drivers/media/platform/davinci/vpbe_venc.c @@ -521,9 +521,7 @@ static int venc_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, return ret; } -static long venc_ioctl(struct v4l2_subdev *sd, - unsigned int cmd, - void *arg) +static long venc_command(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { u32 val; @@ -542,7 +540,7 @@ static long venc_ioctl(struct v4l2_subdev *sd, } static const struct v4l2_subdev_core_ops venc_core_ops = { - .ioctl = venc_ioctl, + .command = venc_command, }; static const struct v4l2_subdev_video_ops venc_video_ops = { diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c index 27a3c92c73bce4c031546ecb8bac185b603178e1..f1cf847d1cc2d9fd2f2a75018b8059fb39c79096 100644 --- a/drivers/media/platform/exynos-gsc/gsc-m2m.c +++ b/drivers/media/platform/exynos-gsc/gsc-m2m.c @@ -56,10 +56,8 @@ static void __gsc_m2m_job_abort(struct gsc_ctx *ctx) static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count) { struct gsc_ctx *ctx = q->drv_priv; - int ret; - ret = pm_runtime_get_sync(&ctx->gsc_dev->pdev->dev); - return ret > 0 ? 0 : ret; + return pm_runtime_resume_and_get(&ctx->gsc_dev->pdev->dev); } static void __gsc_m2m_cleanup_queue(struct gsc_ctx *ctx) diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c index 6000a4e789adb017f1310291003d12acb26a3908..808b490c1910f46a7ad6ec731cc640ebee7ca453 100644 --- a/drivers/media/platform/exynos4-is/fimc-capture.c +++ b/drivers/media/platform/exynos4-is/fimc-capture.c @@ -478,11 +478,9 @@ static int fimc_capture_open(struct file *file) goto unlock; set_bit(ST_CAPT_BUSY, &fimc->state); - ret = pm_runtime_get_sync(&fimc->pdev->dev); - if (ret < 0) { - pm_runtime_put_sync(&fimc->pdev->dev); + ret = pm_runtime_resume_and_get(&fimc->pdev->dev); + if (ret < 0) goto unlock; - } ret = v4l2_fh_open(file); if (ret) { diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c index 32ab01e89196d2c49c3ca5bc215355528be769b6..d26fa5967d82154a75f925f66de2868ac9a1603d 100644 --- a/drivers/media/platform/exynos4-is/fimc-is.c +++ b/drivers/media/platform/exynos4-is/fimc-is.c @@ -828,9 +828,9 @@ static int fimc_is_probe(struct platform_device *pdev) goto err_irq; } - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) - goto err_pm; + goto err_irq; vb2_dma_contig_set_max_seg_size(dev, DMA_BIT_MASK(32)); diff --git a/drivers/media/platform/exynos4-is/fimc-isp-video.c b/drivers/media/platform/exynos4-is/fimc-isp-video.c index 612b9872afc87199870bb2660da83b7922d1a686..83688a7982f7034751b8708b44664073e449a07f 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp-video.c +++ b/drivers/media/platform/exynos4-is/fimc-isp-video.c @@ -275,7 +275,7 @@ static int isp_video_open(struct file *file) if (ret < 0) goto unlock; - ret = pm_runtime_get_sync(&isp->pdev->dev); + ret = pm_runtime_resume_and_get(&isp->pdev->dev); if (ret < 0) goto rel_fh; @@ -293,7 +293,6 @@ static int isp_video_open(struct file *file) if (!ret) goto unlock; rel_fh: - pm_runtime_put_noidle(&isp->pdev->dev); v4l2_fh_release(file); unlock: mutex_unlock(&isp->video_lock); @@ -306,17 +305,20 @@ static int isp_video_release(struct file *file) struct fimc_is_video *ivc = &isp->video_capture; struct media_entity *entity = &ivc->ve.vdev.entity; struct media_device *mdev = entity->graph_obj.mdev; + bool is_singular_file; mutex_lock(&isp->video_lock); - if (v4l2_fh_is_singular_file(file) && ivc->streaming) { + is_singular_file = v4l2_fh_is_singular_file(file); + + if (is_singular_file && ivc->streaming) { media_pipeline_stop(entity); ivc->streaming = 0; } _vb2_fop_release(file, NULL); - if (v4l2_fh_is_singular_file(file)) { + if (is_singular_file) { fimc_pipeline_call(&ivc->ve, close); mutex_lock(&mdev->graph_mutex); diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c index a77c49b1851151644cefbcd74d718f245412d833..74b49d30901ed634d42b6c744fa9487398f5093b 100644 --- a/drivers/media/platform/exynos4-is/fimc-isp.c +++ b/drivers/media/platform/exynos4-is/fimc-isp.c @@ -304,11 +304,10 @@ static int fimc_isp_subdev_s_power(struct v4l2_subdev *sd, int on) pr_debug("on: %d\n", on); if (on) { - ret = pm_runtime_get_sync(&is->pdev->dev); - if (ret < 0) { - pm_runtime_put(&is->pdev->dev); + ret = pm_runtime_resume_and_get(&is->pdev->dev); + if (ret < 0) return ret; - } + set_bit(IS_ST_PWR_ON, &is->state); ret = fimc_is_start_firmware(is); diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c index fdd0d369b19251f59b7de1fb12ba0a8d95d110cd..d279f282d592133f3c225f5b6b42cd333499d078 100644 --- a/drivers/media/platform/exynos4-is/fimc-lite.c +++ b/drivers/media/platform/exynos4-is/fimc-lite.c @@ -469,9 +469,9 @@ static int fimc_lite_open(struct file *file) } set_bit(ST_FLITE_IN_USE, &fimc->state); - ret = pm_runtime_get_sync(&fimc->pdev->dev); + ret = pm_runtime_resume_and_get(&fimc->pdev->dev); if (ret < 0) - goto err_pm; + goto err_in_use; ret = v4l2_fh_open(file); if (ret < 0) @@ -499,6 +499,7 @@ static int fimc_lite_open(struct file *file) v4l2_fh_release(file); err_pm: pm_runtime_put_sync(&fimc->pdev->dev); +err_in_use: clear_bit(ST_FLITE_IN_USE, &fimc->state); unlock: mutex_unlock(&fimc->lock); diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c index 4acb179556c4126f687143acd2b1679b3f17254d..24b1badd20807af7748ec349cc256fad4856a58d 100644 --- a/drivers/media/platform/exynos4-is/fimc-m2m.c +++ b/drivers/media/platform/exynos4-is/fimc-m2m.c @@ -73,17 +73,14 @@ static void fimc_m2m_shutdown(struct fimc_ctx *ctx) static int start_streaming(struct vb2_queue *q, unsigned int count) { struct fimc_ctx *ctx = q->drv_priv; - int ret; - ret = pm_runtime_get_sync(&ctx->fimc_dev->pdev->dev); - return ret > 0 ? 0 : ret; + return pm_runtime_resume_and_get(&ctx->fimc_dev->pdev->dev); } static void stop_streaming(struct vb2_queue *q) { struct fimc_ctx *ctx = q->drv_priv; - fimc_m2m_shutdown(ctx); fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); pm_runtime_put(&ctx->fimc_dev->pdev->dev); diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index e636c33e847bd6cb0832e25075285f2302e9df71..a9a8f0433fb2c7c96ff617bed6be64cd613ba307 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -508,11 +508,9 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd) if (!fmd->pmf) return -ENXIO; - ret = pm_runtime_get_sync(fmd->pmf); - if (ret < 0) { - pm_runtime_put(fmd->pmf); + ret = pm_runtime_resume_and_get(fmd->pmf); + if (ret < 0) return ret; - } fmd->num_sensors = 0; @@ -1282,13 +1280,11 @@ static DEVICE_ATTR(subdev_conf_mode, S_IWUSR | S_IRUGO, static int cam_clk_prepare(struct clk_hw *hw) { struct cam_clk *camclk = to_cam_clk(hw); - int ret; if (camclk->fmd->pmf == NULL) return -ENODEV; - ret = pm_runtime_get_sync(camclk->fmd->pmf); - return ret < 0 ? ret : 0; + return pm_runtime_resume_and_get(camclk->fmd->pmf); } static void cam_clk_unprepare(struct clk_hw *hw) diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c index 1aac167abb175a61835dbf21777bd1caf5d3bfd3..ebf39c8568943085e27a878ce524091fbfb49009 100644 --- a/drivers/media/platform/exynos4-is/mipi-csis.c +++ b/drivers/media/platform/exynos4-is/mipi-csis.c @@ -494,7 +494,7 @@ static int s5pcsis_s_power(struct v4l2_subdev *sd, int on) struct device *dev = &state->pdev->dev; if (on) - return pm_runtime_get_sync(dev); + return pm_runtime_resume_and_get(dev); return pm_runtime_put_sync(dev); } @@ -509,11 +509,9 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable) if (enable) { s5pcsis_clear_counters(state); - ret = pm_runtime_get_sync(&state->pdev->dev); - if (ret && ret != 1) { - pm_runtime_put_noidle(&state->pdev->dev); + ret = pm_runtime_resume_and_get(&state->pdev->dev); + if (ret < 0) return ret; - } } mutex_lock(&state->lock); @@ -535,7 +533,7 @@ unlock: if (!enable) pm_runtime_put(&state->pdev->dev); - return ret == 1 ? 0 : ret; + return ret; } static int s5pcsis_enum_mbus_code(struct v4l2_subdev *sd, diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c index 34266fba824f232fcf169bc18248de038ee25719..e56c5e56e824a887b88bab1a66f0ad7cd6428219 100644 --- a/drivers/media/platform/marvell-ccic/mcam-core.c +++ b/drivers/media/platform/marvell-ccic/mcam-core.c @@ -918,6 +918,7 @@ static int mclk_enable(struct clk_hw *hw) struct mcam_camera *cam = container_of(hw, struct mcam_camera, mclk_hw); int mclk_src; int mclk_div; + int ret; /* * Clock the sensor appropriately. Controller clock should @@ -931,7 +932,9 @@ static int mclk_enable(struct clk_hw *hw) mclk_div = 2; } - pm_runtime_get_sync(cam->dev); + ret = pm_runtime_resume_and_get(cam->dev); + if (ret < 0) + return ret; clk_enable(cam->clk[0]); mcam_reg_write(cam, REG_CLKCTRL, (mclk_src << 29) | mclk_div); mcam_ctlr_power_up(cam); @@ -1611,7 +1614,9 @@ static int mcam_v4l_open(struct file *filp) ret = sensor_call(cam, core, s_power, 1); if (ret) goto out; - pm_runtime_get_sync(cam->dev); + ret = pm_runtime_resume_and_get(cam->dev); + if (ret < 0) + goto out; __mcam_cam_reset(cam); mcam_set_config_needed(cam, 1); } diff --git a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c index 724c7333b6e5a75f6838d7c76553e8680df9d078..45fc741c5541149f938e4ae52e194306342d4f77 100644 --- a/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c +++ b/drivers/media/platform/mtk-mdp/mtk_mdp_m2m.c @@ -394,12 +394,12 @@ static int mtk_mdp_m2m_start_streaming(struct vb2_queue *q, unsigned int count) struct mtk_mdp_ctx *ctx = q->drv_priv; int ret; - ret = pm_runtime_get_sync(&ctx->mdp_dev->pdev->dev); + ret = pm_runtime_resume_and_get(&ctx->mdp_dev->pdev->dev); if (ret < 0) - mtk_mdp_dbg(1, "[%d] pm_runtime_get_sync failed:%d", + mtk_mdp_dbg(1, "[%d] pm_runtime_resume_and_get failed:%d", ctx->id, ret); - return 0; + return ret; } static void *mtk_mdp_m2m_buf_remove(struct mtk_mdp_ctx *ctx, diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c index 145686d2c219c49a39438cfe28525ad2c7aef950..f59ef8c8c9db4369c049abe77403d3563bd4d37b 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_drv.c @@ -126,7 +126,9 @@ static int fops_vcodec_open(struct file *file) mtk_vcodec_dec_set_default_params(ctx); if (v4l2_fh_is_singular(&ctx->fh)) { - mtk_vcodec_dec_pw_on(&dev->pm); + ret = mtk_vcodec_dec_pw_on(&dev->pm); + if (ret < 0) + goto err_load_fw; /* * Does nothing if firmware was already loaded. */ diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c index ddee7046ce4225fca0cf95c490e576b3d9e106cc..6038db96f71c31f1c65433e654c76e9fc905ee9b 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.c @@ -88,13 +88,15 @@ void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev) put_device(dev->pm.larbvdec); } -void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) +int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm) { int ret; - ret = pm_runtime_get_sync(pm->dev); + ret = pm_runtime_resume_and_get(pm->dev); if (ret) - mtk_v4l2_err("pm_runtime_get_sync fail %d", ret); + mtk_v4l2_err("pm_runtime_resume_and_get fail %d", ret); + + return ret; } void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm) diff --git a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h index 872d8bf8cfaf3c6f1f20e2df129bf1482986a859..280aeaefdb6514d976adf1fda0e0120917376f50 100644 --- a/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h +++ b/drivers/media/platform/mtk-vcodec/mtk_vcodec_dec_pm.h @@ -12,7 +12,7 @@ int mtk_vcodec_init_dec_pm(struct mtk_vcodec_dev *dev); void mtk_vcodec_release_dec_pm(struct mtk_vcodec_dev *dev); -void mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm); +int mtk_vcodec_dec_pw_on(struct mtk_vcodec_pm *pm); void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm); void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm); void mtk_vcodec_dec_clock_off(struct mtk_vcodec_pm *pm); diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index b1fc4518e275d59171819536af0b7225042d3c49..1311b4996ecebbd32bd987c8b88f29562bb50bc4 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2126,21 +2126,6 @@ static void isp_parse_of_csi1_endpoint(struct device *dev, buscfg->bus.ccp2.crc = 1; } -static int isp_alloc_isd(struct isp_async_subdev **isd, - struct isp_bus_cfg **buscfg) -{ - struct isp_async_subdev *__isd; - - __isd = kzalloc(sizeof(*__isd), GFP_KERNEL); - if (!__isd) - return -ENOMEM; - - *isd = __isd; - *buscfg = &__isd->bus; - - return 0; -} - static struct { u32 phy; u32 csi2_if; @@ -2156,7 +2141,7 @@ static int isp_parse_of_endpoints(struct isp_device *isp) { struct fwnode_handle *ep; struct isp_async_subdev *isd = NULL; - struct isp_bus_cfg *buscfg; + struct v4l2_async_subdev *asd; unsigned int i; ep = fwnode_graph_get_endpoint_by_id( @@ -2174,20 +2159,15 @@ static int isp_parse_of_endpoints(struct isp_device *isp) ret = v4l2_fwnode_endpoint_parse(ep, &vep); if (!ret) { - ret = isp_alloc_isd(&isd, &buscfg); - if (ret) - return ret; - } - - if (!ret) { - isp_parse_of_parallel_endpoint(isp->dev, &vep, buscfg); - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &isp->notifier, ep, &isd->asd); + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &isp->notifier, ep, sizeof(*isd)); + if (!IS_ERR(asd)) { + isd = container_of(asd, struct isp_async_subdev, asd); + isp_parse_of_parallel_endpoint(isp->dev, &vep, &isd->bus); + } } fwnode_handle_put(ep); - if (ret) - kfree(isd); } for (i = 0; i < ARRAY_SIZE(isp_bus_interfaces); i++) { @@ -2206,15 +2186,8 @@ static int isp_parse_of_endpoints(struct isp_device *isp) dev_dbg(isp->dev, "parsing serial interface %u, node %pOF\n", i, to_of_node(ep)); - ret = isp_alloc_isd(&isd, &buscfg); - if (ret) - return ret; - ret = v4l2_fwnode_endpoint_parse(ep, &vep); - if (!ret) { - buscfg->interface = isp_bus_interfaces[i].csi2_if; - isp_parse_of_csi2_endpoint(isp->dev, &vep, buscfg); - } else if (ret == -ENXIO) { + if (ret == -ENXIO) { vep = (struct v4l2_fwnode_endpoint) { .bus_type = V4L2_MBUS_CSI1 }; ret = v4l2_fwnode_endpoint_parse(ep, &vep); @@ -2224,21 +2197,35 @@ static int isp_parse_of_endpoints(struct isp_device *isp) { .bus_type = V4L2_MBUS_CCP2 }; ret = v4l2_fwnode_endpoint_parse(ep, &vep); } - if (!ret) { - buscfg->interface = - isp_bus_interfaces[i].csi1_if; - isp_parse_of_csi1_endpoint(isp->dev, &vep, - buscfg); - } } - if (!ret) - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &isp->notifier, ep, &isd->asd); + if (!ret) { + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &isp->notifier, ep, sizeof(*isd)); + + if (!IS_ERR(asd)) { + isd = container_of(asd, struct isp_async_subdev, asd); + + switch (vep.bus_type) { + case V4L2_MBUS_CSI2_DPHY: + isd->bus.interface = + isp_bus_interfaces[i].csi2_if; + isp_parse_of_csi2_endpoint(isp->dev, &vep, &isd->bus); + break; + case V4L2_MBUS_CSI1: + case V4L2_MBUS_CCP2: + isd->bus.interface = + isp_bus_interfaces[i].csi1_if; + isp_parse_of_csi1_endpoint(isp->dev, &vep, + &isd->bus); + break; + default: + break; + } + } + } fwnode_handle_put(ep); - if (ret) - kfree(isd); } return 0; diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index fd5993b3e674335ea4c21893204fe67b1b3b7a64..58ddebbb84468a08363da2f45e72bfa03abe280f 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -48,52 +48,86 @@ static const struct hfi_core_ops venus_core_ops = { .event_notify = venus_event_notify, }; +#define RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS 10 + static void venus_sys_error_handler(struct work_struct *work) { struct venus_core *core = container_of(work, struct venus_core, work.work); - int ret = 0; - - pm_runtime_get_sync(core->dev); + int ret, i, max_attempts = RPM_WAIT_FOR_IDLE_MAX_ATTEMPTS; + const char *err_msg = ""; + bool failed = false; + + ret = pm_runtime_get_sync(core->dev); + if (ret < 0) { + err_msg = "resume runtime PM"; + max_attempts = 0; + failed = true; + } hfi_core_deinit(core, true); - dev_warn(core->dev, "system error has occurred, starting recovery!\n"); - mutex_lock(&core->lock); - while (pm_runtime_active(core->dev_dec) || pm_runtime_active(core->dev_enc)) + for (i = 0; i < max_attempts; i++) { + if (!pm_runtime_active(core->dev_dec) && !pm_runtime_active(core->dev_enc)) + break; msleep(10); + } venus_shutdown(core); pm_runtime_put_sync(core->dev); - while (core->pmdomains[0] && pm_runtime_active(core->pmdomains[0])) + for (i = 0; i < max_attempts; i++) { + if (!core->pmdomains[0] || !pm_runtime_active(core->pmdomains[0])) + break; usleep_range(1000, 1500); + } hfi_reinit(core); - pm_runtime_get_sync(core->dev); + ret = pm_runtime_get_sync(core->dev); + if (ret < 0) { + err_msg = "resume runtime PM"; + failed = true; + } + + ret = venus_boot(core); + if (ret && !failed) { + err_msg = "boot Venus"; + failed = true; + } - ret |= venus_boot(core); - ret |= hfi_core_resume(core, true); + ret = hfi_core_resume(core, true); + if (ret && !failed) { + err_msg = "resume HFI"; + failed = true; + } enable_irq(core->irq); mutex_unlock(&core->lock); - ret |= hfi_core_init(core); + ret = hfi_core_init(core); + if (ret && !failed) { + err_msg = "init HFI"; + failed = true; + } pm_runtime_put_sync(core->dev); - if (ret) { + if (failed) { disable_irq_nosync(core->irq); - dev_warn(core->dev, "recovery failed (%d)\n", ret); + dev_warn_ratelimited(core->dev, + "System error has occurred, recovery failed to %s\n", + err_msg); schedule_delayed_work(&core->work, msecs_to_jiffies(10)); return; } + dev_warn(core->dev, "system error has occurred (recovered)\n"); + mutex_lock(&core->lock); core->sys_error = false; mutex_unlock(&core->lock); diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c index 15bcb7f6e113c264b755035d5833773f8267ab4e..1cb5eaabf340b34f583dc36f43d4817f2ee0b279 100644 --- a/drivers/media/platform/s5p-g2d/g2d.c +++ b/drivers/media/platform/s5p-g2d/g2d.c @@ -276,6 +276,9 @@ static int g2d_release(struct file *file) struct g2d_dev *dev = video_drvdata(file); struct g2d_ctx *ctx = fh2ctx(file->private_data); + mutex_lock(&dev->mutex); + v4l2_m2m_ctx_release(ctx->fh.m2m_ctx); + mutex_unlock(&dev->mutex); v4l2_ctrl_handler_free(&ctx->ctrl_handler); v4l2_fh_del(&ctx->fh); v4l2_fh_exit(&ctx->fh); diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c index 9b22dd8e34f44b907db4889928487b94cec50fc2..d515eb08c3ee47e6fe5ccd56233c51c95d97ea3a 100644 --- a/drivers/media/platform/s5p-jpeg/jpeg-core.c +++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c @@ -2566,11 +2566,8 @@ static void s5p_jpeg_buf_queue(struct vb2_buffer *vb) static int s5p_jpeg_start_streaming(struct vb2_queue *q, unsigned int count) { struct s5p_jpeg_ctx *ctx = vb2_get_drv_priv(q); - int ret; - - ret = pm_runtime_get_sync(ctx->jpeg->dev); - return ret > 0 ? 0 : ret; + return pm_runtime_resume_and_get(ctx->jpeg->dev); } static void s5p_jpeg_stop_streaming(struct vb2_queue *q) diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c index b22dc1d725276f61bf2c47dfff21b00d93d54b3f..7d30e0c9447e8c6c3bfb98bdf9ff1e0e97457236 100644 --- a/drivers/media/platform/sh_vou.c +++ b/drivers/media/platform/sh_vou.c @@ -1133,7 +1133,11 @@ static int sh_vou_open(struct file *file) if (v4l2_fh_is_singular_file(file) && vou_dev->status == SH_VOU_INITIALISING) { /* First open */ - pm_runtime_get_sync(vou_dev->v4l2_dev.dev); + err = pm_runtime_resume_and_get(vou_dev->v4l2_dev.dev); + if (err < 0) { + v4l2_fh_release(file); + goto done_open; + } err = sh_vou_hw_init(vou_dev); if (err < 0) { pm_runtime_put(vou_dev->v4l2_dev.dev); diff --git a/drivers/media/platform/sti/bdisp/Makefile b/drivers/media/platform/sti/bdisp/Makefile index caf7ccd193eaaa0f4de0cd162d59b7d519543dc6..39ade0a34723634c92758a4ad3bdabcbf940cc5f 100644 --- a/drivers/media/platform/sti/bdisp/Makefile +++ b/drivers/media/platform/sti/bdisp/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_VIDEO_STI_BDISP) := bdisp.o +obj-$(CONFIG_VIDEO_STI_BDISP) += bdisp.o bdisp-objs := bdisp-v4l2.o bdisp-hw.o bdisp-debug.o diff --git a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c index 060ca85f64d5d0840d446ee84c9c57e1250f7950..85288da9d2ae69edcedc4c8e836205f27ccae8c8 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-v4l2.c +++ b/drivers/media/platform/sti/bdisp/bdisp-v4l2.c @@ -499,7 +499,7 @@ static int bdisp_start_streaming(struct vb2_queue *q, unsigned int count) { struct bdisp_ctx *ctx = q->drv_priv; struct vb2_v4l2_buffer *buf; - int ret = pm_runtime_get_sync(ctx->bdisp_dev->dev); + int ret = pm_runtime_resume_and_get(ctx->bdisp_dev->dev); if (ret < 0) { dev_err(ctx->bdisp_dev->dev, "failed to set runtime PM\n"); @@ -1364,10 +1364,10 @@ static int bdisp_probe(struct platform_device *pdev) /* Power management */ pm_runtime_enable(dev); - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { dev_err(dev, "failed to set PM\n"); - goto err_pm; + goto err_remove; } /* Filters */ @@ -1395,6 +1395,7 @@ err_filter: bdisp_hw_free_filters(bdisp->dev); err_pm: pm_runtime_put(dev); +err_remove: bdisp_debugfs_remove(bdisp); v4l2_device_unregister(&bdisp->v4l2_dev); err_clk: diff --git a/drivers/media/platform/sti/delta/Makefile b/drivers/media/platform/sti/delta/Makefile index 92b37e216f004e2e0bb0e9b4fc0bb601fffaaff8..32412fa4c63283b163210882a38a5a2b9f4b2bb1 100644 --- a/drivers/media/platform/sti/delta/Makefile +++ b/drivers/media/platform/sti/delta/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) := st-delta.o +obj-$(CONFIG_VIDEO_STI_DELTA_DRIVER) += st-delta.o st-delta-y := delta-v4l2.o delta-mem.o delta-ipc.o delta-debug.o # MJPEG support diff --git a/drivers/media/platform/sti/hva/Makefile b/drivers/media/platform/sti/hva/Makefile index 74b41ec52f9766aed33b1edc5ffdec1b660a8123..b5a5478bdd01692ab4c295837306ab0f0837da8f 100644 --- a/drivers/media/platform/sti/hva/Makefile +++ b/drivers/media/platform/sti/hva/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_VIDEO_STI_HVA) := st-hva.o +obj-$(CONFIG_VIDEO_STI_HVA) += st-hva.o st-hva-y := hva-v4l2.o hva-hw.o hva-mem.o hva-h264.o st-hva-$(CONFIG_VIDEO_STI_HVA_DEBUGFS) += hva-debugfs.o diff --git a/drivers/media/platform/sti/hva/hva-hw.c b/drivers/media/platform/sti/hva/hva-hw.c index 43f279e2a6a380cf8e077a8f661d85943200a7aa..cf4c891bf619aba574febaa56c3f699572177c6b 100644 --- a/drivers/media/platform/sti/hva/hva-hw.c +++ b/drivers/media/platform/sti/hva/hva-hw.c @@ -130,8 +130,7 @@ static irqreturn_t hva_hw_its_irq_thread(int irq, void *arg) ctx_id = (hva->sts_reg & 0xFF00) >> 8; if (ctx_id >= HVA_MAX_INSTANCES) { dev_err(dev, "%s %s: bad context identifier: %d\n", - ctx->name, __func__, ctx_id); - ctx->hw_err = true; + HVA_PREFIX, __func__, ctx_id); goto out; } diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c index eb15c8c725ca0bfd2b205c36508c5c517568a2cb..64f25921463e940ca3df634710198b7ecff76313 100644 --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.c @@ -118,6 +118,7 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_PARALLEL, }; + struct v4l2_async_subdev *asd; struct fwnode_handle *ep; int ret; @@ -134,10 +135,12 @@ static int sun4i_csi_notifier_init(struct sun4i_csi *csi) csi->bus = vep.bus.parallel; - ret = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier, - ep, &csi->asd); - if (ret) + asd = v4l2_async_notifier_add_fwnode_remote_subdev(&csi->notifier, + ep, sizeof(*asd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); goto out; + } csi->notifier.ops = &sun4i_csi_notify_ops; diff --git a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h index 0f67ff652c2e14bc757e32563228f98ab638c73c..a5f61ee0ec4df8b68d568986559194eb4b433e99 100644 --- a/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h +++ b/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h @@ -139,7 +139,6 @@ struct sun4i_csi { struct v4l2_mbus_framefmt subdev_fmt; /* V4L2 Async variables */ - struct v4l2_async_subdev asd; struct v4l2_async_notifier notifier; struct v4l2_subdev *src_subdev; int src_pad; diff --git a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c index 3f81dd17755cb68b3dd917b5f84314b1ee4b5d35..fbcca59a0517ce2b2a9b9dcdbd44f0fae7b0678c 100644 --- a/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c +++ b/drivers/media/platform/sunxi/sun8i-rotate/sun8i_rotate.c @@ -494,7 +494,7 @@ static int rotate_start_streaming(struct vb2_queue *vq, unsigned int count) struct device *dev = ctx->dev->dev; int ret; - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) { dev_err(dev, "Failed to enable module\n"); diff --git a/drivers/media/platform/video-mux.c b/drivers/media/platform/video-mux.c index 53570250a25d5ac8bd7ccdc7ead8e82d95287b7d..640ce76fe0d92b27230817e01cecaf62c4d7de8f 100644 --- a/drivers/media/platform/video-mux.c +++ b/drivers/media/platform/video-mux.c @@ -362,7 +362,7 @@ static int video_mux_async_register(struct video_mux *vmux, for (i = 0; i < num_input_pads; i++) { struct v4l2_async_subdev *asd; - struct fwnode_handle *ep; + struct fwnode_handle *ep, *remote_ep; ep = fwnode_graph_get_endpoint_by_id( dev_fwnode(vmux->subdev.dev), i, 0, @@ -370,19 +370,21 @@ static int video_mux_async_register(struct video_mux *vmux, if (!ep) continue; - asd = kzalloc(sizeof(*asd), GFP_KERNEL); - if (!asd) { + /* Skip dangling endpoints for backwards compatibility */ + remote_ep = fwnode_graph_get_remote_endpoint(ep); + if (!remote_ep) { fwnode_handle_put(ep); - return -ENOMEM; + continue; } + fwnode_handle_put(remote_ep); - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &vmux->notifier, ep, asd); + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &vmux->notifier, ep, sizeof(*asd)); fwnode_handle_put(ep); - if (ret) { - kfree(asd); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); /* OK if asd already exists */ if (ret != -EEXIST) return ret; diff --git a/drivers/media/rc/bpf-lirc.c b/drivers/media/rc/bpf-lirc.c index 3fe3edd8087656013846c33d3ac690d4700f542f..afae0afe3f810e969fe090d95c94c4ffcb93d229 100644 --- a/drivers/media/rc/bpf-lirc.c +++ b/drivers/media/rc/bpf-lirc.c @@ -326,7 +326,8 @@ int lirc_prog_query(const union bpf_attr *attr, union bpf_attr __user *uattr) } if (attr->query.prog_cnt != 0 && prog_ids && cnt) - ret = bpf_prog_array_copy_to_user(progs, prog_ids, cnt); + ret = bpf_prog_array_copy_to_user(progs, prog_ids, + attr->query.prog_cnt); unlock: mutex_unlock(&ir_raw_handler_lock); diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c index a8a72d5fbd129945a4ef005c05ce28108913567a..caefac07af927f0e62516ef1c4bda3bf6b3b0ce6 100644 --- a/drivers/media/usb/au0828/au0828-core.c +++ b/drivers/media/usb/au0828/au0828-core.c @@ -199,8 +199,8 @@ static int au0828_media_device_init(struct au0828_dev *dev, struct media_device *mdev; mdev = media_device_usb_allocate(udev, KBUILD_MODNAME, THIS_MODULE); - if (!mdev) - return -ENOMEM; + if (IS_ERR(mdev)) + return PTR_ERR(mdev); dev->media_dev = mdev; #endif diff --git a/drivers/media/usb/cpia2/cpia2.h b/drivers/media/usb/cpia2/cpia2.h index 50835f5f7512c22651eacd7f7a2980d0c6d6304b..57b7f1ea68da52f2e8f252a1d30f06c590bac5ab 100644 --- a/drivers/media/usb/cpia2/cpia2.h +++ b/drivers/media/usb/cpia2/cpia2.h @@ -429,6 +429,7 @@ int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd); int cpia2_do_command(struct camera_data *cam, unsigned int command, unsigned char direction, unsigned char param); +void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf); struct camera_data *cpia2_init_camera_struct(struct usb_interface *intf); int cpia2_init_camera(struct camera_data *cam); int cpia2_allocate_buffers(struct camera_data *cam); diff --git a/drivers/media/usb/cpia2/cpia2_core.c b/drivers/media/usb/cpia2/cpia2_core.c index e747548ab28695fd2d965a1336edc3dc225b6ec5..b5a2d06fb356b302479fd32f5e03b4e6f10ac531 100644 --- a/drivers/media/usb/cpia2/cpia2_core.c +++ b/drivers/media/usb/cpia2/cpia2_core.c @@ -2163,6 +2163,18 @@ static void reset_camera_struct(struct camera_data *cam) cam->height = cam->params.roi.height; } +/****************************************************************************** + * + * cpia2_init_camera_struct + * + * Deinitialize camera struct + *****************************************************************************/ +void cpia2_deinit_camera_struct(struct camera_data *cam, struct usb_interface *intf) +{ + v4l2_device_unregister(&cam->v4l2_dev); + kfree(cam); +} + /****************************************************************************** * * cpia2_init_camera_struct diff --git a/drivers/media/usb/cpia2/cpia2_usb.c b/drivers/media/usb/cpia2/cpia2_usb.c index 3ab80a7b44985d7b694a99accdad6fc374f2a9ae..76aac06f9fb8e2cb5b85ada5a77be10900e37dfc 100644 --- a/drivers/media/usb/cpia2/cpia2_usb.c +++ b/drivers/media/usb/cpia2/cpia2_usb.c @@ -844,15 +844,13 @@ static int cpia2_usb_probe(struct usb_interface *intf, ret = set_alternate(cam, USBIF_CMDONLY); if (ret < 0) { ERR("%s: usb_set_interface error (ret = %d)\n", __func__, ret); - kfree(cam); - return ret; + goto alt_err; } if((ret = cpia2_init_camera(cam)) < 0) { ERR("%s: failed to initialize cpia2 camera (ret = %d)\n", __func__, ret); - kfree(cam); - return ret; + goto alt_err; } LOG(" CPiA Version: %d.%02d (%d.%d)\n", cam->params.version.firmware_revision_hi, @@ -872,11 +870,14 @@ static int cpia2_usb_probe(struct usb_interface *intf, ret = cpia2_register_camera(cam); if (ret < 0) { ERR("%s: Failed to register cpia2 camera (ret = %d)\n", __func__, ret); - kfree(cam); - return ret; + goto alt_err; } return 0; + +alt_err: + cpia2_deinit_camera_struct(cam, intf); + return ret; } /****************************************************************************** diff --git a/drivers/media/usb/dvb-usb/cinergyT2-core.c b/drivers/media/usb/dvb-usb/cinergyT2-core.c index 969a7ec71dff7fcb4f930a35a97136466e59d032..4116ba5c45fcb457d95f86aa2824c90ca1c98ba3 100644 --- a/drivers/media/usb/dvb-usb/cinergyT2-core.c +++ b/drivers/media/usb/dvb-usb/cinergyT2-core.c @@ -78,6 +78,8 @@ static int cinergyt2_frontend_attach(struct dvb_usb_adapter *adap) ret = dvb_usb_generic_rw(d, st->data, 1, st->data, 3, 0); if (ret < 0) { + if (adap->fe_adap[0].fe) + adap->fe_adap[0].fe->ops.release(adap->fe_adap[0].fe); deb_rc("cinergyt2_power_ctrl() Failed to retrieve sleep state info\n"); } mutex_unlock(&d->data_mutex); diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c index 761992ad05e2a141996977b07f42f576cfcd8ac3..7707de7bae7caea07f19fc24b24da4d7a3a86b02 100644 --- a/drivers/media/usb/dvb-usb/cxusb.c +++ b/drivers/media/usb/dvb-usb/cxusb.c @@ -1947,7 +1947,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_lgz201_properties = { .size_of_priv = sizeof(struct cxusb_state), - .num_adapters = 2, + .num_adapters = 1, .adapter = { { .num_frontends = 1, diff --git a/drivers/media/usb/dvb-usb/dtv5100.c b/drivers/media/usb/dvb-usb/dtv5100.c index fba06932a9e0e2d772f153bfc4c9493cfb9bec08..1c13e493322cc7323fc679f40a974851160e1a90 100644 --- a/drivers/media/usb/dvb-usb/dtv5100.c +++ b/drivers/media/usb/dvb-usb/dtv5100.c @@ -26,6 +26,7 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen) { struct dtv5100_state *st = d->priv; + unsigned int pipe; u8 request; u8 type; u16 value; @@ -34,6 +35,7 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, switch (wlen) { case 1: /* write { reg }, read { value } */ + pipe = usb_rcvctrlpipe(d->udev, 0); request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ : DTV5100_TUNER_READ); type = USB_TYPE_VENDOR | USB_DIR_IN; @@ -41,6 +43,7 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, break; case 2: /* write { reg, value } */ + pipe = usb_sndctrlpipe(d->udev, 0); request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE : DTV5100_TUNER_WRITE); type = USB_TYPE_VENDOR | USB_DIR_OUT; @@ -54,7 +57,7 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr, memcpy(st->data, rbuf, rlen); msleep(1); /* avoid I2C errors */ - return usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), request, + return usb_control_msg(d->udev, pipe, request, type, value, index, st->data, rlen, DTV5100_USB_TIMEOUT); } @@ -141,7 +144,7 @@ static int dtv5100_probe(struct usb_interface *intf, /* initialize non qt1010/zl10353 part? */ for (i = 0; dtv5100_init[i].request; i++) { - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), dtv5100_init[i].request, USB_TYPE_VENDOR | USB_DIR_OUT, dtv5100_init[i].value, diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index 5aa15a7a49def8f08cc0218da48fd028431111ac..59529cbf9cd0b6da25a66eba95d3aedbb71375f1 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -720,7 +720,8 @@ static int em28xx_ir_init(struct em28xx *dev) dev->board.has_ir_i2c = 0; dev_warn(&dev->intf->dev, "No i2c IR remote control device found.\n"); - return -ENODEV; + err = -ENODEV; + goto ref_put; } } @@ -735,7 +736,7 @@ static int em28xx_ir_init(struct em28xx *dev) ir = kzalloc(sizeof(*ir), GFP_KERNEL); if (!ir) - return -ENOMEM; + goto ref_put; rc = rc_allocate_device(RC_DRIVER_SCANCODE); if (!rc) goto error; @@ -839,6 +840,9 @@ error: dev->ir = NULL; rc_free_device(rc); kfree(ir); +ref_put: + em28xx_shutdown_buttons(dev); + kref_put(&dev->ref, em28xx_free_device); return err; } diff --git a/drivers/media/usb/gspca/gl860/gl860.c b/drivers/media/usb/gspca/gl860/gl860.c index 2c05ea2598e7630a50c0ae13e7fe433f33947bde..ce4ee8bc75c85804364aa95701fac8a17d8458c5 100644 --- a/drivers/media/usb/gspca/gl860/gl860.c +++ b/drivers/media/usb/gspca/gl860/gl860.c @@ -561,8 +561,8 @@ int gl860_RTx(struct gspca_dev *gspca_dev, len, 400 + 200 * (len > 1)); memcpy(pdata, gspca_dev->usb_buf, len); } else { - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - req, pref, val, index, NULL, len, 400); + gspca_err(gspca_dev, "zero-length read request\n"); + r = -EINVAL; } } diff --git a/drivers/media/usb/gspca/sq905.c b/drivers/media/usb/gspca/sq905.c index 949111070971822fcdeeac6cf33139588c326cac..32504ebcfd4dee6ad0da4f4b0affa3c07bf3fd97 100644 --- a/drivers/media/usb/gspca/sq905.c +++ b/drivers/media/usb/gspca/sq905.c @@ -116,7 +116,7 @@ static int sq905_command(struct gspca_dev *gspca_dev, u16 index) } ret = usb_control_msg(gspca_dev->dev, - usb_sndctrlpipe(gspca_dev->dev, 0), + usb_rcvctrlpipe(gspca_dev->dev, 0), USB_REQ_SYNCH_FRAME, /* request */ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, SQ905_PING, 0, gspca_dev->usb_buf, 1, diff --git a/drivers/media/usb/gspca/sunplus.c b/drivers/media/usb/gspca/sunplus.c index ace3da40006e74ccb36082dddd48f71dc0116d89..971dee0a56dae8354052de001556afcaa1a77f8b 100644 --- a/drivers/media/usb/gspca/sunplus.c +++ b/drivers/media/usb/gspca/sunplus.c @@ -242,6 +242,10 @@ static void reg_r(struct gspca_dev *gspca_dev, gspca_err(gspca_dev, "reg_r: buffer overflow\n"); return; } + if (len == 0) { + gspca_err(gspca_dev, "reg_r: zero-length read\n"); + return; + } if (gspca_dev->usb_err < 0) return; ret = usb_control_msg(gspca_dev->dev, @@ -250,7 +254,7 @@ static void reg_r(struct gspca_dev *gspca_dev, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 0, /* value */ index, - len ? gspca_dev->usb_buf : NULL, len, + gspca_dev->usb_buf, len, 500); if (ret < 0) { pr_err("reg_r err %d\n", ret); @@ -727,7 +731,7 @@ static int sd_start(struct gspca_dev *gspca_dev) case MegaImageVI: reg_w_riv(gspca_dev, 0xf0, 0, 0); spca504B_WaitCmdStatus(gspca_dev); - reg_r(gspca_dev, 0xf0, 4, 0); + reg_w_riv(gspca_dev, 0xf0, 4, 0); spca504B_WaitCmdStatus(gspca_dev); break; default: diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index f4a727918e352883f46ef4023b60929d43144ac8..d38dee1792e41f21b2f21758fe393e92b5a061d4 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -2676,9 +2676,8 @@ void pvr2_hdw_destroy(struct pvr2_hdw *hdw) pvr2_stream_destroy(hdw->vid_stream); hdw->vid_stream = NULL; } - pvr2_i2c_core_done(hdw); v4l2_device_unregister(&hdw->v4l2_dev); - pvr2_hdw_remove_usb_stuff(hdw); + pvr2_hdw_disconnect(hdw); mutex_lock(&pvr2_unit_mtx); do { if ((hdw->unit_number >= 0) && @@ -2705,6 +2704,7 @@ void pvr2_hdw_disconnect(struct pvr2_hdw *hdw) { pvr2_trace(PVR2_TRACE_INIT,"pvr2_hdw_disconnect(hdw=%p)",hdw); LOCK_TAKE(hdw->big_lock); + pvr2_i2c_core_done(hdw); LOCK_TAKE(hdw->ctl_lock); pvr2_hdw_remove_usb_stuff(hdw); LOCK_GIVE(hdw->ctl_lock); diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index 5ad5282641350eeeaaf3a0b3ba14c6cd4d1002d9..282f3d2388cc20612d612fa39622d99f208f4095 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -1588,6 +1588,31 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, return -EINVAL; } + /* + * Some devices reference an output terminal as the + * source of extension units. This is incorrect, as + * output terminals only have an input pin, and thus + * can't be connected to any entity in the forward + * direction. The resulting topology would cause issues + * when registering the media controller graph. To + * avoid this problem, connect the extension unit to + * the source of the output terminal instead. + */ + if (UVC_ENTITY_IS_OTERM(entity)) { + struct uvc_entity *source; + + source = uvc_entity_by_id(chain->dev, + entity->baSourceID[0]); + if (!source) { + uvc_trace(UVC_TRACE_DESCR, + "Can't connect extension unit %u in chain\n", + forward->id); + break; + } + + forward->baSourceID[0] = source->id; + } + list_add_tail(&forward->chain, &chain->entities); if (uvc_trace_param & UVC_TRACE_PROBE) { if (!found) @@ -1608,6 +1633,13 @@ static int uvc_scan_chain_forward(struct uvc_video_chain *chain, return -EINVAL; } + if (UVC_ENTITY_IS_OTERM(entity)) { + uvc_trace(UVC_TRACE_DESCR, + "Unsupported connection between output terminals %u and %u\n", + entity->id, forward->id); + break; + } + list_add_tail(&forward->chain, &chain->entities); if (uvc_trace_param & UVC_TRACE_PROBE) { if (!found) diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c index a6a441d92b94887082cb1108bc98204c8cf9060c..5878c783348625651b2833bd818cd3869d3f437c 100644 --- a/drivers/media/usb/uvc/uvc_video.c +++ b/drivers/media/usb/uvc/uvc_video.c @@ -124,10 +124,37 @@ int uvc_query_ctrl(struct uvc_device *dev, u8 query, u8 unit, static void uvc_fixup_video_ctrl(struct uvc_streaming *stream, struct uvc_streaming_control *ctrl) { + static const struct usb_device_id elgato_cam_link_4k = { + USB_DEVICE(0x0fd9, 0x0066) + }; struct uvc_format *format = NULL; struct uvc_frame *frame = NULL; unsigned int i; + /* + * The response of the Elgato Cam Link 4K is incorrect: The second byte + * contains bFormatIndex (instead of being the second byte of bmHint). + * The first byte is always zero. The third byte is always 1. + * + * The UVC 1.5 class specification defines the first five bits in the + * bmHint bitfield. The remaining bits are reserved and should be zero. + * Therefore a valid bmHint will be less than 32. + * + * Latest Elgato Cam Link 4K firmware as of 2021-03-23 needs this fix. + * MCU: 20.02.19, FPGA: 67 + */ + if (usb_match_one_id(stream->dev->intf, &elgato_cam_link_4k) && + ctrl->bmHint > 255) { + u8 corrected_format_index = ctrl->bmHint >> 8; + + /* uvc_dbg(stream->dev, VIDEO, + "Correct USB video probe response from {bmHint: 0x%04x, bFormatIndex: %u} to {bmHint: 0x%04x, bFormatIndex: %u}\n", + ctrl->bmHint, ctrl->bFormatIndex, + 1, corrected_format_index); */ + ctrl->bmHint = 1; + ctrl->bFormatIndex = corrected_format_index; + } + for (i = 0; i < stream->nformats; ++i) { if (stream->format[i].index == ctrl->bFormatIndex) { format = &stream->format[i]; diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c index 8c670934d9207dcc3efceee6d352a60b21602dfa..1b79053b2a052fe5322987c51973525d2d90aafc 100644 --- a/drivers/media/usb/zr364xx/zr364xx.c +++ b/drivers/media/usb/zr364xx/zr364xx.c @@ -1034,6 +1034,7 @@ static int zr364xx_start_readpipe(struct zr364xx_camera *cam) DBG("submitting URB %p\n", pipe_info->stream_urb); retval = usb_submit_urb(pipe_info->stream_urb, GFP_KERNEL); if (retval) { + usb_free_urb(pipe_info->stream_urb); printk(KERN_ERR KBUILD_MODNAME ": start read pipe failed\n"); return retval; } diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c index e3ab003a6c851881475e2c77ada44482c6e7e0d2..33babe6e8b3a224c5f7266b6bc6b87d7456be08e 100644 --- a/drivers/media/v4l2-core/v4l2-async.c +++ b/drivers/media/v4l2-core/v4l2-async.c @@ -673,26 +673,26 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, } EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_subdev); -int +struct v4l2_async_subdev * v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif, struct fwnode_handle *endpoint, - struct v4l2_async_subdev *asd) + unsigned int asd_struct_size) { + struct v4l2_async_subdev *asd; struct fwnode_handle *remote; - int ret; remote = fwnode_graph_get_remote_port_parent(endpoint); if (!remote) - return -ENOTCONN; + return ERR_PTR(-ENOTCONN); - asd->match_type = V4L2_ASYNC_MATCH_FWNODE; - asd->match.fwnode = remote; - - ret = v4l2_async_notifier_add_subdev(notif, asd); - if (ret) - fwnode_handle_put(remote); - - return ret; + asd = v4l2_async_notifier_add_fwnode_subdev(notif, remote, + asd_struct_size); + /* + * Calling v4l2_async_notifier_add_fwnode_subdev grabs a refcount, + * so drop the one we got in fwnode_graph_get_remote_port_parent. + */ + fwnode_handle_put(remote); + return asd; } EXPORT_SYMBOL_GPL(v4l2_async_notifier_add_fwnode_remote_subdev); diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c index 684574f58e82daa35394d5f07c06352925055a55..90eec79ee995a2d214590beeacc91b9f8f33236d 100644 --- a/drivers/media/v4l2-core/v4l2-fh.c +++ b/drivers/media/v4l2-core/v4l2-fh.c @@ -96,6 +96,7 @@ int v4l2_fh_release(struct file *filp) v4l2_fh_del(fh); v4l2_fh_exit(fh); kfree(fh); + filp->private_data = NULL; } return 0; } diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c index a7d508e74d6b3bd62e19c7f319b9806052c6516c..fbf0dcb313c820cd0d86d1b9a873767ea2b4beb1 100644 --- a/drivers/media/v4l2-core/v4l2-subdev.c +++ b/drivers/media/v4l2-core/v4l2-subdev.c @@ -428,30 +428,6 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg) return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK); - case VIDIOC_DQEVENT_TIME32: { - struct v4l2_event_time32 *ev32 = arg; - struct v4l2_event ev = { }; - - if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS)) - return -ENOIOCTLCMD; - - rval = v4l2_event_dequeue(vfh, &ev, file->f_flags & O_NONBLOCK); - - *ev32 = (struct v4l2_event_time32) { - .type = ev.type, - .pending = ev.pending, - .sequence = ev.sequence, - .timestamp.tv_sec = ev.timestamp.tv_sec, - .timestamp.tv_nsec = ev.timestamp.tv_nsec, - .id = ev.id, - }; - - memcpy(&ev32->u, &ev.u, sizeof(ev.u)); - memcpy(&ev32->reserved, &ev.reserved, sizeof(ev.reserved)); - - return rval; - } - case VIDIOC_SUBSCRIBE_EVENT: return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg); diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index 14386d0b5f57800a9b68c2f2d10cd7df1d459488..c267283b01fdaf74c2ef094926fd65da72af0ca5 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c @@ -600,8 +600,10 @@ static int atmel_ebi_probe(struct platform_device *pdev) child); ret = atmel_ebi_dev_disable(ebi, child); - if (ret) + if (ret) { + of_node_put(child); return ret; + } } } diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c index bda24c70c886ce98495eb7a5825a39063b36e2ed..dc1006cd0ca10db3c3a1df66f97ed725fb06cc17 100644 --- a/drivers/memory/fsl_ifc.c +++ b/drivers/memory/fsl_ifc.c @@ -100,7 +100,6 @@ static int fsl_ifc_ctrl_remove(struct platform_device *dev) iounmap(ctrl->gregs); dev_set_drvdata(&dev->dev, NULL); - kfree(ctrl); return 0; } @@ -212,7 +211,8 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) dev_info(&dev->dev, "Freescale Integrated Flash Controller\n"); - fsl_ifc_ctrl_dev = kzalloc(sizeof(*fsl_ifc_ctrl_dev), GFP_KERNEL); + fsl_ifc_ctrl_dev = devm_kzalloc(&dev->dev, sizeof(*fsl_ifc_ctrl_dev), + GFP_KERNEL); if (!fsl_ifc_ctrl_dev) return -ENOMEM; @@ -222,8 +222,7 @@ static int fsl_ifc_ctrl_probe(struct platform_device *dev) fsl_ifc_ctrl_dev->gregs = of_iomap(dev->dev.of_node, 0); if (!fsl_ifc_ctrl_dev->gregs) { dev_err(&dev->dev, "failed to get memory region\n"); - ret = -ENODEV; - goto err; + return -ENODEV; } if (of_property_read_bool(dev->dev.of_node, "little-endian")) { @@ -298,6 +297,7 @@ err_irq: free_irq(fsl_ifc_ctrl_dev->irq, fsl_ifc_ctrl_dev); irq_dispose_mapping(fsl_ifc_ctrl_dev->irq); err: + iounmap(fsl_ifc_ctrl_dev->gregs); return ret; } diff --git a/drivers/memory/pl353-smc.c b/drivers/memory/pl353-smc.c index b42804b1801e6d5a35c8b1f8409bb3cb066d6ef6..cc01979780d87eb04fffdaae933d5ecd240bac16 100644 --- a/drivers/memory/pl353-smc.c +++ b/drivers/memory/pl353-smc.c @@ -407,6 +407,7 @@ static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id) break; } if (!match) { + err = -ENODEV; dev_err(&adev->dev, "no matching children\n"); goto out_clk_disable; } diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c index 4d5758c419c551efddc285e5200392a0c8326d09..ffec26a99313bd1ef3cc7ddd01d2332d300e1e62 100644 --- a/drivers/memory/stm32-fmc2-ebi.c +++ b/drivers/memory/stm32-fmc2-ebi.c @@ -1048,16 +1048,19 @@ static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi) if (ret) { dev_err(dev, "could not retrieve reg property: %d\n", ret); + of_node_put(child); return ret; } if (bank >= FMC2_MAX_BANKS) { dev_err(dev, "invalid reg value: %d\n", bank); + of_node_put(child); return -EINVAL; } if (ebi->bank_assigned & BIT(bank)) { dev_err(dev, "bank already assigned: %d\n", bank); + of_node_put(child); return -EINVAL; } @@ -1066,6 +1069,7 @@ static int stm32_fmc2_ebi_parse_dt(struct stm32_fmc2_ebi *ebi) if (ret) { dev_err(dev, "setup chip select %d failed: %d\n", bank, ret); + of_node_put(child); return ret; } } diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c index 102dbb8080da5c71f99672dcaee6119f7fc3afcc..29271ad4728a2f180a2c60c1468820a79d7b0b5a 100644 --- a/drivers/memstick/host/rtsx_usb_ms.c +++ b/drivers/memstick/host/rtsx_usb_ms.c @@ -799,9 +799,9 @@ static int rtsx_usb_ms_drv_probe(struct platform_device *pdev) return 0; err_out: - memstick_free_host(msh); pm_runtime_disable(ms_dev(host)); pm_runtime_put_noidle(ms_dev(host)); + memstick_free_host(msh); return err; } @@ -828,9 +828,6 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) } mutex_unlock(&host->host_mutex); - memstick_remove_host(msh); - memstick_free_host(msh); - /* Balance possible unbalanced usage count * e.g. unconditional module removal */ @@ -838,10 +835,11 @@ static int rtsx_usb_ms_drv_remove(struct platform_device *pdev) pm_runtime_put(ms_dev(host)); pm_runtime_disable(ms_dev(host)); - platform_set_drvdata(pdev, NULL); - + memstick_remove_host(msh); dev_dbg(ms_dev(host), ": Realtek USB Memstick controller has been removed\n"); + memstick_free_host(msh); + platform_set_drvdata(pdev, NULL); return 0; } diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 302927f7b42c5ad29f3f419b7eec1f4ca7d35920..b7b91fd5d1d0eed8be2422b37e4ad80c786ff01b 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -465,6 +465,7 @@ config MFD_MP2629 tristate "Monolithic Power Systems MP2629 ADC and Battery charger" depends on I2C select REGMAP_I2C + select MFD_CORE help Select this option to enable support for Monolithic Power Systems battery charger. This provides ADC, thermal and battery charger power diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index 47556d2d9abe238386489fb8bcbd63d2eedec375..8ebfc7bbe4e010270aadb41a098284c495ad372e 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c @@ -113,6 +113,7 @@ static const struct i2c_device_id da9052_i2c_id[] = { {"da9053-bc", DA9053_BC}, {} }; +MODULE_DEVICE_TABLE(i2c, da9052_i2c_id); #ifdef CONFIG_OF static const struct of_device_id dialog_dt_ids[] = { diff --git a/drivers/mfd/motorola-cpcap.c b/drivers/mfd/motorola-cpcap.c index 30d82bfe5b02fa28061dad73e5acf32bd5b0b9fe..6fb206da27298e2e24403efddfe89412e9f589ed 100644 --- a/drivers/mfd/motorola-cpcap.c +++ b/drivers/mfd/motorola-cpcap.c @@ -327,6 +327,10 @@ static int cpcap_probe(struct spi_device *spi) if (ret) return ret; + /* Parent SPI controller uses DMA, CPCAP and child devices do not */ + spi->dev.coherent_dma_mask = 0; + spi->dev.dma_mask = &spi->dev.coherent_dma_mask; + return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices, ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL); } diff --git a/drivers/mfd/rn5t618.c b/drivers/mfd/rn5t618.c index dc452df1f1bfe635f390c419a86534ee7f4ba0c0..652a5e60067f8dbf00da5d71e6df4e74224a833a 100644 --- a/drivers/mfd/rn5t618.c +++ b/drivers/mfd/rn5t618.c @@ -104,7 +104,7 @@ static int rn5t618_irq_init(struct rn5t618 *rn5t618) ret = devm_regmap_add_irq_chip(rn5t618->dev, rn5t618->regmap, rn5t618->irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, 0, irq_chip, &rn5t618->irq_data); if (ret) dev_err(rn5t618->dev, "Failed to register IRQ chip\n"); diff --git a/drivers/mfd/stmpe-i2c.c b/drivers/mfd/stmpe-i2c.c index 61aa020199f57a5ecf765d9dc9a11962e2e72dc6..cd2f45257dc165f6ece99cd24dfc2efbd6be7c8d 100644 --- a/drivers/mfd/stmpe-i2c.c +++ b/drivers/mfd/stmpe-i2c.c @@ -109,7 +109,7 @@ static const struct i2c_device_id stmpe_i2c_id[] = { { "stmpe2403", STMPE2403 }, { } }; -MODULE_DEVICE_TABLE(i2c, stmpe_id); +MODULE_DEVICE_TABLE(i2c, stmpe_i2c_id); static struct i2c_driver stmpe_i2c_driver = { .driver = { diff --git a/drivers/mfd/syscon.c b/drivers/mfd/syscon.c index ca465794ea9c83e162e8c8609ba1d19cb6c94841..df5cebb372a592fce06bd03412375452cecbd658 100644 --- a/drivers/mfd/syscon.c +++ b/drivers/mfd/syscon.c @@ -108,6 +108,7 @@ static struct syscon *of_syscon_register(struct device_node *np, bool check_clk) syscon_config.max_register = resource_size(&res) - reg_io_width; regmap = regmap_init_mmio(NULL, base, &syscon_config); + kfree(syscon_config.name); if (IS_ERR(regmap)) { pr_err("regmap init failed\n"); ret = PTR_ERR(regmap); @@ -144,7 +145,6 @@ err_clk: regmap_exit(regmap); err_regmap: iounmap(base); - kfree(syscon_config.name); err_map: kfree(syscon); return ERR_PTR(ret); diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c index cd402c89189ea059f42c9e7774ac6dec9ced8631..de6d44a158bbae69f22ed2deed3000928f7cb6fa 100644 --- a/drivers/misc/cardreader/alcor_pci.c +++ b/drivers/misc/cardreader/alcor_pci.c @@ -139,7 +139,13 @@ static void alcor_pci_init_check_aspm(struct alcor_pci_priv *priv) u32 val32; priv->pdev_cap_off = alcor_pci_find_cap_offset(priv, priv->pdev); - priv->parent_cap_off = alcor_pci_find_cap_offset(priv, + /* + * A device might be attached to root complex directly and + * priv->parent_pdev will be NULL. In this case we don't check its + * capability and disable ASPM completely. + */ + if (priv->parent_pdev) + priv->parent_cap_off = alcor_pci_find_cap_offset(priv, priv->parent_pdev); if ((priv->pdev_cap_off == 0) || (priv->parent_cap_off == 0)) { diff --git a/drivers/misc/eeprom/idt_89hpesx.c b/drivers/misc/eeprom/idt_89hpesx.c index 81c70e5bc168f491b84e3445fa71f89a0b551b3c..3e4a594c110b3e93d73945d03c0d2eadafa6344f 100644 --- a/drivers/misc/eeprom/idt_89hpesx.c +++ b/drivers/misc/eeprom/idt_89hpesx.c @@ -1126,11 +1126,10 @@ static void idt_get_fw_data(struct idt_89hpesx_dev *pdev) device_for_each_child_node(dev, fwnode) { ee_id = idt_ee_match_id(fwnode); - if (!ee_id) { - dev_warn(dev, "Skip unsupported EEPROM device"); - continue; - } else + if (ee_id) break; + + dev_warn(dev, "Skip unsupported EEPROM device %pfw\n", fwnode); } /* If there is no fwnode EEPROM device, then set zero size */ @@ -1161,6 +1160,7 @@ static void idt_get_fw_data(struct idt_89hpesx_dev *pdev) else /* if (!fwnode_property_read_bool(node, "read-only")) */ pdev->eero = false; + fwnode_handle_put(fwnode); dev_info(dev, "EEPROM of %d bytes found by 0x%x", pdev->eesize, pdev->eeaddr); } diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c index 3bcef64a677aeb7e5b8a15b45d052ecfda21a5a1..ded92b3cbdb27999dfa95180003f164d1fca7a13 100644 --- a/drivers/misc/habanalabs/common/habanalabs_drv.c +++ b/drivers/misc/habanalabs/common/habanalabs_drv.c @@ -421,6 +421,7 @@ static int hl_pci_probe(struct pci_dev *pdev, return 0; disable_device: + pci_disable_pcie_error_reporting(pdev); pci_set_drvdata(pdev, NULL); destroy_hdev(hdev); diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c index 68f661aca3ff2e387b7af88d476957b06aeb2d3e..37edd663603f69d086aeea4a2e1f4aca9eeaa1bb 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/misc/habanalabs/gaudi/gaudi.c @@ -2164,7 +2164,7 @@ static void gaudi_init_mme_qman(struct hl_device *hdev, u32 mme_offset, /* Configure RAZWI IRQ */ mme_id = mme_offset / - (mmMME1_QM_GLBL_CFG0 - mmMME0_QM_GLBL_CFG0); + (mmMME1_QM_GLBL_CFG0 - mmMME0_QM_GLBL_CFG0) / 2; mme_qm_err_cfg = MME_QMAN_GLBL_ERR_CFG_MSG_EN_MASK; if (hdev->stop_on_err) { @@ -3708,6 +3708,7 @@ already_pinned: return 0; unpin_memory: + list_del(&userptr->job_node); hl_unpin_host_memory(hdev, userptr); free_userptr: kfree(userptr); diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index 986ed3c072088b7506717da1d94ca039ecaccb0f..5b5d6275c2495b8b8d2698ad9e6c64438e4d2278 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -3190,6 +3190,7 @@ already_pinned: return 0; unpin_memory: + list_del(&userptr->job_node); hl_unpin_host_memory(hdev, userptr); free_userptr: kfree(userptr); diff --git a/drivers/misc/ibmasm/module.c b/drivers/misc/ibmasm/module.c index 4edad6c445d374c9d4927644775ff3bee3c6c5a3..dc8a06c06c63759f00e03338b6d1eff3ae8b6817 100644 --- a/drivers/misc/ibmasm/module.c +++ b/drivers/misc/ibmasm/module.c @@ -111,7 +111,7 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) result = ibmasm_init_remote_input_dev(sp); if (result) { dev_err(sp->dev, "Failed to initialize remote queue\n"); - goto error_send_message; + goto error_init_remote; } result = ibmasm_send_driver_vpd(sp); @@ -131,8 +131,9 @@ static int ibmasm_init_one(struct pci_dev *pdev, const struct pci_device_id *id) return 0; error_send_message: - disable_sp_interrupts(sp->base_address); ibmasm_free_remote_input_dev(sp); +error_init_remote: + disable_sp_interrupts(sp->base_address); free_irq(sp->irq, (void *)sp); error_request_irq: iounmap(sp->base_address); diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index a0675d4154d2fdaff4e8f8f1c08d7a79143246e7..a337f97b30e28c73c824c8c7d5e6f4fb96bfd51c 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -144,6 +144,9 @@ void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) if (*p == 0) val = 0x87654321; *p = val; + + if (IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)) + pr_err("XFAIL: arch has CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS\n"); } void lkdtm_SOFTLOCKUP(void) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 3246598e4d7e30e598c51782cde493278af67ce3..87bac99207023a8580a82f6756ede4fa8e7fe906 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1003,6 +1003,12 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) switch (mq_rq->drv_op) { case MMC_DRV_OP_IOCTL: + if (card->ext_csd.cmdq_en) { + ret = mmc_cmdq_disable(card); + if (ret) + break; + } + fallthrough; case MMC_DRV_OP_IOCTL_RPMB: idata = mq_rq->drv_op_data; for (i = 0, ret = 0; i < mq_rq->ioc_count; i++) { @@ -1013,6 +1019,8 @@ static void mmc_blk_issue_drv_op(struct mmc_queue *mq, struct request *req) /* Always switch back to main area after RPMB access */ if (rpmb_ioctl) mmc_blk_part_switch(card, 0); + else if (card->reenable_cmdq && !card->ext_csd.cmdq_en) + mmc_cmdq_enable(card); break; case MMC_DRV_OP_BOOT_WP: ret = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BOOT_WP, diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index eaf4810fe656dec168699d2335e5563ef9af26bd..b5f3f160c842090f04c09330e052aa1d3b96bd2b 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -936,11 +936,14 @@ int mmc_execute_tuning(struct mmc_card *card) err = host->ops->execute_tuning(host, opcode); - if (err) + if (err) { pr_err("%s: tuning execution failed: %d\n", mmc_hostname(host), err); - else + } else { + host->retune_now = 0; + host->need_retune = 0; mmc_retune_enable(host); + } return err; } diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index d0693222c4fcccf2ecabcc2a98a32591f51ae56c..4f736da411d391e29691076566ce870ff92436de 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -853,11 +853,13 @@ try_again: return err; /* - * In case CCS and S18A in the response is set, start Signal Voltage - * Switch procedure. SPI mode doesn't support CMD11. + * In case the S18A bit is set in the response, let's start the signal + * voltage switch procedure. SPI mode doesn't support CMD11. + * Note that, according to the spec, the S18A bit is not valid unless + * the CCS bit is set as well. We deliberately deviate from the spec in + * regards to this, which allows UHS-I to be supported for SDSC cards. */ - if (!mmc_host_is_spi(host) && rocr && - ((*rocr & 0x41000000) == 0x41000000)) { + if (!mmc_host_is_spi(host) && rocr && (*rocr & 0x01000000)) { err = mmc_set_uhs_voltage(host, pocr); if (err == -EAGAIN) { retries--; diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index 4ec41579940a311395ed43329d98455fc5462e8c..d3f40c9a8c6c8c1d2ec219f20331017b5b964c27 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -165,6 +165,7 @@ struct meson_host { unsigned int bounce_buf_size; void *bounce_buf; + void __iomem *bounce_iomem_buf; dma_addr_t bounce_dma_addr; struct sd_emmc_desc *descs; dma_addr_t descs_dma_addr; @@ -734,6 +735,47 @@ static void meson_mmc_desc_chain_transfer(struct mmc_host *mmc, u32 cmd_cfg) writel(start, host->regs + SD_EMMC_START); } +/* local sg copy to buffer version with _to/fromio usage for dram_access_quirk */ +static void meson_mmc_copy_buffer(struct meson_host *host, struct mmc_data *data, + size_t buflen, bool to_buffer) +{ + unsigned int sg_flags = SG_MITER_ATOMIC; + struct scatterlist *sgl = data->sg; + unsigned int nents = data->sg_len; + struct sg_mapping_iter miter; + unsigned int offset = 0; + + if (to_buffer) + sg_flags |= SG_MITER_FROM_SG; + else + sg_flags |= SG_MITER_TO_SG; + + sg_miter_start(&miter, sgl, nents, sg_flags); + + while ((offset < buflen) && sg_miter_next(&miter)) { + unsigned int len; + + len = min(miter.length, buflen - offset); + + /* When dram_access_quirk, the bounce buffer is a iomem mapping */ + if (host->dram_access_quirk) { + if (to_buffer) + memcpy_toio(host->bounce_iomem_buf + offset, miter.addr, len); + else + memcpy_fromio(miter.addr, host->bounce_iomem_buf + offset, len); + } else { + if (to_buffer) + memcpy(host->bounce_buf + offset, miter.addr, len); + else + memcpy(miter.addr, host->bounce_buf + offset, len); + } + + offset += len; + } + + sg_miter_stop(&miter); +} + static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) { struct meson_host *host = mmc_priv(mmc); @@ -777,8 +819,7 @@ static void meson_mmc_start_cmd(struct mmc_host *mmc, struct mmc_command *cmd) if (data->flags & MMC_DATA_WRITE) { cmd_cfg |= CMD_CFG_DATA_WR; WARN_ON(xfer_bytes > host->bounce_buf_size); - sg_copy_to_buffer(data->sg, data->sg_len, - host->bounce_buf, xfer_bytes); + meson_mmc_copy_buffer(host, data, xfer_bytes, true); dma_wmb(); } @@ -947,8 +988,7 @@ static irqreturn_t meson_mmc_irq_thread(int irq, void *dev_id) if (meson_mmc_bounce_buf_read(data)) { xfer_bytes = data->blksz * data->blocks; WARN_ON(xfer_bytes > host->bounce_buf_size); - sg_copy_from_buffer(data->sg, data->sg_len, - host->bounce_buf, xfer_bytes); + meson_mmc_copy_buffer(host, data, xfer_bytes, false); } next_cmd = meson_mmc_get_next_command(cmd); @@ -1168,7 +1208,7 @@ static int meson_mmc_probe(struct platform_device *pdev) * instead of the DDR memory */ host->bounce_buf_size = SD_EMMC_SRAM_DATA_BUF_LEN; - host->bounce_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF; + host->bounce_iomem_buf = host->regs + SD_EMMC_SRAM_DATA_BUF_OFF; host->bounce_dma_addr = res->start + SD_EMMC_SRAM_DATA_BUF_OFF; } else { /* data bounce buffer */ diff --git a/drivers/mmc/host/sdhci-acpi.c b/drivers/mmc/host/sdhci-acpi.c index 54205e3be9e875f574ac14a07b9c07f6a2e814af..a2cdb37fcbbecf80a4b0a0e7531a0d18176aabff 100644 --- a/drivers/mmc/host/sdhci-acpi.c +++ b/drivers/mmc/host/sdhci-acpi.c @@ -788,6 +788,17 @@ static const struct dmi_system_id sdhci_acpi_quirks[] = { }, .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT, }, + { + /* + * The Toshiba WT8-B's microSD slot always reports the card being + * write-protected. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "TOSHIBA ENCORE 2 WT8-B"), + }, + .driver_data = (void *)DMI_QUIRK_SD_NO_WRITE_PROTECT, + }, {} /* Terminating entry */ }; diff --git a/drivers/mmc/host/sdhci-sprd.c b/drivers/mmc/host/sdhci-sprd.c index 19cbb6171b358cc8b98f27711a3bbe88a5348587..9cd8862e6cbd04f32f39c6f7fda680f9b75e6702 100644 --- a/drivers/mmc/host/sdhci-sprd.c +++ b/drivers/mmc/host/sdhci-sprd.c @@ -393,6 +393,7 @@ static void sdhci_sprd_request_done(struct sdhci_host *host, static struct sdhci_ops sdhci_sprd_ops = { .read_l = sdhci_sprd_readl, .write_l = sdhci_sprd_writel, + .write_w = sdhci_sprd_writew, .write_b = sdhci_sprd_writeb, .set_clock = sdhci_sprd_set_clock, .get_max_clock = sdhci_sprd_get_max_clock, diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index b7839f678ed3d3b8b1ec4009b48a0e010f57b0e9..97cd08d669205015911f07485eb3fe95d0e5bb42 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c @@ -1813,6 +1813,10 @@ static u16 sdhci_get_preset_value(struct sdhci_host *host) u16 preset = 0; switch (host->timing) { + case MMC_TIMING_MMC_HS: + case MMC_TIMING_SD_HS: + preset = sdhci_readw(host, SDHCI_PRESET_FOR_HIGH_SPEED); + break; case MMC_TIMING_UHS_SDR12: preset = sdhci_readw(host, SDHCI_PRESET_FOR_SDR12); break; diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 0770c036e2ff5d75dbfbd757cd5bc3876e8ce1c0..960fed78529e10c7caf6d7d8d00a74631007e24a 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -253,6 +253,7 @@ /* 60-FB reserved */ +#define SDHCI_PRESET_FOR_HIGH_SPEED 0x64 #define SDHCI_PRESET_FOR_SDR12 0x66 #define SDHCI_PRESET_FOR_SDR25 0x68 #define SDHCI_PRESET_FOR_SDR50 0x6A diff --git a/drivers/mmc/host/usdhi6rol0.c b/drivers/mmc/host/usdhi6rol0.c index 615f3d008af1e058357d3ea4a4ac49928cf32e1f..b9b79b1089a00192881dd6511a9727833afd771b 100644 --- a/drivers/mmc/host/usdhi6rol0.c +++ b/drivers/mmc/host/usdhi6rol0.c @@ -1801,6 +1801,7 @@ static int usdhi6_probe(struct platform_device *pdev) version = usdhi6_read(host, USDHI6_VERSION); if ((version & 0xfff) != 0xa0d) { + ret = -EPERM; dev_err(dev, "Version not recognized %x\n", version); goto e_clk_off; } diff --git a/drivers/mmc/host/via-sdmmc.c b/drivers/mmc/host/via-sdmmc.c index 9b755ea0fa03cc912ea4ebfe81058a95f3204c10..f07c71db3cafeacd1bede3255198d23ad1e10cce 100644 --- a/drivers/mmc/host/via-sdmmc.c +++ b/drivers/mmc/host/via-sdmmc.c @@ -857,6 +857,9 @@ static void via_sdc_data_isr(struct via_crdr_mmc_host *host, u16 intmask) { BUG_ON(intmask == 0); + if (!host->data) + return; + if (intmask & VIA_CRDR_SDSTS_DT) host->data->error = -ETIMEDOUT; else if (intmask & (VIA_CRDR_SDSTS_RC | VIA_CRDR_SDSTS_WC)) diff --git a/drivers/mmc/host/vub300.c b/drivers/mmc/host/vub300.c index 739cf63ef6e2f85fa4e9c2561794ded1049821d1..4950d10d3a19111b121d1fca07a2045f0c31f1a4 100644 --- a/drivers/mmc/host/vub300.c +++ b/drivers/mmc/host/vub300.c @@ -2279,7 +2279,7 @@ static int vub300_probe(struct usb_interface *interface, if (retval < 0) goto error5; retval = - usb_control_msg(vub300->udev, usb_rcvctrlpipe(vub300->udev, 0), + usb_control_msg(vub300->udev, usb_sndctrlpipe(vub300->udev, 0), SET_ROM_WAIT_STATES, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, firmware_rom_wait_states, 0x0000, NULL, 0, HZ); diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c index fbb4ea751be8ee7fb7b6a632cdd14d96508b6d42..0ee3192916d97e5bedd8257c0578d22c96cf2fb4 100644 --- a/drivers/mtd/nand/raw/arasan-nand-controller.c +++ b/drivers/mtd/nand/raw/arasan-nand-controller.c @@ -272,6 +272,37 @@ static int anfc_pkt_len_config(unsigned int len, unsigned int *steps, return 0; } +static int anfc_select_target(struct nand_chip *chip, int target) +{ + struct anand *anand = to_anand(chip); + struct arasan_nfc *nfc = to_anfc(chip->controller); + int ret; + + /* Update the controller timings and the potential ECC configuration */ + writel_relaxed(anand->timings, nfc->base + DATA_INTERFACE_REG); + + /* Update clock frequency */ + if (nfc->cur_clk != anand->clk) { + clk_disable_unprepare(nfc->controller_clk); + ret = clk_set_rate(nfc->controller_clk, anand->clk); + if (ret) { + dev_err(nfc->dev, "Failed to change clock rate\n"); + return ret; + } + + ret = clk_prepare_enable(nfc->controller_clk); + if (ret) { + dev_err(nfc->dev, + "Failed to re-enable the controller clock\n"); + return ret; + } + + nfc->cur_clk = anand->clk; + } + + return 0; +} + /* * When using the embedded hardware ECC engine, the controller is in charge of * feeding the engine with, first, the ECC residue present in the data array. @@ -400,6 +431,18 @@ static int anfc_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, return 0; } +static int anfc_sel_read_page_hw_ecc(struct nand_chip *chip, u8 *buf, + int oob_required, int page) +{ + int ret; + + ret = anfc_select_target(chip, chip->cur_cs); + if (ret) + return ret; + + return anfc_read_page_hw_ecc(chip, buf, oob_required, page); +}; + static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, int oob_required, int page) { @@ -460,6 +503,18 @@ static int anfc_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, return ret; } +static int anfc_sel_write_page_hw_ecc(struct nand_chip *chip, const u8 *buf, + int oob_required, int page) +{ + int ret; + + ret = anfc_select_target(chip, chip->cur_cs); + if (ret) + return ret; + + return anfc_write_page_hw_ecc(chip, buf, oob_required, page); +}; + /* NAND framework ->exec_op() hooks and related helpers */ static int anfc_parse_instructions(struct nand_chip *chip, const struct nand_subop *subop, @@ -752,37 +807,6 @@ static const struct nand_op_parser anfc_op_parser = NAND_OP_PARSER( NAND_OP_PARSER_PAT_WAITRDY_ELEM(false)), ); -static int anfc_select_target(struct nand_chip *chip, int target) -{ - struct anand *anand = to_anand(chip); - struct arasan_nfc *nfc = to_anfc(chip->controller); - int ret; - - /* Update the controller timings and the potential ECC configuration */ - writel_relaxed(anand->timings, nfc->base + DATA_INTERFACE_REG); - - /* Update clock frequency */ - if (nfc->cur_clk != anand->clk) { - clk_disable_unprepare(nfc->controller_clk); - ret = clk_set_rate(nfc->controller_clk, anand->clk); - if (ret) { - dev_err(nfc->dev, "Failed to change clock rate\n"); - return ret; - } - - ret = clk_prepare_enable(nfc->controller_clk); - if (ret) { - dev_err(nfc->dev, - "Failed to re-enable the controller clock\n"); - return ret; - } - - nfc->cur_clk = anand->clk; - } - - return 0; -} - static int anfc_check_op(struct nand_chip *chip, const struct nand_operation *op) { @@ -1006,8 +1030,8 @@ static int anfc_init_hw_ecc_controller(struct arasan_nfc *nfc, if (!anand->bch) return -EINVAL; - ecc->read_page = anfc_read_page_hw_ecc; - ecc->write_page = anfc_write_page_hw_ecc; + ecc->read_page = anfc_sel_read_page_hw_ecc; + ecc->write_page = anfc_sel_write_page_hw_ecc; return 0; } diff --git a/drivers/mtd/nand/raw/marvell_nand.c b/drivers/mtd/nand/raw/marvell_nand.c index f5ca2002d08e8ed82057f4f639856c373aaf1ff6..d00c916f133bd59a00c674b3aa199b1e8fad761b 100644 --- a/drivers/mtd/nand/raw/marvell_nand.c +++ b/drivers/mtd/nand/raw/marvell_nand.c @@ -3036,8 +3036,10 @@ static int __maybe_unused marvell_nfc_resume(struct device *dev) return ret; ret = clk_prepare_enable(nfc->reg_clk); - if (ret < 0) + if (ret < 0) { + clk_disable_unprepare(nfc->core_clk); return ret; + } /* * Reset nfc->selected_chip so the next command will cause the timing diff --git a/drivers/mtd/parsers/redboot.c b/drivers/mtd/parsers/redboot.c index 91146bdc4713214267458144b3a433d5e0c301f8..3ccd6363ee8cba9cd99f2581a4064d0a50ea1006 100644 --- a/drivers/mtd/parsers/redboot.c +++ b/drivers/mtd/parsers/redboot.c @@ -45,6 +45,7 @@ static inline int redboot_checksum(struct fis_image_desc *img) static void parse_redboot_of(struct mtd_info *master) { struct device_node *np; + struct device_node *npart; u32 dirblock; int ret; @@ -52,7 +53,11 @@ static void parse_redboot_of(struct mtd_info *master) if (!np) return; - ret = of_property_read_u32(np, "fis-index-block", &dirblock); + npart = of_get_child_by_name(np, "partitions"); + if (!npart) + return; + + ret = of_property_read_u32(npart, "fis-index-block", &dirblock); if (ret) return; diff --git a/drivers/net/caif/caif_serial.c b/drivers/net/caif/caif_serial.c index d025ea4349339477c9c42dd82991539ab9cb0f5b..39fbd0be179c2e7c67582693124ec6525ae6b9c6 100644 --- a/drivers/net/caif/caif_serial.c +++ b/drivers/net/caif/caif_serial.c @@ -351,6 +351,7 @@ static int ldisc_open(struct tty_struct *tty) rtnl_lock(); result = register_netdevice(dev); if (result) { + tty_kref_put(tty); rtnl_unlock(); free_netdev(dev); return -ENODEV; diff --git a/drivers/net/can/peak_canfd/peak_canfd.c b/drivers/net/can/peak_canfd/peak_canfd.c index 40c33b8a5fda3af93013c0e524f66d1ba6288907..ac5801a98680d6eddf7e88b98866a86b79c7d208 100644 --- a/drivers/net/can/peak_canfd/peak_canfd.c +++ b/drivers/net/can/peak_canfd/peak_canfd.c @@ -351,8 +351,8 @@ static int pucan_handle_status(struct peak_canfd_priv *priv, return err; } - /* start network queue (echo_skb array is empty) */ - netif_start_queue(ndev); + /* wake network queue up (echo_skb array is empty) */ + netif_wake_queue(ndev); return 0; } diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 4f52810bebf8973532d886cf653b359b5c4863ed..db9f15f17610b6cb01992edca3c18b8604474aa9 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -1053,7 +1053,6 @@ static void ems_usb_disconnect(struct usb_interface *intf) if (dev) { unregister_netdev(dev->netdev); - free_candev(dev->netdev); unlink_all_urbs(dev); @@ -1061,6 +1060,8 @@ static void ems_usb_disconnect(struct usb_interface *intf) kfree(dev->intr_in_buffer); kfree(dev->tx_msg_buffer); + + free_candev(dev->netdev); } } diff --git a/drivers/net/dsa/ocelot/seville_vsc9953.c b/drivers/net/dsa/ocelot/seville_vsc9953.c index ebbaf6817ec86898417a684f3530582b7c5c6216..7026523f886c87a7697a1c2947038c489dd500dd 100644 --- a/drivers/net/dsa/ocelot/seville_vsc9953.c +++ b/drivers/net/dsa/ocelot/seville_vsc9953.c @@ -1214,6 +1214,11 @@ static int seville_probe(struct platform_device *pdev) felix->info = &seville_info_vsc9953; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; + dev_err(&pdev->dev, "Invalid resource\n"); + goto err_alloc_felix; + } felix->switch_base = res->start; ds = kzalloc(sizeof(struct dsa_switch), GFP_KERNEL); diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index e273b2bd82ba7c9812e04e46a89954b6d557cdf5..82852c57cc0e4808339807f7b1cadd9024583cb9 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -1711,6 +1711,12 @@ static int sja1105_reload_cbs(struct sja1105_private *priv) { int rc = 0, i; + /* The credit based shapers are only allocated if + * CONFIG_NET_SCH_CBS is enabled. + */ + if (!priv->cbs) + return 0; + for (i = 0; i < priv->info->num_cbs_shapers; i++) { struct sja1105_cbs_entry *cbs = &priv->cbs[i]; diff --git a/drivers/net/ethernet/aeroflex/greth.c b/drivers/net/ethernet/aeroflex/greth.c index 9c5891bbfe61afbd798efcad906e632b07ca38a3..f4f50b3a472e179620a776b031243ed005586838 100644 --- a/drivers/net/ethernet/aeroflex/greth.c +++ b/drivers/net/ethernet/aeroflex/greth.c @@ -1539,10 +1539,11 @@ static int greth_of_remove(struct platform_device *of_dev) mdiobus_unregister(greth->mdio); unregister_netdev(ndev); - free_netdev(ndev); of_iounmap(&of_dev->resource[0], greth->regs, resource_size(&of_dev->resource[0])); + free_netdev(ndev); + return 0; } diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h index f5fba8b8cdea9bde746bfdf3080ce5d926f59895..a47e2710487ecae808f59a99f9d7fa85ec68eb55 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_macsec.h @@ -91,7 +91,7 @@ struct aq_macsec_txsc { u32 hw_sc_idx; unsigned long tx_sa_idx_busy; const struct macsec_secy *sw_secy; - u8 tx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN]; + u8 tx_sa_key[MACSEC_NUM_AN][MACSEC_MAX_KEY_LEN]; struct aq_macsec_tx_sc_stats stats; struct aq_macsec_tx_sa_stats tx_sa_stats[MACSEC_NUM_AN]; }; @@ -101,7 +101,7 @@ struct aq_macsec_rxsc { unsigned long rx_sa_idx_busy; const struct macsec_secy *sw_secy; const struct macsec_rx_sc *sw_rxsc; - u8 rx_sa_key[MACSEC_NUM_AN][MACSEC_KEYID_LEN]; + u8 rx_sa_key[MACSEC_NUM_AN][MACSEC_MAX_KEY_LEN]; struct aq_macsec_rx_sa_stats rx_sa_stats[MACSEC_NUM_AN]; }; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index fcca023f22e54f6e4a1dd40ae8dc083c81035874..41f7f078cd27c556393a049eadf0d42ddcf29f43 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -4296,3 +4296,4 @@ MODULE_AUTHOR("Broadcom Corporation"); MODULE_DESCRIPTION("Broadcom GENET Ethernet controller driver"); MODULE_ALIAS("platform:bcmgenet"); MODULE_LICENSE("GPL"); +MODULE_SOFTDEP("pre: mdio-bcm-unimac"); diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c index 6fb6c3556285485a24eca1f6b33228365a50139c..f9e91304d232788977fd9473dfec2266f1615f82 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmmii.c +++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c @@ -423,6 +423,10 @@ static int bcmgenet_mii_register(struct bcmgenet_priv *priv) int id, ret; pres = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!pres) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } memset(&res, 0, sizeof(res)); memset(&ppd, 0, sizeof(ppd)); diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 701c12c9e03371ca07cda5a86f2065feb58fb1b5..649c5c429bd7cf5a892948d38080c37129f59120 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c @@ -550,7 +550,7 @@ int be_process_mcc(struct be_adapter *adapter) int num = 0, status = 0; struct be_mcc_obj *mcc_obj = &adapter->mcc_obj; - spin_lock_bh(&adapter->mcc_cq_lock); + spin_lock(&adapter->mcc_cq_lock); while ((compl = be_mcc_compl_get(adapter))) { if (compl->flags & CQE_FLAGS_ASYNC_MASK) { @@ -566,7 +566,7 @@ int be_process_mcc(struct be_adapter *adapter) if (num) be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num); - spin_unlock_bh(&adapter->mcc_cq_lock); + spin_unlock(&adapter->mcc_cq_lock); return status; } @@ -581,7 +581,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter) if (be_check_error(adapter, BE_ERROR_ANY)) return -EIO; + local_bh_disable(); status = be_process_mcc(adapter); + local_bh_enable(); if (atomic_read(&mcc_obj->q.used) == 0) break; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index cb1e1ad652d0977b2d29450730c9444a55be57c9..89697cb09d1c0669e98ce103cbfcf598c040d111 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -5509,7 +5509,9 @@ static void be_worker(struct work_struct *work) * mcc completions */ if (!netif_running(adapter->netdev)) { + local_bh_disable(); be_process_mcc(adapter); + local_bh_enable(); goto reschedule; } diff --git a/drivers/net/ethernet/ezchip/nps_enet.c b/drivers/net/ethernet/ezchip/nps_enet.c index 815fb62c4b02e8738c052f86e2b0f9b93121b5b5..3d74401b4f102dc33a2c741384eaaf93992acef3 100644 --- a/drivers/net/ethernet/ezchip/nps_enet.c +++ b/drivers/net/ethernet/ezchip/nps_enet.c @@ -610,7 +610,7 @@ static s32 nps_enet_probe(struct platform_device *pdev) /* Get IRQ number */ priv->irq = platform_get_irq(pdev, 0); - if (!priv->irq) { + if (priv->irq < 0) { dev_err(dev, "failed to retrieve <irq Rx-Tx> value from device tree\n"); err = -ENODEV; goto out_netdev; @@ -645,8 +645,8 @@ static s32 nps_enet_remove(struct platform_device *pdev) struct nps_enet_priv *priv = netdev_priv(ndev); unregister_netdev(ndev); - free_netdev(ndev); netif_napi_del(&priv->napi); + free_netdev(ndev); return 0; } diff --git a/drivers/net/ethernet/faraday/ftgmac100.c b/drivers/net/ethernet/faraday/ftgmac100.c index c9c380c5087918043b4bd11872d1b8cdc026f528..5bc11d1bb9df844d336d10e277a3fa920635f20c 100644 --- a/drivers/net/ethernet/faraday/ftgmac100.c +++ b/drivers/net/ethernet/faraday/ftgmac100.c @@ -1831,14 +1831,17 @@ static int ftgmac100_probe(struct platform_device *pdev) if (np && of_get_property(np, "use-ncsi", NULL)) { if (!IS_ENABLED(CONFIG_NET_NCSI)) { dev_err(&pdev->dev, "NCSI stack not enabled\n"); + err = -EINVAL; goto err_ncsi_dev; } dev_info(&pdev->dev, "Using NCSI interface\n"); priv->use_ncsi = true; priv->ndev = ncsi_register_dev(netdev, ftgmac100_ncsi_handler); - if (!priv->ndev) + if (!priv->ndev) { + err = -EINVAL; goto err_ncsi_dev; + } } else if (np && of_get_property(np, "phy-handle", NULL)) { struct phy_device *phy; @@ -1846,6 +1849,7 @@ static int ftgmac100_probe(struct platform_device *pdev) &ftgmac100_adjust_link); if (!phy) { dev_err(&pdev->dev, "Failed to connect to phy\n"); + err = -EINVAL; goto err_setup_mdio; } diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index b3eac8a14f5d5e0099353e91d6dc7c2c5064d4e8..32923a16925a5ea7cb87be7ef6008f0a39af4cf6 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3443,12 +3443,12 @@ static int fec_set_features(struct net_device *netdev, return 0; } -u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb) +static u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb) { struct vlan_ethhdr *vhdr; unsigned short vlan_TCI = 0; - if (skb->protocol == ntohs(ETH_P_ALL)) { + if (skb->protocol == htons(ETH_P_ALL)) { vhdr = (struct vlan_ethhdr *)(skb->data); vlan_TCI = ntohs(vhdr->h_vlan_TCI); } @@ -3456,8 +3456,8 @@ u16 fec_enet_get_raw_vlan_tci(struct sk_buff *skb) return vlan_TCI; } -u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, - struct net_device *sb_dev) +static u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, + struct net_device *sb_dev) { struct fec_enet_private *fep = netdev_priv(ndev); u16 vlan_tag; @@ -3469,7 +3469,7 @@ u16 fec_enet_select_queue(struct net_device *ndev, struct sk_buff *skb, if (!vlan_tag) return vlan_tag; - return fec_enet_vlan_pri_to_queue[vlan_tag >> 13]; + return fec_enet_vlan_pri_to_queue[vlan_tag >> 13]; } static const struct net_device_ops fec_netdev_ops = { diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c index d6e35421d8f7bf2501e9a04726e020503a853c0e..3a74e4645ce650633e913d7eb986526c954e65cf 100644 --- a/drivers/net/ethernet/google/gve/gve_main.c +++ b/drivers/net/ethernet/google/gve/gve_main.c @@ -1286,8 +1286,8 @@ static int gve_probe(struct pci_dev *pdev, const struct pci_device_id *ent) gve_write_version(®_bar->driver_version); /* Get max queues to alloc etherdev */ - max_rx_queues = ioread32be(®_bar->max_tx_queues); - max_tx_queues = ioread32be(®_bar->max_rx_queues); + max_tx_queues = ioread32be(®_bar->max_tx_queues); + max_rx_queues = ioread32be(®_bar->max_rx_queues); /* Alloc and setup the netdev and priv */ dev = alloc_etherdev_mqs(sizeof(*priv), max_tx_queues, max_rx_queues); if (!dev) { diff --git a/drivers/net/ethernet/ibm/ehea/ehea_main.c b/drivers/net/ethernet/ibm/ehea/ehea_main.c index c2e7404757869ca227f49df08b1890552d28f44c..f6306673642531625c0da663d9976312e1b29627 100644 --- a/drivers/net/ethernet/ibm/ehea/ehea_main.c +++ b/drivers/net/ethernet/ibm/ehea/ehea_main.c @@ -2617,10 +2617,8 @@ static int ehea_restart_qps(struct net_device *dev) u16 dummy16 = 0; cb0 = (void *)get_zeroed_page(GFP_KERNEL); - if (!cb0) { - ret = -ENOMEM; - goto out; - } + if (!cb0) + return -ENOMEM; for (i = 0; i < (port->num_def_qps); i++) { struct ehea_port_res *pr = &port->port_res[i]; @@ -2640,6 +2638,7 @@ static int ehea_restart_qps(struct net_device *dev) cb0); if (hret != H_SUCCESS) { netdev_err(dev, "query_ehea_qp failed (1)\n"); + ret = -EFAULT; goto out; } @@ -2652,6 +2651,7 @@ static int ehea_restart_qps(struct net_device *dev) &dummy64, &dummy16, &dummy16); if (hret != H_SUCCESS) { netdev_err(dev, "modify_ehea_qp failed (1)\n"); + ret = -EFAULT; goto out; } @@ -2660,6 +2660,7 @@ static int ehea_restart_qps(struct net_device *dev) cb0); if (hret != H_SUCCESS) { netdev_err(dev, "query_ehea_qp failed (2)\n"); + ret = -EFAULT; goto out; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 8cc444684491ac95928f6d9321112de79fadff65..3134c1988db36a2f7afd9d592995cf4f9b6b4b14 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -212,12 +212,11 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter, mutex_lock(&adapter->fw_lock); adapter->fw_done_rc = 0; reinit_completion(&adapter->fw_done); - rc = send_request_map(adapter, ltb->addr, - ltb->size, ltb->map_id); + + rc = send_request_map(adapter, ltb->addr, ltb->size, ltb->map_id); if (rc) { - dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); - mutex_unlock(&adapter->fw_lock); - return rc; + dev_err(dev, "send_request_map failed, rc = %d\n", rc); + goto out; } rc = ibmvnic_wait_for_completion(adapter, &adapter->fw_done, 10000); @@ -225,20 +224,23 @@ static int alloc_long_term_buff(struct ibmvnic_adapter *adapter, dev_err(dev, "Long term map request aborted or timed out,rc = %d\n", rc); - dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); - mutex_unlock(&adapter->fw_lock); - return rc; + goto out; } if (adapter->fw_done_rc) { dev_err(dev, "Couldn't map long term buffer,rc = %d\n", adapter->fw_done_rc); + rc = -1; + goto out; + } + rc = 0; +out: + if (rc) { dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); - mutex_unlock(&adapter->fw_lock); - return -1; + ltb->buff = NULL; } mutex_unlock(&adapter->fw_lock); - return 0; + return rc; } static void free_long_term_buff(struct ibmvnic_adapter *adapter, @@ -258,6 +260,8 @@ static void free_long_term_buff(struct ibmvnic_adapter *adapter, adapter->reset_reason != VNIC_RESET_TIMEOUT) send_request_unmap(adapter, ltb->map_id); dma_free_coherent(dev, ltb->size, ltb->buff, ltb->addr); + ltb->buff = NULL; + ltb->map_id = 0; } static int reset_long_term_buff(struct ibmvnic_adapter *adapter, @@ -747,8 +751,11 @@ static int init_tx_pools(struct net_device *netdev) adapter->tso_pool = kcalloc(tx_subcrqs, sizeof(struct ibmvnic_tx_pool), GFP_KERNEL); - if (!adapter->tso_pool) + if (!adapter->tso_pool) { + kfree(adapter->tx_pool); + adapter->tx_pool = NULL; return -1; + } adapter->num_active_tx_pools = tx_subcrqs; @@ -1166,6 +1173,11 @@ static int __ibmvnic_open(struct net_device *netdev) netif_tx_start_all_queues(netdev); + if (prev_state == VNIC_CLOSED) { + for (i = 0; i < adapter->req_rx_queues; i++) + napi_schedule(&adapter->napi[i]); + } + adapter->state = VNIC_OPEN; return rc; } diff --git a/drivers/net/ethernet/intel/e100.c b/drivers/net/ethernet/intel/e100.c index 8cc651d37a7fd21e466aab8441ed76db2c4efb51..609e47b8287d1fa8a88cb14d40a0213ad38fc3f4 100644 --- a/drivers/net/ethernet/intel/e100.c +++ b/drivers/net/ethernet/intel/e100.c @@ -1395,7 +1395,7 @@ static int e100_phy_check_without_mii(struct nic *nic) u8 phy_type; int without_mii; - phy_type = (nic->eeprom[eeprom_phy_iface] >> 8) & 0x0f; + phy_type = (le16_to_cpu(nic->eeprom[eeprom_phy_iface]) >> 8) & 0x0f; switch (phy_type) { case NoSuchPhy: /* Non-MII PHY; UNTESTED! */ @@ -1515,7 +1515,7 @@ static int e100_phy_init(struct nic *nic) mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr); } else if ((nic->mac >= mac_82550_D102) || ((nic->flags & ich) && (mdio_read(netdev, nic->mii.phy_id, MII_TPISTATUS) & 0x8000) && - (nic->eeprom[eeprom_cnfg_mdix] & eeprom_mdix_enabled))) { + (le16_to_cpu(nic->eeprom[eeprom_cnfg_mdix]) & eeprom_mdix_enabled))) { /* enable/disable MDI/MDI-X auto-switching. */ mdio_write(netdev, nic->mii.phy_id, MII_NCONFIG, nic->mii.force_media ? 0 : NCONFIG_AUTO_SWITCH); @@ -2263,9 +2263,9 @@ static int e100_asf(struct nic *nic) { /* ASF can be enabled from eeprom */ return (nic->pdev->device >= 0x1050) && (nic->pdev->device <= 0x1057) && - (nic->eeprom[eeprom_config_asf] & eeprom_asf) && - !(nic->eeprom[eeprom_config_asf] & eeprom_gcl) && - ((nic->eeprom[eeprom_smbus_addr] & 0xFF) != 0xFE); + (le16_to_cpu(nic->eeprom[eeprom_config_asf]) & eeprom_asf) && + !(le16_to_cpu(nic->eeprom[eeprom_config_asf]) & eeprom_gcl) && + ((le16_to_cpu(nic->eeprom[eeprom_smbus_addr]) & 0xFF) != 0xFE); } static int e100_up(struct nic *nic) @@ -2920,7 +2920,7 @@ static int e100_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Wol magic packet can be enabled from eeprom */ if ((nic->mac >= mac_82558_D101_A4) && - (nic->eeprom[eeprom_id] & eeprom_id_wol)) { + (le16_to_cpu(nic->eeprom[eeprom_id]) & eeprom_id_wol)) { nic->flags |= wol_magic; device_set_wakeup_enable(&pdev->dev, true); } diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index a0948002ddf8584b59956755afadbf0cc3cdf8c3..b3ad95ac3d85937ac7e6fdd10dd51b762191af02 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -5222,18 +5222,20 @@ static void e1000_watchdog_task(struct work_struct *work) pm_runtime_resume(netdev->dev.parent); /* Checking if MAC is in DMoff state*/ - pcim_state = er32(STATUS); - while (pcim_state & E1000_STATUS_PCIM_STATE) { - if (tries++ == dmoff_exit_timeout) { - e_dbg("Error in exiting dmoff\n"); - break; - } - usleep_range(10000, 20000); + if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { pcim_state = er32(STATUS); - - /* Checking if MAC exited DMoff state */ - if (!(pcim_state & E1000_STATUS_PCIM_STATE)) - e1000_phy_hw_reset(&adapter->hw); + while (pcim_state & E1000_STATUS_PCIM_STATE) { + if (tries++ == dmoff_exit_timeout) { + e_dbg("Error in exiting dmoff\n"); + break; + } + usleep_range(10000, 20000); + pcim_state = er32(STATUS); + + /* Checking if MAC exited DMoff state */ + if (!(pcim_state & E1000_STATUS_PCIM_STATE)) + e1000_phy_hw_reset(&adapter->hw); + } } /* update snapshot of PHY registers on LSC */ diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 5d48bc0c3f6c4b952a4464124a3f406dc8271230..874073f7f024873fadd5d80c67bf3fe3d1ab5749 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1262,8 +1262,7 @@ static int i40e_set_link_ksettings(struct net_device *netdev, if (ethtool_link_ksettings_test_link_mode(&safe_ks, supported, Autoneg) && - hw->phy.link_info.phy_type != - I40E_PHY_TYPE_10GBASE_T) { + hw->phy.media_type != I40E_MEDIA_TYPE_BASET) { netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); err = -EINVAL; goto done; diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f0edea7cdbcccc3d7c90a4be4d7dff4b24dfad6f..52e31f712a54504c5be97c95226f8ba364190387 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -31,7 +31,7 @@ static void i40e_vsi_reinit_locked(struct i40e_vsi *vsi); static void i40e_handle_reset_warning(struct i40e_pf *pf, bool lock_acquired); static int i40e_add_vsi(struct i40e_vsi *vsi); static int i40e_add_veb(struct i40e_veb *veb, struct i40e_vsi *vsi); -static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit); +static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit, bool lock_acquired); static int i40e_setup_misc_vector(struct i40e_pf *pf); static void i40e_determine_queue_usage(struct i40e_pf *pf); static int i40e_setup_pf_filter_control(struct i40e_pf *pf); @@ -8347,6 +8347,8 @@ int i40e_vsi_open(struct i40e_vsi *vsi) dev_driver_string(&pf->pdev->dev), dev_name(&pf->pdev->dev)); err = i40e_vsi_request_irq(vsi, int_name); + if (err) + goto err_setup_rx; } else { err = -EINVAL; @@ -10112,7 +10114,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) /* do basic switch setup */ if (!lock_acquired) rtnl_lock(); - ret = i40e_setup_pf_switch(pf, reinit); + ret = i40e_setup_pf_switch(pf, reinit, true); if (ret) goto end_unlock; @@ -14167,10 +14169,11 @@ int i40e_fetch_switch_configuration(struct i40e_pf *pf, bool printconfig) * i40e_setup_pf_switch - Setup the HW switch on startup or after reset * @pf: board private structure * @reinit: if the Main VSI needs to re-initialized. + * @lock_acquired: indicates whether or not the lock has been acquired * * Returns 0 on success, negative value on failure **/ -static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) +static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit, bool lock_acquired) { u16 flags = 0; int ret; @@ -14272,9 +14275,15 @@ static int i40e_setup_pf_switch(struct i40e_pf *pf, bool reinit) i40e_ptp_init(pf); + if (!lock_acquired) + rtnl_lock(); + /* repopulate tunnel port filters */ udp_tunnel_nic_reset_ntf(pf->vsi[pf->lan_vsi]->netdev); + if (!lock_acquired) + rtnl_unlock(); + return ret; } @@ -15046,7 +15055,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pf->flags |= I40E_FLAG_VEB_MODE_ENABLED; } #endif - err = i40e_setup_pf_switch(pf, false); + err = i40e_setup_pf_switch(pf, false, false); if (err) { dev_info(&pdev->dev, "setup_pf_switch failed: %d\n", err); goto err_vsis; diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 7a879614ca55e9772579c4c95325d2511aa667b8..1dad6c93ac9c8ba0819455203ec4caef6ec8fed3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -11,13 +11,14 @@ * operate with the nanosecond field directly without fear of overflow. * * Much like the 82599, the update period is dependent upon the link speed: - * At 40Gb link or no link, the period is 1.6ns. - * At 10Gb link, the period is multiplied by 2. (3.2ns) + * At 40Gb, 25Gb, or no link, the period is 1.6ns. + * At 10Gb or 5Gb link, the period is multiplied by 2. (3.2ns) * At 1Gb link, the period is multiplied by 20. (32ns) * 1588 functionality is not supported at 100Mbps. */ #define I40E_PTP_40GB_INCVAL 0x0199999999ULL #define I40E_PTP_10GB_INCVAL_MULT 2 +#define I40E_PTP_5GB_INCVAL_MULT 2 #define I40E_PTP_1GB_INCVAL_MULT 20 #define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 BIT(I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) @@ -465,6 +466,9 @@ void i40e_ptp_set_increment(struct i40e_pf *pf) case I40E_LINK_SPEED_10GB: mult = I40E_PTP_10GB_INCVAL_MULT; break; + case I40E_LINK_SPEED_5GB: + mult = I40E_PTP_5GB_INCVAL_MULT; + break; case I40E_LINK_SPEED_1GB: mult = I40E_PTP_1GB_INCVAL_MULT; break; diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index a7975afecf70f50878c6a7fec2caed4170eb58d0..14eba9bc174d8fb64e345122c1d574adf3976486 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3492,13 +3492,9 @@ static int ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, struct ice_ring_container *rc) { - struct ice_pf *pf; - if (!rc->ring) return -EINVAL; - pf = rc->ring->vsi->back; - switch (c_type) { case ICE_RX_CONTAINER: ec->use_adaptive_rx_coalesce = ITR_IS_DYNAMIC(rc->itr_setting); @@ -3510,7 +3506,7 @@ ice_get_rc_coalesce(struct ethtool_coalesce *ec, enum ice_container_type c_type, ec->tx_coalesce_usecs = rc->itr_setting & ~ICE_ITR_DYNAMIC; break; default: - dev_dbg(ice_pf_to_dev(pf), "Invalid c_type %d\n", c_type); + dev_dbg(ice_pf_to_dev(rc->ring->vsi->back), "Invalid c_type %d\n", c_type); return -EINVAL; } diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h index 4ec24c3e813fe695485e5ce3df816407cb45acdb..c0ee0541e53fc14c92ef083b6accea03bc156d49 100644 --- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h +++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h @@ -608,7 +608,7 @@ static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = { /* L2 Packet types */ ICE_PTT_UNUSED_ENTRY(0), ICE_PTT(1, L2, NONE, NOF, NONE, NONE, NOF, NONE, PAY2), - ICE_PTT(2, L2, NONE, NOF, NONE, NONE, NOF, NONE, NONE), + ICE_PTT_UNUSED_ENTRY(2), ICE_PTT_UNUSED_ENTRY(3), ICE_PTT_UNUSED_ENTRY(4), ICE_PTT_UNUSED_ENTRY(5), @@ -722,7 +722,7 @@ static const struct ice_rx_ptype_decoded ice_ptype_lkup[] = { /* Non Tunneled IPv6 */ ICE_PTT(88, IP, IPV6, FRG, NONE, NONE, NOF, NONE, PAY3), ICE_PTT(89, IP, IPV6, NOF, NONE, NONE, NOF, NONE, PAY3), - ICE_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY3), + ICE_PTT(90, IP, IPV6, NOF, NONE, NONE, NOF, UDP, PAY4), ICE_PTT_UNUSED_ENTRY(91), ICE_PTT(92, IP, IPV6, NOF, NONE, NONE, NOF, TCP, PAY4), ICE_PTT(93, IP, IPV6, NOF, NONE, NONE, NOF, SCTP, PAY4), diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 1bed183d96a0db285754056e48223a4883aab8ec..ee3497d254646270b32f6e96330a3dbce9ad0789 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -63,7 +63,7 @@ enum ice_aq_res_ids { /* FW update timeout definitions are in milliseconds */ #define ICE_NVM_TIMEOUT 180000 #define ICE_CHANGE_LOCK_TIMEOUT 1000 -#define ICE_GLOBAL_CFG_LOCK_TIMEOUT 3000 +#define ICE_GLOBAL_CFG_LOCK_TIMEOUT 5000 enum ice_aq_res_access_type { ICE_RES_READ = 1, diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 5c87c0a7ce3d7e7f480dc0188668f788abf6410a..4b9b5148c916b40605c10efaef0ac9a881ac8178 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -2643,7 +2643,8 @@ static int igb_parse_cls_flower(struct igb_adapter *adapter, } input->filter.match_flags |= IGB_FILTER_FLAG_VLAN_TCI; - input->filter.vlan_tci = match.key->vlan_priority; + input->filter.vlan_tci = + (__force __be16)match.key->vlan_priority; } } @@ -6288,12 +6289,12 @@ int igb_xmit_xdp_ring(struct igb_adapter *adapter, cmd_type |= len | IGB_TXD_DCMD; tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type); - olinfo_status = cpu_to_le32(len << E1000_ADVTXD_PAYLEN_SHIFT); + olinfo_status = len << E1000_ADVTXD_PAYLEN_SHIFT; /* 82575 requires a unique index per ring */ if (test_bit(IGB_RING_FLAG_TX_CTX_IDX, &tx_ring->flags)) olinfo_status |= tx_ring->reg_idx << 4; - tx_desc->read.olinfo_status = olinfo_status; + tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status); netdev_tx_sent_queue(txring_txq(tx_ring), tx_buffer->bytecount); @@ -8617,7 +8618,7 @@ static void igb_process_skb_fields(struct igb_ring *rx_ring, if (igb_test_staterr(rx_desc, E1000_RXDEXT_STATERR_LB) && test_bit(IGB_RING_FLAG_RX_LB_VLAN_BSWAP, &rx_ring->flags)) - vid = be16_to_cpu(rx_desc->wb.upper.vlan); + vid = be16_to_cpu((__force __be16)rx_desc->wb.upper.vlan); else vid = le16_to_cpu(rx_desc->wb.upper.vlan); diff --git a/drivers/net/ethernet/intel/igbvf/netdev.c b/drivers/net/ethernet/intel/igbvf/netdev.c index ee9f8c1dca8365cd04aa42c2495c1b305c236fda..07c9e9e0546f50f5867b92976095b6932feee914 100644 --- a/drivers/net/ethernet/intel/igbvf/netdev.c +++ b/drivers/net/ethernet/intel/igbvf/netdev.c @@ -83,14 +83,14 @@ static int igbvf_desc_unused(struct igbvf_ring *ring) static void igbvf_receive_skb(struct igbvf_adapter *adapter, struct net_device *netdev, struct sk_buff *skb, - u32 status, u16 vlan) + u32 status, __le16 vlan) { u16 vid; if (status & E1000_RXD_STAT_VP) { if ((adapter->flags & IGBVF_FLAG_RX_LB_VLAN_BSWAP) && (status & E1000_RXDEXT_STATERR_LB)) - vid = be16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; + vid = be16_to_cpu((__force __be16)vlan) & E1000_RXD_SPC_VLAN_MASK; else vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; if (test_bit(vid, adapter->active_vlans)) diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 6aa13c9f9fc9c3e4890c119c5e38871bbe3e3b0a..ec9b6c564300e8c4f9dffc3f99c156973d6718d2 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -6871,6 +6871,10 @@ static int mvpp2_probe(struct platform_device *pdev) return PTR_ERR(priv->lms_base); } else { res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } if (has_acpi_companion(&pdev->dev)) { /* In case the MDIO memory region is declared in * the ACPI, it can already appear as 'in-use' @@ -7045,6 +7049,8 @@ static int mvpp2_probe(struct platform_device *pdev) return 0; err_port_probe: + fwnode_handle_put(port_fwnode); + i = 0; fwnode_for_each_available_child_node(fwnode, port_fwnode) { if (priv->port_list[i]) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 7e1f8660dfec082604df3c9496987f723b465e30..f327b78261ec4eaf306115690163219e469ece04 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1318,7 +1318,8 @@ static void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) if (rep->vlan && skb_vlan_tag_present(skb)) skb_vlan_pop(skb); - if (!mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv)) { + if (unlikely(!mlx5_ipsec_is_rx_flow(cqe) && + !mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv))) { dev_kfree_skb_any(skb); goto free_wqe; } @@ -1375,7 +1376,8 @@ static void mlx5e_handle_rx_cqe_mpwrq_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 mlx5e_complete_rx_cqe(rq, cqe, cqe_bcnt, skb); - if (!mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv)) { + if (unlikely(!mlx5_ipsec_is_rx_flow(cqe) && + !mlx5e_rep_tc_update_skb(cqe, skb, &tc_priv))) { dev_kfree_skb_any(skb); goto mpwrq_cqe_out; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag.c index 9025e5f38bb658375a76bf2ac8ede6072ec4918a..fe5476a76464fbc53e2083909f0869fbeec74f05 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/lag.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/lag.c @@ -118,17 +118,24 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev) static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker, u8 *port1, u8 *port2) { + bool p1en; + bool p2en; + + p1en = tracker->netdev_state[MLX5_LAG_P1].tx_enabled && + tracker->netdev_state[MLX5_LAG_P1].link_up; + + p2en = tracker->netdev_state[MLX5_LAG_P2].tx_enabled && + tracker->netdev_state[MLX5_LAG_P2].link_up; + *port1 = 1; *port2 = 2; - if (!tracker->netdev_state[MLX5_LAG_P1].tx_enabled || - !tracker->netdev_state[MLX5_LAG_P1].link_up) { - *port1 = 2; + if ((!p1en && !p2en) || (p1en && p2en)) return; - } - if (!tracker->netdev_state[MLX5_LAG_P2].tx_enabled || - !tracker->netdev_state[MLX5_LAG_P2].link_up) + if (p1en) *port2 = 1; + else + *port1 = 2; } void mlx5_modify_lag(struct mlx5_lag *ldev, diff --git a/drivers/net/ethernet/micrel/ks8842.c b/drivers/net/ethernet/micrel/ks8842.c index caa251d0e3815e6c222e67a8b3ffb57ad0382ebf..b27713906d3a65bd442df0f10fefa3d45a0d4fe2 100644 --- a/drivers/net/ethernet/micrel/ks8842.c +++ b/drivers/net/ethernet/micrel/ks8842.c @@ -1135,6 +1135,10 @@ static int ks8842_probe(struct platform_device *pdev) unsigned i; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!iomem) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME)) goto err_mem_region; diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c index 49fd843c4c8a02afd3be7d9b0ba87d17fe9eb323..a4380c45f668909a814322e7fbe44d685e588e53 100644 --- a/drivers/net/ethernet/moxa/moxart_ether.c +++ b/drivers/net/ethernet/moxa/moxart_ether.c @@ -481,14 +481,13 @@ static int moxart_mac_probe(struct platform_device *pdev) priv->ndev = ndev; priv->pdev = pdev; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - ndev->base_addr = res->start; - priv->base = devm_ioremap_resource(p_dev, res); + priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res); if (IS_ERR(priv->base)) { dev_err(p_dev, "devm_ioremap_resource failed\n"); ret = PTR_ERR(priv->base); goto init_fail; } + ndev->base_addr = res->start; spin_lock_init(&priv->txlock); diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index ade8c44c01cd18156ca6a96c2a797ab1f684586f..2942102efd4884609a70218118f120e0883972dd 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c @@ -107,7 +107,7 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) { u8 *data = skb->data; unsigned int offset; - u16 *hi, *id; + u16 hi, id; u32 lo; if (ptp_classify_raw(skb) == PTP_CLASS_NONE) @@ -118,14 +118,11 @@ static int pch_ptp_match(struct sk_buff *skb, u16 uid_hi, u32 uid_lo, u16 seqid) if (skb->len < offset + OFF_PTP_SEQUENCE_ID + sizeof(seqid)) return 0; - hi = (u16 *)(data + offset + OFF_PTP_SOURCE_UUID); - id = (u16 *)(data + offset + OFF_PTP_SEQUENCE_ID); + hi = get_unaligned_be16(data + offset + OFF_PTP_SOURCE_UUID + 0); + lo = get_unaligned_be32(data + offset + OFF_PTP_SOURCE_UUID + 2); + id = get_unaligned_be16(data + offset + OFF_PTP_SEQUENCE_ID); - memcpy(&lo, &hi[1], sizeof(lo)); - - return (uid_hi == *hi && - uid_lo == lo && - seqid == *id); + return (uid_hi == hi && uid_lo == lo && seqid == id); } static void @@ -135,7 +132,6 @@ pch_rx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb) struct pci_dev *pdev; u64 ns; u32 hi, lo, val; - u16 uid, seq; if (!adapter->hwts_rx_en) return; @@ -151,10 +147,7 @@ pch_rx_timestamp(struct pch_gbe_adapter *adapter, struct sk_buff *skb) lo = pch_src_uuid_lo_read(pdev); hi = pch_src_uuid_hi_read(pdev); - uid = hi & 0xffff; - seq = (hi >> 16) & 0xffff; - - if (!pch_ptp_match(skb, htons(uid), htonl(lo), htons(seq))) + if (!pch_ptp_match(skb, hi, lo, hi >> 16)) goto out; ns = pch_rx_snap_read(pdev); @@ -2536,9 +2529,13 @@ static int pch_gbe_probe(struct pci_dev *pdev, adapter->pdev = pdev; adapter->hw.back = adapter; adapter->hw.reg = pcim_iomap_table(pdev)[PCH_GBE_PCI_BAR]; + adapter->pdata = (struct pch_gbe_privdata *)pci_id->driver_data; - if (adapter->pdata && adapter->pdata->platform_init) - adapter->pdata->platform_init(pdev); + if (adapter->pdata && adapter->pdata->platform_init) { + ret = adapter->pdata->platform_init(pdev); + if (ret) + goto err_free_netdev; + } adapter->ptp_pdev = pci_get_domain_bus_and_slot(pci_domain_nr(adapter->pdev->bus), @@ -2633,7 +2630,7 @@ err_free_netdev: */ static int pch_gbe_minnow_platform_init(struct pci_dev *pdev) { - unsigned long flags = GPIOF_DIR_OUT | GPIOF_INIT_HIGH | GPIOF_EXPORT; + unsigned long flags = GPIOF_OUT_INIT_HIGH; unsigned gpio = MINNOW_PHY_RESET_GPIO; int ret; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c index 17d5b649eb36b991d786e34d359b6d0b6183fda0..e81dd34a3cac20b960b49a743ab8ec76a2352022 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c @@ -1266,9 +1266,11 @@ int qed_dcbx_get_config_params(struct qed_hwfn *p_hwfn, p_hwfn->p_dcbx_info->set.ver_num |= DCBX_CONFIG_VERSION_STATIC; p_hwfn->p_dcbx_info->set.enabled = dcbx_info->operational.enabled; + BUILD_BUG_ON(sizeof(dcbx_info->operational.params) != + sizeof(p_hwfn->p_dcbx_info->set.config.params)); memcpy(&p_hwfn->p_dcbx_info->set.config.params, &dcbx_info->operational.params, - sizeof(struct qed_dcbx_admin_params)); + sizeof(p_hwfn->p_dcbx_info->set.config.params)); p_hwfn->p_dcbx_info->set.config.valid = true; memcpy(params, &p_hwfn->p_dcbx_info->set, sizeof(struct qed_dcbx_set)); diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 3bb36f4a984e85b4eb9f15fb6a63f98ce3f079d2..9010aabd978263f8db10a639a6b5a41404bee697 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -1673,7 +1673,7 @@ static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) { switch(stringset) { case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); + memcpy(data, rtl8169_gstrings, sizeof(rtl8169_gstrings)); break; } } @@ -3547,7 +3547,6 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp) rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000); rtl_pcie_state_l2l3_disable(tp); - rtl_hw_aspm_clkreq_enable(tp, true); } DECLARE_RTL_COND(rtl_mac_ocp_e00e_cond) diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 6d84266c03cafd5b06e16b68606c9be8ded49137..5cab2d3c00236047ebc9f08e594e700f3b8052bc 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -2287,7 +2287,7 @@ static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data) { switch (stringset) { case ETH_SS_STATS: - memcpy(data, *sh_eth_gstrings_stats, + memcpy(data, sh_eth_gstrings_stats, sizeof(sh_eth_gstrings_stats)); break; } diff --git a/drivers/net/ethernet/sfc/ef10_sriov.c b/drivers/net/ethernet/sfc/ef10_sriov.c index 21fa6c0e88734ea5a7cf81dc2b1a12febc122be4..84041cd587d784e214e6d62409a803d43c172c31 100644 --- a/drivers/net/ethernet/sfc/ef10_sriov.c +++ b/drivers/net/ethernet/sfc/ef10_sriov.c @@ -402,12 +402,17 @@ fail1: return rc; } +/* Disable SRIOV and remove VFs + * If some VFs are attached to a guest (using Xen, only) nothing is + * done if force=false, and vports are freed if force=true (for the non + * attachedc ones, only) but SRIOV is not disabled and VFs are not + * removed in either case. + */ static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force) { struct pci_dev *dev = efx->pci_dev; - unsigned int vfs_assigned = 0; - - vfs_assigned = pci_vfs_assigned(dev); + unsigned int vfs_assigned = pci_vfs_assigned(dev); + int rc = 0; if (vfs_assigned && !force) { netif_info(efx, drv, efx->net_dev, "VFs are assigned to guests; " @@ -417,10 +422,12 @@ static int efx_ef10_pci_sriov_disable(struct efx_nic *efx, bool force) if (!vfs_assigned) pci_disable_sriov(dev); + else + rc = -EBUSY; efx_ef10_sriov_free_vf_vswitching(efx); efx->vf_count = 0; - return 0; + return rc; } int efx_ef10_sriov_configure(struct efx_nic *efx, int num_vfs) @@ -439,7 +446,6 @@ int efx_ef10_sriov_init(struct efx_nic *efx) void efx_ef10_sriov_fini(struct efx_nic *efx) { struct efx_ef10_nic_data *nic_data = efx->nic_data; - unsigned int i; int rc; if (!nic_data->vf) { @@ -449,14 +455,7 @@ void efx_ef10_sriov_fini(struct efx_nic *efx) return; } - /* Remove any VFs in the host */ - for (i = 0; i < efx->vf_count; ++i) { - struct efx_nic *vf_efx = nic_data->vf[i].efx; - - if (vf_efx) - vf_efx->pci_dev->driver->remove(vf_efx->pci_dev); - } - + /* Disable SRIOV and remove any VFs in the host */ rc = efx_ef10_pci_sriov_disable(efx, true); if (rc) netif_dbg(efx, drv, efx->net_dev, diff --git a/drivers/net/ethernet/sgi/ioc3-eth.c b/drivers/net/ethernet/sgi/ioc3-eth.c index 6eef0f45b133beda41ddff121a37e354266adb69..2b29fd4cbdf44e4840ed9c020faee1ea502018f8 100644 --- a/drivers/net/ethernet/sgi/ioc3-eth.c +++ b/drivers/net/ethernet/sgi/ioc3-eth.c @@ -835,6 +835,10 @@ static int ioc3eth_probe(struct platform_device *pdev) int err; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "Invalid resource\n"); + return -EINVAL; + } /* get mac addr from one wire prom */ if (ioc3eth_get_mac_addr(regs, mac_addr)) return -EPROBE_DEFER; /* not available yet */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 5a667dcd79d18b783ccbe8e385623c8dd6bacb23..f24bef2a8162e8f7a3e5aa298343af9f88205466 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -450,6 +450,12 @@ int stmmac_mdio_register(struct net_device *ndev) found = 1; } + if (!found && !mdio_node) { + dev_warn(dev, "No PHY found\n"); + err = -ENODEV; + goto no_phy_found; + } + /* Try to probe the XPCS by scanning all addresses. */ if (priv->hw->xpcs) { struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args; @@ -458,6 +464,7 @@ int stmmac_mdio_register(struct net_device *ndev) xpcs->bus = new_bus; + found = 0; for (addr = 0; addr < max_addr; addr++) { xpcs->addr = addr; @@ -467,13 +474,12 @@ int stmmac_mdio_register(struct net_device *ndev) break; } } - } - if (!found && !mdio_node) { - dev_warn(dev, "No PHY found\n"); - mdiobus_unregister(new_bus); - mdiobus_free(new_bus); - return -ENODEV; + if (!found && !mdio_node) { + dev_warn(dev, "No XPCS found\n"); + err = -ENODEV; + goto no_xpcs_found; + } } bus_register_done: @@ -481,6 +487,9 @@ bus_register_done: return 0; +no_xpcs_found: +no_phy_found: + mdiobus_unregister(new_bus); bus_register_fail: mdiobus_free(new_bus); return err; diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 501d676fd88b99d3487c487786585dd04efc94eb..0805edef56254685020363df247ed0c374624231 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -1433,12 +1433,12 @@ static void am65_cpsw_nuss_free_tx_chns(void *data) for (i = 0; i < common->tx_ch_num; i++) { struct am65_cpsw_tx_chn *tx_chn = &common->tx_chns[i]; - if (!IS_ERR_OR_NULL(tx_chn->tx_chn)) - k3_udma_glue_release_tx_chn(tx_chn->tx_chn); - if (!IS_ERR_OR_NULL(tx_chn->desc_pool)) k3_cppi_desc_pool_destroy(tx_chn->desc_pool); + if (!IS_ERR_OR_NULL(tx_chn->tx_chn)) + k3_udma_glue_release_tx_chn(tx_chn->tx_chn); + memset(tx_chn, 0, sizeof(*tx_chn)); } } @@ -1458,12 +1458,12 @@ void am65_cpsw_nuss_remove_tx_chns(struct am65_cpsw_common *common) netif_napi_del(&tx_chn->napi_tx); - if (!IS_ERR_OR_NULL(tx_chn->tx_chn)) - k3_udma_glue_release_tx_chn(tx_chn->tx_chn); - if (!IS_ERR_OR_NULL(tx_chn->desc_pool)) k3_cppi_desc_pool_destroy(tx_chn->desc_pool); + if (!IS_ERR_OR_NULL(tx_chn->tx_chn)) + k3_udma_glue_release_tx_chn(tx_chn->tx_chn); + memset(tx_chn, 0, sizeof(*tx_chn)); } } @@ -1550,11 +1550,11 @@ static void am65_cpsw_nuss_free_rx_chns(void *data) rx_chn = &common->rx_chns; - if (!IS_ERR_OR_NULL(rx_chn->rx_chn)) - k3_udma_glue_release_rx_chn(rx_chn->rx_chn); - if (!IS_ERR_OR_NULL(rx_chn->desc_pool)) k3_cppi_desc_pool_destroy(rx_chn->desc_pool); + + if (!IS_ERR_OR_NULL(rx_chn->rx_chn)) + k3_udma_glue_release_rx_chn(rx_chn->rx_chn); } static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common) diff --git a/drivers/net/ethernet/xilinx/ll_temac_main.c b/drivers/net/ethernet/xilinx/ll_temac_main.c index 01bb36e7cff0ac8cdaa1fa70e0a99a1bad3c9f33..6bd3a389d389c7d9e41ef08e949b1c2e034b04c1 100644 --- a/drivers/net/ethernet/xilinx/ll_temac_main.c +++ b/drivers/net/ethernet/xilinx/ll_temac_main.c @@ -774,12 +774,15 @@ static void temac_start_xmit_done(struct net_device *ndev) stat = be32_to_cpu(cur_p->app0); while (stat & STS_CTRL_APP0_CMPLT) { + /* Make sure that the other fields are read after bd is + * released by dma + */ + rmb(); dma_unmap_single(ndev->dev.parent, be32_to_cpu(cur_p->phys), be32_to_cpu(cur_p->len), DMA_TO_DEVICE); skb = (struct sk_buff *)ptr_from_txbd(cur_p); if (skb) dev_consume_skb_irq(skb); - cur_p->app0 = 0; cur_p->app1 = 0; cur_p->app2 = 0; cur_p->app3 = 0; @@ -788,6 +791,12 @@ static void temac_start_xmit_done(struct net_device *ndev) ndev->stats.tx_packets++; ndev->stats.tx_bytes += be32_to_cpu(cur_p->len); + /* app0 must be visible last, as it is used to flag + * availability of the bd + */ + smp_mb(); + cur_p->app0 = 0; + lp->tx_bd_ci++; if (lp->tx_bd_ci >= lp->tx_bd_num) lp->tx_bd_ci = 0; @@ -814,6 +823,9 @@ static inline int temac_check_tx_bd_space(struct temac_local *lp, int num_frag) if (cur_p->app0) return NETDEV_TX_BUSY; + /* Make sure to read next bd app0 after this one */ + rmb(); + tail++; if (tail >= lp->tx_bd_num) tail = 0; @@ -930,6 +942,11 @@ temac_start_xmit(struct sk_buff *skb, struct net_device *ndev) wmb(); lp->dma_out(lp, TX_TAILDESC_PTR, tail_p); /* DMA start */ + if (temac_check_tx_bd_space(lp, MAX_SKB_FRAGS + 1)) { + netdev_info(ndev, "%s -> netif_stop_queue\n", __func__); + netif_stop_queue(ndev); + } + return NETDEV_TX_OK; } diff --git a/drivers/net/fjes/fjes_main.c b/drivers/net/fjes/fjes_main.c index 466622664424dcd14085257b76c32790f8eff6e6..e449d946612259cf77ac78ea87449f0b3ebb0b40 100644 --- a/drivers/net/fjes/fjes_main.c +++ b/drivers/net/fjes/fjes_main.c @@ -1262,6 +1262,10 @@ static int fjes_probe(struct platform_device *plat_dev) adapter->interrupt_watch_enable = false; res = platform_get_resource(plat_dev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; + goto err_free_control_wq; + } hw->hw_res.start = res->start; hw->hw_res.size = resource_size(res); hw->hw_res.irq = platform_get_irq(plat_dev, 0); diff --git a/drivers/net/ieee802154/mac802154_hwsim.c b/drivers/net/ieee802154/mac802154_hwsim.c index c0bf7d78276e42e2f2c995501fd0c22cbd960198..626e1ce817fcfed1b3da69c26a0d3f5dea89c7f7 100644 --- a/drivers/net/ieee802154/mac802154_hwsim.c +++ b/drivers/net/ieee802154/mac802154_hwsim.c @@ -480,7 +480,7 @@ static int hwsim_del_edge_nl(struct sk_buff *msg, struct genl_info *info) struct hwsim_edge *e; u32 v0, v1; - if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] && + if (!info->attrs[MAC802154_HWSIM_ATTR_RADIO_ID] || !info->attrs[MAC802154_HWSIM_ATTR_RADIO_EDGE]) return -EINVAL; @@ -715,6 +715,8 @@ static int hwsim_subscribe_all_others(struct hwsim_phy *phy) return 0; +sub_fail: + hwsim_edge_unsubscribe_me(phy); me_fail: rcu_read_lock(); list_for_each_entry_rcu(e, &phy->edges, list) { @@ -722,8 +724,6 @@ me_fail: hwsim_free_edge(e); } rcu_read_unlock(); -sub_fail: - hwsim_edge_unsubscribe_me(phy); return -ENOMEM; } @@ -824,12 +824,17 @@ err_pib: static void hwsim_del(struct hwsim_phy *phy) { struct hwsim_pib *pib; + struct hwsim_edge *e; hwsim_edge_unsubscribe_me(phy); list_del(&phy->list); rcu_read_lock(); + list_for_each_entry_rcu(e, &phy->edges, list) { + list_del_rcu(&e->list); + hwsim_free_edge(e); + } pib = rcu_dereference(phy->pib); rcu_read_unlock(); diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c index cd4d993b0bbb255cb6434648caa6a041ade9e3f3..4162a608a3bf9c5fd0e513d0e2a469aa55a442e3 100644 --- a/drivers/net/ipa/ipa_main.c +++ b/drivers/net/ipa/ipa_main.c @@ -589,6 +589,7 @@ static int ipa_firmware_load(struct device *dev) } ret = of_address_to_resource(node, 0, &res); + of_node_put(node); if (ret) { dev_err(dev, "error %d getting \"memory-region\" resource\n", ret); diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 11ca5fa902a161c040699b8190b01f6ef2f98973..c601d3df272202bd52d23888c59312cbf2e87b4e 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -1818,7 +1818,7 @@ static int macsec_add_rxsa(struct sk_buff *skb, struct genl_info *info) ctx.sa.rx_sa = rx_sa; ctx.secy = secy; memcpy(ctx.sa.key, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]), - MACSEC_KEYID_LEN); + secy->key_len); err = macsec_offload(ops->mdo_add_rxsa, &ctx); if (err) @@ -2060,7 +2060,7 @@ static int macsec_add_txsa(struct sk_buff *skb, struct genl_info *info) ctx.sa.tx_sa = tx_sa; ctx.secy = secy; memcpy(ctx.sa.key, nla_data(tb_sa[MACSEC_SA_ATTR_KEY]), - MACSEC_KEYID_LEN); + secy->key_len); err = macsec_offload(ops->mdo_add_txsa, &ctx); if (err) diff --git a/drivers/net/mdio/mdio-ipq8064.c b/drivers/net/mdio/mdio-ipq8064.c index 1bd18857e1c5e0e26ded6d2b3dcbb00a3c0e3024..f0a6bfa61645e1f98d2a9ecddfb430c6f9ed79a0 100644 --- a/drivers/net/mdio/mdio-ipq8064.c +++ b/drivers/net/mdio/mdio-ipq8064.c @@ -10,7 +10,7 @@ #include <linux/module.h> #include <linux/regmap.h> #include <linux/of_mdio.h> -#include <linux/phy.h> +#include <linux/of_address.h> #include <linux/platform_device.h> #include <linux/mfd/syscon.h> @@ -96,14 +96,34 @@ ipq8064_mdio_write(struct mii_bus *bus, int phy_addr, int reg_offset, u16 data) return ipq8064_mdio_wait_busy(priv); } +static const struct regmap_config ipq8064_mdio_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .can_multi_write = false, + /* the mdio lock is used by any user of this mdio driver */ + .disable_locking = true, + + .cache_type = REGCACHE_NONE, +}; + static int ipq8064_mdio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct ipq8064_mdio *priv; + struct resource res; struct mii_bus *bus; + void __iomem *base; int ret; + if (of_address_to_resource(np, 0, &res)) + return -ENOMEM; + + base = ioremap(res.start, resource_size(&res)); + if (!base) + return -ENOMEM; + bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); if (!bus) return -ENOMEM; @@ -115,15 +135,10 @@ ipq8064_mdio_probe(struct platform_device *pdev) bus->parent = &pdev->dev; priv = bus->priv; - priv->base = device_node_to_regmap(np); - if (IS_ERR(priv->base)) { - if (priv->base == ERR_PTR(-EPROBE_DEFER)) - return -EPROBE_DEFER; - - dev_err(&pdev->dev, "error getting device regmap, error=%pe\n", - priv->base); + priv->base = devm_regmap_init_mmio(&pdev->dev, base, + &ipq8064_mdio_regmap_config); + if (IS_ERR(priv->base)) return PTR_ERR(priv->base); - } ret = of_mdiobus_register(bus, np); if (ret) diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c index 69d3eacc2b96cbda0432d38d14a82829fb8685e2..c716074fdef0bd8c805020733c53365e9dd1e946 100644 --- a/drivers/net/phy/dp83867.c +++ b/drivers/net/phy/dp83867.c @@ -792,16 +792,12 @@ static int dp83867_phy_reset(struct phy_device *phydev) { int err; - err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESET); + err = phy_write(phydev, DP83867_CTRL, DP83867_SW_RESTART); if (err < 0) return err; usleep_range(10, 20); - /* After reset FORCE_LINK_GOOD bit is set. Although the - * default value should be unset. Disable FORCE_LINK_GOOD - * for the phy to work properly. - */ return phy_modify(phydev, MII_DP83867_PHYCTRL, DP83867_PHYCR_FORCE_LINK_GOOD, 0); } diff --git a/drivers/net/phy/mscc/mscc_macsec.c b/drivers/net/phy/mscc/mscc_macsec.c index 10be266e48e8b74f73a124111b132a086e055c05..b7b2521c73fb629b341ea89a48dc43fb6458d930 100644 --- a/drivers/net/phy/mscc/mscc_macsec.c +++ b/drivers/net/phy/mscc/mscc_macsec.c @@ -501,7 +501,7 @@ static u32 vsc8584_macsec_flow_context_id(struct macsec_flow *flow) } /* Derive the AES key to get a key for the hash autentication */ -static int vsc8584_macsec_derive_key(const u8 key[MACSEC_KEYID_LEN], +static int vsc8584_macsec_derive_key(const u8 key[MACSEC_MAX_KEY_LEN], u16 key_len, u8 hkey[16]) { const u8 input[AES_BLOCK_SIZE] = {0}; diff --git a/drivers/net/phy/mscc/mscc_macsec.h b/drivers/net/phy/mscc/mscc_macsec.h index 9c6d25e36de2a85b7007f363ef4ba92ec6a03c1f..453304bae778449dc1ee2a65d64910da97ee94c2 100644 --- a/drivers/net/phy/mscc/mscc_macsec.h +++ b/drivers/net/phy/mscc/mscc_macsec.h @@ -81,7 +81,7 @@ struct macsec_flow { /* Highest takes precedence [0..15] */ u8 priority; - u8 key[MACSEC_KEYID_LEN]; + u8 key[MACSEC_MAX_KEY_LEN]; union { struct macsec_rx_sa *rx_sa; diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index f5010f8ac1ec7278204a76038bf9123f5219b257..95e27fb7d2c10fa669384c178a1ee90b0d782674 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -6054,7 +6054,7 @@ static void rtl8152_get_strings(struct net_device *dev, u32 stringset, u8 *data) { switch (stringset) { case ETH_SS_STATS: - memcpy(data, *rtl8152_gstrings, sizeof(rtl8152_gstrings)); + memcpy(data, rtl8152_gstrings, sizeof(rtl8152_gstrings)); break; } } diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 286f836a53bfe80b7091c7aa523ba2b153ed7243..7d1f609306f94d311271c7080658e4c47debb327 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -660,6 +660,12 @@ static struct sk_buff *receive_small(struct net_device *dev, len -= vi->hdr_len; stats->bytes += len; + if (unlikely(len > GOOD_PACKET_LEN)) { + pr_debug("%s: rx error: len %u exceeds max size %d\n", + dev->name, len, GOOD_PACKET_LEN); + dev->stats.rx_length_errors++; + goto err_len; + } rcu_read_lock(); xdp_prog = rcu_dereference(rq->xdp_prog); if (xdp_prog) { @@ -763,6 +769,7 @@ err: err_xdp: rcu_read_unlock(); stats->xdp_drops++; +err_len: stats->drops++; put_page(page); xdp_xmit: @@ -816,6 +823,12 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, head_skb = NULL; stats->bytes += len - vi->hdr_len; + if (unlikely(len > truesize)) { + pr_debug("%s: rx error: len %u exceeds truesize %lu\n", + dev->name, len, (unsigned long)ctx); + dev->stats.rx_length_errors++; + goto err_skb; + } rcu_read_lock(); xdp_prog = rcu_dereference(rq->xdp_prog); if (xdp_prog) { @@ -943,13 +956,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev, } rcu_read_unlock(); - if (unlikely(len > truesize)) { - pr_debug("%s: rx error: len %u exceeds truesize %lu\n", - dev->name, len, (unsigned long)ctx); - dev->stats.rx_length_errors++; - goto err_skb; - } - head_skb = page_to_skb(vi, rq, page, offset, len, truesize, !xdp_prog, metasize); curr_skb = head_skb; @@ -1513,6 +1519,8 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget) struct virtnet_info *vi = sq->vq->vdev->priv; unsigned int index = vq2txq(sq->vq); struct netdev_queue *txq; + int opaque; + bool done; if (unlikely(is_xdp_raw_buffer_queue(vi, index))) { /* We don't need to enable cb for XDP */ @@ -1522,10 +1530,28 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget) txq = netdev_get_tx_queue(vi->dev, index); __netif_tx_lock(txq, raw_smp_processor_id()); + virtqueue_disable_cb(sq->vq); free_old_xmit_skbs(sq, true); + + opaque = virtqueue_enable_cb_prepare(sq->vq); + + done = napi_complete_done(napi, 0); + + if (!done) + virtqueue_disable_cb(sq->vq); + __netif_tx_unlock(txq); - virtqueue_napi_complete(napi, sq->vq, 0); + if (done) { + if (unlikely(virtqueue_poll(sq->vq, opaque))) { + if (napi_schedule_prep(napi)) { + __netif_tx_lock(txq, raw_smp_processor_id()); + virtqueue_disable_cb(sq->vq); + __netif_tx_unlock(txq); + __napi_schedule(napi); + } + } + } if (sq->vq->num_free >= 2 + MAX_SKB_FRAGS) netif_tx_wake_queue(txq); @@ -1557,7 +1583,7 @@ static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) if (virtio_net_hdr_from_skb(skb, &hdr->hdr, virtio_is_little_endian(vi->vdev), false, 0)) - BUG(); + return -EPROTO; if (vi->mergeable_rx_bufs) hdr->num_buffers = 0; @@ -3228,8 +3254,11 @@ static __maybe_unused int virtnet_restore(struct virtio_device *vdev) virtnet_set_queues(vi, vi->curr_queue_pairs); err = virtnet_cpu_notif_add(vi); - if (err) + if (err) { + virtnet_freeze_down(vdev); + remove_vq_common(vi); return err; + } return 0; } diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index bc96ac0c5769c75971ac788b1263fde2d4e0a129..2746f77745e4d8840fabeb7f6717bfed234fa724 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -1312,22 +1312,22 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev, int orig_iif = skb->skb_iif; bool need_strict = rt6_need_strict(&ipv6_hdr(skb)->daddr); bool is_ndisc = ipv6_ndisc_frame(skb); - bool is_ll_src; /* loopback, multicast & non-ND link-local traffic; do not push through * packet taps again. Reset pkt_type for upper layers to process skb. - * for packets with lladdr src, however, skip so that the dst can be - * determine at input using original ifindex in the case that daddr - * needs strict + * For strict packets with a source LLA, determine the dst using the + * original ifindex. */ - is_ll_src = ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL; - if (skb->pkt_type == PACKET_LOOPBACK || - (need_strict && !is_ndisc && !is_ll_src)) { + if (skb->pkt_type == PACKET_LOOPBACK || (need_strict && !is_ndisc)) { skb->dev = vrf_dev; skb->skb_iif = vrf_dev->ifindex; IP6CB(skb)->flags |= IP6SKB_L3SLAVE; + if (skb->pkt_type == PACKET_LOOPBACK) skb->pkt_type = PACKET_HOST; + else if (ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL) + vrf_ip6_input_dst(skb, vrf_dev, orig_iif); + goto out; } diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index d3b698d9e2e6a87474a857dd0eaa5e25977b6ae5..48fbdce6a70e7667040935a6567b7be8ac92e83e 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2163,6 +2163,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) struct neighbour *n; struct nd_msg *msg; + rcu_read_lock(); in6_dev = __in6_dev_get(dev); if (!in6_dev) goto out; @@ -2214,6 +2215,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) } out: + rcu_read_unlock(); consume_skb(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index f5c0f9bac8404369c980f9bbc35bc5701cf48f9f..36183fdfb7f03308a28cfa226f2a1e1108b24783 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -5482,6 +5482,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, if (arvif->nohwcrypt && !test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags)) { + ret = -EINVAL; ath10k_warn(ar, "cryptmode module param needed for sw crypto\n"); goto err; } diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 36426efdb2ea01b0e481efaa0aec6bbfbd37628b..86f52bcb3e4dbf1c0067c87c8ad1a1494f3ef472 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3684,8 +3684,10 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); if (bus_params.chip_id != 0xffffffff) { if (!ath10k_pci_chip_is_supported(pdev->device, - bus_params.chip_id)) + bus_params.chip_id)) { + ret = -ENODEV; goto err_unsupported; + } } } @@ -3696,11 +3698,15 @@ static int ath10k_pci_probe(struct pci_dev *pdev, } bus_params.chip_id = ath10k_pci_soc_read32(ar, SOC_CHIP_ID_ADDRESS); - if (bus_params.chip_id == 0xffffffff) + if (bus_params.chip_id == 0xffffffff) { + ret = -ENODEV; goto err_unsupported; + } - if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) - goto err_free_irq; + if (!ath10k_pci_chip_is_supported(pdev->device, bus_params.chip_id)) { + ret = -ENODEV; + goto err_unsupported; + } ret = ath10k_core_register(ar, &bus_params); if (ret) { diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index a68fe3a45a74450226d105643af97f2796ba3972..28de2c7ae89919a2ffad5bd72619d04c0e73e527 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -329,7 +329,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, if (len < ALIGN(ie_len, 4)) { ath11k_err(ab, "invalid length for board ie_id %d ie_len %zu len %zu\n", ie_id, ie_len, len); - return -EINVAL; + ret = -EINVAL; + goto err; } switch (ie_id) { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 0738c784616f15edfa87896666b8369be7678238..63d70aecbd0f1d49ea9c113aada52f7453720830 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -4603,13 +4603,13 @@ err_peer_del: if (ret) { ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", arvif->vdev_id, vif->addr); - return ret; + goto err; } ret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id, vif->addr); if (ret) - return ret; + goto err; ar->num_peers--; } @@ -5123,11 +5123,6 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, if (WARN_ON(!arvif->is_up)) continue; - ret = ath11k_mac_setup_bcn_tmpl(arvif); - if (ret) - ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", - ret); - ret = ath11k_mac_vdev_restart(arvif, &vifs[i].new_ctx->def); if (ret) { ath11k_warn(ab, "failed to restart vdev %d: %d\n", @@ -5135,6 +5130,11 @@ ath11k_mac_update_vif_chan(struct ath11k *ar, continue; } + ret = ath11k_mac_setup_bcn_tmpl(arvif); + if (ret) + ath11k_warn(ab, "failed to update bcn tmpl during csa: %d\n", + ret); + ret = ath11k_wmi_vdev_up(arvif->ar, arvif->vdev_id, arvif->aid, arvif->bssid); if (ret) { diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 8dbf68b94228c8a96661bd0ec6129089cca8070a..ac805f56627ab90b30fb74ce9dac74f8f824d8e9 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -307,6 +307,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) hchan = ah->curchan; } + if (!hchan) { + fastcc = false; + hchan = ath9k_cmn_get_channel(sc->hw, ah, &sc->cur_chan->chandef); + } + if (!ath_prepare_reset(sc)) fastcc = false; diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig index b2d760873992f26b89df97f495a6dfd3aa4bb583..ba9bea79381c57c4027de48e84c4d3e5d6a624db 100644 --- a/drivers/net/wireless/ath/carl9170/Kconfig +++ b/drivers/net/wireless/ath/carl9170/Kconfig @@ -16,13 +16,11 @@ config CARL9170 config CARL9170_LEDS bool "SoftLED Support" - depends on CARL9170 - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS default y + depends on CARL9170 + depends on MAC80211_LEDS help - This option is necessary, if you want your device' LEDs to blink + This option is necessary, if you want your device's LEDs to blink. Say Y, unless you need the LEDs for firmware debugging. diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 706728fba72d7d0534479c08a6b85b061bcc853c..9f8e44210e89ab700882cf98d403808f676f8c21 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -293,23 +293,16 @@ static int wcn36xx_start(struct ieee80211_hw *hw) goto out_free_dxe_pool; } - wcn->hal_buf = kmalloc(WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); - if (!wcn->hal_buf) { - wcn36xx_err("Failed to allocate smd buf\n"); - ret = -ENOMEM; - goto out_free_dxe_ctl; - } - ret = wcn36xx_smd_load_nv(wcn); if (ret) { wcn36xx_err("Failed to push NV to chip\n"); - goto out_free_smd_buf; + goto out_free_dxe_ctl; } ret = wcn36xx_smd_start(wcn); if (ret) { wcn36xx_err("Failed to start chip\n"); - goto out_free_smd_buf; + goto out_free_dxe_ctl; } if (!wcn36xx_is_fw_version(wcn, 1, 2, 2, 24)) { @@ -336,8 +329,6 @@ static int wcn36xx_start(struct ieee80211_hw *hw) out_smd_stop: wcn36xx_smd_stop(wcn); -out_free_smd_buf: - kfree(wcn->hal_buf); out_free_dxe_ctl: wcn36xx_dxe_free_ctl_blks(wcn); out_free_dxe_pool: @@ -372,8 +363,6 @@ static void wcn36xx_stop(struct ieee80211_hw *hw) wcn36xx_dxe_free_mem_pools(wcn); wcn36xx_dxe_free_ctl_blks(wcn); - - kfree(wcn->hal_buf); } static void wcn36xx_change_ps(struct wcn36xx *wcn, bool enable) @@ -1398,6 +1387,12 @@ static int wcn36xx_probe(struct platform_device *pdev) mutex_init(&wcn->hal_mutex); mutex_init(&wcn->scan_lock); + wcn->hal_buf = devm_kmalloc(wcn->dev, WCN36XX_HAL_BUF_SIZE, GFP_KERNEL); + if (!wcn->hal_buf) { + ret = -ENOMEM; + goto out_wq; + } + ret = dma_set_mask_and_coherent(wcn->dev, DMA_BIT_MASK(32)); if (ret < 0) { wcn36xx_err("failed to set DMA mask: %d\n", ret); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 23e6422c2251b3f87a2b32d2aeb811e96379ee39..c2b6e5c966d047caec06d1c2aac2fb846f480b98 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -2767,8 +2767,9 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_sta_info_le sta_info_le; u32 sta_flags; u32 is_tdls_peer; - s32 total_rssi; - s32 count_rssi; + s32 total_rssi_avg = 0; + s32 total_rssi = 0; + s32 count_rssi = 0; int rssi; u32 i; @@ -2834,25 +2835,27 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_BYTES); sinfo->rx_bytes = le64_to_cpu(sta_info_le.rx_tot_bytes); } - total_rssi = 0; - count_rssi = 0; for (i = 0; i < BRCMF_ANT_MAX; i++) { - if (sta_info_le.rssi[i]) { - sinfo->chain_signal_avg[count_rssi] = - sta_info_le.rssi[i]; - sinfo->chain_signal[count_rssi] = - sta_info_le.rssi[i]; - total_rssi += sta_info_le.rssi[i]; - count_rssi++; - } + if (sta_info_le.rssi[i] == 0 || + sta_info_le.rx_lastpkt_rssi[i] == 0) + continue; + sinfo->chains |= BIT(count_rssi); + sinfo->chain_signal[count_rssi] = + sta_info_le.rx_lastpkt_rssi[i]; + sinfo->chain_signal_avg[count_rssi] = + sta_info_le.rssi[i]; + total_rssi += sta_info_le.rx_lastpkt_rssi[i]; + total_rssi_avg += sta_info_le.rssi[i]; + count_rssi++; } if (count_rssi) { - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); - sinfo->chains = count_rssi; - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL); - total_rssi /= count_rssi; - sinfo->signal = total_rssi; + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL); + sinfo->filled |= + BIT_ULL(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); + sinfo->signal = total_rssi / count_rssi; + sinfo->signal_avg = total_rssi_avg / count_rssi; } else if (test_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state)) { memset(&scb_val, 0, sizeof(scb_val)); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c index 59c2b2b6027da00d259fe1aa8d4a26e3457d65bb..6d5d5c39c635960b7ab715b18d3a939a0615a7a2 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c @@ -4157,7 +4157,6 @@ static int brcmf_sdio_bus_reset(struct device *dev) if (ret) { brcmf_err("Failed to probe after sdio device reset: ret %d\n", ret); - brcmf_sdiod_remove(sdiodev); } return ret; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c index 818e523f6025d97cc9ac391cb6cb972e1fd9195f..fb76b4a69a059642ca49e7c64c1682e07c81d090 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/mac80211_if.c @@ -1221,6 +1221,7 @@ static int brcms_bcma_probe(struct bcma_device *pdev) { struct brcms_info *wl; struct ieee80211_hw *hw; + int ret; dev_info(&pdev->dev, "mfg %x core %x rev %d class %d irq %d\n", pdev->id.manuf, pdev->id.id, pdev->id.rev, pdev->id.class, @@ -1245,11 +1246,16 @@ static int brcms_bcma_probe(struct bcma_device *pdev) wl = brcms_attach(pdev); if (!wl) { pr_err("%s: brcms_attach failed!\n", __func__); - return -ENODEV; + ret = -ENODEV; + goto err_free_ieee80211; } brcms_led_register(wl); return 0; + +err_free_ieee80211: + ieee80211_free_hw(hw); + return ret; } static int brcms_suspend(struct bcma_device *pdev) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h index e4f91bce222d889824c6bdb38bf80f4c4ca4c70f..61d3d4e0b7d94cd84bcbd77dd16cf0c32da84ec0 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/pnvm.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */ /****************************************************************************** * - * Copyright(c) 2020 Intel Corporation + * Copyright(c) 2020-2021 Intel Corporation * *****************************************************************************/ @@ -10,7 +10,7 @@ #include "fw/notif-wait.h" -#define MVM_UCODE_PNVM_TIMEOUT (HZ / 10) +#define MVM_UCODE_PNVM_TIMEOUT (HZ / 4) int iwl_pnvm_load(struct iwl_trans *trans, struct iwl_notif_wait_data *notif_wait); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index d42165559df6e76ccc9edd13f5a3bb8d5db7a134..8cba923b1ec6c1ae8e1f2a8bc85e434efe4f6216 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -3794,6 +3794,7 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); struct cfg80211_chan_def chandef; struct iwl_mvm_phy_ctxt *phy_ctxt; + bool band_change_removal; int ret, i; IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value, @@ -3874,19 +3875,30 @@ static int iwl_mvm_roc(struct ieee80211_hw *hw, cfg80211_chandef_create(&chandef, channel, NL80211_CHAN_NO_HT); /* - * Change the PHY context configuration as it is currently referenced - * only by the P2P Device MAC + * Check if the remain-on-channel is on a different band and that + * requires context removal, see iwl_mvm_phy_ctxt_changed(). If + * so, we'll need to release and then re-configure here, since we + * must not remove a PHY context that's part of a binding. */ - if (mvmvif->phy_ctxt->ref == 1) { + band_change_removal = + fw_has_capa(&mvm->fw->ucode_capa, + IWL_UCODE_TLV_CAPA_BINDING_CDB_SUPPORT) && + mvmvif->phy_ctxt->channel->band != chandef.chan->band; + + if (mvmvif->phy_ctxt->ref == 1 && !band_change_removal) { + /* + * Change the PHY context configuration as it is currently + * referenced only by the P2P Device MAC (and we can modify it) + */ ret = iwl_mvm_phy_ctxt_changed(mvm, mvmvif->phy_ctxt, &chandef, 1, 1); if (ret) goto out_unlock; } else { /* - * The PHY context is shared with other MACs. Need to remove the - * P2P Device from the binding, allocate an new PHY context and - * create a new binding + * The PHY context is shared with other MACs (or we're trying to + * switch bands), so remove the P2P Device from the binding, + * allocate an new PHY context and create a new binding. */ phy_ctxt = iwl_mvm_get_free_phy_ctxt(mvm); if (!phy_ctxt) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c index 3939eccd3d5ac036008c6472d5d591afb2f80c2e..394598b14a17335ca0cae9c1057edb8cdde73cc0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/time-event.c @@ -345,6 +345,8 @@ static void iwl_mvm_te_handle_notif(struct iwl_mvm *mvm, * and know the dtim period. */ iwl_mvm_te_check_disconnect(mvm, te_data->vif, + !te_data->vif->bss_conf.assoc ? + "Not associated and the time event is over already..." : "No beacon heard and the time event is over already..."); break; default: @@ -843,6 +845,8 @@ void iwl_mvm_rx_session_protect_notif(struct iwl_mvm *mvm, * and know the dtim period. */ iwl_mvm_te_check_disconnect(mvm, vif, + !vif->bss_conf.assoc ? + "Not associated and the session protection is over already..." : "No beacon heard and the session protection is over already..."); spin_lock_bh(&mvm->time_event_lock); iwl_mvm_te_clear_data(mvm, te_data); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 7626117c01fa302a87aef10fcbaee31750370059..7186e1dbbd6b50dab22cfe4d04da223d16ac0504 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -1085,6 +1085,9 @@ static int iwl_mvm_tx_mpdu(struct iwl_mvm *mvm, struct sk_buff *skb, if (WARN_ON_ONCE(mvmsta->sta_id == IWL_MVM_INVALID_STA)) return -1; + if (unlikely(ieee80211_is_any_nullfunc(fc)) && sta->he_cap.has_he) + return -1; + if (unlikely(ieee80211_is_probe_resp(fc))) iwl_mvm_probe_resp_set_noa(mvm, skb); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index ec1d6025081de556e753ee5fa5211aa9ce7d0487..56f63f5f5dd34156b1cd07eedddf08c933e40fee 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -126,7 +126,6 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, struct iwl_prph_scratch *prph_scratch; struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl; struct iwl_prph_info *prph_info; - void *iml_img; u32 control_flags = 0; int ret; int cmdq_size = max_t(u32, IWL_CMD_QUEUE_SIZE, @@ -234,14 +233,15 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, trans_pcie->prph_scratch = prph_scratch; /* Allocate IML */ - iml_img = dma_alloc_coherent(trans->dev, trans->iml_len, - &trans_pcie->iml_dma_addr, GFP_KERNEL); - if (!iml_img) { + trans_pcie->iml = dma_alloc_coherent(trans->dev, trans->iml_len, + &trans_pcie->iml_dma_addr, + GFP_KERNEL); + if (!trans_pcie->iml) { ret = -ENOMEM; goto err_free_ctxt_info; } - memcpy(iml_img, trans->iml, trans->iml_len); + memcpy(trans_pcie->iml, trans->iml, trans->iml_len); iwl_enable_fw_load_int_ctx_info(trans); @@ -290,6 +290,11 @@ void iwl_pcie_ctxt_info_gen3_free(struct iwl_trans *trans) trans_pcie->ctxt_info_dma_addr = 0; trans_pcie->ctxt_info_gen3 = NULL; + dma_free_coherent(trans->dev, trans->iml_len, trans_pcie->iml, + trans_pcie->iml_dma_addr); + trans_pcie->iml_dma_addr = 0; + trans_pcie->iml = NULL; + iwl_pcie_ctxt_info_free_fw_img(trans); dma_free_coherent(trans->dev, sizeof(*trans_pcie->prph_scratch), diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index ff542d2f0054bcda19d258fb3f0818cc5aab3f10..f05025e8d11d5d51da74777e09175a7257c0266b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -336,6 +336,8 @@ struct cont_rec { * Context information addresses will be taken from here. * This is driver's local copy for keeping track of size and * count for allocating and freeing the memory. + * @iml: image loader image virtual address + * @iml_dma_addr: image loader image DMA address * @trans: pointer to the generic transport area * @scd_base_addr: scheduler sram base address in SRAM * @kw: keep warm address @@ -388,6 +390,7 @@ struct iwl_trans_pcie { }; struct iwl_prph_info *prph_info; struct iwl_prph_scratch *prph_scratch; + void *iml; dma_addr_t ctxt_info_dma_addr; dma_addr_t prph_info_dma_addr; dma_addr_t prph_scratch_dma_addr; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 4c3ca2a37696402dc483e35e20045e320a373102..b031e9304983c40ed32abf549576923e99150304 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -269,7 +269,8 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr) /* now that we got alive we can free the fw image & the context info. * paging memory cannot be freed included since FW will still use it */ - iwl_pcie_ctxt_info_free(trans); + if (trans->trans_cfg->device_family < IWL_DEVICE_FAMILY_AX210) + iwl_pcie_ctxt_info_free(trans); /* * Re-enable all the interrupts, including the RF-Kill one, now that diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 3b3fc7c9c91dc1b0f391d5fac0f74f8c691fd8a7..4ca0b06d09adde6587003b277154206d36b405da 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -557,6 +557,7 @@ struct mac80211_hwsim_data { u32 ciphers[ARRAY_SIZE(hwsim_ciphers)]; struct mac_address addresses[2]; + struct ieee80211_chanctx_conf *chanctx; int channels, idx; bool use_chanctx; bool destroy_on_close; @@ -1187,7 +1188,8 @@ static inline u16 trans_tx_rate_flags_ieee2hwsim(struct ieee80211_tx_rate *rate) static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, struct sk_buff *my_skb, - int dst_portid) + int dst_portid, + struct ieee80211_channel *channel) { struct sk_buff *skb; struct mac80211_hwsim_data *data = hw->priv; @@ -1242,7 +1244,7 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) goto nla_put_failure; - if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) + if (nla_put_u32(skb, HWSIM_ATTR_FREQ, channel->center_freq)) goto nla_put_failure; /* We get the tx control (rate and retries) info*/ @@ -1589,7 +1591,7 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, _portid = READ_ONCE(data->wmediumd); if (_portid || hwsim_virtio_enabled) - return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); + return mac80211_hwsim_tx_frame_nl(hw, skb, _portid, channel); /* NO wmediumd detected, perfect medium simulation */ data->tx_pkts++; @@ -1623,8 +1625,13 @@ static int mac80211_hwsim_start(struct ieee80211_hw *hw) static void mac80211_hwsim_stop(struct ieee80211_hw *hw) { struct mac80211_hwsim_data *data = hw->priv; + data->started = false; hrtimer_cancel(&data->beacon_timer); + + while (!skb_queue_empty(&data->pending)) + ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); + wiphy_dbg(hw->wiphy, "%s\n", __func__); } @@ -1700,7 +1707,7 @@ static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, mac80211_hwsim_monitor_rx(hw, skb, chan); if (_pid || hwsim_virtio_enabled) - return mac80211_hwsim_tx_frame_nl(hw, skb, _pid); + return mac80211_hwsim_tx_frame_nl(hw, skb, _pid, chan); mac80211_hwsim_tx_frame_no_nl(hw, skb, chan); dev_kfree_skb(skb); @@ -2439,6 +2446,11 @@ static int mac80211_hwsim_croc(struct ieee80211_hw *hw, static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + hwsim->chanctx = ctx; + mutex_unlock(&hwsim->mutex); hwsim_set_chanctx_magic(ctx); wiphy_dbg(hw->wiphy, "add channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", @@ -2450,6 +2462,11 @@ static int mac80211_hwsim_add_chanctx(struct ieee80211_hw *hw, static void mac80211_hwsim_remove_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx) { + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + hwsim->chanctx = NULL; + mutex_unlock(&hwsim->mutex); wiphy_dbg(hw->wiphy, "remove channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", ctx->def.chan->center_freq, ctx->def.width, @@ -2462,6 +2479,11 @@ static void mac80211_hwsim_change_chanctx(struct ieee80211_hw *hw, struct ieee80211_chanctx_conf *ctx, u32 changed) { + struct mac80211_hwsim_data *hwsim = hw->priv; + + mutex_lock(&hwsim->mutex); + hwsim->chanctx = ctx; + mutex_unlock(&hwsim->mutex); hwsim_check_chanctx_magic(ctx); wiphy_dbg(hw->wiphy, "change channel context control: %d MHz/width: %d/cfreqs:%d/%d MHz\n", @@ -3054,6 +3076,7 @@ static int mac80211_hwsim_new_radio(struct genl_info *info, hw->wiphy->max_remain_on_channel_duration = 1000; data->if_combination.radar_detect_widths = 0; data->if_combination.num_different_channels = data->channels; + data->chanctx = NULL; } else { data->if_combination.num_different_channels = 1; data->if_combination.radar_detect_widths = @@ -3561,6 +3584,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, int frame_data_len; void *frame_data; struct sk_buff *skb = NULL; + struct ieee80211_channel *channel = NULL; if (!info->attrs[HWSIM_ATTR_ADDR_RECEIVER] || !info->attrs[HWSIM_ATTR_FRAME] || @@ -3587,6 +3611,17 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, if (!data2) goto out; + if (data2->use_chanctx) { + if (data2->tmp_chan) + channel = data2->tmp_chan; + else if (data2->chanctx) + channel = data2->chanctx->def.chan; + } else { + channel = data2->channel; + } + if (!channel) + goto out; + if (!hwsim_virtio_enabled) { if (hwsim_net_get_netgroup(genl_info_net(info)) != data2->netgroup) @@ -3598,7 +3633,7 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, /* check if radio is configured properly */ - if (data2->idle || !data2->started) + if ((data2->idle && !data2->tmp_chan) || !data2->started) goto out; /* A frame is received from user space */ @@ -3611,18 +3646,16 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, mutex_lock(&data2->mutex); rx_status.freq = nla_get_u32(info->attrs[HWSIM_ATTR_FREQ]); - if (rx_status.freq != data2->channel->center_freq && - (!data2->tmp_chan || - rx_status.freq != data2->tmp_chan->center_freq)) { + if (rx_status.freq != channel->center_freq) { mutex_unlock(&data2->mutex); goto out; } mutex_unlock(&data2->mutex); } else { - rx_status.freq = data2->channel->center_freq; + rx_status.freq = channel->center_freq; } - rx_status.band = data2->channel->band; + rx_status.band = channel->band; rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); diff --git a/drivers/net/wireless/marvell/mwifiex/pcie.c b/drivers/net/wireless/marvell/mwifiex/pcie.c index 33cf952cc01d3a155910757413a07cf937864525..b2de8d03c5fac352778a3ee91e64e674b847aa22 100644 --- a/drivers/net/wireless/marvell/mwifiex/pcie.c +++ b/drivers/net/wireless/marvell/mwifiex/pcie.c @@ -1232,7 +1232,7 @@ static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter) { struct pcie_service_card *card = adapter->card; - u32 tmp; + u32 *cookie; card->sleep_cookie_vbase = dma_alloc_coherent(&card->dev->dev, sizeof(u32), @@ -1243,13 +1243,11 @@ static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter) "dma_alloc_coherent failed!\n"); return -ENOMEM; } + cookie = (u32 *)card->sleep_cookie_vbase; /* Init val of Sleep Cookie */ - tmp = FW_AWAKE_COOKIE; - put_unaligned(tmp, card->sleep_cookie_vbase); + *cookie = FW_AWAKE_COOKIE; - mwifiex_dbg(adapter, INFO, - "alloc_scook: sleep cookie=0x%x\n", - get_unaligned(card->sleep_cookie_vbase)); + mwifiex_dbg(adapter, INFO, "alloc_scook: sleep cookie=0x%x\n", *cookie); return 0; } diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 5795e44f8a52929661c85b52aa22e7e17d5e952e..f44f478bb970ea202d0adeff3f37b1a8d2047fd8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -1177,22 +1177,20 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, int first_idx = 0, last_idx; int i, idx, count; bool fixed_rate, ack_timeout; - bool probe, ampdu, cck = false; + bool ampdu, cck = false; bool rs_idx; u32 rate_set_tsf; u32 final_rate, final_rate_flags, final_nss, txs; - fixed_rate = info->status.rates[0].count; - probe = !!(info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE); - txs = le32_to_cpu(txs_data[1]); - ampdu = !fixed_rate && (txs & MT_TXS1_AMPDU); + ampdu = txs & MT_TXS1_AMPDU; txs = le32_to_cpu(txs_data[3]); count = FIELD_GET(MT_TXS3_TX_COUNT, txs); last_idx = FIELD_GET(MT_TXS3_LAST_TX_RATE, txs); txs = le32_to_cpu(txs_data[0]); + fixed_rate = txs & MT_TXS0_FIXED_RATE; final_rate = FIELD_GET(MT_TXS0_TX_RATE, txs); ack_timeout = txs & MT_TXS0_ACK_TIMEOUT; @@ -1214,7 +1212,7 @@ static bool mt7615_fill_txs(struct mt7615_dev *dev, struct mt7615_sta *sta, first_idx = max_t(int, 0, last_idx - (count - 1) / MT7615_RATE_RETRY); - if (fixed_rate && !probe) { + if (fixed_rate) { info->status.rates[0].count = count; i = 0; goto out; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c index 4cf7c5d343258cdbebcd20b704204e57273cb066..490d55651de390a458c70e870ea0d1e747cdae62 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c @@ -133,20 +133,21 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct mt76_tx_info *tx_info) { struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); - struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb); struct ieee80211_key_conf *key = info->control.hw_key; int pid, id; u8 *txwi = (u8 *)txwi_ptr; struct mt76_txwi_cache *t; + struct mt7615_sta *msta; void *txp; + msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL; if (!wcid) wcid = &dev->mt76.global_wcid; pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb); - if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) { + if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) { struct mt7615_phy *phy = &dev->phy; if ((info->hw_queue & MT_TX_HW_QUEUE_EXT_PHY) && mdev->phy2) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c index 3b29a6d3dc6412a04aebcdbfb20f412e00af0bf5..18082b4ce7d3dbdd3be3f18420940a895678f59a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -243,14 +243,15 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct ieee80211_sta *sta, struct mt76_tx_info *tx_info) { - struct mt7615_sta *msta = container_of(wcid, struct mt7615_sta, wcid); struct mt7615_dev *dev = container_of(mdev, struct mt7615_dev, mt76); struct sk_buff *skb = tx_info->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); + struct mt7615_sta *msta; int pad; + msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL; if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && - !msta->rate_probe) { + msta && !msta->rate_probe) { /* request to configure sampling rate */ spin_lock_bh(&dev->mt76.lock); mt7615_mac_set_rates(&dev->phy, msta, &info->control.rates[0], diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c index 0232b66acb4f993ad85276158256b708c3af7a33..8f01ca1694bca564faef7d3c776b11f786bf9cf8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -335,6 +335,9 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, if (nss < 2) return; + /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ + elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3; + if (vif != NL80211_IFTYPE_AP) return; @@ -348,9 +351,6 @@ mt7915_set_stream_he_txbf_caps(struct ieee80211_sta_he_cap *he_cap, c = IEEE80211_HE_PHY_CAP6_TRIG_SU_BEAMFORMER_FB | IEEE80211_HE_PHY_CAP6_TRIG_MU_BEAMFORMER_FB; elem->phy_cap_info[6] |= c; - - /* the maximum cap is 4 x 3, (Nr, Nc) = (3, 2) */ - elem->phy_cap_info[7] |= min_t(int, nss - 1, 2) << 3; } static void diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index 44ef4bc7a46e5bdd270c464db81e9cf7276dc066..073c29eb2ed8fc0c8d72148ce7e04104ea215f44 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -278,7 +278,7 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, skb_set_queue_mapping(skb, qid); } - if (!(wcid->tx_info & MT_WCID_TX_INFO_SET)) + if (wcid && !(wcid->tx_info & MT_WCID_TX_INFO_SET)) ieee80211_get_tx_rates(info->control.vif, sta, skb, info->control.rates, 1); diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h index d6d1be4169e5fe6a00ebc6f6789d521c9c4f65d6..acb6b0cd36672718dd274b4efe0eb08dd0a449b3 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu.h @@ -853,15 +853,10 @@ struct rtl8192eu_efuse { u8 usb_optional_function; u8 res9[2]; u8 mac_addr[ETH_ALEN]; /* 0xd7 */ - u8 res10[2]; - u8 vendor_name[7]; - u8 res11[2]; - u8 device_name[0x0b]; /* 0xe8 */ - u8 res12[2]; - u8 serial[0x0b]; /* 0xf5 */ - u8 res13[0x30]; + u8 device_info[80]; + u8 res11[3]; u8 unknown[0x0d]; /* 0x130 */ - u8 res14[0xc3]; + u8 res12[0xc3]; }; struct rtl8xxxu_reg8val { diff --git a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c index 9f1f93d04145d83ff29b8e9701d3578324383d39..199e7e031d7d90d8dc12be691b730d32424a6d39 100644 --- a/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c +++ b/drivers/net/wireless/realtek/rtl8xxxu/rtl8xxxu_8192e.c @@ -554,9 +554,43 @@ rtl8192e_set_tx_power(struct rtl8xxxu_priv *priv, int channel, bool ht40) } } +static void rtl8192eu_log_next_device_info(struct rtl8xxxu_priv *priv, + char *record_name, + char *device_info, + unsigned int *record_offset) +{ + char *record = device_info + *record_offset; + + /* A record is [ total length | 0x03 | value ] */ + unsigned char l = record[0]; + + /* + * The whole device info section seems to be 80 characters, make sure + * we don't read further. + */ + if (*record_offset + l > 80) { + dev_warn(&priv->udev->dev, + "invalid record length %d while parsing \"%s\" at offset %u.\n", + l, record_name, *record_offset); + return; + } + + if (l >= 2) { + char value[80]; + + memcpy(value, &record[2], l - 2); + value[l - 2] = '\0'; + dev_info(&priv->udev->dev, "%s: %s\n", record_name, value); + *record_offset = *record_offset + l; + } else { + dev_info(&priv->udev->dev, "%s not available.\n", record_name); + } +} + static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) { struct rtl8192eu_efuse *efuse = &priv->efuse_wifi.efuse8192eu; + unsigned int record_offset; int i; if (efuse->rtl_id != cpu_to_le16(0x8129)) @@ -604,12 +638,25 @@ static int rtl8192eu_parse_efuse(struct rtl8xxxu_priv *priv) priv->has_xtalk = 1; priv->xtalk = priv->efuse_wifi.efuse8192eu.xtal_k & 0x3f; - dev_info(&priv->udev->dev, "Vendor: %.7s\n", efuse->vendor_name); - dev_info(&priv->udev->dev, "Product: %.11s\n", efuse->device_name); - if (memchr_inv(efuse->serial, 0xff, 11)) - dev_info(&priv->udev->dev, "Serial: %.11s\n", efuse->serial); - else - dev_info(&priv->udev->dev, "Serial not available.\n"); + /* + * device_info section seems to be laid out as records + * [ total length | 0x03 | value ] so: + * - vendor length + 2 + * - 0x03 + * - vendor string (not null terminated) + * - product length + 2 + * - 0x03 + * - product string (not null terminated) + * Then there is one or 2 0x00 on all the 4 devices I own or found + * dumped online. + * As previous version of the code handled an optional serial + * string, I now assume there may be a third record if the + * length is not 0. + */ + record_offset = 0; + rtl8192eu_log_next_device_info(priv, "Vendor", efuse->device_info, &record_offset); + rtl8192eu_log_next_device_info(priv, "Product", efuse->device_info, &record_offset); + rtl8192eu_log_next_device_info(priv, "Serial", efuse->device_info, &record_offset); if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) { unsigned char *raw = priv->efuse_wifi.raw; diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index b718f5d810be8ed71cb89b36b26a281928b31c86..79ad6232dce8303353548ce52c5b4f2dde9018c8 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3510,26 +3510,28 @@ static void rtw8822c_pwrtrack_set(struct rtw_dev *rtwdev, u8 rf_path) } } -static void rtw8822c_pwr_track_path(struct rtw_dev *rtwdev, - struct rtw_swing_table *swing_table, - u8 path) +static void rtw8822c_pwr_track_stats(struct rtw_dev *rtwdev, u8 path) { - struct rtw_dm_info *dm_info = &rtwdev->dm_info; - u8 thermal_value, delta; + u8 thermal_value; if (rtwdev->efuse.thermal_meter[path] == 0xff) return; thermal_value = rtw_read_rf(rtwdev, path, RF_T_METER, 0x7e); - rtw_phy_pwrtrack_avg(rtwdev, thermal_value, path); +} - delta = rtw_phy_pwrtrack_get_delta(rtwdev, path); +static void rtw8822c_pwr_track_path(struct rtw_dev *rtwdev, + struct rtw_swing_table *swing_table, + u8 path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 delta; + delta = rtw_phy_pwrtrack_get_delta(rtwdev, path); dm_info->delta_power_index[path] = rtw_phy_pwrtrack_get_pwridx(rtwdev, swing_table, path, path, delta); - rtw8822c_pwrtrack_set(rtwdev, path); } @@ -3540,12 +3542,12 @@ static void __rtw8822c_pwr_track(struct rtw_dev *rtwdev) rtw_phy_config_swing_table(rtwdev, &swing_table); + for (i = 0; i < rtwdev->hal.rf_path_num; i++) + rtw8822c_pwr_track_stats(rtwdev, i); if (rtw_phy_pwrtrack_need_lck(rtwdev)) rtw8822c_do_lck(rtwdev); - for (i = 0; i < rtwdev->hal.rf_path_num; i++) rtw8822c_pwr_track_path(rtwdev, &swing_table, i); - } static void rtw8822c_pwr_track(struct rtw_dev *rtwdev) diff --git a/drivers/net/wireless/rsi/rsi_91x_hal.c b/drivers/net/wireless/rsi/rsi_91x_hal.c index ce9892152f4d4089075645bf47a4dfbc7c3d32e9..99b21a2c83861da4e69374873dd53a6246337651 100644 --- a/drivers/net/wireless/rsi/rsi_91x_hal.c +++ b/drivers/net/wireless/rsi/rsi_91x_hal.c @@ -203,7 +203,7 @@ int rsi_prepare_data_desc(struct rsi_common *common, struct sk_buff *skb) wh->frame_control |= cpu_to_le16(RSI_SET_PS_ENABLE); if ((!(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) && - (common->secinfo.security_enable)) { + info->control.hw_key) { if (rsi_is_cipher_wep(common)) ieee80211_size += 4; else @@ -470,9 +470,9 @@ int rsi_prepare_beacon(struct rsi_common *common, struct sk_buff *skb) } if (common->band == NL80211_BAND_2GHZ) - bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_1); + bcn_frm->rate_info |= cpu_to_le16(RSI_RATE_1); else - bcn_frm->bbp_info |= cpu_to_le16(RSI_RATE_6); + bcn_frm->rate_info |= cpu_to_le16(RSI_RATE_6); if (mac_bcn->data[tim_offset + 2] == 0) bcn_frm->frame_info |= cpu_to_le16(RSI_DATA_DESC_DTIM_BEACON); diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c index 16025300cddb37e90c3783a3d2cf183d9febfee1..57c9e3559dfd1916897c35e0a870c72a4076c4e9 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c +++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c @@ -1028,7 +1028,6 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, mutex_lock(&common->mutex); switch (cmd) { case SET_KEY: - secinfo->security_enable = true; status = rsi_hal_key_config(hw, vif, key, sta); if (status) { mutex_unlock(&common->mutex); @@ -1047,8 +1046,6 @@ static int rsi_mac80211_set_key(struct ieee80211_hw *hw, break; case DISABLE_KEY: - if (vif->type == NL80211_IFTYPE_STATION) - secinfo->security_enable = false; rsi_dbg(ERR_ZONE, "%s: RSI del key\n", __func__); memset(key, 0, sizeof(struct ieee80211_key_conf)); status = rsi_hal_key_config(hw, vif, key, sta); diff --git a/drivers/net/wireless/rsi/rsi_91x_mgmt.c b/drivers/net/wireless/rsi/rsi_91x_mgmt.c index 33c76d39a8e965aa17acd88313de9f6f718ea4ac..b6d050a2fbe7e84ed1fee1419572783a0bb18c32 100644 --- a/drivers/net/wireless/rsi/rsi_91x_mgmt.c +++ b/drivers/net/wireless/rsi/rsi_91x_mgmt.c @@ -1803,8 +1803,7 @@ int rsi_send_wowlan_request(struct rsi_common *common, u16 flags, RSI_WIFI_MGMT_Q); cmd_frame->desc.desc_dword0.frame_type = WOWLAN_CONFIG_PARAMS; cmd_frame->host_sleep_status = sleep_status; - if (common->secinfo.security_enable && - common->secinfo.gtk_cipher) + if (common->secinfo.gtk_cipher) flags |= RSI_WOW_GTK_REKEY; if (sleep_status) cmd_frame->wow_flags = flags; diff --git a/drivers/net/wireless/rsi/rsi_main.h b/drivers/net/wireless/rsi/rsi_main.h index 73a19e43106b1efe62eddb72143dcb2a3474bcc3..b3e25bc28682c751b507af49b67547bbb5573558 100644 --- a/drivers/net/wireless/rsi/rsi_main.h +++ b/drivers/net/wireless/rsi/rsi_main.h @@ -151,7 +151,6 @@ enum edca_queue { }; struct security_info { - bool security_enable; u32 ptk_cipher; u32 gtk_cipher; }; diff --git a/drivers/net/wireless/st/cw1200/cw1200_sdio.c b/drivers/net/wireless/st/cw1200/cw1200_sdio.c index b65ec14136c7ee7c1818710f78cab01b80a59669..4c30b5772ce0fea4efbab998f8dcdb2798c12aa9 100644 --- a/drivers/net/wireless/st/cw1200/cw1200_sdio.c +++ b/drivers/net/wireless/st/cw1200/cw1200_sdio.c @@ -53,6 +53,7 @@ static const struct sdio_device_id cw1200_sdio_ids[] = { { SDIO_DEVICE(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200) }, { /* end: all zeroes */ }, }; +MODULE_DEVICE_TABLE(sdio, cw1200_sdio_ids); /* hwbus_ops implemetation */ diff --git a/drivers/net/wireless/st/cw1200/scan.c b/drivers/net/wireless/st/cw1200/scan.c index 988581cc134b7cf7f0bcdb4098bac7a5d4f764e0..1f856fbbc0ea4ba204db4ab95c86361f1dcf25b1 100644 --- a/drivers/net/wireless/st/cw1200/scan.c +++ b/drivers/net/wireless/st/cw1200/scan.c @@ -75,30 +75,27 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) return -EINVAL; - /* will be unlocked in cw1200_scan_work() */ - down(&priv->scan.lock); - mutex_lock(&priv->conf_mutex); - frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0, req->ie_len); - if (!frame.skb) { - mutex_unlock(&priv->conf_mutex); - up(&priv->scan.lock); + if (!frame.skb) return -ENOMEM; - } if (req->ie_len) skb_put_data(frame.skb, req->ie, req->ie_len); + /* will be unlocked in cw1200_scan_work() */ + down(&priv->scan.lock); + mutex_lock(&priv->conf_mutex); + ret = wsm_set_template_frame(priv, &frame); if (!ret) { /* Host want to be the probe responder. */ ret = wsm_set_probe_responder(priv, true); } if (ret) { - dev_kfree_skb(frame.skb); mutex_unlock(&priv->conf_mutex); up(&priv->scan.lock); + dev_kfree_skb(frame.skb); return ret; } @@ -120,8 +117,8 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, ++priv->scan.n_ssids; } - dev_kfree_skb(frame.skb); mutex_unlock(&priv->conf_mutex); + dev_kfree_skb(frame.skb); queue_work(priv->workqueue, &priv->scan.work); return 0; } diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c index 9547aea01b0fbd3be677a7b524d287f444af826f..ea0215246c5c835239f3af77334b98b06fda102f 100644 --- a/drivers/net/wireless/ti/wl1251/cmd.c +++ b/drivers/net/wireless/ti/wl1251/cmd.c @@ -466,9 +466,12 @@ int wl1251_cmd_scan(struct wl1251 *wl, u8 *ssid, size_t ssid_len, cmd->channels[i].channel = channels[i]->hw_value; } - cmd->params.ssid_len = ssid_len; - if (ssid) - memcpy(cmd->params.ssid, ssid, ssid_len); + if (ssid) { + int len = clamp_val(ssid_len, 0, IEEE80211_MAX_SSID_LEN); + + cmd->params.ssid_len = len; + memcpy(cmd->params.ssid, ssid, len); + } ret = wl1251_cmd_send(wl, CMD_SCAN, cmd, sizeof(*cmd)); if (ret < 0) { diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 9d7dbfe7fe0c328cce76553669c6c02e4bf46f7d..c6da0cfb4afbe7683856515871f092c652af17ec 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1503,6 +1503,13 @@ static int wl12xx_get_fuse_mac(struct wl1271 *wl) u32 mac1, mac2; int ret; + /* Device may be in ELP from the bootloader or kexec */ + ret = wlcore_write32(wl, WL12XX_WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); + if (ret < 0) + goto out; + + usleep_range(500000, 700000); + ret = wlcore_set_partition(wl, &wl->ptable[PART_DRPW]); if (ret < 0) goto out; diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index c1f3446216c5cecd62292e8909adf2849061ee00..3f05df98697d3be90e1d39cbe6f70a11b9ee48ae 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -1027,7 +1027,7 @@ static inline void nvme_handle_cqe(struct nvme_queue *nvmeq, u16 idx) static inline void nvme_update_cq_head(struct nvme_queue *nvmeq) { - u16 tmp = nvmeq->cq_head + 1; + u32 tmp = nvmeq->cq_head + 1; if (tmp == nvmeq->q_depth) { nvmeq->cq_head = 0; @@ -2836,10 +2836,7 @@ static unsigned long check_vendor_combination_bug(struct pci_dev *pdev) #ifdef CONFIG_ACPI static bool nvme_acpi_storage_d3(struct pci_dev *dev) { - struct acpi_device *adev; - struct pci_dev *root; - acpi_handle handle; - acpi_status status; + struct acpi_device *adev = ACPI_COMPANION(&dev->dev); u8 val; /* @@ -2847,28 +2844,9 @@ static bool nvme_acpi_storage_d3(struct pci_dev *dev) * must use D3 to support deep platform power savings during * suspend-to-idle. */ - root = pcie_find_root_port(dev); - if (!root) - return false; - adev = ACPI_COMPANION(&root->dev); if (!adev) return false; - - /* - * The property is defined in the PXSX device for South complex ports - * and in the PEGP device for North complex ports. - */ - status = acpi_get_handle(adev->handle, "PXSX", &handle); - if (ACPI_FAILURE(status)) { - status = acpi_get_handle(adev->handle, "PEGP", &handle); - if (ACPI_FAILURE(status)) - return false; - } - - if (acpi_bus_get_device(handle, &adev)) - return false; - if (fwnode_property_read_u8(acpi_fwnode_handle(adev), "StorageD3Enable", &val)) return false; diff --git a/drivers/nvme/target/fc.c b/drivers/nvme/target/fc.c index cd4e73aa98074e85e00004a36672e5c928af9b92..640031cbda7cc6b4171fa724b7c0a4448d7d4588 100644 --- a/drivers/nvme/target/fc.c +++ b/drivers/nvme/target/fc.c @@ -2499,13 +2499,6 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, u32 xfrlen = be32_to_cpu(cmdiu->data_len); int ret; - /* - * if there is no nvmet mapping to the targetport there - * shouldn't be requests. just terminate them. - */ - if (!tgtport->pe) - goto transport_error; - /* * Fused commands are currently not supported in the linux * implementation. @@ -2533,7 +2526,8 @@ nvmet_fc_handle_fcp_rqst(struct nvmet_fc_tgtport *tgtport, fod->req.cmd = &fod->cmdiubuf.sqe; fod->req.cqe = &fod->rspiubuf.cqe; - fod->req.port = tgtport->pe->port; + if (tgtport->pe) + fod->req.port = tgtport->pe->port; /* clear any response payload */ memset(&fod->rspiubuf, 0, sizeof(fod->rspiubuf)); diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 4df4f37e6b895ddd17a52e4517855bdcab8c585a..dedcb7aaf0d822318ddcd703672a6518bf490e20 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -1467,7 +1467,6 @@ static void nvmet_tcp_state_change(struct sock *sk) case TCP_CLOSE_WAIT: case TCP_CLOSE: /* FALLTHRU */ - sk->sk_user_data = NULL; nvmet_tcp_schedule_release_queue(queue); break; default: diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 9b6ab83956c3b7ac948961d3b055d3a1c0588341..bb8fb2b3711d43cea971bb33824de40efd886951 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -549,15 +549,17 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) continue; if (len < 2 * sizeof(u32)) { dev_err(dev, "nvmem: invalid reg on %pOF\n", child); + of_node_put(child); return -EINVAL; } cell = kzalloc(sizeof(*cell), GFP_KERNEL); - if (!cell) + if (!cell) { + of_node_put(child); return -ENOMEM; + } cell->nvmem = nvmem; - cell->np = of_node_get(child); cell->offset = be32_to_cpup(addr++); cell->bytes = be32_to_cpup(addr); cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); @@ -578,11 +580,12 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem) cell->name, nvmem->stride); /* Cells already added will be freed later. */ kfree_const(cell->name); - of_node_put(cell->np); kfree(cell); + of_node_put(child); return -EINVAL; } + cell->np = of_node_get(child); nvmem_cell_add(cell); } diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index f2e697000b96f8b457f0a33d115822b57db05037..57ff31b6b1e47fb2bcfbf6b7d8c179830f5c117c 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -501,11 +501,11 @@ static int __init __reserved_mem_reserve_reg(unsigned long node, if (size && early_init_dt_reserve_memory_arch(base, size, nomap) == 0) - pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %ld MiB\n", - uname, &base, (unsigned long)size / SZ_1M); + pr_debug("Reserved memory: reserved region for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); else - pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %ld MiB\n", - uname, &base, (unsigned long)size / SZ_1M); + pr_info("Reserved memory: failed to reserve memory for node '%s': base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); len -= t_len; if (first) { diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index e144cce212122d10c1a72ef5eca47b0ac60d3e14..dea8c4fc4676426be8587e2fc76ac4b76de54720 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -153,9 +153,9 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ret = early_init_dt_alloc_reserved_memory_arch(node, size, align, start, end, nomap, &base); if (ret == 0) { - pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n", + pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n", uname, &base, - (unsigned long)size / SZ_1M); + (unsigned long)(size / SZ_1M)); break; } len -= t_len; @@ -165,8 +165,8 @@ static int __init __reserved_mem_alloc_size(unsigned long node, ret = early_init_dt_alloc_reserved_memory_arch(node, size, align, 0, 0, nomap, &base); if (ret == 0) - pr_debug("allocated memory for '%s' node: base %pa, size %ld MiB\n", - uname, &base, (unsigned long)size / SZ_1M); + pr_debug("allocated memory for '%s' node: base %pa, size %lu MiB\n", + uname, &base, (unsigned long)(size / SZ_1M)); } if (base == 0) { diff --git a/drivers/pci/controller/dwc/pcie-intel-gw.c b/drivers/pci/controller/dwc/pcie-intel-gw.c index 5650cb78acbad31ceb492279302567b11f6e5087..5e1a284fdc538eb80381286f19d0f507af8b7417 100644 --- a/drivers/pci/controller/dwc/pcie-intel-gw.c +++ b/drivers/pci/controller/dwc/pcie-intel-gw.c @@ -39,6 +39,10 @@ #define PCIE_APP_IRN_PM_TO_ACK BIT(9) #define PCIE_APP_IRN_LINK_AUTO_BW_STAT BIT(11) #define PCIE_APP_IRN_BW_MGT BIT(12) +#define PCIE_APP_IRN_INTA BIT(13) +#define PCIE_APP_IRN_INTB BIT(14) +#define PCIE_APP_IRN_INTC BIT(15) +#define PCIE_APP_IRN_INTD BIT(16) #define PCIE_APP_IRN_MSG_LTR BIT(18) #define PCIE_APP_IRN_SYS_ERR_RC BIT(29) #define PCIE_APP_INTX_OFST 12 @@ -48,10 +52,8 @@ PCIE_APP_IRN_RX_VDM_MSG | PCIE_APP_IRN_SYS_ERR_RC | \ PCIE_APP_IRN_PM_TO_ACK | PCIE_APP_IRN_MSG_LTR | \ PCIE_APP_IRN_BW_MGT | PCIE_APP_IRN_LINK_AUTO_BW_STAT | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTA) | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTB) | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTC) | \ - (PCIE_APP_INTX_OFST + PCI_INTERRUPT_INTD)) + PCIE_APP_IRN_INTA | PCIE_APP_IRN_INTB | \ + PCIE_APP_IRN_INTC | PCIE_APP_IRN_INTD) #define BUS_IATU_OFFSET SZ_256M #define RESET_INTERVAL_MS 100 diff --git a/drivers/pci/controller/dwc/pcie-tegra194.c b/drivers/pci/controller/dwc/pcie-tegra194.c index d788f4d7f9aa3f57fd4bc306a10d96f2c0cd79e5..506f6a294eac3c024722b909c47e9bf21150891c 100644 --- a/drivers/pci/controller/dwc/pcie-tegra194.c +++ b/drivers/pci/controller/dwc/pcie-tegra194.c @@ -1841,7 +1841,7 @@ static int tegra_pcie_ep_raise_msi_irq(struct tegra_pcie_dw *pcie, u16 irq) if (unlikely(irq > 31)) return -EINVAL; - appl_writel(pcie, (1 << irq), APPL_MSI_CTRL_1); + appl_writel(pcie, BIT(irq), APPL_MSI_CTRL_1); return 0; } diff --git a/drivers/pci/controller/pci-aardvark.c b/drivers/pci/controller/pci-aardvark.c index 41be72c74e3a4c05b7982a32cf73c63ae55d5bbc..b1b41b61e0bd003daa651b9d0e3956712a02401a 100644 --- a/drivers/pci/controller/pci-aardvark.c +++ b/drivers/pci/controller/pci-aardvark.c @@ -56,7 +56,7 @@ #define PIO_COMPLETION_STATUS_UR 1 #define PIO_COMPLETION_STATUS_CRS 2 #define PIO_COMPLETION_STATUS_CA 4 -#define PIO_NON_POSTED_REQ BIT(0) +#define PIO_NON_POSTED_REQ BIT(10) #define PIO_ADDR_LS (PIO_BASE_ADDR + 0x8) #define PIO_ADDR_MS (PIO_BASE_ADDR + 0xc) #define PIO_WR_DATA (PIO_BASE_ADDR + 0x10) @@ -124,6 +124,7 @@ #define LTSSM_MASK 0x3f #define LTSSM_L0 0x10 #define RC_BAR_CONFIG 0x300 +#define VENDOR_ID_REG (LMI_BASE_ADDR + 0x44) /* PCIe core controller registers */ #define CTRL_CORE_BASE_ADDR 0x18000 @@ -385,6 +386,16 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie) reg |= (IS_RC_MSK << IS_RC_SHIFT); advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG); + /* + * Replace incorrect PCI vendor id value 0x1b4b by correct value 0x11ab. + * VENDOR_ID_REG contains vendor id in low 16 bits and subsystem vendor + * id in high 16 bits. Updating this register changes readback value of + * read-only vendor id bits in PCIE_CORE_DEV_ID_REG register. Workaround + * for erratum 4.1: "The value of device and vendor ID is incorrect". + */ + reg = (PCI_VENDOR_ID_MARVELL << 16) | PCI_VENDOR_ID_MARVELL; + advk_writel(pcie, reg, VENDOR_ID_REG); + /* Set Advanced Error Capabilities and Control PF0 register */ reg = PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX | PCIE_CORE_ERR_CAPCTL_ECRC_CHK_TX_EN | diff --git a/drivers/pci/controller/pci-ftpci100.c b/drivers/pci/controller/pci-ftpci100.c index da3cd216da0078edc7b17471a67f1fa845020710..aefef1986201acae7c09d69f8bf47aee3b7be160 100644 --- a/drivers/pci/controller/pci-ftpci100.c +++ b/drivers/pci/controller/pci-ftpci100.c @@ -34,12 +34,12 @@ * Special configuration registers directly in the first few words * in I/O space. */ -#define PCI_IOSIZE 0x00 -#define PCI_PROT 0x04 /* AHB protection */ -#define PCI_CTRL 0x08 /* PCI control signal */ -#define PCI_SOFTRST 0x10 /* Soft reset counter and response error enable */ -#define PCI_CONFIG 0x28 /* PCI configuration command register */ -#define PCI_DATA 0x2C +#define FTPCI_IOSIZE 0x00 +#define FTPCI_PROT 0x04 /* AHB protection */ +#define FTPCI_CTRL 0x08 /* PCI control signal */ +#define FTPCI_SOFTRST 0x10 /* Soft reset counter and response error enable */ +#define FTPCI_CONFIG 0x28 /* PCI configuration command register */ +#define FTPCI_DATA 0x2C #define FARADAY_PCI_STATUS_CMD 0x04 /* Status and command */ #define FARADAY_PCI_PMC 0x40 /* Power management control */ @@ -195,9 +195,9 @@ static int faraday_raw_pci_read_config(struct faraday_pci *p, int bus_number, PCI_CONF_FUNCTION(PCI_FUNC(fn)) | PCI_CONF_WHERE(config) | PCI_CONF_ENABLE, - p->base + PCI_CONFIG); + p->base + FTPCI_CONFIG); - *value = readl(p->base + PCI_DATA); + *value = readl(p->base + FTPCI_DATA); if (size == 1) *value = (*value >> (8 * (config & 3))) & 0xFF; @@ -230,17 +230,17 @@ static int faraday_raw_pci_write_config(struct faraday_pci *p, int bus_number, PCI_CONF_FUNCTION(PCI_FUNC(fn)) | PCI_CONF_WHERE(config) | PCI_CONF_ENABLE, - p->base + PCI_CONFIG); + p->base + FTPCI_CONFIG); switch (size) { case 4: - writel(value, p->base + PCI_DATA); + writel(value, p->base + FTPCI_DATA); break; case 2: - writew(value, p->base + PCI_DATA + (config & 3)); + writew(value, p->base + FTPCI_DATA + (config & 3)); break; case 1: - writeb(value, p->base + PCI_DATA + (config & 3)); + writeb(value, p->base + FTPCI_DATA + (config & 3)); break; default: ret = PCIBIOS_BAD_REGISTER_NUMBER; @@ -469,7 +469,7 @@ static int faraday_pci_probe(struct platform_device *pdev) if (!faraday_res_to_memcfg(io->start - win->offset, resource_size(io), &val)) { /* setup I/O space size */ - writel(val, p->base + PCI_IOSIZE); + writel(val, p->base + FTPCI_IOSIZE); } else { dev_err(dev, "illegal IO mem size\n"); return -EINVAL; @@ -477,11 +477,11 @@ static int faraday_pci_probe(struct platform_device *pdev) } /* Setup hostbridge */ - val = readl(p->base + PCI_CTRL); + val = readl(p->base + FTPCI_CTRL); val |= PCI_COMMAND_IO; val |= PCI_COMMAND_MEMORY; val |= PCI_COMMAND_MASTER; - writel(val, p->base + PCI_CTRL); + writel(val, p->base + FTPCI_CTRL); /* Mask and clear all interrupts */ faraday_raw_pci_write_config(p, 0, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000); if (variant->cascaded_irq) { diff --git a/drivers/pci/controller/pci-hyperv.c b/drivers/pci/controller/pci-hyperv.c index 03ed5cb1c4b25224b7175fe7fca4dbe1745e1527..44e15f0e3a2edc580d1169c2e8c98c3d930aa8e1 100644 --- a/drivers/pci/controller/pci-hyperv.c +++ b/drivers/pci/controller/pci-hyperv.c @@ -444,7 +444,6 @@ enum hv_pcibus_state { hv_pcibus_probed, hv_pcibus_installed, hv_pcibus_removing, - hv_pcibus_removed, hv_pcibus_maximum }; @@ -3247,8 +3246,9 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) struct pci_packet teardown_packet; u8 buffer[sizeof(struct pci_message)]; } pkt; - struct hv_dr_state *dr; struct hv_pci_compl comp_pkt; + struct hv_pci_dev *hpdev, *tmp; + unsigned long flags; int ret; /* @@ -3260,9 +3260,16 @@ static int hv_pci_bus_exit(struct hv_device *hdev, bool keep_devs) if (!keep_devs) { /* Delete any children which might still exist. */ - dr = kzalloc(sizeof(*dr), GFP_KERNEL); - if (dr && hv_pci_start_relations_work(hbus, dr)) - kfree(dr); + spin_lock_irqsave(&hbus->device_list_lock, flags); + list_for_each_entry_safe(hpdev, tmp, &hbus->children, list_entry) { + list_del(&hpdev->list_entry); + if (hpdev->pci_slot) + pci_destroy_slot(hpdev->pci_slot); + /* For the two refs got in new_pcichild_device() */ + put_pcichild(hpdev); + put_pcichild(hpdev); + } + spin_unlock_irqrestore(&hbus->device_list_lock, flags); } ret = hv_send_resources_released(hdev); @@ -3305,13 +3312,23 @@ static int hv_pci_remove(struct hv_device *hdev) hbus = hv_get_drvdata(hdev); if (hbus->state == hv_pcibus_installed) { + tasklet_disable(&hdev->channel->callback_event); + hbus->state = hv_pcibus_removing; + tasklet_enable(&hdev->channel->callback_event); + destroy_workqueue(hbus->wq); + hbus->wq = NULL; + /* + * At this point, no work is running or can be scheduled + * on hbus-wq. We can't race with hv_pci_devices_present() + * or hv_pci_eject_device(), it's safe to proceed. + */ + /* Remove the bus from PCI's point of view. */ pci_lock_rescan_remove(); pci_stop_root_bus(hbus->pci_bus); hv_pci_remove_slots(hbus); pci_remove_root_bus(hbus->pci_bus); pci_unlock_rescan_remove(); - hbus->state = hv_pcibus_removed; } ret = hv_pci_bus_exit(hdev, false); @@ -3326,7 +3343,6 @@ static int hv_pci_remove(struct hv_device *hdev) irq_domain_free_fwnode(hbus->sysdata.fwnode); put_hvpcibus(hbus); wait_for_completion(&hbus->remove_event); - destroy_workqueue(hbus->wq); hv_put_dom_num(hbus->sysdata.domain); @@ -3480,6 +3496,9 @@ static void __exit exit_hv_pci_drv(void) static int __init init_hv_pci_drv(void) { + if (!hv_is_hyperv_initialized()) + return -ENODEV; + /* Set the invalid domain number's bit, so it will not be used */ set_bit(HVPCI_DOM_INVALID, hvpci_dom_map); diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index 8fcabed7c6a676c71118a0e8d58dbcb8183b6bd9..1a2af963599ca069b3c35d564a9b18a69930e004 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -2506,6 +2506,7 @@ static const struct of_device_id tegra_pcie_of_match[] = { { .compatible = "nvidia,tegra20-pcie", .data = &tegra20_pcie }, { }, }; +MODULE_DEVICE_TABLE(of, tegra_pcie_of_match); static void *tegra_pcie_ports_seq_start(struct seq_file *s, loff_t *pos) { diff --git a/drivers/pci/controller/pcie-iproc-msi.c b/drivers/pci/controller/pcie-iproc-msi.c index eede4e8f3f75afdddb40cc316e09a0ee1159145f..81b4effeb1309ddc10d001cc9e19073c248d0a36 100644 --- a/drivers/pci/controller/pcie-iproc-msi.c +++ b/drivers/pci/controller/pcie-iproc-msi.c @@ -171,7 +171,7 @@ static struct irq_chip iproc_msi_irq_chip = { static struct msi_domain_info iproc_msi_domain_info = { .flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | - MSI_FLAG_MULTI_PCI_MSI | MSI_FLAG_PCI_MSIX, + MSI_FLAG_PCI_MSIX, .chip = &iproc_msi_irq_chip, }; @@ -250,20 +250,23 @@ static int iproc_msi_irq_domain_alloc(struct irq_domain *domain, struct iproc_msi *msi = domain->host_data; int hwirq, i; + if (msi->nr_cpus > 1 && nr_irqs > 1) + return -EINVAL; + mutex_lock(&msi->bitmap_lock); - /* Allocate 'nr_cpus' number of MSI vectors each time */ - hwirq = bitmap_find_next_zero_area(msi->bitmap, msi->nr_msi_vecs, 0, - msi->nr_cpus, 0); - if (hwirq < msi->nr_msi_vecs) { - bitmap_set(msi->bitmap, hwirq, msi->nr_cpus); - } else { - mutex_unlock(&msi->bitmap_lock); - return -ENOSPC; - } + /* + * Allocate 'nr_irqs' multiplied by 'nr_cpus' number of MSI vectors + * each time + */ + hwirq = bitmap_find_free_region(msi->bitmap, msi->nr_msi_vecs, + order_base_2(msi->nr_cpus * nr_irqs)); mutex_unlock(&msi->bitmap_lock); + if (hwirq < 0) + return -ENOSPC; + for (i = 0; i < nr_irqs; i++) { irq_domain_set_info(domain, virq + i, hwirq + i, &iproc_msi_bottom_irq_chip, @@ -284,7 +287,8 @@ static void iproc_msi_irq_domain_free(struct irq_domain *domain, mutex_lock(&msi->bitmap_lock); hwirq = hwirq_to_canonical_hwirq(msi, data->hwirq); - bitmap_clear(msi->bitmap, hwirq, msi->nr_cpus); + bitmap_release_region(msi->bitmap, hwirq, + order_base_2(msi->nr_cpus * nr_irqs)); mutex_unlock(&msi->bitmap_lock); @@ -539,6 +543,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node) mutex_init(&msi->bitmap_lock); msi->nr_cpus = num_possible_cpus(); + if (msi->nr_cpus == 1) + iproc_msi_domain_info.flags |= MSI_FLAG_MULTI_PCI_MSI; + msi->nr_irqs = of_irq_count(node); if (!msi->nr_irqs) { dev_err(pcie->dev, "found no MSI GIC interrupt\n"); diff --git a/drivers/pci/controller/pcie-rockchip-host.c b/drivers/pci/controller/pcie-rockchip-host.c index 9705059523a6e8bc8bd5bc21d343648133cb8447..0d6df73bb91816e8a56eb677593943367841b5ee 100644 --- a/drivers/pci/controller/pcie-rockchip-host.c +++ b/drivers/pci/controller/pcie-rockchip-host.c @@ -593,10 +593,6 @@ static int rockchip_pcie_parse_host_dt(struct rockchip_pcie *rockchip) if (err) return err; - err = rockchip_pcie_setup_irq(rockchip); - if (err) - return err; - rockchip->vpcie12v = devm_regulator_get_optional(dev, "vpcie12v"); if (IS_ERR(rockchip->vpcie12v)) { if (PTR_ERR(rockchip->vpcie12v) != -ENODEV) @@ -974,8 +970,6 @@ static int rockchip_pcie_probe(struct platform_device *pdev) if (err) goto err_vpcie; - rockchip_pcie_enable_interrupts(rockchip); - err = rockchip_pcie_init_irq_domain(rockchip); if (err < 0) goto err_deinit_port; @@ -993,6 +987,12 @@ static int rockchip_pcie_probe(struct platform_device *pdev) bridge->sysdata = rockchip; bridge->ops = &rockchip_pcie_ops; + err = rockchip_pcie_setup_irq(rockchip); + if (err) + goto err_remove_irq_domain; + + rockchip_pcie_enable_interrupts(rockchip); + err = pci_host_probe(bridge); if (err < 0) goto err_remove_irq_domain; diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index fb3840e222addf7527469b59513b33bf74861aad..9d06939736c0f0634670bf346df2138905854d71 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -563,6 +563,32 @@ void pciehp_power_off_slot(struct controller *ctrl) PCI_EXP_SLTCTL_PWR_OFF); } +static void pciehp_ignore_dpc_link_change(struct controller *ctrl, + struct pci_dev *pdev, int irq) +{ + /* + * Ignore link changes which occurred while waiting for DPC recovery. + * Could be several if DPC triggered multiple times consecutively. + */ + synchronize_hardirq(irq); + atomic_and(~PCI_EXP_SLTSTA_DLLSC, &ctrl->pending_events); + if (pciehp_poll_mode) + pcie_capability_write_word(pdev, PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_DLLSC); + ctrl_info(ctrl, "Slot(%s): Link Down/Up ignored (recovered by DPC)\n", + slot_name(ctrl)); + + /* + * If the link is unexpectedly down after successful recovery, + * the corresponding link change may have been ignored above. + * Synthesize it to ensure that it is acted on. + */ + down_read(&ctrl->reset_lock); + if (!pciehp_check_link_active(ctrl)) + pciehp_request(ctrl, PCI_EXP_SLTSTA_DLLSC); + up_read(&ctrl->reset_lock); +} + static irqreturn_t pciehp_isr(int irq, void *dev_id) { struct controller *ctrl = (struct controller *)dev_id; @@ -706,6 +732,16 @@ static irqreturn_t pciehp_ist(int irq, void *dev_id) PCI_EXP_SLTCTL_ATTN_IND_ON); } + /* + * Ignore Link Down/Up events caused by Downstream Port Containment + * if recovery from the error succeeded. + */ + if ((events & PCI_EXP_SLTSTA_DLLSC) && pci_dpc_recovered(pdev) && + ctrl->state == ON_STATE) { + events &= ~PCI_EXP_SLTSTA_DLLSC; + pciehp_ignore_dpc_link_change(ctrl, pdev, irq); + } + /* * Disable requests have higher priority than Presence Detect Changed * or Data Link Layer State Changed events. diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c index de1c331dbed43fdbfb743380a9af9439a2b2638a..f07c5dbc94e10c13d7ff2481ea57eefdad86a126 100644 --- a/drivers/pci/p2pdma.c +++ b/drivers/pci/p2pdma.c @@ -308,10 +308,41 @@ static const struct pci_p2pdma_whitelist_entry { {} }; +/* + * This lookup function tries to find the PCI device corresponding to a given + * host bridge. + * + * It assumes the host bridge device is the first PCI device in the + * bus->devices list and that the devfn is 00.0. These assumptions should hold + * for all the devices in the whitelist above. + * + * This function is equivalent to pci_get_slot(host->bus, 0), however it does + * not take the pci_bus_sem lock seeing __host_bridge_whitelist() must not + * sleep. + * + * For this to be safe, the caller should hold a reference to a device on the + * bridge, which should ensure the host_bridge device will not be freed + * or removed from the head of the devices list. + */ +static struct pci_dev *pci_host_bridge_dev(struct pci_host_bridge *host) +{ + struct pci_dev *root; + + root = list_first_entry_or_null(&host->bus->devices, + struct pci_dev, bus_list); + + if (!root) + return NULL; + if (root->devfn != PCI_DEVFN(0, 0)) + return NULL; + + return root; +} + static bool __host_bridge_whitelist(struct pci_host_bridge *host, bool same_host_bridge) { - struct pci_dev *root = pci_get_slot(host->bus, PCI_DEVFN(0, 0)); + struct pci_dev *root = pci_host_bridge_dev(host); const struct pci_p2pdma_whitelist_entry *entry; unsigned short vendor, device; @@ -320,7 +351,6 @@ static bool __host_bridge_whitelist(struct pci_host_bridge *host, vendor = root->vendor; device = root->device; - pci_dev_put(root); for (entry = pci_p2pdma_whitelist; entry->vendor; entry++) { if (vendor != entry->vendor || device != entry->device) diff --git a/drivers/pci/pci-label.c b/drivers/pci/pci-label.c index 781e45cf60d1c3093950604bc367882f4c3d93e8..cd84cf52a92e18fe22013936b3fe23dcd0cc437d 100644 --- a/drivers/pci/pci-label.c +++ b/drivers/pci/pci-label.c @@ -162,7 +162,7 @@ static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf) len = utf16s_to_utf8s((const wchar_t *)obj->buffer.pointer, obj->buffer.length, UTF16_LITTLE_ENDIAN, - buf, PAGE_SIZE); + buf, PAGE_SIZE - 1); buf[len] = '\n'; } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d5d9ea864fe6645640becfdebbc0429033ab2566..9e971fffeb6a3e642da56b971ff00aaa2586373d 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -1874,11 +1874,21 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) int err; int i, bars = 0; - if (atomic_inc_return(&dev->enable_cnt) > 1) { - pci_update_current_state(dev, dev->current_state); - return 0; /* already enabled */ + /* + * Power state could be unknown at this point, either due to a fresh + * boot or a device removal call. So get the current power state + * so that things like MSI message writing will behave as expected + * (e.g. if the device really is in D0 at enable time). + */ + if (dev->pm_cap) { + u16 pmcsr; + pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr); + dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK); } + if (atomic_inc_return(&dev->enable_cnt) > 1) + return 0; /* already enabled */ + bridge = pci_upstream_bridge(dev); if (bridge) pci_enable_bridge(bridge); diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index 09ebc134d0d74d59ed6d106c3c71674e4acdf81e..a96dc6f5307601abfd68975c9ce4d32bf51b8d1f 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -409,6 +409,8 @@ static inline bool pci_dev_is_disconnected(const struct pci_dev *dev) /* pci_dev priv_flags */ #define PCI_DEV_ADDED 0 +#define PCI_DPC_RECOVERED 1 +#define PCI_DPC_RECOVERING 2 static inline void pci_dev_assign_added(struct pci_dev *dev, bool added) { @@ -454,10 +456,12 @@ void pci_restore_dpc_state(struct pci_dev *dev); void pci_dpc_init(struct pci_dev *pdev); void dpc_process_error(struct pci_dev *pdev); pci_ers_result_t dpc_reset_link(struct pci_dev *pdev); +bool pci_dpc_recovered(struct pci_dev *pdev); #else static inline void pci_save_dpc_state(struct pci_dev *dev) {} static inline void pci_restore_dpc_state(struct pci_dev *dev) {} static inline void pci_dpc_init(struct pci_dev *pdev) {} +static inline bool pci_dpc_recovered(struct pci_dev *pdev) { return false; } #endif #ifdef CONFIG_PCI_ATS diff --git a/drivers/pci/pcie/dpc.c b/drivers/pci/pcie/dpc.c index e05aba86a317920d1520b2a1773454360266a0e2..c556e7beafe38d8e26c59906df74f371a13cf6a9 100644 --- a/drivers/pci/pcie/dpc.c +++ b/drivers/pci/pcie/dpc.c @@ -71,6 +71,58 @@ void pci_restore_dpc_state(struct pci_dev *dev) pci_write_config_word(dev, dev->dpc_cap + PCI_EXP_DPC_CTL, *cap); } +static DECLARE_WAIT_QUEUE_HEAD(dpc_completed_waitqueue); + +#ifdef CONFIG_HOTPLUG_PCI_PCIE +static bool dpc_completed(struct pci_dev *pdev) +{ + u16 status; + + pci_read_config_word(pdev, pdev->dpc_cap + PCI_EXP_DPC_STATUS, &status); + if ((status != 0xffff) && (status & PCI_EXP_DPC_STATUS_TRIGGER)) + return false; + + if (test_bit(PCI_DPC_RECOVERING, &pdev->priv_flags)) + return false; + + return true; +} + +/** + * pci_dpc_recovered - whether DPC triggered and has recovered successfully + * @pdev: PCI device + * + * Return true if DPC was triggered for @pdev and has recovered successfully. + * Wait for recovery if it hasn't completed yet. Called from the PCIe hotplug + * driver to recognize and ignore Link Down/Up events caused by DPC. + */ +bool pci_dpc_recovered(struct pci_dev *pdev) +{ + struct pci_host_bridge *host; + + if (!pdev->dpc_cap) + return false; + + /* + * Synchronization between hotplug and DPC is not supported + * if DPC is owned by firmware and EDR is not enabled. + */ + host = pci_find_host_bridge(pdev->bus); + if (!host->native_dpc && !IS_ENABLED(CONFIG_PCIE_EDR)) + return false; + + /* + * Need a timeout in case DPC never completes due to failure of + * dpc_wait_rp_inactive(). The spec doesn't mandate a time limit, + * but reports indicate that DPC completes within 4 seconds. + */ + wait_event_timeout(dpc_completed_waitqueue, dpc_completed(pdev), + msecs_to_jiffies(4000)); + + return test_and_clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); +} +#endif /* CONFIG_HOTPLUG_PCI_PCIE */ + static int dpc_wait_rp_inactive(struct pci_dev *pdev) { unsigned long timeout = jiffies + HZ; @@ -91,8 +143,11 @@ static int dpc_wait_rp_inactive(struct pci_dev *pdev) pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) { + pci_ers_result_t ret; u16 cap; + set_bit(PCI_DPC_RECOVERING, &pdev->priv_flags); + /* * DPC disables the Link automatically in hardware, so it has * already been reset by the time we get here. @@ -106,18 +161,27 @@ pci_ers_result_t dpc_reset_link(struct pci_dev *pdev) if (!pcie_wait_for_link(pdev, false)) pci_info(pdev, "Data Link Layer Link Active not cleared in 1000 msec\n"); - if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev)) - return PCI_ERS_RESULT_DISCONNECT; + if (pdev->dpc_rp_extensions && dpc_wait_rp_inactive(pdev)) { + clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); + ret = PCI_ERS_RESULT_DISCONNECT; + goto out; + } pci_write_config_word(pdev, cap + PCI_EXP_DPC_STATUS, PCI_EXP_DPC_STATUS_TRIGGER); if (!pcie_wait_for_link(pdev, true)) { pci_info(pdev, "Data Link Layer Link Active not set in 1000 msec\n"); - return PCI_ERS_RESULT_DISCONNECT; + clear_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); + ret = PCI_ERS_RESULT_DISCONNECT; + } else { + set_bit(PCI_DPC_RECOVERED, &pdev->priv_flags); + ret = PCI_ERS_RESULT_RECOVERED; } - - return PCI_ERS_RESULT_RECOVERED; +out: + clear_bit(PCI_DPC_RECOVERING, &pdev->priv_flags); + wake_up_all(&dpc_completed_waitqueue); + return ret; } static void dpc_process_rp_pio_error(struct pci_dev *pdev) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f43f78912c5bd54109221bcc62c92a2ba61e19a5..d8307e5a6b061a96d3651d026d541b0cd470292c 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -27,6 +27,7 @@ #include <linux/nvme.h> #include <linux/platform_data/x86/apple.h> #include <linux/pm_runtime.h> +#include <linux/suspend.h> #include <linux/switchtec.h> #include <asm/dma.h> /* isa_dma_bridge_buggy */ #include "pci.h" @@ -3670,6 +3671,16 @@ static void quirk_apple_poweroff_thunderbolt(struct pci_dev *dev) return; if (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) return; + + /* + * SXIO/SXFP/SXLF turns off power to the Thunderbolt controller. + * We don't know how to turn it back on again, but firmware does, + * so we can only use SXIO/SXFP/SXLF if we're suspending via + * firmware. + */ + if (!pm_suspend_via_firmware()) + return; + bridge = ACPI_HANDLE(&dev->dev); if (!bridge) return; diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c index 46defb1dcf8677071dab80b327faf3c8a94afaac..bb019e38398882fb301d760de894db91a53f99a4 100644 --- a/drivers/perf/arm-cmn.c +++ b/drivers/perf/arm-cmn.c @@ -1212,7 +1212,7 @@ static int arm_cmn_init_irqs(struct arm_cmn *cmn) irq = cmn->dtc[i].irq; for (j = i; j--; ) { if (cmn->dtc[j].irq == irq) { - cmn->dtc[j].irq_friend = j - i; + cmn->dtc[j].irq_friend = i - j; goto next; } } diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c index 5274f7fe359ebb678f09bd2916f11d935419d6db..afa8efbdad8faee7a96f147f059647a8728d0dbd 100644 --- a/drivers/perf/arm_smmuv3_pmu.c +++ b/drivers/perf/arm_smmuv3_pmu.c @@ -275,7 +275,7 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu, struct perf_event *event, int idx) { u32 span, sid; - unsigned int num_ctrs = smmu_pmu->num_counters; + unsigned int cur_idx, num_ctrs = smmu_pmu->num_counters; bool filter_en = !!get_filter_enable(event); span = filter_en ? get_filter_span(event) : @@ -283,17 +283,19 @@ static int smmu_pmu_apply_event_filter(struct smmu_pmu *smmu_pmu, sid = filter_en ? get_filter_stream_id(event) : SMMU_PMCG_DEFAULT_FILTER_SID; - /* Support individual filter settings */ - if (!smmu_pmu->global_filter) { + cur_idx = find_first_bit(smmu_pmu->used_counters, num_ctrs); + /* + * Per-counter filtering, or scheduling the first globally-filtered + * event into an empty PMU so idx == 0 and it works out equivalent. + */ + if (!smmu_pmu->global_filter || cur_idx == num_ctrs) { smmu_pmu_set_event_filter(event, idx, span, sid); return 0; } - /* Requested settings same as current global settings*/ - idx = find_first_bit(smmu_pmu->used_counters, num_ctrs); - if (idx == num_ctrs || - smmu_pmu_check_global_filter(smmu_pmu->events[idx], event)) { - smmu_pmu_set_event_filter(event, 0, span, sid); + /* Otherwise, must match whatever's currently scheduled */ + if (smmu_pmu_check_global_filter(smmu_pmu->events[cur_idx], event)) { + smmu_pmu_set_evtyper(smmu_pmu, idx, get_event(event)); return 0; } diff --git a/drivers/perf/fsl_imx8_ddr_perf.c b/drivers/perf/fsl_imx8_ddr_perf.c index 53a51954762a5e3e60e1f9b43e847bcde37b4b8d..557aad5a6f2031503ed537a0df24479e118556e6 100644 --- a/drivers/perf/fsl_imx8_ddr_perf.c +++ b/drivers/perf/fsl_imx8_ddr_perf.c @@ -822,8 +822,10 @@ static int ddr_perf_probe(struct platform_device *pdev) return ret; } else return -EINVAL; - if (!name) - return -ENOMEM; + if (!name) { + ret = -ENOMEM; + goto cpuhp_state_err; + } pmu->cpu = raw_smp_processor_id(); ret = cpuhp_setup_state_multi(CPUHP_AP_ONLINE_DYN, diff --git a/drivers/phy/intel/phy-intel-keembay-emmc.c b/drivers/phy/intel/phy-intel-keembay-emmc.c index eb7c635ed89aea5abddf7609720441b0f6f3a993..0eb11ac7c2e2e3b2409bf27b7192129e6427242c 100644 --- a/drivers/phy/intel/phy-intel-keembay-emmc.c +++ b/drivers/phy/intel/phy-intel-keembay-emmc.c @@ -95,7 +95,8 @@ static int keembay_emmc_phy_power(struct phy *phy, bool on_off) else freqsel = 0x0; - if (mhz < 50 || mhz > 200) + /* Check for EMMC clock rate*/ + if (mhz > 175) dev_warn(&phy->dev, "Unsupported rate: %d MHz\n", mhz); /* diff --git a/drivers/phy/socionext/phy-uniphier-pcie.c b/drivers/phy/socionext/phy-uniphier-pcie.c index e4adab375c73706cdc510327939a25e381209822..6bdbd1f214dd46960ba65c80703d05c01b74dfb6 100644 --- a/drivers/phy/socionext/phy-uniphier-pcie.c +++ b/drivers/phy/socionext/phy-uniphier-pcie.c @@ -24,11 +24,13 @@ #define PORT_SEL_1 FIELD_PREP(PORT_SEL_MASK, 1) #define PCL_PHY_TEST_I 0x2000 -#define PCL_PHY_TEST_O 0x2004 #define TESTI_DAT_MASK GENMASK(13, 6) #define TESTI_ADR_MASK GENMASK(5, 1) #define TESTI_WR_EN BIT(0) +#define PCL_PHY_TEST_O 0x2004 +#define TESTO_DAT_MASK GENMASK(7, 0) + #define PCL_PHY_RESET 0x200c #define PCL_PHY_RESET_N_MNMODE BIT(8) /* =1:manual */ #define PCL_PHY_RESET_N BIT(0) /* =1:deasssert */ @@ -77,11 +79,12 @@ static void uniphier_pciephy_set_param(struct uniphier_pciephy_priv *priv, val = FIELD_PREP(TESTI_DAT_MASK, 1); val |= FIELD_PREP(TESTI_ADR_MASK, reg); uniphier_pciephy_testio_write(priv, val); - val = readl(priv->base + PCL_PHY_TEST_O); + val = readl(priv->base + PCL_PHY_TEST_O) & TESTO_DAT_MASK; /* update value */ - val &= ~FIELD_PREP(TESTI_DAT_MASK, mask); - val = FIELD_PREP(TESTI_DAT_MASK, mask & param); + val &= ~mask; + val |= mask & param; + val = FIELD_PREP(TESTI_DAT_MASK, val); val |= FIELD_PREP(TESTI_ADR_MASK, reg); uniphier_pciephy_testio_write(priv, val); uniphier_pciephy_testio_write(priv, val | TESTI_WR_EN); diff --git a/drivers/phy/ti/phy-dm816x-usb.c b/drivers/phy/ti/phy-dm816x-usb.c index 57adc08a89b2dd24f3b34a999b5da4e2a1cdb4af..9fe6ea6fdae55c9b9fef5faef3848805f5ca73f7 100644 --- a/drivers/phy/ti/phy-dm816x-usb.c +++ b/drivers/phy/ti/phy-dm816x-usb.c @@ -242,19 +242,28 @@ static int dm816x_usb_phy_probe(struct platform_device *pdev) pm_runtime_enable(phy->dev); generic_phy = devm_phy_create(phy->dev, NULL, &ops); - if (IS_ERR(generic_phy)) - return PTR_ERR(generic_phy); + if (IS_ERR(generic_phy)) { + error = PTR_ERR(generic_phy); + goto clk_unprepare; + } phy_set_drvdata(generic_phy, phy); phy_provider = devm_of_phy_provider_register(phy->dev, of_phy_simple_xlate); - if (IS_ERR(phy_provider)) - return PTR_ERR(phy_provider); + if (IS_ERR(phy_provider)) { + error = PTR_ERR(phy_provider); + goto clk_unprepare; + } usb_add_phy_dev(&phy->phy); return 0; + +clk_unprepare: + pm_runtime_disable(phy->dev); + clk_unprepare(phy->refclk); + return error; } static int dm816x_usb_phy_remove(struct platform_device *pdev) diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 899c16c17b6da4c0c7b42faff86d259603d2ddfe..ef49402c0623de8fcfb37e4b53badd1ec0ecd5e9 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -952,6 +952,7 @@ static int amd_gpio_remove(struct platform_device *pdev) static const struct acpi_device_id amd_gpio_acpi_match[] = { { "AMD0030", 0 }, { "AMDI0030", 0}, + { "AMDI0031", 0}, { }, }; MODULE_DEVICE_TABLE(acpi, amd_gpio_acpi_match); diff --git a/drivers/pinctrl/pinctrl-equilibrium.c b/drivers/pinctrl/pinctrl-equilibrium.c index 067271b7d35a3f2cd31705dce1f93720c0ea7ec4..ac1c47f542c11fc055ac3fa5f5864086b6853817 100644 --- a/drivers/pinctrl/pinctrl-equilibrium.c +++ b/drivers/pinctrl/pinctrl-equilibrium.c @@ -929,6 +929,7 @@ static const struct of_device_id eqbr_pinctrl_dt_match[] = { { .compatible = "intel,lgm-io" }, {} }; +MODULE_DEVICE_TABLE(of, eqbr_pinctrl_dt_match); static struct platform_driver eqbr_pinctrl_driver = { .probe = eqbr_pinctrl_probe, diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index ce2d8014b7e0bc7553ef9585cf9302ccc8aea04e..d0259577934e95af4be6ab50297fc2766ffe4dea 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -351,6 +351,11 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) if (mcp_read(mcp, MCP_INTF, &intf)) goto unlock; + if (intf == 0) { + /* There is no interrupt pending */ + goto unlock; + } + if (mcp_read(mcp, MCP_INTCAP, &intcap)) goto unlock; @@ -368,11 +373,6 @@ static irqreturn_t mcp23s08_irq(int irq, void *data) mcp->cached_gpio = gpio; mutex_unlock(&mcp->lock); - if (intf == 0) { - /* There is no interrupt pending */ - return IRQ_HANDLED; - } - dev_dbg(mcp->chip.parent, "intcap 0x%04X intf 0x%04X gpio_orig 0x%04X gpio 0x%04X\n", intcap, intf, gpio_orig, gpio); diff --git a/drivers/pinctrl/renesas/pfc-r8a7796.c b/drivers/pinctrl/renesas/pfc-r8a7796.c index 55f0344a3d3e9af63fec0cef135e4338ee05b20a..3878d6b0db149196ec215de85469c83486bea934 100644 --- a/drivers/pinctrl/renesas/pfc-r8a7796.c +++ b/drivers/pinctrl/renesas/pfc-r8a7796.c @@ -68,6 +68,7 @@ PIN_NOGP_CFG(QSPI1_MOSI_IO0, "QSPI1_MOSI_IO0", fn, CFG_FLAGS), \ PIN_NOGP_CFG(QSPI1_SPCLK, "QSPI1_SPCLK", fn, CFG_FLAGS), \ PIN_NOGP_CFG(QSPI1_SSL, "QSPI1_SSL", fn, CFG_FLAGS), \ + PIN_NOGP_CFG(PRESET_N, "PRESET#", fn, SH_PFC_PIN_CFG_PULL_DOWN),\ PIN_NOGP_CFG(RPC_INT_N, "RPC_INT#", fn, CFG_FLAGS), \ PIN_NOGP_CFG(RPC_RESET_N, "RPC_RESET#", fn, CFG_FLAGS), \ PIN_NOGP_CFG(RPC_WP_N, "RPC_WP#", fn, CFG_FLAGS), \ @@ -6109,7 +6110,7 @@ static const struct pinmux_bias_reg pinmux_bias_regs[] = { [ 4] = RCAR_GP_PIN(6, 29), /* USB30_OVC */ [ 5] = RCAR_GP_PIN(6, 30), /* GP6_30 */ [ 6] = RCAR_GP_PIN(6, 31), /* GP6_31 */ - [ 7] = SH_PFC_PIN_NONE, + [ 7] = PIN_PRESET_N, /* PRESET# */ [ 8] = SH_PFC_PIN_NONE, [ 9] = SH_PFC_PIN_NONE, [10] = SH_PFC_PIN_NONE, diff --git a/drivers/pinctrl/renesas/pfc-r8a77990.c b/drivers/pinctrl/renesas/pfc-r8a77990.c index aed04a4c61163cb27f71c4a0ab9ceb205ea54de7..240aadc4611fb7bc9c3d09c440eae2c586bc55f2 100644 --- a/drivers/pinctrl/renesas/pfc-r8a77990.c +++ b/drivers/pinctrl/renesas/pfc-r8a77990.c @@ -54,10 +54,10 @@ PIN_NOGP_CFG(FSCLKST_N, "FSCLKST_N", fn, CFG_FLAGS), \ PIN_NOGP_CFG(MLB_REF, "MLB_REF", fn, CFG_FLAGS), \ PIN_NOGP_CFG(PRESETOUT_N, "PRESETOUT_N", fn, CFG_FLAGS), \ - PIN_NOGP_CFG(TCK, "TCK", fn, CFG_FLAGS), \ - PIN_NOGP_CFG(TDI, "TDI", fn, CFG_FLAGS), \ - PIN_NOGP_CFG(TMS, "TMS", fn, CFG_FLAGS), \ - PIN_NOGP_CFG(TRST_N, "TRST_N", fn, CFG_FLAGS) + PIN_NOGP_CFG(TCK, "TCK", fn, SH_PFC_PIN_CFG_PULL_UP), \ + PIN_NOGP_CFG(TDI, "TDI", fn, SH_PFC_PIN_CFG_PULL_UP), \ + PIN_NOGP_CFG(TMS, "TMS", fn, SH_PFC_PIN_CFG_PULL_UP), \ + PIN_NOGP_CFG(TRST_N, "TRST_N", fn, SH_PFC_PIN_CFG_PULL_UP) /* * F_() : just information diff --git a/drivers/pinctrl/stm32/pinctrl-stm32.c b/drivers/pinctrl/stm32/pinctrl-stm32.c index 7d9bdedcd71bbee364570f3191b0ff1fa9b9aeb8..3af4430543dcae165fdf32ddf72598135f046d2a 100644 --- a/drivers/pinctrl/stm32/pinctrl-stm32.c +++ b/drivers/pinctrl/stm32/pinctrl-stm32.c @@ -1229,7 +1229,7 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, struct device *dev = pctl->dev; struct resource res; int npins = STM32_GPIO_PINS_PER_BANK; - int bank_nr, err; + int bank_nr, err, i = 0; if (!IS_ERR(bank->rstc)) reset_control_deassert(bank->rstc); @@ -1251,9 +1251,14 @@ static int stm32_gpiolib_register_bank(struct stm32_pinctrl *pctl, of_property_read_string(np, "st,bank-name", &bank->gpio_chip.label); - if (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, 0, &args)) { + if (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, i, &args)) { bank_nr = args.args[1] / STM32_GPIO_PINS_PER_BANK; bank->gpio_chip.base = args.args[1]; + + npins = args.args[2]; + while (!of_parse_phandle_with_fixed_args(np, "gpio-ranges", 3, + ++i, &args)) + npins += args.args[2]; } else { bank_nr = pctl->nbanks; bank->gpio_chip.base = bank_nr * STM32_GPIO_PINS_PER_BANK; diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c index 1d9fbabd02fb7dbe7e0a7b0cf06abf4164265664..949ddeb673bc564e4bc88b4d45535dc0a90f04cc 100644 --- a/drivers/platform/x86/asus-nb-wmi.c +++ b/drivers/platform/x86/asus-nb-wmi.c @@ -110,11 +110,6 @@ static struct quirk_entry quirk_asus_forceals = { .wmi_force_als_set = true, }; -static struct quirk_entry quirk_asus_vendor_backlight = { - .wmi_backlight_power = true, - .wmi_backlight_set_devstate = true, -}; - static struct quirk_entry quirk_asus_use_kbd_dock_devid = { .use_kbd_dock_devid = true, }; @@ -420,78 +415,6 @@ static const struct dmi_system_id asus_quirks[] = { }, .driver_data = &quirk_asus_forceals, }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA401IH", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA401IH"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA401II", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA401II"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA401IU", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA401IU"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA401IV", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA401IV"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA401IVC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA401IVC"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA502II", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA502II"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA502IU", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA502IU"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, - { - .callback = dmi_matched, - .ident = "ASUSTeK COMPUTER INC. GA502IV", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), - DMI_MATCH(DMI_PRODUCT_NAME, "GA502IV"), - }, - .driver_data = &quirk_asus_vendor_backlight, - }, { .callback = dmi_matched, .ident = "Asus Transformer T100TA / T100HA / T100CHI", diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index fa7232ad8c3952cb3067bf669fedb5a31538ac8e..352508d30467535ba12d4826292a818db52f40d3 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -2831,6 +2831,7 @@ static int toshiba_acpi_setup_keyboard(struct toshiba_acpi_dev *dev) if (!dev->info_supported && !dev->system_event_supported) { pr_warn("No hotkey query interface found\n"); + error = -EINVAL; goto err_remove_filter; } diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c index 3743d895399e78275c87fef813c42694a3e8f39c..99260915122c00e101eda9efbaaf1bf34ef1a4a8 100644 --- a/drivers/platform/x86/touchscreen_dmi.c +++ b/drivers/platform/x86/touchscreen_dmi.c @@ -299,6 +299,35 @@ static const struct ts_dmi_data estar_beauty_hd_data = { .properties = estar_beauty_hd_props, }; +/* Generic props + data for upside-down mounted GDIX1001 touchscreens */ +static const struct property_entry gdix1001_upside_down_props[] = { + PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"), + PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"), + { } +}; + +static const struct ts_dmi_data gdix1001_00_upside_down_data = { + .acpi_name = "GDIX1001:00", + .properties = gdix1001_upside_down_props, +}; + +static const struct ts_dmi_data gdix1001_01_upside_down_data = { + .acpi_name = "GDIX1001:01", + .properties = gdix1001_upside_down_props, +}; + +static const struct property_entry glavey_tm800a550l_props[] = { + PROPERTY_ENTRY_STRING("firmware-name", "gt912-glavey-tm800a550l.fw"), + PROPERTY_ENTRY_STRING("goodix,config-name", "gt912-glavey-tm800a550l.cfg"), + PROPERTY_ENTRY_U32("goodix,main-clk", 54), + { } +}; + +static const struct ts_dmi_data glavey_tm800a550l_data = { + .acpi_name = "GDIX1001:00", + .properties = glavey_tm800a550l_props, +}; + static const struct property_entry gp_electronic_t701_props[] = { PROPERTY_ENTRY_U32("touchscreen-size-x", 960), PROPERTY_ENTRY_U32("touchscreen-size-y", 640), @@ -995,6 +1024,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "eSTAR BEAUTY HD Intel Quad core"), }, }, + { /* Glavey TM800A550L */ + .driver_data = (void *)&glavey_tm800a550l_data, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"), + DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"), + /* Above strings are too generic, also match on BIOS version */ + DMI_MATCH(DMI_BIOS_VERSION, "ZY-8-BI-PX4S70VTR400-X423B-005-D"), + }, + }, { /* GP-electronic T701 */ .driver_data = (void *)&gp_electronic_t701_data, @@ -1268,6 +1306,24 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "X3 Plus"), }, }, + { + /* Teclast X89 (Android version / BIOS) */ + .driver_data = (void *)&gdix1001_00_upside_down_data, + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "WISKY"), + DMI_MATCH(DMI_BOARD_NAME, "3G062i"), + }, + }, + { + /* Teclast X89 (Windows version / BIOS) */ + .driver_data = (void *)&gdix1001_01_upside_down_data, + .matches = { + /* tPAD is too generic, also match on bios date */ + DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), + DMI_MATCH(DMI_BOARD_NAME, "tPAD"), + DMI_MATCH(DMI_BIOS_DATE, "12/19/2014"), + }, + }, { /* Teclast X98 Plus II */ .driver_data = (void *)&teclast_x98plus2_data, @@ -1276,6 +1332,19 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "X98 Plus II"), }, }, + { + /* Teclast X98 Pro */ + .driver_data = (void *)&gdix1001_00_upside_down_data, + .matches = { + /* + * Only match BIOS date, because the manufacturers + * BIOS does not report the board name at all + * (sometimes)... + */ + DMI_MATCH(DMI_BOARD_VENDOR, "TECLAST"), + DMI_MATCH(DMI_BIOS_DATE, "10/28/2015"), + }, + }, { /* Trekstor Primebook C11 */ .driver_data = (void *)&trekstor_primebook_c11_data, @@ -1351,6 +1420,22 @@ const struct dmi_system_id touchscreen_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "VINGA Twizzle J116"), }, }, + { + /* "WinBook TW100" */ + .driver_data = (void *)&gdix1001_00_upside_down_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), + DMI_MATCH(DMI_PRODUCT_NAME, "TW100") + } + }, + { + /* WinBook TW700 */ + .driver_data = (void *)&gdix1001_00_upside_down_data, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "WinBook"), + DMI_MATCH(DMI_PRODUCT_NAME, "TW700") + }, + }, { /* Yours Y8W81, same case and touchscreen as Chuwi Vi8 */ .driver_data = (void *)&chuwi_vi8_data, diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c index c5067eb753706b0e592801bc9d3afdc2bd6454b8..1c5af2fef1423af68dbbbd1880b8aab6480f2957 100644 --- a/drivers/power/reset/gpio-poweroff.c +++ b/drivers/power/reset/gpio-poweroff.c @@ -90,6 +90,7 @@ static const struct of_device_id of_gpio_poweroff_match[] = { { .compatible = "gpio-poweroff", }, {}, }; +MODULE_DEVICE_TABLE(of, of_gpio_poweroff_match); static struct platform_driver gpio_poweroff_driver = { .probe = gpio_poweroff_probe, diff --git a/drivers/power/supply/Kconfig b/drivers/power/supply/Kconfig index 8ba3e9d9335d5d5d37b34a315df0ee19f91310ba..34ac6d2c04655549fea81e9063ea6b610d5eca44 100644 --- a/drivers/power/supply/Kconfig +++ b/drivers/power/supply/Kconfig @@ -700,7 +700,8 @@ config BATTERY_GOLDFISH config BATTERY_RT5033 tristate "RT5033 fuel gauge support" - depends on MFD_RT5033 + depends on I2C + select REGMAP_I2C help This adds support for battery fuel gauge in Richtek RT5033 PMIC. The fuelgauge calculates and determines the battery state of charge diff --git a/drivers/power/supply/ab8500_btemp.c b/drivers/power/supply/ab8500_btemp.c index 909f0242bacbc89fc86f4b61eedabecc8e2a4128..4417d64c31f97fac061aad75208923f02d45d1bb 100644 --- a/drivers/power/supply/ab8500_btemp.c +++ b/drivers/power/supply/ab8500_btemp.c @@ -1142,6 +1142,7 @@ static const struct of_device_id ab8500_btemp_match[] = { { .compatible = "stericsson,ab8500-btemp", }, { }, }; +MODULE_DEVICE_TABLE(of, ab8500_btemp_match); static struct platform_driver ab8500_btemp_driver = { .probe = ab8500_btemp_probe, diff --git a/drivers/power/supply/ab8500_charger.c b/drivers/power/supply/ab8500_charger.c index db65be0269206dd043acea31ed78c53533b519b6..3d627768ad7b23169ca2174f3d686be143ba47e5 100644 --- a/drivers/power/supply/ab8500_charger.c +++ b/drivers/power/supply/ab8500_charger.c @@ -413,6 +413,14 @@ disable_otp: static void ab8500_power_supply_changed(struct ab8500_charger *di, struct power_supply *psy) { + /* + * This happens if we get notifications or interrupts and + * the platform has been configured not to support one or + * other type of charging. + */ + if (!psy) + return; + if (di->autopower_cfg) { if (!di->usb.charger_connected && !di->ac.charger_connected && @@ -439,7 +447,15 @@ static void ab8500_charger_set_usb_connected(struct ab8500_charger *di, if (!connected) di->flags.vbus_drop_end = false; - sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, "present"); + /* + * Sometimes the platform is configured not to support + * USB charging and no psy has been created, but we still + * will get these notifications. + */ + if (di->usb_chg.psy) { + sysfs_notify(&di->usb_chg.psy->dev.kobj, NULL, + "present"); + } if (connected) { mutex_lock(&di->charger_attached_mutex); @@ -3663,6 +3679,7 @@ static const struct of_device_id ab8500_charger_match[] = { { .compatible = "stericsson,ab8500-charger", }, { }, }; +MODULE_DEVICE_TABLE(of, ab8500_charger_match); static struct platform_driver ab8500_charger_driver = { .probe = ab8500_charger_probe, diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c index 592a73d4dde68ec6dade734542da471b6902aa6a..f1da757c939f8acdfa192997bfc3fb6325b15eee 100644 --- a/drivers/power/supply/ab8500_fg.c +++ b/drivers/power/supply/ab8500_fg.c @@ -3249,6 +3249,7 @@ static const struct of_device_id ab8500_fg_match[] = { { .compatible = "stericsson,ab8500-fg", }, { }, }; +MODULE_DEVICE_TABLE(of, ab8500_fg_match); static struct platform_driver ab8500_fg_driver = { .probe = ab8500_fg_probe, diff --git a/drivers/power/supply/charger-manager.c b/drivers/power/supply/charger-manager.c index 6fcebe4415522c1e019c0840d018025379af98f2..333349275b964e7edc6364c4dc4988f899fa5238 100644 --- a/drivers/power/supply/charger-manager.c +++ b/drivers/power/supply/charger-manager.c @@ -1279,6 +1279,7 @@ static const struct of_device_id charger_manager_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, charger_manager_match); static struct charger_desc *of_cm_parse_desc(struct device *dev) { diff --git a/drivers/power/supply/max17042_battery.c b/drivers/power/supply/max17042_battery.c index 2e9672fe4df1f284491f4f5d228566154b3a5167..794caf03658d7398131ac410637cdfd8ec403b4c 100644 --- a/drivers/power/supply/max17042_battery.c +++ b/drivers/power/supply/max17042_battery.c @@ -1094,7 +1094,7 @@ static int max17042_probe(struct i2c_client *client, } if (client->irq) { - unsigned int flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; + unsigned int flags = IRQF_ONESHOT; /* * On ACPI systems the IRQ may be handled by ACPI-event code, diff --git a/drivers/power/supply/rt5033_battery.c b/drivers/power/supply/rt5033_battery.c index f330452341f02953189d3328c830c21160d68e95..9ad0afe83d1b785838b79a3eed293ecb613cb2be 100644 --- a/drivers/power/supply/rt5033_battery.c +++ b/drivers/power/supply/rt5033_battery.c @@ -164,9 +164,16 @@ static const struct i2c_device_id rt5033_battery_id[] = { }; MODULE_DEVICE_TABLE(i2c, rt5033_battery_id); +static const struct of_device_id rt5033_battery_of_match[] = { + { .compatible = "richtek,rt5033-battery", }, + { } +}; +MODULE_DEVICE_TABLE(of, rt5033_battery_of_match); + static struct i2c_driver rt5033_battery_driver = { .driver = { .name = "rt5033-battery", + .of_match_table = rt5033_battery_of_match, }, .probe = rt5033_battery_probe, .remove = rt5033_battery_remove, diff --git a/drivers/power/supply/sc2731_charger.c b/drivers/power/supply/sc2731_charger.c index 335cb857ef3071ba99b8fcba1ad2afcdfc8c7b35..288b79836c139ed42d5a356d38360d0072f2d4b0 100644 --- a/drivers/power/supply/sc2731_charger.c +++ b/drivers/power/supply/sc2731_charger.c @@ -524,6 +524,7 @@ static const struct of_device_id sc2731_charger_of_match[] = { { .compatible = "sprd,sc2731-charger", }, { } }; +MODULE_DEVICE_TABLE(of, sc2731_charger_of_match); static struct platform_driver sc2731_charger_driver = { .driver = { diff --git a/drivers/power/supply/sc27xx_fuel_gauge.c b/drivers/power/supply/sc27xx_fuel_gauge.c index 9c627618c22499fa7e8815af34d0cc9692c1591d..1ae8374e1cebeea46b88f8327d715228913bddd3 100644 --- a/drivers/power/supply/sc27xx_fuel_gauge.c +++ b/drivers/power/supply/sc27xx_fuel_gauge.c @@ -1342,6 +1342,7 @@ static const struct of_device_id sc27xx_fgu_of_match[] = { { .compatible = "sprd,sc2731-fgu", }, { } }; +MODULE_DEVICE_TABLE(of, sc27xx_fgu_of_match); static struct platform_driver sc27xx_fgu_driver = { .probe = sc27xx_fgu_probe, diff --git a/drivers/pwm/pwm-img.c b/drivers/pwm/pwm-img.c index a34d95ed70b20721de211ea5d6bb355f836dcdaf..22c002e685b343de75f0347adbaa6a5ce53ccadc 100644 --- a/drivers/pwm/pwm-img.c +++ b/drivers/pwm/pwm-img.c @@ -156,7 +156,7 @@ static int img_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) struct img_pwm_chip *pwm_chip = to_img_pwm_chip(chip); int ret; - ret = pm_runtime_get_sync(chip->dev); + ret = pm_runtime_resume_and_get(chip->dev); if (ret < 0) return ret; diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c index f8b2c2e001a7a87bba53a367462f0d61e9fef620..c17652c40e1424c4317b860007eae00904b707a7 100644 --- a/drivers/pwm/pwm-imx1.c +++ b/drivers/pwm/pwm-imx1.c @@ -180,8 +180,6 @@ static int pwm_imx1_remove(struct platform_device *pdev) { struct pwm_imx1_chip *imx = platform_get_drvdata(pdev); - pwm_imx1_clk_disable_unprepare(&imx->chip); - return pwmchip_remove(&imx->chip); } diff --git a/drivers/pwm/pwm-spear.c b/drivers/pwm/pwm-spear.c index 6c6b44fd3f438f58ad1de57e850fc601776ca8e5..2d11ac277de8d610115c1d32481f7ef4a7da8a45 100644 --- a/drivers/pwm/pwm-spear.c +++ b/drivers/pwm/pwm-spear.c @@ -231,10 +231,6 @@ static int spear_pwm_probe(struct platform_device *pdev) static int spear_pwm_remove(struct platform_device *pdev) { struct spear_pwm_chip *pc = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < NUM_PWM; i++) - pwm_disable(&pc->chip.pwms[i]); /* clk was prepared in probe, hence unprepare it here */ clk_unprepare(pc->clk); diff --git a/drivers/pwm/pwm-tegra.c b/drivers/pwm/pwm-tegra.c index 1daf591025c0001539915348e4fbbf2d32ea00d7..8c4e6657b61e77e66c19eb9496b25bc76d7a439a 100644 --- a/drivers/pwm/pwm-tegra.c +++ b/drivers/pwm/pwm-tegra.c @@ -303,7 +303,6 @@ static int tegra_pwm_probe(struct platform_device *pdev) static int tegra_pwm_remove(struct platform_device *pdev) { struct tegra_pwm_chip *pc = platform_get_drvdata(pdev); - unsigned int i; int err; if (WARN_ON(!pc)) @@ -313,18 +312,6 @@ static int tegra_pwm_remove(struct platform_device *pdev) if (err < 0) return err; - for (i = 0; i < pc->chip.npwm; i++) { - struct pwm_device *pwm = &pc->chip.pwms[i]; - - if (!pwm_is_enabled(pwm)) - if (clk_prepare_enable(pc->clk) < 0) - continue; - - pwm_writel(pc, i, 0); - - clk_disable_unprepare(pc->clk); - } - reset_control_assert(pc->rst); clk_disable_unprepare(pc->clk); diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index e18d291c7f21c75ed9764985e09d1fe7fc1e292a..23fa429ebe760d71939624f7e017c50e2d89413a 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -250,7 +250,8 @@ static int da9052_regulator_set_voltage_time_sel(struct regulator_dev *rdev, case DA9052_ID_BUCK3: case DA9052_ID_LDO2: case DA9052_ID_LDO3: - ret = (new_sel - old_sel) * info->step_uV / 6250; + ret = DIV_ROUND_UP(abs(new_sel - old_sel) * info->step_uV, + 6250); break; } diff --git a/drivers/regulator/fan53880.c b/drivers/regulator/fan53880.c index 1684faf82ed2598e8bd11f783e9afdbd82104252..94f02f3099dd4cc66e3c2865717a4c62ca4deea0 100644 --- a/drivers/regulator/fan53880.c +++ b/drivers/regulator/fan53880.c @@ -79,7 +79,7 @@ static const struct regulator_desc fan53880_regulators[] = { .n_linear_ranges = 2, .n_voltages = 0xf8, .vsel_reg = FAN53880_BUCKVOUT, - .vsel_mask = 0x7f, + .vsel_mask = 0xff, .enable_reg = FAN53880_ENABLE, .enable_mask = 0x10, .enable_time = 480, diff --git a/drivers/regulator/hi655x-regulator.c b/drivers/regulator/hi655x-regulator.c index ac2ee2030211a3df1cabd9d1a62deb21603dd55b..b44f492a2b8322db42aa5f0b2dbed7e6646e55bf 100644 --- a/drivers/regulator/hi655x-regulator.c +++ b/drivers/regulator/hi655x-regulator.c @@ -72,7 +72,7 @@ enum hi655x_regulator_id { static int hi655x_is_enabled(struct regulator_dev *rdev) { unsigned int value = 0; - struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); + const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); regmap_read(rdev->regmap, regulator->status_reg, &value); return (value & rdev->desc->enable_mask); @@ -80,7 +80,7 @@ static int hi655x_is_enabled(struct regulator_dev *rdev) static int hi655x_disable(struct regulator_dev *rdev) { - struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); + const struct hi655x_regulator *regulator = rdev_get_drvdata(rdev); return regmap_write(rdev->regmap, regulator->disable_reg, rdev->desc->enable_mask); @@ -169,7 +169,6 @@ static const struct hi655x_regulator regulators[] = { static int hi655x_regulator_probe(struct platform_device *pdev) { unsigned int i; - struct hi655x_regulator *regulator; struct hi655x_pmic *pmic; struct regulator_config config = { }; struct regulator_dev *rdev; @@ -180,22 +179,17 @@ static int hi655x_regulator_probe(struct platform_device *pdev) return -ENODEV; } - regulator = devm_kzalloc(&pdev->dev, sizeof(*regulator), GFP_KERNEL); - if (!regulator) - return -ENOMEM; - - platform_set_drvdata(pdev, regulator); - config.dev = pdev->dev.parent; config.regmap = pmic->regmap; - config.driver_data = regulator; for (i = 0; i < ARRAY_SIZE(regulators); i++) { + config.driver_data = (void *) ®ulators[i]; + rdev = devm_regulator_register(&pdev->dev, ®ulators[i].rdesc, &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register regulator %s\n", - regulator->rdesc.name); + regulators[i].rdesc.name); return PTR_ERR(rdev); } } diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c index 13cb6ac9a8929463c80959982b8bb43404023ccb..1d4eb5dc4fac812a104f829e60577801e97f2263 100644 --- a/drivers/regulator/mt6358-regulator.c +++ b/drivers/regulator/mt6358-regulator.c @@ -457,7 +457,7 @@ static struct mt6358_regulator_info mt6358_regulators[] = { MT6358_REG_FIXED("ldo_vaud28", VAUD28, MT6358_LDO_VAUD28_CON0, 0, 2800000), MT6358_LDO("ldo_vdram2", VDRAM2, vdram2_voltages, vdram2_idx, - MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0x10, 0), + MT6358_LDO_VDRAM2_CON0, 0, MT6358_LDO_VDRAM2_ELR0, 0xf, 0), MT6358_LDO("ldo_vsim1", VSIM1, vsim_voltages, vsim_idx, MT6358_LDO_VSIM1_CON0, 0, MT6358_VSIM1_ANA_CON0, 0xf00, 8), MT6358_LDO("ldo_vibr", VIBR, vibr_voltages, vibr_idx, diff --git a/drivers/regulator/uniphier-regulator.c b/drivers/regulator/uniphier-regulator.c index 2e02e26b516c45b617effcad54d0ef2b7a8a037f..e75b0973e3256df049ea61baed46331e31579b19 100644 --- a/drivers/regulator/uniphier-regulator.c +++ b/drivers/regulator/uniphier-regulator.c @@ -201,6 +201,7 @@ static const struct of_device_id uniphier_regulator_match[] = { }, { /* Sentinel */ }, }; +MODULE_DEVICE_TABLE(of, uniphier_regulator_match); static struct platform_driver uniphier_regulator_driver = { .probe = uniphier_regulator_probe, diff --git a/drivers/remoteproc/remoteproc_cdev.c b/drivers/remoteproc/remoteproc_cdev.c index b19ea3057bde4b6beded80c99939187bec1b2e32..ff92ed25d8b0a0a8e71ed72b54cb03eddd678877 100644 --- a/drivers/remoteproc/remoteproc_cdev.c +++ b/drivers/remoteproc/remoteproc_cdev.c @@ -111,7 +111,7 @@ int rproc_char_device_add(struct rproc *rproc) void rproc_char_device_remove(struct rproc *rproc) { - __unregister_chrdev(MAJOR(rproc->dev.devt), rproc->index, 1, "remoteproc"); + cdev_del(&rproc->cdev); } void __init rproc_init_cdev(void) diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index 7651a4b741ca5f5568cfc655541778e3cb900512..47a00794fc360c74c90018471c8a97c2a09b6b25 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -2293,7 +2293,6 @@ int rproc_del(struct rproc *rproc) mutex_unlock(&rproc->lock); rproc_delete_debug_dir(rproc); - rproc_char_device_remove(rproc); /* the rproc is downref'ed as soon as it's removed from the klist */ mutex_lock(&rproc_list_mutex); @@ -2304,6 +2303,7 @@ int rproc_del(struct rproc *rproc) synchronize_rcu(); device_del(&rproc->dev); + rproc_char_device_remove(rproc); return 0; } diff --git a/drivers/remoteproc/ti_k3_r5_remoteproc.c b/drivers/remoteproc/ti_k3_r5_remoteproc.c index d9307935441df999e79f6aa38f36c8601ea39e7a..afeb9d6e4313d83152b255d0f4d647303152cf92 100644 --- a/drivers/remoteproc/ti_k3_r5_remoteproc.c +++ b/drivers/remoteproc/ti_k3_r5_remoteproc.c @@ -1202,9 +1202,9 @@ static int k3_r5_core_of_init(struct platform_device *pdev) core->tsp = k3_r5_core_of_get_tsp(dev, core->ti_sci); if (IS_ERR(core->tsp)) { + ret = PTR_ERR(core->tsp); dev_err(dev, "failed to construct ti-sci proc control, ret = %d\n", ret); - ret = PTR_ERR(core->tsp); goto err; } diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 6b559e83822cd6158ce6c857012d8c43a321bf15..faf12010315119c4e70a5d50513320b3041e3a00 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -52,7 +52,8 @@ config RESET_BRCMSTB config RESET_BRCMSTB_RESCAL bool "Broadcom STB RESCAL reset controller" depends on HAS_IOMEM - default ARCH_BRCMSTB || COMPILE_TEST + depends on ARCH_BRCMSTB || COMPILE_TEST + default ARCH_BRCMSTB help This enables the RESCAL reset controller for SATA, PCIe0, or PCIe1 on BCM7216. @@ -91,6 +92,7 @@ config RESET_IMX8ULP_SIM config RESET_INTEL_GW bool "Intel Reset Controller Driver" + depends on X86 || COMPILE_TEST depends on OF && HAS_IOMEM select REGMAP_MMIO help diff --git a/drivers/reset/core.c b/drivers/reset/core.c index a2df88e9001186c1be07155012d1c2e3ad45537a..f93388b9a4a1f4718d63fde9532cf50d2b4f5dac 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -567,7 +567,10 @@ static struct reset_control *__reset_control_get_internal( if (!rstc) return ERR_PTR(-ENOMEM); - try_module_get(rcdev->owner); + if (!try_module_get(rcdev->owner)) { + kfree(rstc); + return ERR_PTR(-ENODEV); + } rstc->rcdev = rcdev; list_add(&rstc->list, &rcdev->reset_control_head); diff --git a/drivers/reset/reset-a10sr.c b/drivers/reset/reset-a10sr.c index 7eacc89382f8a894479002e0e2132b357c3ae479..99b3bc8382f35da836ac33a149b3e2726d2e2dab 100644 --- a/drivers/reset/reset-a10sr.c +++ b/drivers/reset/reset-a10sr.c @@ -118,6 +118,7 @@ static struct platform_driver a10sr_reset_driver = { .probe = a10sr_reset_probe, .driver = { .name = "altr_a10sr_reset", + .of_match_table = a10sr_reset_of_match, }, }; module_platform_driver(a10sr_reset_driver); diff --git a/drivers/reset/reset-brcmstb.c b/drivers/reset/reset-brcmstb.c index f213264c8567bcac5bec4a9f631c46de4190f8a0..42c9d5241c5306cc74457ed1da570ddedf3b1dd0 100644 --- a/drivers/reset/reset-brcmstb.c +++ b/drivers/reset/reset-brcmstb.c @@ -111,6 +111,7 @@ static const struct of_device_id brcmstb_reset_of_match[] = { { .compatible = "brcm,brcmstb-reset" }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, brcmstb_reset_of_match); static struct platform_driver brcmstb_reset_driver = { .probe = brcmstb_reset_probe, diff --git a/drivers/rtc/proc.c b/drivers/rtc/proc.c index 73344598fc1bef235f6341d2bcc5f4da3482e9a9..cbcdbb19d848e78e6674bd626833151a99773ef0 100644 --- a/drivers/rtc/proc.c +++ b/drivers/rtc/proc.c @@ -23,8 +23,8 @@ static bool is_rtc_hctosys(struct rtc_device *rtc) int size; char name[NAME_SIZE]; - size = scnprintf(name, NAME_SIZE, "rtc%d", rtc->id); - if (size > NAME_SIZE) + size = snprintf(name, NAME_SIZE, "rtc%d", rtc->id); + if (size >= NAME_SIZE) return false; return !strncmp(name, CONFIG_RTC_HCTOSYS_DEVICE, NAME_SIZE); diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c index d774aa18f57a57b2396029f5df58db310e8e886b..d096b58cd06c15f4dca95f083d45c2a5dc2f6f1c 100644 --- a/drivers/rtc/rtc-stm32.c +++ b/drivers/rtc/rtc-stm32.c @@ -754,7 +754,7 @@ static int stm32_rtc_probe(struct platform_device *pdev) ret = clk_prepare_enable(rtc->rtc_ck); if (ret) - goto err; + goto err_no_rtc_ck; if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, @@ -830,10 +830,12 @@ static int stm32_rtc_probe(struct platform_device *pdev) } return 0; + err: + clk_disable_unprepare(rtc->rtc_ck); +err_no_rtc_ck: if (rtc->data->has_pclk) clk_disable_unprepare(rtc->pclk); - clk_disable_unprepare(rtc->rtc_ck); if (rtc->data->need_dbp) regmap_update_bits(rtc->dbp, rtc->dbp_reg, rtc->dbp_mask, 0); diff --git a/drivers/s390/char/sclp_vt220.c b/drivers/s390/char/sclp_vt220.c index 3f9a6ef650fac41c938cc797ced3a62d1b10fa81..3c2ed6d013873aa9a257c229d030c404177ba40a 100644 --- a/drivers/s390/char/sclp_vt220.c +++ b/drivers/s390/char/sclp_vt220.c @@ -35,8 +35,8 @@ #define SCLP_VT220_MINOR 65 #define SCLP_VT220_DRIVER_NAME "sclp_vt220" #define SCLP_VT220_DEVICE_NAME "ttysclp" -#define SCLP_VT220_CONSOLE_NAME "ttyS" -#define SCLP_VT220_CONSOLE_INDEX 1 /* console=ttyS1 */ +#define SCLP_VT220_CONSOLE_NAME "ttysclp" +#define SCLP_VT220_CONSOLE_INDEX 0 /* console=ttysclp0 */ /* Representation of a single write request */ struct sclp_vt220_request { diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index dfcbe54591fbda24eb32a4ead5c7c36ec7fd8162..93e22785a0e092c60a9b0e245a599da376823dba 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c @@ -255,6 +255,9 @@ static ssize_t chp_status_write(struct device *dev, if (!num_args) return count; + /* Wait until previous actions have settled. */ + css_wait_for_slow_path(); + if (!strncasecmp(cmd, "on", 2) || !strcmp(cmd, "1")) { mutex_lock(&cp->lock); error = s390_vary_chpid(cp->chpid, 1); diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index fc06a4002168893e9219bf29ef6ffec3a2c985d0..93aa7eabe8b1f196fd1a5d7b789930cf9815aea8 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c @@ -757,8 +757,6 @@ int chsc_chp_vary(struct chp_id chpid, int on) { struct channel_path *chp = chpid_to_chp(chpid); - /* Wait until previous actions have settled. */ - css_wait_for_slow_path(); /* * Redo PathVerification on the devices the chpid connects to */ diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 8d9662e8b71795bd0c2597aedfcfeeb3048bada3..3c7f5ecf5511df1f15e17ea04fb7600fa9a6ab70 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -487,6 +487,7 @@ static ssize_t zfcp_sysfs_port_fc_security_show(struct device *dev, if (0 == (status & ZFCP_STATUS_COMMON_OPEN) || 0 == (status & ZFCP_STATUS_COMMON_UNBLOCKED) || 0 == (status & ZFCP_STATUS_PORT_PHYS_OPEN) || + 0 != (status & ZFCP_STATUS_PORT_LINK_TEST) || 0 != (status & ZFCP_STATUS_COMMON_ERP_FAILED) || 0 != (status & ZFCP_STATUS_COMMON_ACCESS_BOXED)) i = sprintf(buf, "unknown\n"); diff --git a/drivers/scsi/FlashPoint.c b/drivers/scsi/FlashPoint.c index 24ace18240480a212137e277b3bfa864d90cb6b3..ec8a621d232d6c99a1905b8b12c769b5d0a58025 100644 --- a/drivers/scsi/FlashPoint.c +++ b/drivers/scsi/FlashPoint.c @@ -40,7 +40,7 @@ struct sccb_mgr_info { u16 si_per_targ_ultra_nego; u16 si_per_targ_no_disc; u16 si_per_targ_wide_nego; - u16 si_flags; + u16 si_mflags; unsigned char si_card_family; unsigned char si_bustype; unsigned char si_card_model[3]; @@ -1073,22 +1073,22 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) ScamFlg = (unsigned char)FPT_utilEERead(ioport, SCAM_CONFIG / 2); - pCardInfo->si_flags = 0x0000; + pCardInfo->si_mflags = 0x0000; if (i & 0x01) - pCardInfo->si_flags |= SCSI_PARITY_ENA; + pCardInfo->si_mflags |= SCSI_PARITY_ENA; if (!(i & 0x02)) - pCardInfo->si_flags |= SOFT_RESET; + pCardInfo->si_mflags |= SOFT_RESET; if (i & 0x10) - pCardInfo->si_flags |= EXTENDED_TRANSLATION; + pCardInfo->si_mflags |= EXTENDED_TRANSLATION; if (ScamFlg & SCAM_ENABLED) - pCardInfo->si_flags |= FLAG_SCAM_ENABLED; + pCardInfo->si_mflags |= FLAG_SCAM_ENABLED; if (ScamFlg & SCAM_LEVEL2) - pCardInfo->si_flags |= FLAG_SCAM_LEVEL2; + pCardInfo->si_mflags |= FLAG_SCAM_LEVEL2; j = (RD_HARPOON(ioport + hp_bm_ctrl) & ~SCSI_TERM_ENA_L); if (i & 0x04) { @@ -1104,7 +1104,7 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) if (!(RD_HARPOON(ioport + hp_page_ctrl) & NARROW_SCSI_CARD)) - pCardInfo->si_flags |= SUPPORT_16TAR_32LUN; + pCardInfo->si_mflags |= SUPPORT_16TAR_32LUN; pCardInfo->si_card_family = HARPOON_FAMILY; pCardInfo->si_bustype = BUSTYPE_PCI; @@ -1140,15 +1140,15 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) if (pCardInfo->si_card_model[1] == '3') { if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= LOW_BYTE_TERM; + pCardInfo->si_mflags |= LOW_BYTE_TERM; } else if (pCardInfo->si_card_model[2] == '0') { temp = RD_HARPOON(ioport + hp_xfer_pad); WR_HARPOON(ioport + hp_xfer_pad, (temp & ~BIT(4))); if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= LOW_BYTE_TERM; + pCardInfo->si_mflags |= LOW_BYTE_TERM; WR_HARPOON(ioport + hp_xfer_pad, (temp | BIT(4))); if (RD_HARPOON(ioport + hp_ee_ctrl) & BIT(7)) - pCardInfo->si_flags |= HIGH_BYTE_TERM; + pCardInfo->si_mflags |= HIGH_BYTE_TERM; WR_HARPOON(ioport + hp_xfer_pad, temp); } else { temp = RD_HARPOON(ioport + hp_ee_ctrl); @@ -1166,9 +1166,9 @@ static int FlashPoint_ProbeHostAdapter(struct sccb_mgr_info *pCardInfo) WR_HARPOON(ioport + hp_ee_ctrl, temp); WR_HARPOON(ioport + hp_xfer_pad, temp2); if (!(temp3 & BIT(7))) - pCardInfo->si_flags |= LOW_BYTE_TERM; + pCardInfo->si_mflags |= LOW_BYTE_TERM; if (!(temp3 & BIT(6))) - pCardInfo->si_flags |= HIGH_BYTE_TERM; + pCardInfo->si_mflags |= HIGH_BYTE_TERM; } ARAM_ACCESS(ioport); @@ -1275,7 +1275,7 @@ static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info WR_HARPOON(ioport + hp_arb_id, pCardInfo->si_id); CurrCard->ourId = pCardInfo->si_id; - i = (unsigned char)pCardInfo->si_flags; + i = (unsigned char)pCardInfo->si_mflags; if (i & SCSI_PARITY_ENA) WR_HARPOON(ioport + hp_portctrl_1, (HOST_MODE8 | CHK_SCSI_P)); @@ -1289,14 +1289,14 @@ static void *FlashPoint_HardwareResetHostAdapter(struct sccb_mgr_info j |= SCSI_TERM_ENA_H; WR_HARPOON(ioport + hp_ee_ctrl, j); - if (!(pCardInfo->si_flags & SOFT_RESET)) { + if (!(pCardInfo->si_mflags & SOFT_RESET)) { FPT_sresb(ioport, thisCard); FPT_scini(thisCard, pCardInfo->si_id, 0); } - if (pCardInfo->si_flags & POST_ALL_UNDERRRUNS) + if (pCardInfo->si_mflags & POST_ALL_UNDERRRUNS) CurrCard->globalFlags |= F_NO_FILTER; if (pCurrNvRam) { diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index e4fdb473b990635fd059feb4436ed860042c1353..9294a2c677b3ef9146c3d103313d936fe71e07d6 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -1928,8 +1928,12 @@ static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandContr if (ccb->arc_cdb_size <= 0x300) arc_cdb_size = (ccb->arc_cdb_size - 1) >> 6 | 1; - else - arc_cdb_size = (((ccb->arc_cdb_size + 0xff) >> 8) + 2) << 1 | 1; + else { + arc_cdb_size = ((ccb->arc_cdb_size + 0xff) >> 8) + 2; + if (arc_cdb_size > 0xF) + arc_cdb_size = 0xF; + arc_cdb_size = (arc_cdb_size << 1) | 1; + } ccb_post_stamp = (ccb->smid | arc_cdb_size); writel(0, &pmu->inbound_queueport_high); writel(ccb_post_stamp, &pmu->inbound_queueport_low); @@ -2420,10 +2424,17 @@ static void arcmsr_hbaD_doorbell_isr(struct AdapterControlBlock *pACB) static void arcmsr_hbaE_doorbell_isr(struct AdapterControlBlock *pACB) { - uint32_t outbound_doorbell, in_doorbell, tmp; + uint32_t outbound_doorbell, in_doorbell, tmp, i; struct MessageUnit_E __iomem *reg = pACB->pmuE; - in_doorbell = readl(®->iobound_doorbell); + if (pACB->adapter_type == ACB_ADAPTER_TYPE_F) { + for (i = 0; i < 5; i++) { + in_doorbell = readl(®->iobound_doorbell); + if (in_doorbell != 0) + break; + } + } else + in_doorbell = readl(®->iobound_doorbell); outbound_doorbell = in_doorbell ^ pACB->in_doorbell; do { writel(0, ®->host_int_status); /* clear interrupt */ diff --git a/drivers/scsi/be2iscsi/be_main.c b/drivers/scsi/be2iscsi/be_main.c index 5c3513a4b450ed417ce17007f677e4aca518b31b..987dc8135a9b41f3e67c3aea65dd9efdd216d072 100644 --- a/drivers/scsi/be2iscsi/be_main.c +++ b/drivers/scsi/be2iscsi/be_main.c @@ -416,7 +416,7 @@ static struct beiscsi_hba *beiscsi_hba_alloc(struct pci_dev *pcidev) "beiscsi_hba_alloc - iscsi_host_alloc failed\n"); return NULL; } - shost->max_id = BE2_MAX_SESSIONS; + shost->max_id = BE2_MAX_SESSIONS - 1; shost->max_channel = 0; shost->max_cmd_len = BEISCSI_MAX_CMD_LEN; shost->max_lun = BEISCSI_NUM_MAX_LUN; @@ -5318,7 +5318,7 @@ static int beiscsi_enable_port(struct beiscsi_hba *phba) /* Re-enable UER. If different TPE occurs then it is recoverable. */ beiscsi_set_uer_feature(phba); - phba->shost->max_id = phba->params.cxns_per_ctrl; + phba->shost->max_id = phba->params.cxns_per_ctrl - 1; phba->shost->can_queue = phba->params.ios_per_ctrl; ret = beiscsi_init_port(phba); if (ret < 0) { @@ -5745,6 +5745,7 @@ free_hba: pci_disable_msix(phba->pcidev); pci_dev_put(phba->pcidev); iscsi_host_free(phba->shost); + pci_disable_pcie_error_reporting(pcidev); pci_set_drvdata(pcidev, NULL); disable_pci: pci_release_regions(pcidev); diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index fdd446765311a705c6d1bee24e8ded61b28d65f5..21efc73b87beefa67b6ac0024c89d858d4086baa 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -791,7 +791,7 @@ struct bnx2i_hba *bnx2i_alloc_hba(struct cnic_dev *cnic) return NULL; shost->dma_boundary = cnic->pcidev->dma_mask; shost->transportt = bnx2i_scsi_xport_template; - shost->max_id = ISCSI_MAX_CONNS_PER_HBA; + shost->max_id = ISCSI_MAX_CONNS_PER_HBA - 1; shost->max_channel = 0; shost->max_lun = 512; shost->max_cmd_len = 16; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index f078b3c4e083fb2f8f51920ff469c006140aaaf5..ecb134b4699f2378796c78eab1c71fdf40d5ce2d 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -337,7 +337,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev) EXPORT_SYMBOL_GPL(cxgbi_hbas_remove); int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, - unsigned int max_id, struct scsi_host_template *sht, + unsigned int max_conns, struct scsi_host_template *sht, struct scsi_transport_template *stt) { struct cxgbi_hba *chba; @@ -357,7 +357,7 @@ int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, shost->transportt = stt; shost->max_lun = max_lun; - shost->max_id = max_id; + shost->max_id = max_conns - 1; shost->max_channel = 0; shost->max_cmd_len = SCSI_MAX_VARLEN_CDB_SIZE; diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c index df5a3bbeba5eb2bc12e22ccc426b2234dc58403e..fe8a5e5c0df84f2c7a057f7fe46a42b3fd697491 100644 --- a/drivers/scsi/device_handler/scsi_dh_alua.c +++ b/drivers/scsi/device_handler/scsi_dh_alua.c @@ -508,7 +508,8 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) struct alua_port_group *tmp_pg; int len, k, off, bufflen = ALUA_RTPG_SIZE; unsigned char *desc, *buff; - unsigned err, retval; + unsigned err; + int retval; unsigned int tpg_desc_tbl_off; unsigned char orig_transition_tmo; unsigned long flags; @@ -548,12 +549,12 @@ static int alua_rtpg(struct scsi_device *sdev, struct alua_port_group *pg) kfree(buff); return SCSI_DH_OK; } - if (!scsi_sense_valid(&sense_hdr)) { + if (retval < 0 || !scsi_sense_valid(&sense_hdr)) { sdev_printk(KERN_INFO, sdev, "%s: rtpg failed, result %d\n", ALUA_DH_NAME, retval); kfree(buff); - if (driver_byte(retval) == DRIVER_ERROR) + if (retval < 0) return SCSI_DH_DEV_TEMP_BUSY; return SCSI_DH_IO; } @@ -775,11 +776,11 @@ static unsigned alua_stpg(struct scsi_device *sdev, struct alua_port_group *pg) retval = submit_stpg(sdev, pg->group_id, &sense_hdr); if (retval) { - if (!scsi_sense_valid(&sense_hdr)) { + if (retval < 0 || !scsi_sense_valid(&sense_hdr)) { sdev_printk(KERN_INFO, sdev, "%s: stpg failed, result %d", ALUA_DH_NAME, retval); - if (driver_byte(retval) == DRIVER_ERROR) + if (retval < 0) return SCSI_DH_DEV_TEMP_BUSY; } else { sdev_printk(KERN_INFO, sdev, "%s: stpg failed\n", diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 6c2a97f80b120084e26fc86e4b5264e2df747fa3..2e529d67de7308a2913915ba77faa5e7ff090d86 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1647,7 +1647,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (irq < 0) { dev_err(dev, "irq init: fail map phy interrupt %d\n", idx); - return -ENOENT; + return irq; } rc = devm_request_irq(dev, irq, phy_interrupts[j], 0, @@ -1655,7 +1655,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "irq init: could not request phy interrupt %d, rc=%d\n", irq, rc); - return -ENOENT; + return rc; } } } @@ -1666,7 +1666,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (irq < 0) { dev_err(dev, "irq init: could not map cq interrupt %d\n", idx); - return -ENOENT; + return irq; } rc = devm_request_irq(dev, irq, cq_interrupt_v1_hw, 0, @@ -1674,7 +1674,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "irq init: could not request cq interrupt %d, rc=%d\n", irq, rc); - return -ENOENT; + return rc; } } @@ -1684,7 +1684,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (irq < 0) { dev_err(dev, "irq init: could not map fatal interrupt %d\n", idx); - return -ENOENT; + return irq; } rc = devm_request_irq(dev, irq, fatal_interrupts[i], 0, @@ -1692,7 +1692,7 @@ static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba) if (rc) { dev_err(dev, "irq init: could not request fatal interrupt %d, rc=%d\n", irq, rc); - return -ENOENT; + return rc; } } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index b93dd8ef4ac820f6e27f332bfee686b58f804159..da3920a19d53d036a4dc4c590ca8960d8413e144 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -220,6 +220,9 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, goto fail; } + shost->cmd_per_lun = min_t(short, shost->cmd_per_lun, + shost->can_queue); + error = scsi_init_sense_cache(shost); if (error) goto fail; @@ -490,6 +493,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost_printk(KERN_WARNING, shost, "error handler thread failed to spawn, error = %ld\n", PTR_ERR(shost->ehandler)); + shost->ehandler = NULL; goto fail; } diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 41b8192d207d00847cb68fa2abe9ba34f7cee0ed..30d27b6706746497ace6d23b6e8361e9e1f9ecbd 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -230,11 +230,11 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_task *task) */ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { - struct iscsi_conn *conn = task->conn; - struct iscsi_tm *tmf = &conn->tmhdr; + struct iscsi_session *session = task->conn->session; + struct iscsi_tm *tmf = &session->tmhdr; u64 hdr_lun; - if (conn->tmf_state == TMF_INITIAL) + if (session->tmf_state == TMF_INITIAL) return 0; if ((tmf->opcode & ISCSI_OPCODE_MASK) != ISCSI_OP_SCSI_TMFUNC) @@ -254,24 +254,19 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) * Fail all SCSI cmd PDUs */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) { - iscsi_conn_printk(KERN_INFO, conn, - "task [op %x itt " - "0x%x/0x%x] " - "rejected.\n", - opcode, task->itt, - task->hdr_itt); + iscsi_session_printk(KERN_INFO, session, + "task [op %x itt 0x%x/0x%x] rejected.\n", + opcode, task->itt, task->hdr_itt); return -EACCES; } /* * And also all data-out PDUs in response to R2T * if fast_abort is set. */ - if (conn->session->fast_abort) { - iscsi_conn_printk(KERN_INFO, conn, - "task [op %x itt " - "0x%x/0x%x] fast abort.\n", - opcode, task->itt, - task->hdr_itt); + if (session->fast_abort) { + iscsi_session_printk(KERN_INFO, session, + "task [op %x itt 0x%x/0x%x] fast abort.\n", + opcode, task->itt, task->hdr_itt); return -EACCES; } break; @@ -284,7 +279,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (opcode == ISCSI_OP_SCSI_DATA_OUT && task->hdr_itt == tmf->rtt) { - ISCSI_DBG_SESSION(conn->session, + ISCSI_DBG_SESSION(session, "Preventing task %x/%x from sending " "data-out due to abort task in " "progress\n", task->itt, @@ -923,20 +918,21 @@ iscsi_data_in_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, static void iscsi_tmf_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr) { struct iscsi_tm_rsp *tmf = (struct iscsi_tm_rsp *)hdr; + struct iscsi_session *session = conn->session; conn->exp_statsn = be32_to_cpu(hdr->statsn) + 1; conn->tmfrsp_pdus_cnt++; - if (conn->tmf_state != TMF_QUEUED) + if (session->tmf_state != TMF_QUEUED) return; if (tmf->response == ISCSI_TMF_RSP_COMPLETE) - conn->tmf_state = TMF_SUCCESS; + session->tmf_state = TMF_SUCCESS; else if (tmf->response == ISCSI_TMF_RSP_NO_TASK) - conn->tmf_state = TMF_NOT_FOUND; + session->tmf_state = TMF_NOT_FOUND; else - conn->tmf_state = TMF_FAILED; - wake_up(&conn->ehwait); + session->tmf_state = TMF_FAILED; + wake_up(&session->ehwait); } static int iscsi_send_nopout(struct iscsi_conn *conn, struct iscsi_nopin *rhdr) @@ -1348,7 +1344,6 @@ void iscsi_session_failure(struct iscsi_session *session, enum iscsi_err err) { struct iscsi_conn *conn; - struct device *dev; spin_lock_bh(&session->frwd_lock); conn = session->leadconn; @@ -1357,10 +1352,8 @@ void iscsi_session_failure(struct iscsi_session *session, return; } - dev = get_device(&conn->cls_conn->dev); + iscsi_get_conn(conn->cls_conn); spin_unlock_bh(&session->frwd_lock); - if (!dev) - return; /* * if the host is being removed bypass the connection * recovery initialization because we are going to kill @@ -1370,7 +1363,7 @@ void iscsi_session_failure(struct iscsi_session *session, iscsi_conn_error_event(conn->cls_conn, err); else iscsi_conn_failure(conn, err); - put_device(dev); + iscsi_put_conn(conn->cls_conn); } EXPORT_SYMBOL_GPL(iscsi_session_failure); @@ -1787,15 +1780,14 @@ EXPORT_SYMBOL_GPL(iscsi_target_alloc); static void iscsi_tmf_timedout(struct timer_list *t) { - struct iscsi_conn *conn = from_timer(conn, t, tmf_timer); - struct iscsi_session *session = conn->session; + struct iscsi_session *session = from_timer(session, t, tmf_timer); spin_lock(&session->frwd_lock); - if (conn->tmf_state == TMF_QUEUED) { - conn->tmf_state = TMF_TIMEDOUT; + if (session->tmf_state == TMF_QUEUED) { + session->tmf_state = TMF_TIMEDOUT; ISCSI_DBG_EH(session, "tmf timedout\n"); /* unblock eh_abort() */ - wake_up(&conn->ehwait); + wake_up(&session->ehwait); } spin_unlock(&session->frwd_lock); } @@ -1818,8 +1810,8 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, return -EPERM; } conn->tmfcmd_pdus_cnt++; - conn->tmf_timer.expires = timeout * HZ + jiffies; - add_timer(&conn->tmf_timer); + session->tmf_timer.expires = timeout * HZ + jiffies; + add_timer(&session->tmf_timer); ISCSI_DBG_EH(session, "tmf set timeout\n"); spin_unlock_bh(&session->frwd_lock); @@ -1833,12 +1825,12 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, * 3) session is terminated or restarted or userspace has * given up on recovery */ - wait_event_interruptible(conn->ehwait, age != session->age || + wait_event_interruptible(session->ehwait, age != session->age || session->state != ISCSI_STATE_LOGGED_IN || - conn->tmf_state != TMF_QUEUED); + session->tmf_state != TMF_QUEUED); if (signal_pending(current)) flush_signals(current); - del_timer_sync(&conn->tmf_timer); + del_timer_sync(&session->tmf_timer); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -2198,17 +2190,17 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) } /* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto failed; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED; - hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_abort_task_pdu(task, hdr); if (iscsi_exec_task_mgmt_fn(conn, hdr, age, session->abort_timeout)) goto failed; - switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: spin_unlock_bh(&session->frwd_lock); /* @@ -2223,7 +2215,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) */ spin_lock_bh(&session->frwd_lock); fail_scsi_task(task, DID_ABORT); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); spin_unlock_bh(&session->frwd_lock); iscsi_start_tx(conn); @@ -2234,7 +2226,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) goto failed_unlocked; case TMF_NOT_FOUND: if (!sc->SCp.ptr) { - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; memset(hdr, 0, sizeof(*hdr)); /* task completed before tmf abort response */ ISCSI_DBG_EH(session, "sc completed while abort in " @@ -2243,7 +2235,7 @@ int iscsi_eh_abort(struct scsi_cmnd *sc) } fallthrough; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto failed; } @@ -2300,11 +2292,11 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) conn = session->leadconn; /* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto unlock; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED; - hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_lun_reset_pdu(sc, hdr); if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2313,7 +2305,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) goto unlock; } - switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2321,7 +2313,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto unlock; } @@ -2333,7 +2325,7 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, sc->device->lun, DID_ERROR); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock); iscsi_start_tx(conn); @@ -2356,8 +2348,7 @@ void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session) spin_lock_bh(&session->frwd_lock); if (session->state != ISCSI_STATE_LOGGED_IN) { session->state = ISCSI_STATE_RECOVERY_FAILED; - if (session->leadconn) - wake_up(&session->leadconn->ehwait); + wake_up(&session->ehwait); } spin_unlock_bh(&session->frwd_lock); } @@ -2402,7 +2393,7 @@ failed: iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); ISCSI_DBG_EH(session, "wait for relogin\n"); - wait_event_interruptible(conn->ehwait, + wait_event_interruptible(session->ehwait, session->state == ISCSI_STATE_TERMINATE || session->state == ISCSI_STATE_LOGGED_IN || session->state == ISCSI_STATE_RECOVERY_FAILED); @@ -2463,11 +2454,11 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) conn = session->leadconn; /* only have one tmf outstanding at a time */ - if (conn->tmf_state != TMF_INITIAL) + if (session->tmf_state != TMF_INITIAL) goto unlock; - conn->tmf_state = TMF_QUEUED; + session->tmf_state = TMF_QUEUED; - hdr = &conn->tmhdr; + hdr = &session->tmhdr; iscsi_prep_tgt_reset_pdu(sc, hdr); if (iscsi_exec_task_mgmt_fn(conn, hdr, session->age, @@ -2476,7 +2467,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) goto unlock; } - switch (conn->tmf_state) { + switch (session->tmf_state) { case TMF_SUCCESS: break; case TMF_TIMEDOUT: @@ -2484,7 +2475,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) iscsi_conn_failure(conn, ISCSI_ERR_SCSI_EH_SESSION_RST); goto done; default: - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; goto unlock; } @@ -2496,7 +2487,7 @@ static int iscsi_eh_target_reset(struct scsi_cmnd *sc) spin_lock_bh(&session->frwd_lock); memset(hdr, 0, sizeof(*hdr)); fail_scsi_tasks(conn, -1, DID_ERROR); - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; spin_unlock_bh(&session->frwd_lock); iscsi_start_tx(conn); @@ -2803,7 +2794,10 @@ iscsi_session_setup(struct iscsi_transport *iscsit, struct Scsi_Host *shost, session->tt = iscsit; session->dd_data = cls_session->dd_data + sizeof(*session); + session->tmf_state = TMF_INITIAL; + timer_setup(&session->tmf_timer, iscsi_tmf_timedout, 0); mutex_init(&session->eh_mutex); + spin_lock_init(&session->frwd_lock); spin_lock_init(&session->back_lock); @@ -2907,7 +2901,6 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, conn->c_stage = ISCSI_CONN_INITIAL_STAGE; conn->id = conn_idx; conn->exp_statsn = 0; - conn->tmf_state = TMF_INITIAL; timer_setup(&conn->transport_timer, iscsi_check_transport_timeouts, 0); @@ -2933,8 +2926,7 @@ iscsi_conn_setup(struct iscsi_cls_session *cls_session, int dd_size, goto login_task_data_alloc_fail; conn->login_task->data = conn->data = data; - timer_setup(&conn->tmf_timer, iscsi_tmf_timedout, 0); - init_waitqueue_head(&conn->ehwait); + init_waitqueue_head(&session->ehwait); return cls_conn; @@ -2969,7 +2961,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) * leading connection? then give up on recovery. */ session->state = ISCSI_STATE_TERMINATE; - wake_up(&conn->ehwait); + wake_up(&session->ehwait); } spin_unlock_bh(&session->frwd_lock); @@ -3044,7 +3036,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) * commands after successful recovery */ conn->stop_stage = 0; - conn->tmf_state = TMF_INITIAL; + session->tmf_state = TMF_INITIAL; session->age++; if (session->age == 16) session->age = 0; @@ -3058,7 +3050,7 @@ int iscsi_conn_start(struct iscsi_cls_conn *cls_conn) spin_unlock_bh(&session->frwd_lock); iscsi_unblock_session(session->cls_session); - wake_up(&conn->ehwait); + wake_up(&session->ehwait); return 0; } EXPORT_SYMBOL_GPL(iscsi_conn_start); @@ -3089,9 +3081,10 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) } } -static void iscsi_start_session_recovery(struct iscsi_session *session, - struct iscsi_conn *conn, int flag) +void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; int old_stop_stage; mutex_lock(&session->eh_mutex); @@ -3145,31 +3138,10 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, spin_lock_bh(&session->frwd_lock); fail_scsi_tasks(conn, -1, DID_TRANSPORT_DISRUPTED); fail_mgmt_tasks(session, conn); - memset(&conn->tmhdr, 0, sizeof(conn->tmhdr)); + memset(&session->tmhdr, 0, sizeof(session->tmhdr)); spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); } - -void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - - switch (flag) { - case STOP_CONN_RECOVER: - cls_conn->state = ISCSI_CONN_FAILED; - break; - case STOP_CONN_TERM: - cls_conn->state = ISCSI_CONN_DOWN; - break; - default: - iscsi_conn_printk(KERN_ERR, conn, - "invalid stop flag %d\n", flag); - return; - } - - iscsi_start_session_recovery(session, conn, flag); -} EXPORT_SYMBOL_GPL(iscsi_conn_stop); int iscsi_conn_bind(struct iscsi_cls_session *cls_session, diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index b60945182db8056f253758f5d9c95ae002cb3a0a..3d9889b3d5c8a6ce487d4137501f9bb2ccbcee0b 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1179,6 +1179,15 @@ stop_rr_fcf_flogi: phba->fcf.fcf_redisc_attempted = 0; /* reset */ goto out; } + } else if (vport->port_state > LPFC_FLOGI && + vport->fc_flag & FC_PT2PT) { + /* + * In a p2p topology, it is possible that discovery has + * already progressed, and this completion can be ignored. + * Recheck the indicated topology. + */ + if (!sp->cmn.fPort) + goto out; } flogifail: diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index bf171ef61abd5eb83125f7b3375629cb3d679ae3..990b700de6892a8d5e260665393b29231037a7f8 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -7825,7 +7825,7 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) "0393 Error %d during rpi post operation\n", rc); rc = -ENODEV; - goto out_destroy_queue; + goto out_free_iocblist; } lpfc_sli4_node_prep(phba); @@ -7991,8 +7991,9 @@ out_io_buff_free: out_unset_queue: /* Unset all the queues set up in this routine when error out */ lpfc_sli4_queue_unset(phba); -out_destroy_queue: +out_free_iocblist: lpfc_free_iocb_list(phba); +out_destroy_queue: lpfc_sli4_queue_destroy(phba); out_stop_timers: lpfc_stop_hba_timers(phba); diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 5e4137f10e0e9465d18b1cf28024b7ed5971fa7a..6b8ec57e8bdfa206bfa5c22dd38588e2d05e850c 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -2259,6 +2259,15 @@ enum MR_PERF_MODE { (mode) == MR_LATENCY_PERF_MODE ? "Latency" : \ "Unknown") +enum MEGASAS_LD_TARGET_ID_STATUS { + LD_TARGET_ID_INITIAL, + LD_TARGET_ID_ACTIVE, + LD_TARGET_ID_DELETED, +}; + +#define MEGASAS_TARGET_ID(sdev) \ + (((sdev->channel % 2) * MEGASAS_MAX_DEV_PER_CHANNEL) + sdev->id) + struct megasas_instance { unsigned int *reply_map; @@ -2323,6 +2332,9 @@ struct megasas_instance { struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; struct megasas_pd_list local_pd_list[MEGASAS_MAX_PD]; u8 ld_ids[MEGASAS_MAX_LD_IDS]; + u8 ld_tgtid_status[MEGASAS_MAX_LD_IDS]; + u8 ld_ids_prev[MEGASAS_MAX_LD_IDS]; + u8 ld_ids_from_raidmap[MEGASAS_MAX_LD_IDS]; s8 init_id; u16 max_num_sge; diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c index cc45cdac13844dc9079d2278217dfff46fc6d89a..1a70cc995c28c722d97895e749b0df2135f964a1 100644 --- a/drivers/scsi/megaraid/megaraid_sas_base.c +++ b/drivers/scsi/megaraid/megaraid_sas_base.c @@ -127,6 +127,8 @@ static int megasas_register_aen(struct megasas_instance *instance, u32 seq_num, u32 class_locale_word); static void megasas_get_pd_info(struct megasas_instance *instance, struct scsi_device *sdev); +static void +megasas_set_ld_removed_by_fw(struct megasas_instance *instance); /* * PCI ID table for all supported controllers @@ -421,6 +423,12 @@ megasas_decode_evt(struct megasas_instance *instance) (class_locale.members.locale), format_class(class_locale.members.class), evt_detail->description); + + if (megasas_dbg_lvl & LD_PD_DEBUG) + dev_info(&instance->pdev->dev, + "evt_detail.args.ld.target_id/index %d/%d\n", + evt_detail->args.ld.target_id, evt_detail->args.ld.ld_index); + } /* @@ -1764,6 +1772,7 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) { struct megasas_instance *instance; struct MR_PRIV_DEVICE *mr_device_priv_data; + u32 ld_tgt_id; instance = (struct megasas_instance *) scmd->device->host->hostdata; @@ -1790,17 +1799,21 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd) } } - if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) { + mr_device_priv_data = scmd->device->hostdata; + if (!mr_device_priv_data || + (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR)) { scmd->result = DID_NO_CONNECT << 16; scmd->scsi_done(scmd); return 0; } - mr_device_priv_data = scmd->device->hostdata; - if (!mr_device_priv_data) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; + if (MEGASAS_IS_LOGICAL(scmd->device)) { + ld_tgt_id = MEGASAS_TARGET_ID(scmd->device); + if (instance->ld_tgtid_status[ld_tgt_id] == LD_TARGET_ID_DELETED) { + scmd->result = DID_NO_CONNECT << 16; + scmd->scsi_done(scmd); + return 0; + } } if (atomic_read(&instance->adprecovery) != MEGASAS_HBA_OPERATIONAL) @@ -2080,7 +2093,7 @@ static int megasas_slave_configure(struct scsi_device *sdev) static int megasas_slave_alloc(struct scsi_device *sdev) { - u16 pd_index = 0; + u16 pd_index = 0, ld_tgt_id; struct megasas_instance *instance ; struct MR_PRIV_DEVICE *mr_device_priv_data; @@ -2105,6 +2118,14 @@ scan_target: GFP_KERNEL); if (!mr_device_priv_data) return -ENOMEM; + + if (MEGASAS_IS_LOGICAL(sdev)) { + ld_tgt_id = MEGASAS_TARGET_ID(sdev); + instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_ACTIVE; + if (megasas_dbg_lvl & LD_PD_DEBUG) + sdev_printk(KERN_INFO, sdev, "LD target ID %d created.\n", ld_tgt_id); + } + sdev->hostdata = mr_device_priv_data; atomic_set(&mr_device_priv_data->r1_ldio_hint, @@ -2114,6 +2135,19 @@ scan_target: static void megasas_slave_destroy(struct scsi_device *sdev) { + u16 ld_tgt_id; + struct megasas_instance *instance; + + instance = megasas_lookup_instance(sdev->host->host_no); + + if (MEGASAS_IS_LOGICAL(sdev)) { + ld_tgt_id = MEGASAS_TARGET_ID(sdev); + instance->ld_tgtid_status[ld_tgt_id] = LD_TARGET_ID_DELETED; + if (megasas_dbg_lvl & LD_PD_DEBUG) + sdev_printk(KERN_INFO, sdev, + "LD target ID %d removed from OS stack\n", ld_tgt_id); + } + kfree(sdev->hostdata); sdev->hostdata = NULL; } @@ -3472,6 +3506,22 @@ megasas_complete_abort(struct megasas_instance *instance, } } +static void +megasas_set_ld_removed_by_fw(struct megasas_instance *instance) +{ + uint i; + + for (i = 0; (i < MEGASAS_MAX_LD_IDS); i++) { + if (instance->ld_ids_prev[i] != 0xff && + instance->ld_ids_from_raidmap[i] == 0xff) { + if (megasas_dbg_lvl & LD_PD_DEBUG) + dev_info(&instance->pdev->dev, + "LD target ID %d removed from RAID map\n", i); + instance->ld_tgtid_status[i] = LD_TARGET_ID_DELETED; + } + } +} + /** * megasas_complete_cmd - Completes a command * @instance: Adapter soft state @@ -3634,9 +3684,13 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, fusion->fast_path_io = 0; } + if (instance->adapter_type >= INVADER_SERIES) + megasas_set_ld_removed_by_fw(instance); + megasas_sync_map_info(instance); spin_unlock_irqrestore(instance->host->host_lock, flags); + break; } if (opcode == MR_DCMD_CTRL_EVENT_GET_INFO || @@ -7439,11 +7493,16 @@ static int megasas_probe_one(struct pci_dev *pdev, return 0; fail_start_aen: + instance->unload = 1; + scsi_remove_host(instance->host); fail_io_attach: megasas_mgmt_info.count--; megasas_mgmt_info.max_index--; megasas_mgmt_info.instance[megasas_mgmt_info.max_index] = NULL; + if (instance->requestorId && !instance->skip_heartbeat_timer_del) + del_timer_sync(&instance->sriov_heartbeat_timer); + instance->instancet->disable_intr(instance); megasas_destroy_irqs(instance); @@ -7451,8 +7510,16 @@ fail_io_attach: megasas_release_fusion(instance); else megasas_release_mfi(instance); + if (instance->msix_vectors) pci_free_irq_vectors(instance->pdev); + instance->msix_vectors = 0; + + if (instance->fw_crash_state != UNAVAILABLE) + megasas_free_host_crash_buffer(instance); + + if (instance->adapter_type != MFI_SERIES) + megasas_fusion_stop_watchdog(instance); fail_init_mfi: scsi_host_put(host); fail_alloc_instance: @@ -8764,8 +8831,10 @@ megasas_aen_polling(struct work_struct *work) union megasas_evt_class_locale class_locale; int event_type = 0; u32 seq_num; + u16 ld_target_id; int error; u8 dcmd_ret = DCMD_SUCCESS; + struct scsi_device *sdev1; if (!instance) { printk(KERN_ERR "invalid instance!\n"); @@ -8788,12 +8857,23 @@ megasas_aen_polling(struct work_struct *work) break; case MR_EVT_LD_OFFLINE: - case MR_EVT_CFG_CLEARED: case MR_EVT_LD_DELETED: + ld_target_id = instance->evt_detail->args.ld.target_id; + sdev1 = scsi_device_lookup(instance->host, + MEGASAS_MAX_PD_CHANNELS + + (ld_target_id / MEGASAS_MAX_DEV_PER_CHANNEL), + (ld_target_id - MEGASAS_MAX_DEV_PER_CHANNEL), + 0); + if (sdev1) + megasas_remove_scsi_device(sdev1); + + event_type = SCAN_VD_CHANNEL; + break; case MR_EVT_LD_CREATED: event_type = SCAN_VD_CHANNEL; break; + case MR_EVT_CFG_CLEARED: case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: case MR_EVT_FOREIGN_CFG_IMPORTED: case MR_EVT_LD_STATE_CHANGE: diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c index b6c08d6200335923195e20c1af49d7433f192f58..83f69c33b01a97ff71cb9d005799a56739c7d3db 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fp.c +++ b/drivers/scsi/megaraid/megaraid_sas_fp.c @@ -349,6 +349,10 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) num_lds = le16_to_cpu(drv_map->raidMap.ldCount); + memcpy(instance->ld_ids_prev, + instance->ld_ids_from_raidmap, + sizeof(instance->ld_ids_from_raidmap)); + memset(instance->ld_ids_from_raidmap, 0xff, MEGASAS_MAX_LD_IDS); /*Convert Raid capability values to CPU arch */ for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) { ld = MR_TargetIdToLdGet(i, drv_map); @@ -359,7 +363,7 @@ u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id) raid = MR_LdRaidGet(ld, drv_map); le32_to_cpus((u32 *)&raid->capability); - + instance->ld_ids_from_raidmap[i] = i; num_lds--; } diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index b0c01cf0428f2f8b507421c7251b26a1cfa4540d..13022a42fd6f448383ab0d4f8a2b19afeac3081f 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -3667,6 +3667,7 @@ static void megasas_sync_irqs(unsigned long instance_addr) if (irq_ctx->irq_poll_scheduled) { irq_ctx->irq_poll_scheduled = false; enable_irq(irq_ctx->os_irq); + complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx); } } } @@ -3698,6 +3699,7 @@ int megasas_irqpoll(struct irq_poll *irqpoll, int budget) irq_poll_complete(irqpoll); irq_ctx->irq_poll_scheduled = false; enable_irq(irq_ctx->os_irq); + complete_cmd_fusion(instance, irq_ctx->MSIxIndex, irq_ctx); } return num_entries; @@ -3714,6 +3716,7 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) { struct megasas_instance *instance = (struct megasas_instance *)instance_addr; + struct megasas_irq_context *irq_ctx = NULL; u32 count, MSIxIndex; count = instance->msix_vectors > 0 ? instance->msix_vectors : 1; @@ -3722,8 +3725,10 @@ megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) if (atomic_read(&instance->adprecovery) == MEGASAS_HW_CRITICAL_ERROR) return; - for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) - complete_cmd_fusion(instance, MSIxIndex, NULL); + for (MSIxIndex = 0 ; MSIxIndex < count; MSIxIndex++) { + irq_ctx = &instance->irq_context[MSIxIndex]; + complete_cmd_fusion(instance, MSIxIndex, irq_ctx); + } } /** @@ -5193,6 +5198,7 @@ megasas_alloc_fusion_context(struct megasas_instance *instance) if (!fusion->log_to_span) { dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); + kfree(instance->ctrl_context); return -ENOMEM; } } diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 5f845d7094fcc544447c5d0cf2b3ec4d72f3a6b2..31c384108bc9c209298c4b6181817941f3ee4ee2 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -3526,6 +3526,28 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) ioc->fw_events_cleanup = 1; while ((fw_event = dequeue_next_fw_event(ioc)) || (fw_event = ioc->current_event)) { + + /* + * Don't call cancel_work_sync() for current_event + * other than MPT3SAS_REMOVE_UNRESPONDING_DEVICES; + * otherwise we may observe deadlock if current + * hard reset issued as part of processing the current_event. + * + * Orginal logic of cleaning the current_event is added + * for handling the back to back host reset issued by the user. + * i.e. during back to back host reset, driver use to process + * the two instances of MPT3SAS_REMOVE_UNRESPONDING_DEVICES + * event back to back and this made the drives to unregister + * the devices from SML. + */ + + if (fw_event == ioc->current_event && + ioc->current_event->event != + MPT3SAS_REMOVE_UNRESPONDING_DEVICES) { + ioc->current_event = NULL; + continue; + } + /* * Wait on the fw_event to complete. If this returns 1, then * the event was never executed, and we need a put for the @@ -6007,8 +6029,10 @@ _scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) handle, parent_handle, (u64)sas_expander->sas_address, sas_expander->num_phys); - if (!sas_expander->num_phys) + if (!sas_expander->num_phys) { + rc = -1; goto out_fail; + } sas_expander->phy = kcalloc(sas_expander->num_phys, sizeof(struct _sas_phy), GFP_KERNEL); if (!sas_expander->phy) { diff --git a/drivers/scsi/qedi/qedi.h b/drivers/scsi/qedi/qedi.h index c342defc3f522d3e87c4fcfa6c6e0ee12769a450..ce199a7a16b80c3ba1b5e7f95479ad2942f4837e 100644 --- a/drivers/scsi/qedi/qedi.h +++ b/drivers/scsi/qedi/qedi.h @@ -284,6 +284,7 @@ struct qedi_ctx { #define QEDI_IN_RECOVERY 5 #define QEDI_IN_OFFLINE 6 #define QEDI_IN_SHUTDOWN 7 +#define QEDI_BLOCK_IO 8 u8 mac[ETH_ALEN]; u32 src_ip[4]; diff --git a/drivers/scsi/qedi/qedi_fw.c b/drivers/scsi/qedi/qedi_fw.c index 440ddd2309f1dd1ee13f91c9e796297e1b1c5fdf..4c87640e6a9114e0789f94b0cb3c157dbb9944a1 100644 --- a/drivers/scsi/qedi/qedi_fw.c +++ b/drivers/scsi/qedi/qedi_fw.c @@ -73,7 +73,6 @@ static void qedi_process_logout_resp(struct qedi_ctx *qedi, spin_unlock(&qedi_conn->list_lock); cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr, NULL, 0); spin_unlock(&session->back_lock); @@ -138,7 +137,6 @@ static void qedi_process_text_resp(struct qedi_ctx *qedi, spin_unlock(&qedi_conn->list_lock); cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, qedi_conn->gen_pdu.resp_buf, @@ -161,16 +159,9 @@ static void qedi_tmf_resp_work(struct work_struct *work) set_bit(QEDI_CONN_FW_CLEANUP, &qedi_conn->flags); resp_hdr_ptr = (struct iscsi_tm_rsp *)qedi_cmd->tmf_resp_buf; - iscsi_block_session(session->cls_session); rval = qedi_cleanup_all_io(qedi, qedi_conn, qedi_cmd->task, true); - if (rval) { - qedi_clear_task_idx(qedi, qedi_cmd->task_id); - iscsi_unblock_session(session->cls_session); + if (rval) goto exit_tmf_resp; - } - - iscsi_unblock_session(session->cls_session); - qedi_clear_task_idx(qedi, qedi_cmd->task_id); spin_lock(&session->back_lock); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0); @@ -245,8 +236,6 @@ static void qedi_process_tmf_resp(struct qedi_ctx *qedi, goto unblock_sess; } - qedi_clear_task_idx(qedi, qedi_cmd->task_id); - __iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr_ptr, NULL, 0); kfree(resp_hdr_ptr); @@ -314,7 +303,6 @@ static void qedi_process_login_resp(struct qedi_ctx *qedi, "Freeing tid=0x%x for cid=0x%x\n", cmd->task_id, qedi_conn->iscsi_conn_id); cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id); } static void qedi_get_rq_bdq_buf(struct qedi_ctx *qedi, @@ -468,7 +456,6 @@ static int qedi_process_nopin_mesg(struct qedi_ctx *qedi, } spin_unlock(&qedi_conn->list_lock); - qedi_clear_task_idx(qedi, cmd->task_id); } done: @@ -673,7 +660,6 @@ static void qedi_scsi_completion(struct qedi_ctx *qedi, if (qedi_io_tracing) qedi_trace_io(qedi, task, cmd->task_id, QEDI_IO_TRACE_RSP); - qedi_clear_task_idx(qedi, cmd->task_id); __iscsi_complete_pdu(conn, (struct iscsi_hdr *)hdr, conn->data, datalen); error: @@ -730,7 +716,6 @@ static void qedi_process_nopin_local_cmpl(struct qedi_ctx *qedi, cqe->itid, cmd->task_id); cmd->state = RESPONSE_RECEIVED; - qedi_clear_task_idx(qedi, cmd->task_id); spin_lock_bh(&session->back_lock); __iscsi_put_task(task); @@ -748,7 +733,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, itt_t protoitt = 0; int found = 0; struct qedi_cmd *qedi_cmd = NULL; - u32 rtid = 0; u32 iscsi_cid; struct qedi_conn *qedi_conn; struct qedi_cmd *dbg_cmd; @@ -779,7 +763,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, found = 1; mtask = qedi_cmd->task; tmf_hdr = (struct iscsi_tm *)mtask->hdr; - rtid = work->rtid; list_del_init(&work->list); kfree(work); @@ -821,8 +804,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, if (qedi_cmd->state == CLEANUP_WAIT_FAILED) qedi_cmd->state = CLEANUP_RECV; - qedi_clear_task_idx(qedi_conn->qedi, rtid); - spin_lock(&qedi_conn->list_lock); if (likely(dbg_cmd->io_cmd_in_list)) { dbg_cmd->io_cmd_in_list = false; @@ -856,7 +837,6 @@ static void qedi_process_cmd_cleanup_resp(struct qedi_ctx *qedi, QEDI_INFO(&qedi->dbg_ctx, QEDI_LOG_TID, "Freeing tid=0x%x for cid=0x%x\n", cqe->itid, qedi_conn->iscsi_conn_id); - qedi_clear_task_idx(qedi_conn->qedi, cqe->itid); } else { qedi_get_proto_itt(qedi, cqe->itid, &ptmp_itt); @@ -1453,7 +1433,7 @@ abort_ret: ldel_exit: spin_lock_bh(&qedi_conn->tmf_work_lock); - if (!qedi_cmd->list_tmf_work) { + if (qedi_cmd->list_tmf_work) { list_del_init(&list_work->list); qedi_cmd->list_tmf_work = NULL; kfree(list_work); diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 08c05403cd720f3bf75fad0c1856488ef842ff32..f51723e2d5227d30646beb6cb057621f76a90856 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -330,12 +330,22 @@ free_conn: void qedi_mark_device_missing(struct iscsi_cls_session *cls_session) { - iscsi_block_session(cls_session); + struct iscsi_session *session = cls_session->dd_data; + struct qedi_conn *qedi_conn = session->leadconn->dd_data; + + spin_lock_bh(&session->frwd_lock); + set_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags); + spin_unlock_bh(&session->frwd_lock); } void qedi_mark_device_available(struct iscsi_cls_session *cls_session) { - iscsi_unblock_session(cls_session); + struct iscsi_session *session = cls_session->dd_data; + struct qedi_conn *qedi_conn = session->leadconn->dd_data; + + spin_lock_bh(&session->frwd_lock); + clear_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags); + spin_unlock_bh(&session->frwd_lock); } static int qedi_bind_conn_to_iscsi_cid(struct qedi_ctx *qedi, @@ -772,7 +782,6 @@ static int qedi_mtask_xmit(struct iscsi_conn *conn, struct iscsi_task *task) } cmd->conn = conn->dd_data; - cmd->scsi_cmd = NULL; return qedi_iscsi_send_generic_request(task); } @@ -783,9 +792,16 @@ static int qedi_task_xmit(struct iscsi_task *task) struct qedi_cmd *cmd = task->dd_data; struct scsi_cmnd *sc = task->sc; + /* Clear now so in cleanup_task we know it didn't make it */ + cmd->scsi_cmd = NULL; + cmd->task_id = U16_MAX; + if (test_bit(QEDI_IN_SHUTDOWN, &qedi_conn->qedi->flags)) return -ENODEV; + if (test_bit(QEDI_BLOCK_IO, &qedi_conn->qedi->flags)) + return -EACCES; + cmd->state = 0; cmd->task = NULL; cmd->use_slowpath = false; @@ -1383,13 +1399,24 @@ static umode_t qedi_attr_is_visible(int param_type, int param) static void qedi_cleanup_task(struct iscsi_task *task) { - if (!task->sc || task->state == ISCSI_TASK_PENDING) { + struct qedi_cmd *cmd; + + if (task->state == ISCSI_TASK_PENDING) { QEDI_INFO(NULL, QEDI_LOG_IO, "Returning ref_cnt=%d\n", refcount_read(&task->refcount)); return; } - qedi_iscsi_unmap_sg_list(task->dd_data); + if (task->sc) + qedi_iscsi_unmap_sg_list(task->dd_data); + + cmd = task->dd_data; + if (cmd->task_id != U16_MAX) + qedi_clear_task_idx(iscsi_host_priv(task->conn->session->host), + cmd->task_id); + + cmd->task_id = U16_MAX; + cmd->scsi_cmd = NULL; } struct iscsi_transport qedi_iscsi_transport = { diff --git a/drivers/scsi/qedi/qedi_main.c b/drivers/scsi/qedi/qedi_main.c index 69c5b5ee2169bffedba10eb35d7aadd6cbf32bee..b33eff9ea80baa9cae94c2f3ac879c6708ddd605 100644 --- a/drivers/scsi/qedi/qedi_main.c +++ b/drivers/scsi/qedi/qedi_main.c @@ -642,7 +642,7 @@ static struct qedi_ctx *qedi_host_alloc(struct pci_dev *pdev) goto exit_setup_shost; } - shost->max_id = QEDI_MAX_ISCSI_CONNS_PER_HBA; + shost->max_id = QEDI_MAX_ISCSI_CONNS_PER_HBA - 1; shost->max_channel = 0; shost->max_lun = ~0; shost->max_cmd_len = 16; diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 31d7a6ddc9db7921bf40e8021e9bbdc1af42e50e..d89db29fa829c066b501f0dadc64e1ca8870193e 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -760,6 +760,7 @@ static void scsi_io_completion_action(struct scsi_cmnd *cmd, int result) case 0x07: /* operation in progress */ case 0x08: /* Long write in progress */ case 0x09: /* self test in progress */ + case 0x11: /* notify (enable spinup) required */ case 0x14: /* space allocation in progress */ case 0x1a: /* start stop unit in progress */ case 0x1b: /* sanitize in progress */ @@ -2071,9 +2072,7 @@ EXPORT_SYMBOL_GPL(scsi_mode_select); * @sshdr: place to put sense data (or NULL if no sense to be collected). * must be SCSI_SENSE_BUFFERSIZE big. * - * Returns zero if unsuccessful, or the header offset (either 4 - * or 8 depending on whether a six or ten byte command was - * issued) if successful. + * Returns zero if successful, or a negative error number on failure */ int scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, @@ -2120,6 +2119,8 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer, len, sshdr, timeout, retries, NULL); + if (result < 0) + return result; /* This code looks awful: what it's doing is making sure an * ILLEGAL REQUEST sense return identifies the actual command @@ -2164,13 +2165,15 @@ scsi_mode_sense(struct scsi_device *sdev, int dbd, int modepage, data->block_descriptor_length = buffer[3]; } data->header_length = header_length; + result = 0; } else if ((status_byte(result) == CHECK_CONDITION) && scsi_sense_valid(sshdr) && sshdr->sense_key == UNIT_ATTENTION && retry_count) { retry_count--; goto retry; } - + if (result > 0) + result = -EIO; return result; } EXPORT_SYMBOL(scsi_mode_sense); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index c53c3f9fa526a689b9651d195e9d2bf61bc97115..2171dab3e5dc87f0c859dde9c09fccbd7ebb05fb 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1979,6 +1979,8 @@ static void __iscsi_unblock_session(struct work_struct *work) */ void iscsi_unblock_session(struct iscsi_cls_session *session) { + flush_work(&session->block_work); + queue_work(iscsi_eh_timer_workq, &session->unblock_work); /* * Blocking the session can be done from any context so we only @@ -2351,6 +2353,18 @@ int iscsi_destroy_conn(struct iscsi_cls_conn *conn) } EXPORT_SYMBOL_GPL(iscsi_destroy_conn); +void iscsi_put_conn(struct iscsi_cls_conn *conn) +{ + put_device(&conn->dev); +} +EXPORT_SYMBOL_GPL(iscsi_put_conn); + +void iscsi_get_conn(struct iscsi_cls_conn *conn) +{ + get_device(&conn->dev); +} +EXPORT_SYMBOL_GPL(iscsi_get_conn); + /* * iscsi interface functions */ @@ -2477,9 +2491,22 @@ static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag) * it works. */ mutex_lock(&conn_mutex); + switch (flag) { + case STOP_CONN_RECOVER: + conn->state = ISCSI_CONN_FAILED; + break; + case STOP_CONN_TERM: + conn->state = ISCSI_CONN_DOWN; + break; + default: + iscsi_cls_conn_printk(KERN_ERR, conn, + "invalid stop flag %d\n", flag); + goto unlock; + } + conn->transport->stop_conn(conn, flag); +unlock: mutex_unlock(&conn_mutex); - } static void stop_conn_work_fn(struct work_struct *work) @@ -2904,6 +2931,13 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) default: err = transport->set_param(conn, ev->u.set_param.param, data, ev->u.set_param.len); + if ((conn->state == ISCSI_CONN_BOUND) || + (conn->state == ISCSI_CONN_UP)) { + err = transport->set_param(conn, ev->u.set_param.param, + data, ev->u.set_param.len); + } else { + return -ENOTCONN; + } } return err; @@ -2963,6 +2997,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport, mutex_lock(&conn->ep_mutex); conn->ep = NULL; mutex_unlock(&conn->ep_mutex); + conn->state = ISCSI_CONN_FAILED; } transport->ep_disconnect(ep); @@ -3730,6 +3765,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) ev->r.retcode = transport->bind_conn(session, conn, ev->u.b_conn.transport_eph, ev->u.b_conn.is_leading); + if (!ev->r.retcode) + conn->state = ISCSI_CONN_BOUND; mutex_unlock(&conn_mutex); if (ev->r.retcode || !transport->ep_connect) @@ -3969,7 +4006,8 @@ iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR); static const char *const connection_state_names[] = { [ISCSI_CONN_UP] = "up", [ISCSI_CONN_DOWN] = "down", - [ISCSI_CONN_FAILED] = "failed" + [ISCSI_CONN_FAILED] = "failed", + [ISCSI_CONN_BOUND] = "bound" }; static ssize_t show_conn_state(struct device *dev, diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index c9abed8429c9a041c89ff142616f87814ac533aa..4a96fb05731d2f26f1677c6d429fc4ee16990cb8 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1229,16 +1229,15 @@ int sas_read_port_mode_page(struct scsi_device *sdev) char *buffer = kzalloc(BUF_SIZE, GFP_KERNEL), *msdata; struct sas_end_device *rdev = sas_sdev_to_rdev(sdev); struct scsi_mode_data mode_data; - int res, error; + int error; if (!buffer) return -ENOMEM; - res = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, - &mode_data, NULL); + error = scsi_mode_sense(sdev, 1, 0x19, buffer, BUF_SIZE, 30*HZ, 3, + &mode_data, NULL); - error = -EINVAL; - if (!scsi_status_is_good(res)) + if (error) goto out; msdata = buffer + mode_data.header_length + diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 20a6564f87d9f2b1889d9d4d3df2dda4f0c9f1b0..f0c0935d79099ec4ab47437eb138b32eead8d216 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1389,6 +1389,22 @@ static void sd_uninit_command(struct scsi_cmnd *SCpnt) } } +static bool sd_need_revalidate(struct block_device *bdev, + struct scsi_disk *sdkp) +{ + if (sdkp->device->removable || sdkp->write_prot) { + if (bdev_check_media_change(bdev)) + return true; + } + + /* + * Force a full rescan after ioctl(BLKRRPART). While the disk state has + * nothing to do with partitions, BLKRRPART is used to force a full + * revalidate after things like a format for historical reasons. + */ + return test_bit(GD_NEED_PART_SCAN, &bdev->bd_disk->state); +} + /** * sd_open - open a scsi disk device * @bdev: Block device of the scsi disk to open @@ -1425,10 +1441,8 @@ static int sd_open(struct block_device *bdev, fmode_t mode) if (!scsi_block_when_processing_errors(sdev)) goto error_out; - if (sdev->removable || sdkp->write_prot) { - if (bdev_check_media_change(bdev)) - sd_revalidate_disk(bdev->bd_disk); - } + if (sd_need_revalidate(bdev, sdkp)) + sd_revalidate_disk(bdev->bd_disk); /* * If the drive is empty, just let the open fail. @@ -2673,18 +2687,18 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) * 5: Illegal Request, Sense Code 24: Invalid field in * CDB. */ - if (!scsi_status_is_good(res)) + if (res < 0) res = sd_do_mode_sense(sdkp, 0, 0, buffer, 4, &data, NULL); /* * Third attempt: ask 255 bytes, as we did earlier. */ - if (!scsi_status_is_good(res)) + if (res < 0) res = sd_do_mode_sense(sdkp, 0, 0x3F, buffer, 255, &data, NULL); } - if (!scsi_status_is_good(res)) { + if (res < 0) { sd_first_printk(KERN_WARNING, sdkp, "Test WP failed, assume Write Enabled\n"); } else { @@ -2745,7 +2759,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, first_len, &data, &sshdr); - if (!scsi_status_is_good(res)) + if (res < 0) goto bad_sense; if (!data.header_length) { @@ -2777,7 +2791,7 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) res = sd_do_mode_sense(sdkp, dbd, modepage, buffer, len, &data, &sshdr); - if (scsi_status_is_good(res)) { + if (!res) { int offset = data.header_length + data.block_descriptor_length; while (offset < len) { @@ -2895,7 +2909,7 @@ static void sd_read_app_tag_own(struct scsi_disk *sdkp, unsigned char *buffer) res = scsi_mode_sense(sdp, 1, 0x0a, buffer, 36, SD_TIMEOUT, sdkp->max_retries, &data, &sshdr); - if (!scsi_status_is_good(res) || !data.header_length || + if (res < 0 || !data.header_length || data.length < 6) { sd_first_printk(KERN_WARNING, sdkp, "getting Control mode page failed, assume no ATO\n"); diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index fd4b582110b29f3bb9ad0a6a556813e025495c36..726b7048a7674a24821d7c3b7b41bf74af4c172b 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -220,6 +220,8 @@ static unsigned int sr_get_events(struct scsi_device *sdev) return DISK_EVENT_EJECT_REQUEST; else if (med->media_event_code == 2) return DISK_EVENT_MEDIA_CHANGE; + else if (med->media_event_code == 3) + return DISK_EVENT_EJECT_REQUEST; return 0; } @@ -928,7 +930,7 @@ static void get_capabilities(struct scsi_cd *cd) rc = scsi_mode_sense(cd->device, 0, 0x2a, buffer, ms_len, SR_TIMEOUT, 3, &data, NULL); - if (!scsi_status_is_good(rc) || data.length > ms_len || + if (rc < 0 || data.length > ms_len || data.header_length + data.block_descriptor_length > data.length) { /* failed, drive doesn't have capabilities mode page */ cd->cdi.speed = 1; diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index ded00a89bfc4e04a72fb835aeeed82eaa2050ad6..0ee0b80006e05a4689b03565a481fd79cc0a64d4 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -994,17 +994,40 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, struct storvsc_scan_work *wrk; void (*process_err_fn)(struct work_struct *work); struct hv_host_device *host_dev = shost_priv(host); - bool do_work = false; - switch (SRB_STATUS(vm_srb->srb_status)) { - case SRB_STATUS_ERROR: + /* + * In some situations, Hyper-V sets multiple bits in the + * srb_status, such as ABORTED and ERROR. So process them + * individually, with the most specific bits first. + */ + + if (vm_srb->srb_status & SRB_STATUS_INVALID_LUN) { + set_host_byte(scmnd, DID_NO_CONNECT); + process_err_fn = storvsc_remove_lun; + goto do_work; + } + + if (vm_srb->srb_status & SRB_STATUS_ABORTED) { + if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && + /* Capacity data has changed */ + (asc == 0x2a) && (ascq == 0x9)) { + process_err_fn = storvsc_device_scan; + /* + * Retry the I/O that triggered this. + */ + set_host_byte(scmnd, DID_REQUEUE); + goto do_work; + } + } + + if (vm_srb->srb_status & SRB_STATUS_ERROR) { /* * Let upper layer deal with error when * sense message is present. */ - if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID) - break; + return; + /* * If there is an error; offline the device since all * error recovery strategies would have already been @@ -1017,37 +1040,19 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, set_host_byte(scmnd, DID_PASSTHROUGH); break; /* - * On Some Windows hosts TEST_UNIT_READY command can return - * SRB_STATUS_ERROR, let the upper level code deal with it - * based on the sense information. + * On some Hyper-V hosts TEST_UNIT_READY command can + * return SRB_STATUS_ERROR. Let the upper level code + * deal with it based on the sense information. */ case TEST_UNIT_READY: break; default: set_host_byte(scmnd, DID_ERROR); } - break; - case SRB_STATUS_INVALID_LUN: - set_host_byte(scmnd, DID_NO_CONNECT); - do_work = true; - process_err_fn = storvsc_remove_lun; - break; - case SRB_STATUS_ABORTED: - if (vm_srb->srb_status & SRB_STATUS_AUTOSENSE_VALID && - (asc == 0x2a) && (ascq == 0x9)) { - do_work = true; - process_err_fn = storvsc_device_scan; - /* - * Retry the I/O that triggered this. - */ - set_host_byte(scmnd, DID_REQUEUE); - } - break; } + return; - if (!do_work) - return; - +do_work: /* * We need to schedule work to process this error; schedule it. */ diff --git a/drivers/soundwire/stream.c b/drivers/soundwire/stream.c index a418c3c7001c0220dc5276147581c23a2f30938d..304ff2ee7d75a23c9aee0c39205b0c15461c35bc 100644 --- a/drivers/soundwire/stream.c +++ b/drivers/soundwire/stream.c @@ -422,7 +422,6 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, struct completion *port_ready; struct sdw_dpn_prop *dpn_prop; struct sdw_prepare_ch prep_ch; - unsigned int time_left; bool intr = false; int ret = 0, val; u32 addr; @@ -479,15 +478,15 @@ static int sdw_prep_deprep_slave_ports(struct sdw_bus *bus, /* Wait for completion on port ready */ port_ready = &s_rt->slave->port_ready[prep_ch.num]; - time_left = wait_for_completion_timeout(port_ready, - msecs_to_jiffies(dpn_prop->ch_prep_timeout)); + wait_for_completion_timeout(port_ready, + msecs_to_jiffies(dpn_prop->ch_prep_timeout)); val = sdw_read(s_rt->slave, SDW_DPN_PREPARESTATUS(p_rt->num)); - val &= p_rt->ch_mask; - if (!time_left || val) { + if ((val < 0) || (val & p_rt->ch_mask)) { + ret = (val < 0) ? val : -ETIMEDOUT; dev_err(&s_rt->slave->dev, - "Chn prep failed for port:%d\n", prep_ch.num); - return -ETIMEDOUT; + "Chn prep failed for port %d: %d\n", prep_ch.num, ret); + return ret; } } diff --git a/drivers/spi/spi-loopback-test.c b/drivers/spi/spi-loopback-test.c index df981e55c24c99b618fa4a0e2849bfaab6b88ebc..89b91cdfb2a548c6228913ff2f4fc105dc554819 100644 --- a/drivers/spi/spi-loopback-test.c +++ b/drivers/spi/spi-loopback-test.c @@ -874,7 +874,7 @@ static int spi_test_run_iter(struct spi_device *spi, test.transfers[i].len = len; if (test.transfers[i].tx_buf) test.transfers[i].tx_buf += tx_off; - if (test.transfers[i].tx_buf) + if (test.transfers[i].rx_buf) test.transfers[i].rx_buf += rx_off; } diff --git a/drivers/spi/spi-meson-spicc.c b/drivers/spi/spi-meson-spicc.c index ecba6b4a5d85df106afbbbb14b98cfaf52021302..b2c4621db34d78df86e2e90db2589bfac602db46 100644 --- a/drivers/spi/spi-meson-spicc.c +++ b/drivers/spi/spi-meson-spicc.c @@ -725,7 +725,7 @@ static int meson_spicc_probe(struct platform_device *pdev) ret = clk_prepare_enable(spicc->pclk); if (ret) { dev_err(&pdev->dev, "pclk clock enable failed\n"); - goto out_master; + goto out_core_clk; } device_reset_optional(&pdev->dev); @@ -752,7 +752,7 @@ static int meson_spicc_probe(struct platform_device *pdev) ret = meson_spicc_clk_init(spicc); if (ret) { dev_err(&pdev->dev, "clock registration failed\n"); - goto out_master; + goto out_clk; } ret = devm_spi_register_master(&pdev->dev, master); @@ -764,9 +764,11 @@ static int meson_spicc_probe(struct platform_device *pdev) return 0; out_clk: - clk_disable_unprepare(spicc->core); clk_disable_unprepare(spicc->pclk); +out_core_clk: + clk_disable_unprepare(spicc->core); + out_master: spi_master_put(master); diff --git a/drivers/spi/spi-omap-100k.c b/drivers/spi/spi-omap-100k.c index ccd817ee4917b29ee1f1f77b904d5b712e698804..0d0cd061d3563f5aed7c8ab1d3837a650b3c9e88 100644 --- a/drivers/spi/spi-omap-100k.c +++ b/drivers/spi/spi-omap-100k.c @@ -241,7 +241,7 @@ static int omap1_spi100k_setup_transfer(struct spi_device *spi, else word_len = spi->bits_per_word; - if (spi->bits_per_word > 32) + if (word_len > 32) return -EINVAL; cs->word_len = word_len; diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 19238e1b76b440fef5cf0e056c2bcca722703ebc..803d92f8d031666eb814696abc46012248683664 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -290,6 +290,10 @@ static int sun6i_spi_transfer_one(struct spi_master *master, } sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); + /* Finally enable the bus - doing so before might raise SCK to HIGH */ + reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG); + reg |= SUN6I_GBL_CTL_BUS_ENABLE; + sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg); /* Setup the transfer now... */ if (sspi->tx_buf) @@ -398,7 +402,7 @@ static int sun6i_spi_runtime_resume(struct device *dev) } sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, - SUN6I_GBL_CTL_BUS_ENABLE | SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP); + SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP); return 0; diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index b459e369079f8128d83b152240ea37210f907db4..7fb020a1d66aa6d2d567cc34fd677bebf9578899 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -580,8 +580,10 @@ static void pch_spi_set_tx(struct pch_spi_data *data, int *bpw) data->pkt_tx_buff = kzalloc(size, GFP_KERNEL); if (data->pkt_tx_buff != NULL) { data->pkt_rx_buff = kzalloc(size, GFP_KERNEL); - if (!data->pkt_rx_buff) + if (!data->pkt_rx_buff) { kfree(data->pkt_tx_buff); + data->pkt_tx_buff = NULL; + } } if (!data->pkt_rx_buff) { diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 0cf67de741e7819fc4aa1416f510ab430cda51ef..8c261eac2cee5b64148e9fd3f319f003f5b8ba97 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -2050,6 +2050,7 @@ of_register_spi_device(struct spi_controller *ctlr, struct device_node *nc) /* Store a pointer to the node in the device structure */ of_node_get(nc); spi->dev.of_node = nc; + spi->dev.fwnode = of_fwnode_handle(nc); /* Register the new device */ rc = spi_add_device(spi); @@ -2613,9 +2614,10 @@ static int spi_get_gpio_descs(struct spi_controller *ctlr) native_cs_mask |= BIT(i); } - ctlr->unused_native_cs = ffz(native_cs_mask); - if (num_cs_gpios && ctlr->max_native_cs && - ctlr->unused_native_cs >= ctlr->max_native_cs) { + ctlr->unused_native_cs = ffs(~native_cs_mask) - 1; + + if ((ctlr->flags & SPI_MASTER_GPIO_SS) && num_cs_gpios && + ctlr->max_native_cs && ctlr->unused_native_cs >= ctlr->max_native_cs) { dev_err(dev, "No unused native chip select available\n"); return -EINVAL; } diff --git a/drivers/ssb/scan.c b/drivers/ssb/scan.c index f49ab1aa2149ab28213eed3639804d117ce15ea5..4161e5d1f276e11af68128fcc9edf9a2f8169c28 100644 --- a/drivers/ssb/scan.c +++ b/drivers/ssb/scan.c @@ -325,6 +325,7 @@ int ssb_bus_scan(struct ssb_bus *bus, if (bus->nr_devices > ARRAY_SIZE(bus->devices)) { pr_err("More than %d ssb cores found (%d)\n", SSB_MAX_NR_CORES, bus->nr_devices); + err = -EINVAL; goto err_unmap; } if (bus->bustype == SSB_BUSTYPE_SSB) { diff --git a/drivers/ssb/sdio.c b/drivers/ssb/sdio.c index 7fe0afb42234ff2ecd8db6b876fd5d7d72853064..66c5c2169704b878a783e5b599feae868b8b20b3 100644 --- a/drivers/ssb/sdio.c +++ b/drivers/ssb/sdio.c @@ -411,7 +411,6 @@ static void ssb_sdio_block_write(struct ssb_device *dev, const void *buffer, sdio_claim_host(bus->host_sdio); if (unlikely(ssb_sdio_switch_core(bus, dev))) { error = -EIO; - memset((void *)buffer, 0xff, count); goto err_out; } offset |= bus->sdio_sbaddr & 0xffff; diff --git a/drivers/staging/fbtft/fb_agm1264k-fl.c b/drivers/staging/fbtft/fb_agm1264k-fl.c index eeeeec97ad278158f83f208deb3f46bd0c980c81..b545c2ca80a41273ba2de5d820c201b44455bed9 100644 --- a/drivers/staging/fbtft/fb_agm1264k-fl.c +++ b/drivers/staging/fbtft/fb_agm1264k-fl.c @@ -84,9 +84,9 @@ static void reset(struct fbtft_par *par) dev_dbg(par->info->device, "%s()\n", __func__); - gpiod_set_value(par->gpio.reset, 0); - udelay(20); gpiod_set_value(par->gpio.reset, 1); + udelay(20); + gpiod_set_value(par->gpio.reset, 0); mdelay(120); } @@ -194,12 +194,12 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) /* select chip */ if (*buf) { /* cs1 */ - gpiod_set_value(par->CS0, 1); - gpiod_set_value(par->CS1, 0); - } else { - /* cs0 */ gpiod_set_value(par->CS0, 0); gpiod_set_value(par->CS1, 1); + } else { + /* cs0 */ + gpiod_set_value(par->CS0, 1); + gpiod_set_value(par->CS1, 0); } gpiod_set_value(par->RS, 0); /* RS->0 (command mode) */ @@ -397,8 +397,8 @@ static int write_vmem(struct fbtft_par *par, size_t offset, size_t len) } kfree(convert_buf); - gpiod_set_value(par->CS0, 1); - gpiod_set_value(par->CS1, 1); + gpiod_set_value(par->CS0, 0); + gpiod_set_value(par->CS1, 0); return ret; } @@ -419,10 +419,10 @@ static int write(struct fbtft_par *par, void *buf, size_t len) for (i = 0; i < 8; ++i) gpiod_set_value(par->gpio.db[i], data & (1 << i)); /* set E */ - gpiod_set_value(par->EPIN, 1); + gpiod_set_value(par->EPIN, 0); udelay(5); /* unset E - write */ - gpiod_set_value(par->EPIN, 0); + gpiod_set_value(par->EPIN, 1); udelay(1); } diff --git a/drivers/staging/fbtft/fb_bd663474.c b/drivers/staging/fbtft/fb_bd663474.c index e2c7646588f8c9d5cee07e9514e677163cae4eea..1629c2c440a97d2b549fd2c301de0cd12d23d0ee 100644 --- a/drivers/staging/fbtft/fb_bd663474.c +++ b/drivers/staging/fbtft/fb_bd663474.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -24,9 +23,6 @@ static int init_display(struct fbtft_par *par) { - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - par->fbtftops.reset(par); /* Initialization sequence from Lib_UTFT */ diff --git a/drivers/staging/fbtft/fb_ili9163.c b/drivers/staging/fbtft/fb_ili9163.c index 05648c3ffe474c78260ab3985f544ebaa63b9d57..6582a2c90aafca3d59a45321e916bf2d40ec9fdb 100644 --- a/drivers/staging/fbtft/fb_ili9163.c +++ b/drivers/staging/fbtft/fb_ili9163.c @@ -11,7 +11,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include <video/mipi_display.h> @@ -77,9 +76,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - write_reg(par, MIPI_DCS_SOFT_RESET); /* software reset */ mdelay(500); write_reg(par, MIPI_DCS_EXIT_SLEEP_MODE); /* exit sleep */ diff --git a/drivers/staging/fbtft/fb_ili9320.c b/drivers/staging/fbtft/fb_ili9320.c index f2e72d14431dba301859c74882f64c7ae2943ba5..a8f4c618b754c46d870a77cf476ba5dc2ba0df12 100644 --- a/drivers/staging/fbtft/fb_ili9320.c +++ b/drivers/staging/fbtft/fb_ili9320.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/spi/spi.h> #include <linux/delay.h> diff --git a/drivers/staging/fbtft/fb_ili9325.c b/drivers/staging/fbtft/fb_ili9325.c index c9aa4cb431236b73d303d8cd9df8993883f31b10..16d3b17ca2798dd3cf01222c099f386dca6e503d 100644 --- a/drivers/staging/fbtft/fb_ili9325.c +++ b/drivers/staging/fbtft/fb_ili9325.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -85,9 +84,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - bt &= 0x07; vc &= 0x07; vrh &= 0x0f; diff --git a/drivers/staging/fbtft/fb_ili9340.c b/drivers/staging/fbtft/fb_ili9340.c index 415183c7054a8723d3f27ffdd78e133fc8c2b3f7..704236bcaf3fff2e8bd9ed514675892a54e8cbb2 100644 --- a/drivers/staging/fbtft/fb_ili9340.c +++ b/drivers/staging/fbtft/fb_ili9340.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include <video/mipi_display.h> diff --git a/drivers/staging/fbtft/fb_s6d1121.c b/drivers/staging/fbtft/fb_s6d1121.c index 8c7de3290343417b28f8ff4fa91e6c87c60053c2..62f27172f844904cc60a5638f44e38cfba086190 100644 --- a/drivers/staging/fbtft/fb_s6d1121.c +++ b/drivers/staging/fbtft/fb_s6d1121.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -29,9 +28,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - /* Initialization sequence from Lib_UTFT */ write_reg(par, 0x0011, 0x2004); diff --git a/drivers/staging/fbtft/fb_sh1106.c b/drivers/staging/fbtft/fb_sh1106.c index 6f7249493ea3b4883f92e5be8359ff4a1114b4fc..7b9ab39e1c1a8fd9a7d589d5d94257484e75d211 100644 --- a/drivers/staging/fbtft/fb_sh1106.c +++ b/drivers/staging/fbtft/fb_sh1106.c @@ -9,7 +9,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" diff --git a/drivers/staging/fbtft/fb_ssd1289.c b/drivers/staging/fbtft/fb_ssd1289.c index 7a3fe022cc69db283c2af2d35613cd89e550265d..f27bab38b3ec4cce6a1ebf322115aece4d1606b9 100644 --- a/drivers/staging/fbtft/fb_ssd1289.c +++ b/drivers/staging/fbtft/fb_ssd1289.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include "fbtft.h" @@ -28,9 +27,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - write_reg(par, 0x00, 0x0001); write_reg(par, 0x03, 0xA8A4); write_reg(par, 0x0C, 0x0000); diff --git a/drivers/staging/fbtft/fb_ssd1325.c b/drivers/staging/fbtft/fb_ssd1325.c index 8a3140d41d8bbf64c2e56e0b8af196bd2e77af7c..796a2ac3e19486c9d64296781bc950dfd25702e9 100644 --- a/drivers/staging/fbtft/fb_ssd1325.c +++ b/drivers/staging/fbtft/fb_ssd1325.c @@ -35,8 +35,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - gpiod_set_value(par->gpio.cs, 0); - write_reg(par, 0xb3); write_reg(par, 0xf0); write_reg(par, 0xae); diff --git a/drivers/staging/fbtft/fb_ssd1331.c b/drivers/staging/fbtft/fb_ssd1331.c index 37622c9462aa7da92d25d1016f0c1f68463a86cc..ec5eced7f8cbd6746b869a7e012fba59abbed0d8 100644 --- a/drivers/staging/fbtft/fb_ssd1331.c +++ b/drivers/staging/fbtft/fb_ssd1331.c @@ -81,8 +81,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) va_start(args, len); *buf = (u8)va_arg(args, unsigned int); - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, 0); + gpiod_set_value(par->gpio.dc, 0); ret = par->fbtftops.write(par, par->buf, sizeof(u8)); if (ret < 0) { va_end(args); @@ -104,8 +103,7 @@ static void write_reg8_bus8(struct fbtft_par *par, int len, ...) return; } } - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, 1); + gpiod_set_value(par->gpio.dc, 1); va_end(args); } diff --git a/drivers/staging/fbtft/fb_ssd1351.c b/drivers/staging/fbtft/fb_ssd1351.c index 900b28d826b28a59cdfdc8a578c2999f3e8c857f..cf263a58a1489fe4dd507dfce6b59718ffd1fb68 100644 --- a/drivers/staging/fbtft/fb_ssd1351.c +++ b/drivers/staging/fbtft/fb_ssd1351.c @@ -2,7 +2,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/spi/spi.h> #include <linux/delay.h> diff --git a/drivers/staging/fbtft/fb_upd161704.c b/drivers/staging/fbtft/fb_upd161704.c index c77832ae5e5ba5cffea8cf37915530d29eae745b..c680160d63807fc78a6e17081c6321d79e263c74 100644 --- a/drivers/staging/fbtft/fb_upd161704.c +++ b/drivers/staging/fbtft/fb_upd161704.c @@ -12,7 +12,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" @@ -26,9 +25,6 @@ static int init_display(struct fbtft_par *par) { par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ - /* Initialization sequence from Lib_UTFT */ /* register reset */ diff --git a/drivers/staging/fbtft/fb_watterott.c b/drivers/staging/fbtft/fb_watterott.c index 76b25df376b8f0f5a696e188652da0d57abffae6..a57e1f4feef357e3aa4fe2593f8b5cb9ed068c88 100644 --- a/drivers/staging/fbtft/fb_watterott.c +++ b/drivers/staging/fbtft/fb_watterott.c @@ -8,7 +8,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> -#include <linux/gpio/consumer.h> #include <linux/delay.h> #include "fbtft.h" diff --git a/drivers/staging/fbtft/fbtft-bus.c b/drivers/staging/fbtft/fbtft-bus.c index 63c65dd67b175ca9b28c4121115bac4c001b0cdb..3d422bc1164116bebf81ad8f7e5050310c72ee44 100644 --- a/drivers/staging/fbtft/fbtft-bus.c +++ b/drivers/staging/fbtft/fbtft-bus.c @@ -135,8 +135,7 @@ int fbtft_write_vmem16_bus8(struct fbtft_par *par, size_t offset, size_t len) remain = len / 2; vmem16 = (u16 *)(par->info->screen_buffer + offset); - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, 1); + gpiod_set_value(par->gpio.dc, 1); /* non buffered write */ if (!par->txbuf.buf) diff --git a/drivers/staging/fbtft/fbtft-core.c b/drivers/staging/fbtft/fbtft-core.c index 4f362dad4436a145550eaadf0aa21fd2c89cc6b9..3723269890d5ff613470d0e5c067f42897600837 100644 --- a/drivers/staging/fbtft/fbtft-core.c +++ b/drivers/staging/fbtft/fbtft-core.c @@ -38,8 +38,7 @@ int fbtft_write_buf_dc(struct fbtft_par *par, void *buf, size_t len, int dc) { int ret; - if (par->gpio.dc) - gpiod_set_value(par->gpio.dc, dc); + gpiod_set_value(par->gpio.dc, dc); ret = par->fbtftops.write(par, buf, len); if (ret < 0) @@ -76,20 +75,16 @@ static int fbtft_request_one_gpio(struct fbtft_par *par, struct gpio_desc **gpiop) { struct device *dev = par->info->device; - int ret = 0; *gpiop = devm_gpiod_get_index_optional(dev, name, index, - GPIOD_OUT_HIGH); - if (IS_ERR(*gpiop)) { - ret = PTR_ERR(*gpiop); - dev_err(dev, - "Failed to request %s GPIO: %d\n", name, ret); - return ret; - } + GPIOD_OUT_LOW); + if (IS_ERR(*gpiop)) + return dev_err_probe(dev, PTR_ERR(*gpiop), "Failed to request %s GPIO\n", name); + fbtft_par_dbg(DEBUG_REQUEST_GPIOS, par, "%s: '%s' GPIO\n", __func__, name); - return ret; + return 0; } static int fbtft_request_gpios(struct fbtft_par *par) @@ -226,11 +221,15 @@ static void fbtft_reset(struct fbtft_par *par) { if (!par->gpio.reset) return; + fbtft_par_dbg(DEBUG_RESET, par, "%s()\n", __func__); + gpiod_set_value_cansleep(par->gpio.reset, 1); usleep_range(20, 40); gpiod_set_value_cansleep(par->gpio.reset, 0); msleep(120); + + gpiod_set_value_cansleep(par->gpio.cs, 1); /* Activate chip */ } static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line, @@ -922,8 +921,6 @@ static int fbtft_init_display_from_property(struct fbtft_par *par) goto out_free; par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ index = -1; val = values[++index]; @@ -1018,8 +1015,6 @@ int fbtft_init_display(struct fbtft_par *par) } par->fbtftops.reset(par); - if (par->gpio.cs) - gpiod_set_value(par->gpio.cs, 0); /* Activate chip */ i = 0; while (i < FBTFT_MAX_INIT_SEQUENCE) { diff --git a/drivers/staging/fbtft/fbtft-io.c b/drivers/staging/fbtft/fbtft-io.c index 0863d257d7620edf7cebaf1eb2385735a596f5a2..de1904a443c277364309dcfeb628bc3e41b25ae8 100644 --- a/drivers/staging/fbtft/fbtft-io.c +++ b/drivers/staging/fbtft/fbtft-io.c @@ -142,12 +142,12 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) data = *(u8 *)buf; /* Start writing by pulling down /WR */ - gpiod_set_value(par->gpio.wr, 0); + gpiod_set_value(par->gpio.wr, 1); /* Set data */ #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO if (data == prev_data) { - gpiod_set_value(par->gpio.wr, 0); /* used as delay */ + gpiod_set_value(par->gpio.wr, 1); /* used as delay */ } else { for (i = 0; i < 8; i++) { if ((data & 1) != (prev_data & 1)) @@ -165,7 +165,7 @@ int fbtft_write_gpio8_wr(struct fbtft_par *par, void *buf, size_t len) #endif /* Pullup /WR */ - gpiod_set_value(par->gpio.wr, 1); + gpiod_set_value(par->gpio.wr, 0); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO prev_data = *(u8 *)buf; @@ -192,12 +192,12 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) data = *(u16 *)buf; /* Start writing by pulling down /WR */ - gpiod_set_value(par->gpio.wr, 0); + gpiod_set_value(par->gpio.wr, 1); /* Set data */ #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO if (data == prev_data) { - gpiod_set_value(par->gpio.wr, 0); /* used as delay */ + gpiod_set_value(par->gpio.wr, 1); /* used as delay */ } else { for (i = 0; i < 16; i++) { if ((data & 1) != (prev_data & 1)) @@ -215,7 +215,7 @@ int fbtft_write_gpio16_wr(struct fbtft_par *par, void *buf, size_t len) #endif /* Pullup /WR */ - gpiod_set_value(par->gpio.wr, 1); + gpiod_set_value(par->gpio.wr, 0); #ifndef DO_NOT_OPTIMIZE_FBTFT_WRITE_GPIO prev_data = *(u16 *)buf; diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c index 571f47d394843f66d441b3d7e25dfd2b752a09cf..bd5f874334043217014a2c59c5167d82c838be80 100644 --- a/drivers/staging/gdm724x/gdm_lte.c +++ b/drivers/staging/gdm724x/gdm_lte.c @@ -611,10 +611,12 @@ static void gdm_lte_netif_rx(struct net_device *dev, char *buf, * bytes (99,130,83,99 dec) */ } __packed; - void *addr = buf + sizeof(struct iphdr) + - sizeof(struct udphdr) + - offsetof(struct dhcp_packet, chaddr); - ether_addr_copy(nic->dest_mac_addr, addr); + int offset = sizeof(struct iphdr) + + sizeof(struct udphdr) + + offsetof(struct dhcp_packet, chaddr); + if (offset + ETH_ALEN > len) + return; + ether_addr_copy(nic->dest_mac_addr, buf + offset); } } @@ -677,6 +679,7 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) struct sdu *sdu = NULL; u8 endian = phy_dev->get_endian(phy_dev->priv_dev); u8 *data = (u8 *)multi_sdu->data; + int copied; u16 i = 0; u16 num_packet; u16 hci_len; @@ -688,6 +691,12 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet); for (i = 0; i < num_packet; i++) { + copied = data - multi_sdu->data; + if (len < copied + sizeof(*sdu)) { + pr_err("rx prevent buffer overflow"); + return; + } + sdu = (struct sdu *)data; cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt); @@ -698,7 +707,8 @@ static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len) pr_err("rx sdu wrong hci %04x\n", cmd_evt); return; } - if (hci_len < 12) { + if (hci_len < 12 || + len < copied + sizeof(*sdu) + (hci_len - 12)) { pr_err("rx sdu invalid len %d\n", hci_len); return; } diff --git a/drivers/staging/media/hantro/hantro_drv.c b/drivers/staging/media/hantro/hantro_drv.c index 3cd00cc0a364171dd9cf6d43039c5130c9c19141..7749ca9a8ebbfe7a432bdf4a9b4976b0eebf4a80 100644 --- a/drivers/staging/media/hantro/hantro_drv.c +++ b/drivers/staging/media/hantro/hantro_drv.c @@ -56,16 +56,12 @@ dma_addr_t hantro_get_ref(struct hantro_ctx *ctx, u64 ts) return hantro_get_dec_buf_addr(ctx, buf); } -static void hantro_job_finish(struct hantro_dev *vpu, - struct hantro_ctx *ctx, - enum vb2_buffer_state result) +static void hantro_job_finish_no_pm(struct hantro_dev *vpu, + struct hantro_ctx *ctx, + enum vb2_buffer_state result) { struct vb2_v4l2_buffer *src, *dst; - pm_runtime_mark_last_busy(vpu->dev); - pm_runtime_put_autosuspend(vpu->dev); - clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks); - src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); @@ -81,6 +77,18 @@ static void hantro_job_finish(struct hantro_dev *vpu, result); } +static void hantro_job_finish(struct hantro_dev *vpu, + struct hantro_ctx *ctx, + enum vb2_buffer_state result) +{ + pm_runtime_mark_last_busy(vpu->dev); + pm_runtime_put_autosuspend(vpu->dev); + + clk_bulk_disable(vpu->variant->num_clocks, vpu->clocks); + + hantro_job_finish_no_pm(vpu, ctx, result); +} + void hantro_irq_done(struct hantro_dev *vpu, enum vb2_buffer_state result) { @@ -152,12 +160,15 @@ static void device_run(void *priv) src = hantro_get_src_buf(ctx); dst = hantro_get_dst_buf(ctx); + ret = pm_runtime_get_sync(ctx->dev->dev); + if (ret < 0) { + pm_runtime_put_noidle(ctx->dev->dev); + goto err_cancel_job; + } + ret = clk_bulk_enable(ctx->dev->variant->num_clocks, ctx->dev->clocks); if (ret) goto err_cancel_job; - ret = pm_runtime_get_sync(ctx->dev->dev); - if (ret < 0) - goto err_cancel_job; v4l2_m2m_buf_copy_metadata(src, dst, true); @@ -165,7 +176,7 @@ static void device_run(void *priv) return; err_cancel_job: - hantro_job_finish(ctx->dev, ctx, VB2_BUF_STATE_ERROR); + hantro_job_finish_no_pm(ctx->dev, ctx, VB2_BUF_STATE_ERROR); } static struct v4l2_m2m_ops vpu_m2m_ops = { diff --git a/drivers/staging/media/hantro/hantro_v4l2.c b/drivers/staging/media/hantro/hantro_v4l2.c index f5fbdbc4ffdb183b3bf00a27e7c6b95a25668953..5c2ca61add8e835d3cc7db3b07fd3fdae7ebe066 100644 --- a/drivers/staging/media/hantro/hantro_v4l2.c +++ b/drivers/staging/media/hantro/hantro_v4l2.c @@ -639,7 +639,14 @@ static int hantro_buf_prepare(struct vb2_buffer *vb) ret = hantro_buf_plane_check(vb, pix_fmt); if (ret) return ret; - vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage); + /* + * Buffer's bytesused must be written by driver for CAPTURE buffers. + * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets + * it to buffer length). + */ + if (V4L2_TYPE_IS_CAPTURE(vq->type)) + vb2_set_plane_payload(vb, 0, pix_fmt->plane_fmt[0].sizeimage); + return 0; } diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c index 21ebf77696964f4da12004df69947d44a8cae381..d9a8667b4bedf57cd801a4c4bffa2d5055794a47 100644 --- a/drivers/staging/media/imx/imx-media-csi.c +++ b/drivers/staging/media/imx/imx-media-csi.c @@ -753,9 +753,10 @@ static int csi_setup(struct csi_priv *priv) static int csi_start(struct csi_priv *priv) { - struct v4l2_fract *output_fi; + struct v4l2_fract *input_fi, *output_fi; int ret; + input_fi = &priv->frame_interval[CSI_SINK_PAD]; output_fi = &priv->frame_interval[priv->active_output_pad]; /* start upstream */ @@ -764,6 +765,17 @@ static int csi_start(struct csi_priv *priv) if (ret) return ret; + /* Skip first few frames from a BT.656 source */ + if (priv->upstream_ep.bus_type == V4L2_MBUS_BT656) { + u32 delay_usec, bad_frames = 20; + + delay_usec = DIV_ROUND_UP_ULL((u64)USEC_PER_SEC * + input_fi->numerator * bad_frames, + input_fi->denominator); + + usleep_range(delay_usec, delay_usec + 1000); + } + if (priv->dest == IPU_CSI_DEST_IDMAC) { ret = csi_idmac_start(priv); if (ret) @@ -1930,19 +1942,13 @@ static int imx_csi_async_register(struct csi_priv *priv) port, 0, FWNODE_GRAPH_ENDPOINT_NEXT); if (ep) { - asd = kzalloc(sizeof(*asd), GFP_KERNEL); - if (!asd) { - fwnode_handle_put(ep); - return -ENOMEM; - } - - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &priv->notifier, ep, asd); + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &priv->notifier, ep, sizeof(*asd)); fwnode_handle_put(ep); - if (ret) { - kfree(asd); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); /* OK if asd already exists */ if (ret != -EEXIST) return ret; diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c index 94d87d27d38962e620c4f27c1cafabc9c15f3ef0..9457761b7c8babc4a43de9c1c0dcc31b1532c044 100644 --- a/drivers/staging/media/imx/imx6-mipi-csi2.c +++ b/drivers/staging/media/imx/imx6-mipi-csi2.c @@ -557,7 +557,7 @@ static int csi2_async_register(struct csi2_dev *csi2) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY, }; - struct v4l2_async_subdev *asd = NULL; + struct v4l2_async_subdev *asd; struct fwnode_handle *ep; int ret; @@ -577,19 +577,13 @@ static int csi2_async_register(struct csi2_dev *csi2) dev_dbg(csi2->dev, "data lanes: %d\n", csi2->bus.num_data_lanes); dev_dbg(csi2->dev, "flags: 0x%08x\n", csi2->bus.flags); - asd = kzalloc(sizeof(*asd), GFP_KERNEL); - if (!asd) { - ret = -ENOMEM; - goto err_parse; - } - - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &csi2->notifier, ep, asd); - if (ret) - goto err_parse; - + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &csi2->notifier, ep, sizeof(*asd)); fwnode_handle_put(ep); + if (IS_ERR(asd)) + return PTR_ERR(asd); + csi2->notifier.ops = &csi2_notify_ops; ret = v4l2_async_subdev_notifier_register(&csi2->sd, @@ -601,7 +595,6 @@ static int csi2_async_register(struct csi2_dev *csi2) err_parse: fwnode_handle_put(ep); - kfree(asd); return ret; } diff --git a/drivers/staging/media/imx/imx7-media-csi.c b/drivers/staging/media/imx/imx7-media-csi.c index ac52b1daf991448174077e91713de0c2151399cd..6c59485291ca380464dc142d058405b1be19dccd 100644 --- a/drivers/staging/media/imx/imx7-media-csi.c +++ b/drivers/staging/media/imx/imx7-media-csi.c @@ -1191,7 +1191,7 @@ static const struct v4l2_async_notifier_operations imx7_csi_notify_ops = { static int imx7_csi_async_register(struct imx7_csi *csi) { - struct v4l2_async_subdev *asd = NULL; + struct v4l2_async_subdev *asd; struct fwnode_handle *ep; int ret; @@ -1200,19 +1200,13 @@ static int imx7_csi_async_register(struct imx7_csi *csi) ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(csi->dev), 0, 0, FWNODE_GRAPH_ENDPOINT_NEXT); if (ep) { - asd = kzalloc(sizeof(*asd), GFP_KERNEL); - if (!asd) { - fwnode_handle_put(ep); - return -ENOMEM; - } - - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &csi->notifier, ep, asd); + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &csi->notifier, ep, sizeof(*asd)); fwnode_handle_put(ep); - if (ret) { - kfree(asd); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); /* OK if asd already exists */ if (ret != -EEXIST) return ret; diff --git a/drivers/staging/media/imx/imx7-mipi-csis.c b/drivers/staging/media/imx/imx7-mipi-csis.c index 7612993cc1d68cfa854fac5c7354d2798bdccef6..a392f9012626b103a446ea651f4f6531991d7b20 100644 --- a/drivers/staging/media/imx/imx7-mipi-csis.c +++ b/drivers/staging/media/imx/imx7-mipi-csis.c @@ -597,13 +597,15 @@ static void mipi_csis_clear_counters(struct csi_state *state) static void mipi_csis_log_counters(struct csi_state *state, bool non_errors) { - int i = non_errors ? MIPI_CSIS_NUM_EVENTS : MIPI_CSIS_NUM_EVENTS - 4; + unsigned int num_events = non_errors ? MIPI_CSIS_NUM_EVENTS + : MIPI_CSIS_NUM_EVENTS - 6; struct device *dev = &state->pdev->dev; unsigned long flags; + unsigned int i; spin_lock_irqsave(&state->slock, flags); - for (i--; i >= 0; i--) { + for (i = 0; i < num_events; ++i) { if (state->events[i].counter > 0 || state->debug) dev_info(dev, "%s events: %d\n", state->events[i].name, state->events[i].counter); @@ -1004,7 +1006,7 @@ static int mipi_csis_async_register(struct csi_state *state) struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY, }; - struct v4l2_async_subdev *asd = NULL; + struct v4l2_async_subdev *asd; struct fwnode_handle *ep; int ret; @@ -1024,17 +1026,13 @@ static int mipi_csis_async_register(struct csi_state *state) dev_dbg(state->dev, "data lanes: %d\n", state->bus.num_data_lanes); dev_dbg(state->dev, "flags: 0x%08x\n", state->bus.flags); - asd = kzalloc(sizeof(*asd), GFP_KERNEL); - if (!asd) { - ret = -ENOMEM; + asd = v4l2_async_notifier_add_fwnode_remote_subdev( + &state->notifier, ep, sizeof(*asd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); goto err_parse; } - ret = v4l2_async_notifier_add_fwnode_remote_subdev( - &state->notifier, ep, asd); - if (ret) - goto err_parse; - fwnode_handle_put(ep); state->notifier.ops = &mipi_csis_notify_ops; @@ -1048,7 +1046,6 @@ static int mipi_csis_async_register(struct csi_state *state) err_parse: fwnode_handle_put(ep); - kfree(asd); return ret; } diff --git a/drivers/staging/media/rkisp1/rkisp1-dev.c b/drivers/staging/media/rkisp1/rkisp1-dev.c index 91584695804bbf437307889f8d16aa2d635d474b..06de5540c8af4841ab47d109f389b32c23220541 100644 --- a/drivers/staging/media/rkisp1/rkisp1-dev.c +++ b/drivers/staging/media/rkisp1/rkisp1-dev.c @@ -252,6 +252,7 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1) .bus_type = V4L2_MBUS_CSI2_DPHY }; struct rkisp1_sensor_async *rk_asd = NULL; + struct v4l2_async_subdev *asd; struct fwnode_handle *ep; ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(rkisp1->dev), @@ -263,21 +264,18 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1) if (ret) goto err_parse; - rk_asd = kzalloc(sizeof(*rk_asd), GFP_KERNEL); - if (!rk_asd) { - ret = -ENOMEM; + asd = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep, + sizeof(*rk_asd)); + if (IS_ERR(asd)) { + ret = PTR_ERR(asd); goto err_parse; } + rk_asd = container_of(asd, struct rkisp1_sensor_async, asd); rk_asd->mbus_type = vep.bus_type; rk_asd->mbus_flags = vep.bus.mipi_csi2.flags; rk_asd->lanes = vep.bus.mipi_csi2.num_data_lanes; - ret = v4l2_async_notifier_add_fwnode_remote_subdev(ntf, ep, - &rk_asd->asd); - if (ret) - goto err_parse; - dev_dbg(rkisp1->dev, "registered ep id %d with %d lanes\n", vep.base.id, rk_asd->lanes); @@ -288,7 +286,6 @@ static int rkisp1_subdev_notifier(struct rkisp1_device *rkisp1) continue; err_parse: fwnode_handle_put(ep); - kfree(rk_asd); v4l2_async_notifier_cleanup(ntf); return ret; } diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c index 1263991de76f9ea07fa46d06f1311247c3249177..e68303e2b3907c87a95af982c923827afafcd4b7 100644 --- a/drivers/staging/media/rkvdec/rkvdec.c +++ b/drivers/staging/media/rkvdec/rkvdec.c @@ -471,7 +471,15 @@ static int rkvdec_buf_prepare(struct vb2_buffer *vb) if (vb2_plane_size(vb, i) < sizeimage) return -EINVAL; } - vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); + + /* + * Buffer's bytesused must be written by driver for CAPTURE buffers. + * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets + * it to buffer length). + */ + if (V4L2_TYPE_IS_CAPTURE(vq->type)) + vb2_set_plane_payload(vb, 0, f->fmt.pix_mp.plane_fmt[0].sizeimage); + return 0; } @@ -691,7 +699,7 @@ static void rkvdec_device_run(void *priv) if (WARN_ON(!desc)) return; - ret = pm_runtime_get_sync(rkvdec->dev); + ret = pm_runtime_resume_and_get(rkvdec->dev); if (ret < 0) { rkvdec_job_finish_no_pm(ctx, VB2_BUF_STATE_ERROR); return; diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c index ce497d0197dfc3df8daeb4f6594f34145e9f4827..10744fab7ceaa1e11471d9b4ace77794d45e2bd7 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c @@ -477,8 +477,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, slice_params->flags); reg |= VE_DEC_H265_FLAG(VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_DEPENDENT_SLICE_SEGMENT, - V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT, - pps->flags); + V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT, + slice_params->flags); /* FIXME: For multi-slice support. */ reg |= VE_DEC_H265_DEC_SLICE_HDR_INFO0_FLAG_FIRST_SLICE_SEGMENT_IN_PIC; diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_video.c b/drivers/staging/media/sunxi/cedrus/cedrus_video.c index 911f607d9b092f9dcdaebfd5d76e915a760a6904..16327be904d1a7d8c6988e6f5962c3346c68fdc4 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_video.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_video.c @@ -449,7 +449,13 @@ static int cedrus_buf_prepare(struct vb2_buffer *vb) if (vb2_plane_size(vb, 0) < pix_fmt->sizeimage) return -EINVAL; - vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); + /* + * Buffer's bytesused must be written by driver for CAPTURE buffers. + * (for OUTPUT buffers, if userspace passes 0 bytesused, v4l2-core sets + * it to buffer length). + */ + if (V4L2_TYPE_IS_CAPTURE(vq->type)) + vb2_set_plane_payload(vb, 0, pix_fmt->sizeimage); return 0; } diff --git a/drivers/staging/mt7621-dts/mt7621.dtsi b/drivers/staging/mt7621-dts/mt7621.dtsi index 82aa93634eda3d25a6bb9ee8e19b26fa365c1e5b..27222f7b246fd970d982be1c483a87aa6838b7ac 100644 --- a/drivers/staging/mt7621-dts/mt7621.dtsi +++ b/drivers/staging/mt7621-dts/mt7621.dtsi @@ -519,7 +519,7 @@ bus-range = <0 255>; ranges = < - 0x02000000 0 0x00000000 0x60000000 0 0x10000000 /* pci memory */ + 0x02000000 0 0x60000000 0x60000000 0 0x10000000 /* pci memory */ 0x01000000 0 0x00000000 0x1e160000 0 0x00010000 /* io space */ >; diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c index 715f1fe8b472639263c4b57928d9e3fdae8fa9ee..22974277afa08abf65293d549c25af939cb26cc3 100644 --- a/drivers/staging/rtl8712/hal_init.c +++ b/drivers/staging/rtl8712/hal_init.c @@ -40,7 +40,10 @@ static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context) dev_err(&udev->dev, "r8712u: Firmware request failed\n"); usb_put_dev(udev); usb_set_intfdata(usb_intf, NULL); + r8712_free_drv_sw(adapter); + adapter->dvobj_deinit(adapter); complete(&adapter->rtl8712_fw_ready); + free_netdev(adapter->pnetdev); return; } adapter->fw = firmware; diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c index 0c3ae8495afb7a8e4111ce9522a4e2a3182d911f..2214aca0973088ee183224a1353d9755c1a8c1c7 100644 --- a/drivers/staging/rtl8712/os_intfs.c +++ b/drivers/staging/rtl8712/os_intfs.c @@ -328,8 +328,6 @@ int r8712_init_drv_sw(struct _adapter *padapter) void r8712_free_drv_sw(struct _adapter *padapter) { - struct net_device *pnetdev = padapter->pnetdev; - r8712_free_cmd_priv(&padapter->cmdpriv); r8712_free_evt_priv(&padapter->evtpriv); r8712_DeInitSwLeds(padapter); @@ -339,8 +337,6 @@ void r8712_free_drv_sw(struct _adapter *padapter) _r8712_free_sta_priv(&padapter->stapriv); _r8712_free_recv_priv(&padapter->recvpriv); mp871xdeinit(padapter); - if (pnetdev) - free_netdev(pnetdev); } static void enable_video_mode(struct _adapter *padapter, int cbw40_value) diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index dc21e7743349c0f720f4db041045870c0f63d0dd..b760bc355937347095dd9be2a79427870dd59c04 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c @@ -361,7 +361,7 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, /* step 1. */ pnetdev = r8712_init_netdev(); if (!pnetdev) - goto error; + goto put_dev; padapter = netdev_priv(pnetdev); disable_ht_for_spec_devid(pdid, padapter); pdvobjpriv = &padapter->dvobjpriv; @@ -381,16 +381,16 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, * initialize the dvobj_priv */ if (!padapter->dvobj_init) { - goto error; + goto put_dev; } else { status = padapter->dvobj_init(padapter); if (status != _SUCCESS) - goto error; + goto free_netdev; } /* step 4. */ status = r8712_init_drv_sw(padapter); if (status) - goto error; + goto dvobj_deinit; /* step 5. read efuse/eeprom data and get mac_addr */ { int i, offset; @@ -570,17 +570,20 @@ static int r871xu_drv_init(struct usb_interface *pusb_intf, } /* step 6. Load the firmware asynchronously */ if (rtl871x_load_fw(padapter)) - goto error; + goto deinit_drv_sw; spin_lock_init(&padapter->lock_rx_ff0_filter); mutex_init(&padapter->mutex_start); return 0; -error: + +deinit_drv_sw: + r8712_free_drv_sw(padapter); +dvobj_deinit: + padapter->dvobj_deinit(padapter); +free_netdev: + free_netdev(pnetdev); +put_dev: usb_put_dev(udev); usb_set_intfdata(pusb_intf, NULL); - if (padapter && padapter->dvobj_deinit) - padapter->dvobj_deinit(padapter); - if (pnetdev) - free_netdev(pnetdev); return -ENODEV; } @@ -612,6 +615,7 @@ static void r871xu_dev_remove(struct usb_interface *pusb_intf) r8712_stop_drv_timers(padapter); r871x_dev_unload(padapter); r8712_free_drv_sw(padapter); + free_netdev(pnetdev); /* decrease the reference count of the usb device structure * when disconnect diff --git a/drivers/staging/rtl8723bs/hal/odm.h b/drivers/staging/rtl8723bs/hal/odm.h index 16e8f66a31714dceba9de1e48b8850d848c1535e..a8d232245227b2a9bb10de0e383d7b5285bae7da 100644 --- a/drivers/staging/rtl8723bs/hal/odm.h +++ b/drivers/staging/rtl8723bs/hal/odm.h @@ -197,10 +197,7 @@ typedef struct _ODM_RATE_ADAPTIVE { #define AVG_THERMAL_NUM 8 #define IQK_Matrix_REG_NUM 8 -#define IQK_Matrix_Settings_NUM (14 + 24 + 21) /* Channels_2_4G_NUM - * + Channels_5G_20M_NUM - * + Channels_5G - */ +#define IQK_Matrix_Settings_NUM 14 /* Channels_2_4G_NUM */ #define DM_Type_ByFW 0 #define DM_Type_ByDriver 1 diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c index 9097bcbd67d8226bc68315235af1de25e09cf5e4..d697ea55a0da18791539d5b9e10e97aaaf2ef327 100644 --- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c +++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c @@ -1862,7 +1862,7 @@ int vchiq_mmal_init(struct vchiq_mmal_instance **out_instance) int status; int err = -ENODEV; struct vchiq_mmal_instance *instance; - static struct vchiq_instance *vchiq_instance; + struct vchiq_instance *vchiq_instance; struct vchiq_service_params_kernel params = { .version = VC_MMAL_VER, .version_min = VC_MMAL_MIN_VER, diff --git a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c index af35251232eb30f9546703328988fdcea06e16dd..b044999ad002bae82f88e55f22cd05ae70ef3adc 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_ddp.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_ddp.c @@ -265,12 +265,13 @@ void cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd) struct cxgbit_cmd *ccmd = iscsit_priv_cmd(cmd); if (ccmd->release) { - struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo; - - if (ttinfo->sgl) { + if (cmd->se_cmd.se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC) { + put_page(sg_page(&ccmd->sg)); + } else { struct cxgbit_sock *csk = conn->context; struct cxgbit_device *cdev = csk->com.cdev; struct cxgbi_ppm *ppm = cdev2ppm(cdev); + struct cxgbi_task_tag_info *ttinfo = &ccmd->ttinfo; /* Abort the TCP conn if DDP is not complete to * avoid any possibility of DDP after freeing @@ -280,14 +281,14 @@ void cxgbit_unmap_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd) cmd->se_cmd.data_length)) cxgbit_abort_conn(csk); + if (unlikely(ttinfo->sgl)) { + dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl, + ttinfo->nents, DMA_FROM_DEVICE); + ttinfo->nents = 0; + ttinfo->sgl = NULL; + } cxgbi_ppm_ppod_release(ppm, ttinfo->idx); - - dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl, - ttinfo->nents, DMA_FROM_DEVICE); - } else { - put_page(sg_page(&ccmd->sg)); } - ccmd->release = false; } } diff --git a/drivers/target/iscsi/cxgbit/cxgbit_target.c b/drivers/target/iscsi/cxgbit/cxgbit_target.c index b926e1d6c7b8e540f2078bc491cd7e0fc6bfe457..282297ffc4044b2ed489da59e785e1fe1cab80f5 100644 --- a/drivers/target/iscsi/cxgbit/cxgbit_target.c +++ b/drivers/target/iscsi/cxgbit/cxgbit_target.c @@ -997,17 +997,18 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk) struct scatterlist *sg_start; struct iscsi_conn *conn = csk->conn; struct iscsi_cmd *cmd = NULL; + struct cxgbit_cmd *ccmd; + struct cxgbi_task_tag_info *ttinfo; struct cxgbit_lro_pdu_cb *pdu_cb = cxgbit_rx_pdu_cb(csk->skb); struct iscsi_data *hdr = (struct iscsi_data *)pdu_cb->hdr; u32 data_offset = be32_to_cpu(hdr->offset); - u32 data_len = pdu_cb->dlen; + u32 data_len = ntoh24(hdr->dlength); int rc, sg_nents, sg_off; bool dcrc_err = false; if (pdu_cb->flags & PDUCBF_RX_DDP_CMP) { u32 offset = be32_to_cpu(hdr->offset); u32 ddp_data_len; - u32 payload_length = ntoh24(hdr->dlength); bool success = false; cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, 0); @@ -1022,7 +1023,7 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk) cmd->data_sn = be32_to_cpu(hdr->datasn); rc = __iscsit_check_dataout_hdr(conn, (unsigned char *)hdr, - cmd, payload_length, &success); + cmd, data_len, &success); if (rc < 0) return rc; else if (!success) @@ -1060,6 +1061,20 @@ static int cxgbit_handle_iscsi_dataout(struct cxgbit_sock *csk) cxgbit_skb_copy_to_sg(csk->skb, sg_start, sg_nents, skip); } + ccmd = iscsit_priv_cmd(cmd); + ttinfo = &ccmd->ttinfo; + + if (ccmd->release && ttinfo->sgl && + (cmd->se_cmd.data_length == (cmd->write_data_done + data_len))) { + struct cxgbit_device *cdev = csk->com.cdev; + struct cxgbi_ppm *ppm = cdev2ppm(cdev); + + dma_unmap_sg(&ppm->pdev->dev, ttinfo->sgl, ttinfo->nents, + DMA_FROM_DEVICE); + ttinfo->nents = 0; + ttinfo->sgl = NULL; + } + check_payload: rc = iscsit_check_dataout_payload(cmd, hdr, dcrc_err); diff --git a/drivers/thermal/cpufreq_cooling.c b/drivers/thermal/cpufreq_cooling.c index 3f6a69ccc17378ec75bfb3a521861087433632a0..6e1d6a31ee4fbde6c5bf59de1e9396547c2aa102 100644 --- a/drivers/thermal/cpufreq_cooling.c +++ b/drivers/thermal/cpufreq_cooling.c @@ -443,7 +443,7 @@ static int cpufreq_set_cur_state(struct thermal_cooling_device *cdev, ret = freq_qos_update_request(&cpufreq_cdev->qos_req, frequency); if (ret >= 0) { cpufreq_cdev->cpufreq_state = state; - cpus = cpufreq_cdev->policy->cpus; + cpus = cpufreq_cdev->policy->related_cpus; max_capacity = arch_scale_cpu_capacity(cpumask_first(cpus)); capacity = frequency * max_capacity; capacity /= cpufreq_cdev->policy->cpuinfo.max_freq; diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c index 81e8b15ef405d581121a0ad873ef399ad99bac6c..74158fa660ddf660090a3a6727691a5f4167f797 100644 --- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c @@ -156,24 +156,27 @@ static ssize_t tcc_offset_degree_celsius_show(struct device *dev, if (err) return err; - val = (val >> 24) & 0xff; + val = (val >> 24) & 0x3f; return sprintf(buf, "%d\n", (int)val); } -static int tcc_offset_update(int tcc) +static int tcc_offset_update(unsigned int tcc) { u64 val; int err; - if (!tcc) + if (tcc > 63) return -EINVAL; err = rdmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, &val); if (err) return err; - val &= ~GENMASK_ULL(31, 24); - val |= (tcc & 0xff) << 24; + if (val & BIT(31)) + return -EPERM; + + val &= ~GENMASK_ULL(29, 24); + val |= (tcc & 0x3f) << 24; err = wrmsrl_safe(MSR_IA32_TEMPERATURE_TARGET, val); if (err) @@ -182,14 +185,15 @@ static int tcc_offset_update(int tcc) return 0; } -static int tcc_offset_save; +static unsigned int tcc_offset_save; static ssize_t tcc_offset_degree_celsius_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { + unsigned int tcc; u64 val; - int tcc, err; + int err; err = rdmsrl_safe(MSR_PLATFORM_INFO, &val); if (err) @@ -198,7 +202,7 @@ static ssize_t tcc_offset_degree_celsius_store(struct device *dev, if (!(val & BIT(30))) return -EACCES; - if (kstrtoint(buf, 0, &tcc)) + if (kstrtouint(buf, 0, &tcc)) return -EINVAL; err = tcc_offset_update(tcc); diff --git a/drivers/thermal/rcar_gen3_thermal.c b/drivers/thermal/rcar_gen3_thermal.c index 0dd47dca3e7712563ed007c63cacee78dd3bdc5d..8d724d92d57f40bf11c57a2b1debdf070be2b0ba 100644 --- a/drivers/thermal/rcar_gen3_thermal.c +++ b/drivers/thermal/rcar_gen3_thermal.c @@ -141,7 +141,7 @@ static void rcar_gen3_thermal_calc_coefs(struct rcar_gen3_thermal_tsc *tsc, * Division is not scaled in BSP and if scaled it might overflow * the dividend (4095 * 4095 << 14 > INT_MAX) so keep it unscaled */ - tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * 157) + tsc->tj_t = (FIXPT_INT((ptat[1] - ptat[2]) * (ths_tj_1 - TJ_3)) / (ptat[0] - ptat[2])) + FIXPT_INT(TJ_3); tsc->coef.a1 = FIXPT_DIV(FIXPT_INT(thcode[1] - thcode[2]), diff --git a/drivers/thermal/sprd_thermal.c b/drivers/thermal/sprd_thermal.c index 3682edb2f46692d0892abfe34524f75328bcfe93..fe06cccf14b382adf09be9169f102d7c955cc216 100644 --- a/drivers/thermal/sprd_thermal.c +++ b/drivers/thermal/sprd_thermal.c @@ -532,6 +532,7 @@ static const struct of_device_id sprd_thermal_of_match[] = { { .compatible = "sprd,ums512-thermal", .data = &ums512_data }, { }, }; +MODULE_DEVICE_TABLE(of, sprd_thermal_of_match); static const struct dev_pm_ops sprd_thermal_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(sprd_thm_suspend, sprd_thm_resume) diff --git a/drivers/thunderbolt/test.c b/drivers/thunderbolt/test.c index 464c2d37b992e507b0ca76a907ac8d1e4a46c8a0..e254f8c37cb7393720600d982851b7847959883b 100644 --- a/drivers/thunderbolt/test.c +++ b/drivers/thunderbolt/test.c @@ -259,14 +259,14 @@ static struct tb_switch *alloc_dev_default(struct kunit *test, if (port->dual_link_port && upstream_port->dual_link_port) { port->dual_link_port->remote = upstream_port->dual_link_port; upstream_port->dual_link_port->remote = port->dual_link_port; - } - if (bonded) { - /* Bonding is used */ - port->bonded = true; - port->dual_link_port->bonded = true; - upstream_port->bonded = true; - upstream_port->dual_link_port->bonded = true; + if (bonded) { + /* Bonding is used */ + port->bonded = true; + port->dual_link_port->bonded = true; + upstream_port->bonded = true; + upstream_port->dual_link_port->bonded = true; + } } return sw; diff --git a/drivers/tty/nozomi.c b/drivers/tty/nozomi.c index d42b854cb7df2b08227ebf4cba001615a8a2a0d3..6890418a29a40d431e861ba92629566a06120cce 100644 --- a/drivers/tty/nozomi.c +++ b/drivers/tty/nozomi.c @@ -1394,7 +1394,7 @@ static int nozomi_card_init(struct pci_dev *pdev, NOZOMI_NAME, dc); if (unlikely(ret)) { dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq); - goto err_free_kfifo; + goto err_free_all_kfifo; } DBG1("base_addr: %p", dc->base_addr); @@ -1432,12 +1432,15 @@ static int nozomi_card_init(struct pci_dev *pdev, return 0; err_free_tty: - for (i = 0; i < MAX_PORT; ++i) { + for (i--; i >= 0; i--) { tty_unregister_device(ntty_driver, dc->index_start + i); tty_port_destroy(&dc->port[i].port); } + free_irq(pdev->irq, dc); +err_free_all_kfifo: + i = MAX_PORT; err_free_kfifo: - for (i = 0; i < MAX_PORT; i++) + for (i--; i >= PORT_MDM; i--) kfifo_free(&dc->port[i].fifo_ul); err_free_sbuf: kfree(dc->send_buf); diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c index 0cc6d35a081560b5cdf0c3100ec69995d3501286..95e2d6de4f2134e30dfcd43e931d27f37d52616c 100644 --- a/drivers/tty/serial/8250/8250_omap.c +++ b/drivers/tty/serial/8250/8250_omap.c @@ -27,6 +27,7 @@ #include <linux/pm_qos.h> #include <linux/pm_wakeirq.h> #include <linux/dma-mapping.h> +#include <linux/sys_soc.h> #include "8250.h" @@ -41,6 +42,8 @@ */ #define UART_ERRATA_CLOCK_DISABLE (1 << 3) #define UART_HAS_EFR2 BIT(4) +#define UART_HAS_RHR_IT_DIS BIT(5) +#define UART_RX_TIMEOUT_QUIRK BIT(6) #define OMAP_UART_FCR_RX_TRIG 6 #define OMAP_UART_FCR_TX_TRIG 4 @@ -94,10 +97,17 @@ #define OMAP_UART_REV_52 0x0502 #define OMAP_UART_REV_63 0x0603 +/* Interrupt Enable Register 2 */ +#define UART_OMAP_IER2 0x1B +#define UART_OMAP_IER2_RHR_IT_DIS BIT(2) + /* Enhanced features register 2 */ #define UART_OMAP_EFR2 0x23 #define UART_OMAP_EFR2_TIMEOUT_BEHAVE BIT(6) +/* RX FIFO occupancy indicator */ +#define UART_OMAP_RX_LVL 0x64 + struct omap8250_priv { int line; u8 habit; @@ -592,6 +602,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port); static irqreturn_t omap8250_irq(int irq, void *dev_id) { struct uart_port *port = dev_id; + struct omap8250_priv *priv = port->private_data; struct uart_8250_port *up = up_to_u8250p(port); unsigned int iir; int ret; @@ -606,6 +617,18 @@ static irqreturn_t omap8250_irq(int irq, void *dev_id) serial8250_rpm_get(up); iir = serial_port_in(port, UART_IIR); ret = serial8250_handle_irq(port, iir); + + /* + * On K3 SoCs, it is observed that RX TIMEOUT is signalled after + * FIFO has been drained, in which case a dummy read of RX FIFO + * is required to clear RX TIMEOUT condition. + */ + if (priv->habit & UART_RX_TIMEOUT_QUIRK && + (iir & UART_IIR_RX_TIMEOUT) == UART_IIR_RX_TIMEOUT && + serial_port_in(port, UART_OMAP_RX_LVL) == 0) { + serial_port_in(port, UART_RX); + } + serial8250_rpm_put(up); return IRQ_RETVAL(ret); @@ -756,17 +779,27 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) { struct uart_8250_dma *dma = p->dma; struct tty_port *tty_port = &p->port.state->port; + struct omap8250_priv *priv = p->port.private_data; struct dma_chan *rxchan = dma->rxchan; dma_cookie_t cookie; struct dma_tx_state state; int count; int ret; + u32 reg; if (!dma->rx_running) goto out; cookie = dma->rx_cookie; dma->rx_running = 0; + + /* Re-enable RX FIFO interrupt now that transfer is complete */ + if (priv->habit & UART_HAS_RHR_IT_DIS) { + reg = serial_in(p, UART_OMAP_IER2); + reg &= ~UART_OMAP_IER2_RHR_IT_DIS; + serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS); + } + dmaengine_tx_status(rxchan, cookie, &state); count = dma->rx_size - state.residue + state.in_flight_bytes; @@ -784,7 +817,7 @@ static void __dma_rx_do_complete(struct uart_8250_port *p) poll_count--) cpu_relax(); - if (!poll_count) + if (poll_count == -1) dev_err(p->port.dev, "teardown incomplete\n"); } } @@ -862,6 +895,7 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) int err = 0; struct dma_async_tx_descriptor *desc; unsigned long flags; + u32 reg; if (priv->rx_dma_broken) return -EINVAL; @@ -897,6 +931,17 @@ static int omap_8250_rx_dma(struct uart_8250_port *p) dma->rx_cookie = dmaengine_submit(desc); + /* + * Disable RX FIFO interrupt while RX DMA is enabled, else + * spurious interrupt may be raised when data is in the RX FIFO + * but is yet to be drained by DMA. + */ + if (priv->habit & UART_HAS_RHR_IT_DIS) { + reg = serial_in(p, UART_OMAP_IER2); + reg |= UART_OMAP_IER2_RHR_IT_DIS; + serial_out(p, UART_OMAP_IER2, UART_OMAP_IER2_RHR_IT_DIS); + } + dma_async_issue_pending(dma->rxchan); out: spin_unlock_irqrestore(&priv->rx_dma_lock, flags); @@ -1163,6 +1208,11 @@ static int omap8250_no_handle_irq(struct uart_port *port) return 0; } +static const struct soc_device_attribute k3_soc_devices[] = { + { .family = "AM65X", }, + { .family = "J721E", .revision = "SR1.0" }, +}; + static struct omap8250_dma_params am654_dma = { .rx_size = SZ_2K, .rx_trigger = 1, @@ -1177,7 +1227,8 @@ static struct omap8250_dma_params am33xx_dma = { static struct omap8250_platdata am654_platdata = { .dma_params = &am654_dma, - .habit = UART_HAS_EFR2, + .habit = UART_HAS_EFR2 | UART_HAS_RHR_IT_DIS | + UART_RX_TIMEOUT_QUIRK, }; static struct omap8250_platdata am33xx_platdata = { @@ -1367,6 +1418,13 @@ static int omap8250_probe(struct platform_device *pdev) up.dma->rxconf.src_maxburst = RX_TRIGGER; up.dma->txconf.dst_maxburst = TX_TRIGGER; } + + /* + * AM65x SR1.0, AM65x SR2.0 and J721e SR1.0 don't + * don't have RHR_IT_DIS bit in IER2 register + */ + if (soc_device_match(k3_soc_devices)) + priv->habit &= ~UART_HAS_RHR_IT_DIS; } #endif ret = serial8250_register_8250_port(&up); diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 6e141429c98085daacc3da8ddc317e4153018935..6d9c494bed7d25b7b9becbc71e04b51a1ad4a147 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2635,6 +2635,21 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, struct ktermios *old) { unsigned int tolerance = port->uartclk / 100; + unsigned int min; + unsigned int max; + + /* + * Handle magic divisors for baud rates above baud_base on SMSC + * Super I/O chips. Enable custom rates of clk/4 and clk/8, but + * disable divisor values beyond 32767, which are unavailable. + */ + if (port->flags & UPF_MAGIC_MULTIPLIER) { + min = port->uartclk / 16 / UART_DIV_MAX >> 1; + max = (port->uartclk + tolerance) / 4; + } else { + min = port->uartclk / 16 / UART_DIV_MAX; + max = (port->uartclk + tolerance) / 16; + } /* * Ask the core to calculate the divisor for us. @@ -2642,9 +2657,7 @@ static unsigned int serial8250_get_baud_rate(struct uart_port *port, * slower than nominal still match standard baud rates without * causing transmission errors. */ - return uart_get_baud_rate(port, termios, old, - port->uartclk / 16 / UART_DIV_MAX, - (port->uartclk + tolerance) / 16); + return uart_get_baud_rate(port, termios, old, min, max); } /* diff --git a/drivers/tty/serial/8250/serial_cs.c b/drivers/tty/serial/8250/serial_cs.c index e3d10794dbba348e03912b44aad8942770437165..7c3ea68e533e2d68d912dfae223c98fc1b931e12 100644 --- a/drivers/tty/serial/8250/serial_cs.c +++ b/drivers/tty/serial/8250/serial_cs.c @@ -306,6 +306,7 @@ static int serial_resume(struct pcmcia_device *link) static int serial_probe(struct pcmcia_device *link) { struct serial_info *info; + int ret; dev_dbg(&link->dev, "serial_attach()\n"); @@ -320,7 +321,15 @@ static int serial_probe(struct pcmcia_device *link) if (do_sound) link->config_flags |= CONF_ENABLE_SPKR; - return serial_config(link); + ret = serial_config(link); + if (ret) + goto free_info; + + return 0; + +free_info: + kfree(info); + return ret; } static void serial_detach(struct pcmcia_device *link) @@ -780,6 +789,7 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_PROD_ID12("Multi-Tech", "MT2834LT", 0x5f73be51, 0x4cd7c09e), PCMCIA_DEVICE_PROD_ID12("OEM ", "C288MX ", 0xb572d360, 0xd2385b7a), PCMCIA_DEVICE_PROD_ID12("Option International", "V34bis GSM/PSTN Data/Fax Modem", 0x9d7cd6f5, 0x5cb8bf41), + PCMCIA_DEVICE_PROD_ID12("Option International", "GSM-Ready 56K/ISDN", 0x9d7cd6f5, 0xb23844aa), PCMCIA_DEVICE_PROD_ID12("PCMCIA ", "C336MX ", 0x99bcafe9, 0xaa25bcab), PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "PCMCIA Dual RS-232 Serial Port Card", 0xc4420b35, 0x92abc92f), PCMCIA_DEVICE_PROD_ID12("Quatech Inc", "Dual RS-232 Serial Port PC Card", 0xc4420b35, 0x031a380d), @@ -807,7 +817,6 @@ static const struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"), - PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "cis/GLOBETROTTER.cis"), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100 1.00.", 0x19ca78af, 0xf964f42b), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL100", 0x19ca78af, 0x71d98e83), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.", "SERIAL CARD: SL232 1.00.", 0x19ca78af, 0x69fb7490), diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 1825639030fdcf9e34e73220a7231198ff87e343..79b8f0a57d5c83891c8fc7b60605e1f221e7f129 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1603,17 +1603,7 @@ static unsigned int lpuart_get_mctrl(struct uart_port *port) static unsigned int lpuart32_get_mctrl(struct uart_port *port) { - unsigned int temp = 0; - unsigned long reg; - - reg = lpuart32_read(port, UARTMODIR); - if (reg & UARTMODIR_TXCTSE) - temp |= TIOCM_CTS; - - if (reg & UARTMODIR_RXRTSE) - temp |= TIOCM_RTS; - - return temp; + return 0; } static void lpuart_set_mctrl(struct uart_port *port, unsigned int mctrl) @@ -1813,6 +1803,9 @@ static void lpuart_tx_dma_startup(struct lpuart_port *sport) u32 uartbaud; int ret; + if (uart_console(&sport->port)) + goto err; + if (!sport->dma_tx_chan) goto err; @@ -1842,6 +1835,9 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport) int ret; unsigned char cr3; + if (uart_console(&sport->port)) + goto err; + if (!sport->dma_rx_chan) goto err; @@ -1857,7 +1853,7 @@ static void lpuart_rx_dma_startup(struct lpuart_port *sport) sport->lpuart_dma_rx_use = true; rx_dma_timer_init(sport); - if (sport->port.has_sysrq) { + if (sport->port.has_sysrq && !lpuart_is_32(sport)) { cr3 = readb(sport->port.membase + UARTCR3); cr3 |= UARTCR3_FEIE; writeb(cr3, sport->port.membase + UARTCR3); @@ -2695,6 +2691,9 @@ lpuart32_console_get_options(struct lpuart_port *sport, int *baud, bd = lpuart32_read(&sport->port, UARTBAUD); bd &= UARTBAUD_SBR_MASK; + if (!bd) + return; + sbr = bd; uartclk = lpuart_get_baud_clk_rate(sport); /* diff --git a/drivers/tty/serial/mvebu-uart.c b/drivers/tty/serial/mvebu-uart.c index 51b0ecabf2ec963ffefcd33999b08f1d9830931e..1e26220c78527bd7e6f1d6618be0d9105b3384fa 100644 --- a/drivers/tty/serial/mvebu-uart.c +++ b/drivers/tty/serial/mvebu-uart.c @@ -445,12 +445,11 @@ static void mvebu_uart_shutdown(struct uart_port *port) static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud) { - struct mvebu_uart *mvuart = to_mvuart(port); unsigned int d_divisor, m_divisor; u32 brdv, osamp; - if (IS_ERR(mvuart->clk)) - return -PTR_ERR(mvuart->clk); + if (!port->uartclk) + return -EOPNOTSUPP; /* * The baudrate is derived from the UART clock thanks to two divisors: @@ -463,7 +462,7 @@ static int mvebu_uart_baud_rate_set(struct uart_port *port, unsigned int baud) * makes use of D to configure the desired baudrate. */ m_divisor = OSAMP_DEFAULT_DIVISOR; - d_divisor = DIV_ROUND_UP(port->uartclk, baud * m_divisor); + d_divisor = DIV_ROUND_CLOSEST(port->uartclk, baud * m_divisor); brdv = readl(port->membase + UART_BRDV); brdv &= ~BRDV_BAUD_MASK; @@ -482,7 +481,7 @@ static void mvebu_uart_set_termios(struct uart_port *port, struct ktermios *old) { unsigned long flags; - unsigned int baud; + unsigned int baud, min_baud, max_baud; spin_lock_irqsave(&port->lock, flags); @@ -501,16 +500,21 @@ static void mvebu_uart_set_termios(struct uart_port *port, port->ignore_status_mask |= STAT_RX_RDY(port) | STAT_BRK_ERR; /* + * Maximal divisor is 1023 * 16 when using default (x16) scheme. * Maximum achievable frequency with simple baudrate divisor is 230400. * Since the error per bit frame would be of more than 15%, achieving * higher frequencies would require to implement the fractional divisor * feature. */ - baud = uart_get_baud_rate(port, termios, old, 0, 230400); + min_baud = DIV_ROUND_UP(port->uartclk, 1023 * 16); + max_baud = 230400; + + baud = uart_get_baud_rate(port, termios, old, min_baud, max_baud); if (mvebu_uart_baud_rate_set(port, baud)) { /* No clock available, baudrate cannot be changed */ if (old) - baud = uart_get_baud_rate(port, old, NULL, 0, 230400); + baud = uart_get_baud_rate(port, old, NULL, + min_baud, max_baud); } else { tty_termios_encode_baud_rate(termios, baud, baud); uart_update_timeout(port, termios->c_cflag, baud); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index 3b1aaa93d750e264bea1d3205250a91b8a024c7d..70898a999a498d3a878303da30321701c68da40c 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -610,6 +610,14 @@ static void sci_stop_tx(struct uart_port *port) ctrl &= ~SCSCR_TIE; serial_port_out(port, SCSCR, ctrl); + +#ifdef CONFIG_SERIAL_SH_SCI_DMA + if (to_sci_port(port)->chan_tx && + !dma_submit_error(to_sci_port(port)->cookie_tx)) { + dmaengine_terminate_async(to_sci_port(port)->chan_tx); + to_sci_port(port)->cookie_tx = -EINVAL; + } +#endif } static void sci_start_rx(struct uart_port *port) diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c index 09379db613d8b7f69cab5ffa66d0a90c868cdec2..7081ab322b4028e1284d11391c88741f30470650 100644 --- a/drivers/tty/serial/uartlite.c +++ b/drivers/tty/serial/uartlite.c @@ -505,21 +505,23 @@ static void ulite_console_write(struct console *co, const char *s, static int ulite_console_setup(struct console *co, char *options) { - struct uart_port *port; + struct uart_port *port = NULL; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - - port = console_port; + if (co->index >= 0 && co->index < ULITE_NR_UARTS) + port = ulite_ports + co->index; /* Has the device been initialized yet? */ - if (!port->mapbase) { + if (!port || !port->mapbase) { pr_debug("console on ttyUL%i not present\n", co->index); return -ENODEV; } + console_port = port; + /* not initialized yet? */ if (!port->membase) { if (ulite_request_port(port)) @@ -655,17 +657,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, dev_set_drvdata(dev, port); -#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* - * If console hasn't been found yet try to assign this port - * because it is required to be assigned for console setup function. - * If register_console() don't assign value, then console_port pointer - * is cleanup. - */ - if (ulite_uart_driver.cons->index == -1) - console_port = port; -#endif - /* Register the port */ rc = uart_add_one_port(&ulite_uart_driver, port); if (rc) { @@ -675,12 +666,6 @@ static int ulite_assign(struct device *dev, int id, u32 base, int irq, return rc; } -#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE - /* This is not port which is used for console that's why clean it up */ - if (ulite_uart_driver.cons->index == -1) - console_port = NULL; -#endif - return 0; } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6fbabf56dbb765e8e4890f56555b5d7e037dce59..df5b2d1e214f1805557e412b632875f7a9095e35 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1948,6 +1948,11 @@ static const struct usb_device_id acm_ids[] = { .driver_info = IGNORE_DEVICE, }, + /* Exclude Heimann Sensor GmbH USB appset demo */ + { USB_DEVICE(0x32a7, 0x0000), + .driver_info = IGNORE_DEVICE, + }, + /* control interfaces without any protocol set */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, USB_CDC_PROTO_NONE) }, diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c index 6c4e3a19f42cb07f0ced9a946f890fb8098a6728..c9545a4eff664df1c46ebfd3cf2876a046059445 100644 --- a/drivers/usb/common/usb-conn-gpio.c +++ b/drivers/usb/common/usb-conn-gpio.c @@ -149,14 +149,32 @@ static int usb_charger_get_property(struct power_supply *psy, return 0; } -static int usb_conn_probe(struct platform_device *pdev) +static int usb_conn_psy_register(struct usb_conn_info *info) { - struct device *dev = &pdev->dev; - struct power_supply_desc *desc; - struct usb_conn_info *info; + struct device *dev = info->dev; + struct power_supply_desc *desc = &info->desc; struct power_supply_config cfg = { .of_node = dev->of_node, }; + + desc->name = "usb-charger"; + desc->properties = usb_charger_properties; + desc->num_properties = ARRAY_SIZE(usb_charger_properties); + desc->get_property = usb_charger_get_property; + desc->type = POWER_SUPPLY_TYPE_USB; + cfg.drv_data = info; + + info->charger = devm_power_supply_register(dev, desc, &cfg); + if (IS_ERR(info->charger)) + dev_err(dev, "Unable to register charger\n"); + + return PTR_ERR_OR_ZERO(info->charger); +} + +static int usb_conn_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct usb_conn_info *info; bool need_vbus = true; int ret = 0; @@ -218,6 +236,10 @@ static int usb_conn_probe(struct platform_device *pdev) return PTR_ERR(info->role_sw); } + ret = usb_conn_psy_register(info); + if (ret) + goto put_role_sw; + if (info->id_gpiod) { info->id_irq = gpiod_to_irq(info->id_gpiod); if (info->id_irq < 0) { @@ -252,20 +274,6 @@ static int usb_conn_probe(struct platform_device *pdev) } } - desc = &info->desc; - desc->name = "usb-charger"; - desc->properties = usb_charger_properties; - desc->num_properties = ARRAY_SIZE(usb_charger_properties); - desc->get_property = usb_charger_get_property; - desc->type = POWER_SUPPLY_TYPE_USB; - cfg.drv_data = info; - - info->charger = devm_power_supply_register(dev, desc, &cfg); - if (IS_ERR(info->charger)) { - dev_err(dev, "Unable to register charger\n"); - return PTR_ERR(info->charger); - } - platform_set_drvdata(pdev, info); /* Perform initial detection */ diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c index fec17a2d2447dd5a863bf37fc940832737501c0c..15911ac7582b466f22ac3e4bd0938076d8489097 100644 --- a/drivers/usb/dwc2/core.c +++ b/drivers/usb/dwc2/core.c @@ -1167,15 +1167,6 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) usbcfg &= ~(GUSBCFG_ULPI_UTMI_SEL | GUSBCFG_PHYIF16); if (hsotg->params.phy_utmi_width == 16) usbcfg |= GUSBCFG_PHYIF16; - - /* Set turnaround time */ - if (dwc2_is_device_mode(hsotg)) { - usbcfg &= ~GUSBCFG_USBTRDTIM_MASK; - if (hsotg->params.phy_utmi_width == 16) - usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT; - else - usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT; - } break; default: dev_err(hsotg->dev, "FS PHY selected at HS!\n"); @@ -1197,6 +1188,24 @@ static int dwc2_hs_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) return retval; } +static void dwc2_set_turnaround_time(struct dwc2_hsotg *hsotg) +{ + u32 usbcfg; + + if (hsotg->params.phy_type != DWC2_PHY_TYPE_PARAM_UTMI) + return; + + usbcfg = dwc2_readl(hsotg, GUSBCFG); + + usbcfg &= ~GUSBCFG_USBTRDTIM_MASK; + if (hsotg->params.phy_utmi_width == 16) + usbcfg |= 5 << GUSBCFG_USBTRDTIM_SHIFT; + else + usbcfg |= 9 << GUSBCFG_USBTRDTIM_SHIFT; + + dwc2_writel(hsotg, usbcfg, GUSBCFG); +} + int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) { u32 usbcfg; @@ -1214,6 +1223,9 @@ int dwc2_phy_init(struct dwc2_hsotg *hsotg, bool select_phy) retval = dwc2_hs_phy_init(hsotg, select_phy); if (retval) return retval; + + if (dwc2_is_device_mode(hsotg)) + dwc2_set_turnaround_time(hsotg); } if (hsotg->hw_params.hs_phy_type == GHWCFG2_HS_PHY_TYPE_ULPI && diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index e7e1f1db1ca65e92bb552d9bc4d5c30e4d3ae720..39d95bd9fec6aa4495eafb9a24b9e100d9561b2a 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1746,17 +1746,18 @@ static int dwc3_probe(struct platform_device *pdev) } dwc3_check_params(dwc); + dwc3_debugfs_init(dwc); ret = dwc3_core_init_mode(dwc); if (ret) goto err5; - dwc3_debugfs_init(dwc); pm_runtime_put(dev); return 0; err5: + dwc3_debugfs_exit(dwc); dwc3_event_buffers_cleanup(dwc); usb_phy_shutdown(dwc->usb2_phy); diff --git a/drivers/usb/gadget/function/f_eem.c b/drivers/usb/gadget/function/f_eem.c index 2cd9942707b46a132663cd0f2570ed077a7081d1..5d38f29bda720ed40ef9881251f568ad10352604 100644 --- a/drivers/usb/gadget/function/f_eem.c +++ b/drivers/usb/gadget/function/f_eem.c @@ -30,6 +30,11 @@ struct f_eem { u8 ctrl_id; }; +struct in_context { + struct sk_buff *skb; + struct usb_ep *ep; +}; + static inline struct f_eem *func_to_eem(struct usb_function *f) { return container_of(f, struct f_eem, port.func); @@ -320,9 +325,12 @@ fail: static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) { - struct sk_buff *skb = (struct sk_buff *)req->context; + struct in_context *ctx = req->context; - dev_kfree_skb_any(skb); + dev_kfree_skb_any(ctx->skb); + kfree(req->buf); + usb_ep_free_request(ctx->ep, req); + kfree(ctx); } /* @@ -410,7 +418,9 @@ static int eem_unwrap(struct gether *port, * b15: bmType (0 == data, 1 == command) */ if (header & BIT(15)) { - struct usb_request *req = cdev->req; + struct usb_request *req; + struct in_context *ctx; + struct usb_ep *ep; u16 bmEEMCmd; /* EEM command packet format: @@ -439,11 +449,36 @@ static int eem_unwrap(struct gether *port, skb_trim(skb2, len); put_unaligned_le16(BIT(15) | BIT(11) | len, skb_push(skb2, 2)); + + ep = port->in_ep; + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (!req) { + dev_kfree_skb_any(skb2); + goto next; + } + + req->buf = kmalloc(skb2->len, GFP_KERNEL); + if (!req->buf) { + usb_ep_free_request(ep, req); + dev_kfree_skb_any(skb2); + goto next; + } + + ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + kfree(req->buf); + usb_ep_free_request(ep, req); + dev_kfree_skb_any(skb2); + goto next; + } + ctx->skb = skb2; + ctx->ep = ep; + skb_copy_bits(skb2, 0, req->buf, skb2->len); req->length = skb2->len; req->complete = eem_cmd_complete; req->zero = 1; - req->context = skb2; + req->context = ctx; if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC)) DBG(cdev, "echo response queue fail\n"); break; diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 7df180b110afca44ab720269de30321026fec043..725e35167837eb4f87f570b20970812d2cd47928 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -250,8 +250,8 @@ EXPORT_SYMBOL_GPL(ffs_lock); static struct ffs_dev *_ffs_find_dev(const char *name); static struct ffs_dev *_ffs_alloc_dev(void); static void _ffs_free_dev(struct ffs_dev *dev); -static void *ffs_acquire_dev(const char *dev_name); -static void ffs_release_dev(struct ffs_data *ffs_data); +static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data); +static void ffs_release_dev(struct ffs_dev *ffs_dev); static int ffs_ready(struct ffs_data *ffs); static void ffs_closed(struct ffs_data *ffs); @@ -1553,8 +1553,8 @@ unmapped_value: static int ffs_fs_get_tree(struct fs_context *fc) { struct ffs_sb_fill_data *ctx = fc->fs_private; - void *ffs_dev; struct ffs_data *ffs; + int ret; ENTER(); @@ -1573,13 +1573,12 @@ static int ffs_fs_get_tree(struct fs_context *fc) return -ENOMEM; } - ffs_dev = ffs_acquire_dev(ffs->dev_name); - if (IS_ERR(ffs_dev)) { + ret = ffs_acquire_dev(ffs->dev_name, ffs); + if (ret) { ffs_data_put(ffs); - return PTR_ERR(ffs_dev); + return ret; } - ffs->private_data = ffs_dev; ctx->ffs_data = ffs; return get_tree_nodev(fc, ffs_sb_fill); } @@ -1590,7 +1589,6 @@ static void ffs_fs_free_fc(struct fs_context *fc) if (ctx) { if (ctx->ffs_data) { - ffs_release_dev(ctx->ffs_data); ffs_data_put(ctx->ffs_data); } @@ -1629,10 +1627,8 @@ ffs_fs_kill_sb(struct super_block *sb) ENTER(); kill_litter_super(sb); - if (sb->s_fs_info) { - ffs_release_dev(sb->s_fs_info); + if (sb->s_fs_info) ffs_data_closed(sb->s_fs_info); - } } static struct file_system_type ffs_fs_type = { @@ -1702,6 +1698,7 @@ static void ffs_data_put(struct ffs_data *ffs) if (unlikely(refcount_dec_and_test(&ffs->ref))) { pr_info("%s(): freeing\n", __func__); ffs_data_clear(ffs); + ffs_release_dev(ffs->private_data); BUG_ON(waitqueue_active(&ffs->ev.waitq) || swait_active(&ffs->ep0req_completion.wait) || waitqueue_active(&ffs->wait)); @@ -3031,6 +3028,7 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, struct ffs_function *func = ffs_func_from_usb(f); struct f_fs_opts *ffs_opts = container_of(f->fi, struct f_fs_opts, func_inst); + struct ffs_data *ffs_data; int ret; ENTER(); @@ -3045,12 +3043,13 @@ static inline struct f_fs_opts *ffs_do_functionfs_bind(struct usb_function *f, if (!ffs_opts->no_configfs) ffs_dev_lock(); ret = ffs_opts->dev->desc_ready ? 0 : -ENODEV; - func->ffs = ffs_opts->dev->ffs_data; + ffs_data = ffs_opts->dev->ffs_data; if (!ffs_opts->no_configfs) ffs_dev_unlock(); if (ret) return ERR_PTR(ret); + func->ffs = ffs_data; func->conf = c; func->gadget = c->cdev->gadget; @@ -3505,6 +3504,7 @@ static void ffs_free_inst(struct usb_function_instance *f) struct f_fs_opts *opts; opts = to_f_fs_opts(f); + ffs_release_dev(opts->dev); ffs_dev_lock(); _ffs_free_dev(opts->dev); ffs_dev_unlock(); @@ -3692,47 +3692,48 @@ static void _ffs_free_dev(struct ffs_dev *dev) { list_del(&dev->entry); - /* Clear the private_data pointer to stop incorrect dev access */ - if (dev->ffs_data) - dev->ffs_data->private_data = NULL; - kfree(dev); if (list_empty(&ffs_devices)) functionfs_cleanup(); } -static void *ffs_acquire_dev(const char *dev_name) +static int ffs_acquire_dev(const char *dev_name, struct ffs_data *ffs_data) { + int ret = 0; struct ffs_dev *ffs_dev; ENTER(); ffs_dev_lock(); ffs_dev = _ffs_find_dev(dev_name); - if (!ffs_dev) - ffs_dev = ERR_PTR(-ENOENT); - else if (ffs_dev->mounted) - ffs_dev = ERR_PTR(-EBUSY); - else if (ffs_dev->ffs_acquire_dev_callback && - ffs_dev->ffs_acquire_dev_callback(ffs_dev)) - ffs_dev = ERR_PTR(-ENOENT); - else + if (!ffs_dev) { + ret = -ENOENT; + } else if (ffs_dev->mounted) { + ret = -EBUSY; + } else if (ffs_dev->ffs_acquire_dev_callback && + ffs_dev->ffs_acquire_dev_callback(ffs_dev)) { + ret = -ENOENT; + } else { ffs_dev->mounted = true; + ffs_dev->ffs_data = ffs_data; + ffs_data->private_data = ffs_dev; + } ffs_dev_unlock(); - return ffs_dev; + return ret; } -static void ffs_release_dev(struct ffs_data *ffs_data) +static void ffs_release_dev(struct ffs_dev *ffs_dev) { - struct ffs_dev *ffs_dev; - ENTER(); ffs_dev_lock(); - ffs_dev = ffs_data->private_data; - if (ffs_dev) { + if (ffs_dev && ffs_dev->mounted) { ffs_dev->mounted = false; + if (ffs_dev->ffs_data) { + ffs_dev->ffs_data->private_data = NULL; + ffs_dev->ffs_data = NULL; + } if (ffs_dev->ffs_release_dev_callback) ffs_dev->ffs_release_dev_callback(ffs_dev); @@ -3760,7 +3761,6 @@ static int ffs_ready(struct ffs_data *ffs) } ffs_obj->desc_ready = true; - ffs_obj->ffs_data = ffs; if (ffs_obj->ffs_ready_callback) { ret = ffs_obj->ffs_ready_callback(ffs); @@ -3788,7 +3788,6 @@ static void ffs_closed(struct ffs_data *ffs) goto done; ffs_obj->desc_ready = false; - ffs_obj->ffs_data = NULL; if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags) && ffs_obj->ffs_closed_callback) diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c index e556993081170ffb4294024473b6e2a76770eaa9..a82b3de1a54bec62bbd9d003c32a9e80455fba99 100644 --- a/drivers/usb/gadget/function/f_hid.c +++ b/drivers/usb/gadget/function/f_hid.c @@ -88,7 +88,7 @@ static struct usb_interface_descriptor hidg_interface_desc = { static struct hid_descriptor hidg_desc = { .bLength = sizeof hidg_desc, .bDescriptorType = HID_DT_HID, - .bcdHID = 0x0101, + .bcdHID = cpu_to_le16(0x0101), .bCountryCode = 0x00, .bNumDescriptors = 0x1, /*.desc[0].bDescriptorType = DYNAMIC */ diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c index c4eda7fe7ab45a61272096915d10db0b1092b03d..5b27d289443fe2af1feb815243a7b69add588341 100644 --- a/drivers/usb/gadget/legacy/hid.c +++ b/drivers/usb/gadget/legacy/hid.c @@ -171,8 +171,10 @@ static int hid_bind(struct usb_composite_dev *cdev) struct usb_descriptor_header *usb_desc; usb_desc = usb_otg_descriptor_alloc(gadget); - if (!usb_desc) + if (!usb_desc) { + status = -ENOMEM; goto put; + } usb_otg_descriptor_init(gadget, usb_desc); otg_desc[0] = usb_desc; otg_desc[1] = NULL; diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 8ce043e6ed87291eec0320e405d82029174e49d1..ed380ee58ab5d7c0a125a03b9d391ec181d46d20 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1938,6 +1938,7 @@ no_bw: xhci->hw_ports = NULL; xhci->rh_bw = NULL; xhci->ext_caps = NULL; + xhci->port_caps = NULL; xhci->page_size = 0; xhci->page_shift = 0; diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c index f97ac9f52bf4d9cc15b244e067e87e918847a249..431213cdf9e0eabde511e05bff9d9e13afe57e2f 100644 --- a/drivers/usb/host/xhci-pci-renesas.c +++ b/drivers/usb/host/xhci-pci-renesas.c @@ -207,7 +207,8 @@ static int renesas_check_rom_state(struct pci_dev *pdev) return 0; case RENESAS_ROM_STATUS_NO_RESULT: /* No result yet */ - return 0; + dev_dbg(&pdev->dev, "Unknown ROM status ...\n"); + break; case RENESAS_ROM_STATUS_ERROR: /* Error State */ default: /* All other states are marked as "Reserved states" */ @@ -224,13 +225,12 @@ static int renesas_fw_check_running(struct pci_dev *pdev) u8 fw_state; int err; - /* Check if device has ROM and loaded, if so skip everything */ - err = renesas_check_rom(pdev); - if (err) { /* we have rom */ - err = renesas_check_rom_state(pdev); - if (!err) - return err; - } + /* + * Only if device has ROM and loaded FW we can skip loading and + * return success. Otherwise (even unknown state), attempt to load FW. + */ + if (renesas_check_rom(pdev) && !renesas_check_rom_state(pdev)) + return 0; /* * Test if the device is actually needing the firmware. As most diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c index 35eec707cb5120020d8e0c059933d1d5d4be78d1..c7d44daa05c4a2c0a581564917e170b2fbcf7317 100644 --- a/drivers/usb/typec/class.c +++ b/drivers/usb/typec/class.c @@ -446,8 +446,10 @@ typec_register_altmode(struct device *parent, int ret; alt = kzalloc(sizeof(*alt), GFP_KERNEL); - if (!alt) + if (!alt) { + altmode_id_remove(parent, id); return ERR_PTR(-ENOMEM); + } alt->adev.svid = desc->svid; alt->adev.mode = desc->mode; diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 8af30d07f6880db5ed84481cb339ba02e29f138d..fe7ed3212473d10128b5a5cf7a62062f191320d5 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -596,8 +596,8 @@ static void cq_destroy(struct mlx5_vdpa_net *ndev, u16 idx) mlx5_db_free(ndev->mvdev.mdev, &vcq->db); } -static int umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq, int num, - struct mlx5_vdpa_umem **umemp) +static void set_umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq, int num, + struct mlx5_vdpa_umem **umemp) { struct mlx5_core_dev *mdev = ndev->mvdev.mdev; int p_a; @@ -620,7 +620,7 @@ static int umem_size(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *mvq *umemp = &mvq->umem3; break; } - return p_a * mvq->num_ent + p_b; + (*umemp)->size = p_a * mvq->num_ent + p_b; } static void umem_frag_buf_free(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_umem *umem) @@ -636,15 +636,10 @@ static int create_umem(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *m void *in; int err; __be64 *pas; - int size; struct mlx5_vdpa_umem *umem; - size = umem_size(ndev, mvq, num, &umem); - if (size < 0) - return size; - - umem->size = size; - err = umem_frag_buf_alloc(ndev, umem, size); + set_umem_size(ndev, mvq, num, &umem); + err = umem_frag_buf_alloc(ndev, umem, umem->size); if (err) return err; @@ -814,9 +809,9 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque MLX5_SET(virtio_q, vq_ctx, umem_1_id, mvq->umem1.id); MLX5_SET(virtio_q, vq_ctx, umem_1_size, mvq->umem1.size); MLX5_SET(virtio_q, vq_ctx, umem_2_id, mvq->umem2.id); - MLX5_SET(virtio_q, vq_ctx, umem_2_size, mvq->umem1.size); + MLX5_SET(virtio_q, vq_ctx, umem_2_size, mvq->umem2.size); MLX5_SET(virtio_q, vq_ctx, umem_3_id, mvq->umem3.id); - MLX5_SET(virtio_q, vq_ctx, umem_3_size, mvq->umem1.size); + MLX5_SET(virtio_q, vq_ctx, umem_3_size, mvq->umem3.size); MLX5_SET(virtio_q, vq_ctx, pd, ndev->mvdev.res.pdn); if (MLX5_CAP_DEV_VDPA_EMULATION(ndev->mvdev.mdev, eth_frame_offload_type)) MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, 1); @@ -1757,6 +1752,14 @@ out: mutex_unlock(&ndev->reslock); } +static void clear_vqs_ready(struct mlx5_vdpa_net *ndev) +{ + int i; + + for (i = 0; i < ndev->mvdev.max_vqs; i++) + ndev->vqs[i].ready = false; +} + static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) { struct mlx5_vdpa_dev *mvdev = to_mvdev(vdev); @@ -1767,6 +1770,7 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) if (!status) { mlx5_vdpa_info(mvdev, "performing device reset\n"); teardown_driver(ndev); + clear_vqs_ready(ndev); mlx5_vdpa_destroy_mr(&ndev->mvdev); ndev->mvdev.status = 0; ndev->mvdev.mlx_features = 0; diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 48b048edf1ee89595b474624c884a0b46d477c05..57ae8b46b836156607e7514e44664cfbb7f5e231 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -1614,6 +1614,7 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; struct vfio_pci_device *vdev = vma->vm_private_data; + struct vfio_pci_mmap_vma *mmap_vma; vm_fault_t ret = VM_FAULT_NOPAGE; mutex_lock(&vdev->vma_lock); @@ -1621,24 +1622,36 @@ static vm_fault_t vfio_pci_mmap_fault(struct vm_fault *vmf) if (!__vfio_pci_memory_enabled(vdev)) { ret = VM_FAULT_SIGBUS; - mutex_unlock(&vdev->vma_lock); goto up_out; } - if (__vfio_pci_add_vma(vdev, vma)) { - ret = VM_FAULT_OOM; - mutex_unlock(&vdev->vma_lock); - goto up_out; + /* + * We populate the whole vma on fault, so we need to test whether + * the vma has already been mapped, such as for concurrent faults + * to the same vma. io_remap_pfn_range() will trigger a BUG_ON if + * we ask it to fill the same range again. + */ + list_for_each_entry(mmap_vma, &vdev->vma_list, vma_next) { + if (mmap_vma->vma == vma) + goto up_out; } - mutex_unlock(&vdev->vma_lock); - if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - vma->vm_end - vma->vm_start, vma->vm_page_prot)) + vma->vm_end - vma->vm_start, + vma->vm_page_prot)) { ret = VM_FAULT_SIGBUS; + zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); + goto up_out; + } + + if (__vfio_pci_add_vma(vdev, vma)) { + ret = VM_FAULT_OOM; + zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start); + } up_out: up_read(&vdev->memory_lock); + mutex_unlock(&vdev->vma_lock); return ret; } diff --git a/drivers/video/backlight/lm3630a_bl.c b/drivers/video/backlight/lm3630a_bl.c index e88a2b0e59046a27cf3610bfbf43a12cbffe4dee..419b0334cf0879b71aa180d59f3af8b94f934fb6 100644 --- a/drivers/video/backlight/lm3630a_bl.c +++ b/drivers/video/backlight/lm3630a_bl.c @@ -190,7 +190,7 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) if ((pwm_ctrl & LM3630A_PWM_BANK_A) != 0) { lm3630a_pwm_ctrl(pchip, bl->props.brightness, bl->props.max_brightness); - return bl->props.brightness; + return 0; } /* disable sleep */ @@ -210,8 +210,8 @@ static int lm3630a_bank_a_update_status(struct backlight_device *bl) return 0; out_i2c_err: - dev_err(pchip->dev, "i2c failed to access\n"); - return bl->props.brightness; + dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret)); + return ret; } static int lm3630a_bank_a_get_brightness(struct backlight_device *bl) @@ -267,7 +267,7 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) if ((pwm_ctrl & LM3630A_PWM_BANK_B) != 0) { lm3630a_pwm_ctrl(pchip, bl->props.brightness, bl->props.max_brightness); - return bl->props.brightness; + return 0; } /* disable sleep */ @@ -287,8 +287,8 @@ static int lm3630a_bank_b_update_status(struct backlight_device *bl) return 0; out_i2c_err: - dev_err(pchip->dev, "i2c failed to access REG_CTRL\n"); - return bl->props.brightness; + dev_err(pchip->dev, "i2c failed to access (%pe)\n", ERR_PTR(ret)); + return ret; } static int lm3630a_bank_b_get_brightness(struct backlight_device *bl) @@ -482,8 +482,10 @@ static int lm3630a_parse_node(struct lm3630a_chip *pchip, device_for_each_child_node(pchip->dev, node) { ret = lm3630a_parse_bank(pdata, node, &seen_led_sources); - if (ret) + if (ret) { + fwnode_handle_put(node); return ret; + } } return ret; diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index fc2f0c268d447525e3670e026e99b75e66d30ad2..7ecb121c482e6f07776f7b334b26de7d6289408b 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -970,13 +970,11 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var) fb_var_to_videomode(&mode2, &info->var); /* make sure we don't delete the videomode of current var */ ret = fb_mode_is_equal(&mode1, &mode2); - - if (!ret) - fbcon_mode_deleted(info, &mode1); - - if (!ret) - fb_delete_videomode(&mode1, &info->modelist); - + if (!ret) { + ret = fbcon_mode_deleted(info, &mode1); + if (!ret) + fb_delete_videomode(&mode1, &info->modelist); + } return ret ? -EINVAL : 0; } diff --git a/drivers/video/fbdev/imxfb.c b/drivers/video/fbdev/imxfb.c index 884b16efa7e8a93eae6d3b628e11d46142373d30..564bd0407ed81a30afeeabc1c347135c20ee1d2c 100644 --- a/drivers/video/fbdev/imxfb.c +++ b/drivers/video/fbdev/imxfb.c @@ -992,7 +992,7 @@ static int imxfb_probe(struct platform_device *pdev) info->screen_buffer = dma_alloc_wc(&pdev->dev, fbi->map_size, &fbi->map_dma, GFP_KERNEL); if (!info->screen_buffer) { - dev_err(&pdev->dev, "Failed to allocate video RAM: %d\n", ret); + dev_err(&pdev->dev, "Failed to allocate video RAM\n"); ret = -ENOMEM; goto failed_map; } diff --git a/drivers/visorbus/visorchipset.c b/drivers/visorbus/visorchipset.c index cb1eb7e05f871229dc1861f1a9236a52d26f1078..5668cad86e3743bb065236d28989e4c2971fb17f 100644 --- a/drivers/visorbus/visorchipset.c +++ b/drivers/visorbus/visorchipset.c @@ -1561,7 +1561,7 @@ schedule_out: static int visorchipset_init(struct acpi_device *acpi_device) { - int err = -ENODEV; + int err = -ENOMEM; struct visorchannel *controlvm_channel; chipset_dev = kzalloc(sizeof(*chipset_dev), GFP_KERNEL); @@ -1584,8 +1584,10 @@ static int visorchipset_init(struct acpi_device *acpi_device) "controlvm", sizeof(struct visor_controlvm_channel), VISOR_CONTROLVM_CHANNEL_VERSIONID, - VISOR_CHANNEL_SIGNATURE)) + VISOR_CHANNEL_SIGNATURE)) { + err = -ENODEV; goto error_delete_groups; + } /* if booting in a crash kernel */ if (is_kdump_kernel()) INIT_DELAYED_WORK(&chipset_dev->periodic_controlvm_work, diff --git a/drivers/w1/slaves/w1_ds2438.c b/drivers/w1/slaves/w1_ds2438.c index 5cfb0ae23e916c78e1f34bc4754b42071134cf1f..5698566b0ee014e02bbc8d9b73c2cea46deeca1b 100644 --- a/drivers/w1/slaves/w1_ds2438.c +++ b/drivers/w1/slaves/w1_ds2438.c @@ -62,13 +62,13 @@ static int w1_ds2438_get_page(struct w1_slave *sl, int pageno, u8 *buf) if (w1_reset_select_slave(sl)) continue; w1_buf[0] = W1_DS2438_RECALL_MEMORY; - w1_buf[1] = 0x00; + w1_buf[1] = (u8)pageno; w1_write_block(sl->master, w1_buf, 2); if (w1_reset_select_slave(sl)) continue; w1_buf[0] = W1_DS2438_READ_SCRATCH; - w1_buf[1] = 0x00; + w1_buf[1] = (u8)pageno; w1_write_block(sl->master, w1_buf, 2); count = w1_read_block(sl->master, buf, DS2438_PAGE_SIZE + 1); diff --git a/drivers/watchdog/aspeed_wdt.c b/drivers/watchdog/aspeed_wdt.c index 7e00960651fa26763b257a2169780eeaf03fadd7..507fd815d7679f714e7440caa3fdd4323f9a12be 100644 --- a/drivers/watchdog/aspeed_wdt.c +++ b/drivers/watchdog/aspeed_wdt.c @@ -147,7 +147,7 @@ static int aspeed_wdt_set_timeout(struct watchdog_device *wdd, wdd->timeout = timeout; - actual = min(timeout, wdd->max_hw_heartbeat_ms * 1000); + actual = min(timeout, wdd->max_hw_heartbeat_ms / 1000); writel(actual * WDT_RATE_1MHZ, wdt->base + WDT_RELOAD_VALUE); writel(WDT_RESTART_MAGIC, wdt->base + WDT_RESTART); diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index a370a185a41c40811a8f0f3002b17f4678d91264..519a539eeb9e8891d6297c84f89da1c52de774ad 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -73,6 +73,8 @@ #define TCOBASE(p) ((p)->tco_res->start) /* SMI Control and Enable Register */ #define SMI_EN(p) ((p)->smi_res->start) +#define TCO_EN (1 << 13) +#define GBL_SMI_EN (1 << 0) #define TCO_RLD(p) (TCOBASE(p) + 0x00) /* TCO Timer Reload/Curr. Value */ #define TCOv1_TMR(p) (TCOBASE(p) + 0x01) /* TCOv1 Timer Initial Value*/ @@ -357,8 +359,12 @@ static int iTCO_wdt_set_timeout(struct watchdog_device *wd_dev, unsigned int t) tmrval = seconds_to_ticks(p, t); - /* For TCO v1 the timer counts down twice before rebooting */ - if (p->iTCO_version == 1) + /* + * If TCO SMIs are off, the timer counts down twice before rebooting. + * Otherwise, the BIOS generally reboots when the SMI triggers. + */ + if (p->smi_res && + (SMI_EN(p) & (TCO_EN | GBL_SMI_EN)) != (TCO_EN | GBL_SMI_EN)) tmrval /= 2; /* from the specs: */ @@ -523,7 +529,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) * Disables TCO logic generating an SMI# */ val32 = inl(SMI_EN(p)); - val32 &= 0xffffdfff; /* Turn off SMI clearing watchdog */ + val32 &= ~TCO_EN; /* Turn off SMI clearing watchdog */ outl(val32, SMI_EN(p)); } diff --git a/drivers/watchdog/imx_sc_wdt.c b/drivers/watchdog/imx_sc_wdt.c index e9ee22a7cb456e98eed36589fd3c4ce5ea955cf8..8ac021748d160d6d36e7f248e774eb21fd3adba6 100644 --- a/drivers/watchdog/imx_sc_wdt.c +++ b/drivers/watchdog/imx_sc_wdt.c @@ -183,16 +183,12 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) watchdog_stop_on_reboot(wdog); watchdog_stop_on_unregister(wdog); - ret = devm_watchdog_register_device(dev, wdog); - if (ret) - return ret; - ret = imx_scu_irq_group_enable(SC_IRQ_GROUP_WDOG, SC_IRQ_WDOG, true); if (ret) { dev_warn(dev, "Enable irq failed, pretimeout NOT supported\n"); - return 0; + goto register_device; } imx_sc_wdd->wdt_notifier.notifier_call = imx_sc_wdt_notify; @@ -203,7 +199,7 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) false); dev_warn(dev, "Register irq notifier failed, pretimeout NOT supported\n"); - return 0; + goto register_device; } ret = devm_add_action_or_reset(dev, imx_sc_wdt_action, @@ -213,7 +209,8 @@ static int imx_sc_wdt_probe(struct platform_device *pdev) else dev_warn(dev, "Add action failed, pretimeout NOT supported\n"); - return 0; +register_device: + return devm_watchdog_register_device(dev, wdog); } static int __maybe_unused imx_sc_wdt_suspend(struct device *dev) diff --git a/drivers/watchdog/jz4740_wdt.c b/drivers/watchdog/jz4740_wdt.c index bdf9564efa29e284b7810f203136ed46595fed38..395bde79e2920138175330cc209d6741289b24da 100644 --- a/drivers/watchdog/jz4740_wdt.c +++ b/drivers/watchdog/jz4740_wdt.c @@ -176,9 +176,9 @@ static int jz4740_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(jz4740_wdt, drvdata); drvdata->map = device_node_to_regmap(dev->parent->of_node); - if (!drvdata->map) { + if (IS_ERR(drvdata->map)) { dev_err(dev, "regmap not found\n"); - return -EINVAL; + return PTR_ERR(drvdata->map); } return devm_watchdog_register_device(dev, &drvdata->wdt); diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c index 78cf11c949416786a3ca295a44d164e0b0ca7541..60b6d74f267dd67dbd89b5346f9711295c2e93c7 100644 --- a/drivers/watchdog/lpc18xx_wdt.c +++ b/drivers/watchdog/lpc18xx_wdt.c @@ -292,7 +292,7 @@ static int lpc18xx_wdt_remove(struct platform_device *pdev) struct lpc18xx_wdt_dev *lpc18xx_wdt = platform_get_drvdata(pdev); dev_warn(&pdev->dev, "I quit now, hardware will probably reboot!\n"); - del_timer(&lpc18xx_wdt->timer); + del_timer_sync(&lpc18xx_wdt->timer); return 0; } diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index a947a63fb44ae9c082c5f395d69811af1bc038be..7b974802dfc7cf25337d76b4e4ea0a8f2a12c99c 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c @@ -146,7 +146,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); inb_p(wdt_stop); pr_info("Watchdog timer is now disabled...\n"); } diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index e66e6b905964b9e809f3358d8f631e49e303582d..ca65468f4b9ced2b2a251b6e696b30be85714914 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c @@ -186,7 +186,7 @@ static int wdt_startup(void) static int wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); /* Stop the watchdog */ wdt_config(0); diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index 5772cc5d378041ac42c2f924b777990b0f4429d9..f2650863fd0272bd4ce9f92cfe3e8c35579d7e57 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c @@ -166,7 +166,7 @@ static void wdt_startup(void) static void wdt_turnoff(void) { /* Stop the timer */ - del_timer(&timer); + del_timer_sync(&timer); wdt_change(WDT_DISABLE); diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 29bec07205142e7684650d0d1120c3544bd2885c..af0f6ad32522ca58490ff832080d4a6ea5b3e25c 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -583,6 +583,9 @@ static void xen_irq_lateeoi_locked(struct irq_info *info, bool spurious) } info->eoi_time = 0; + + /* is_active hasn't been reset yet, do it now. */ + smp_store_release(&info->is_active, 0); do_unmask(info, EVT_MASK_REASON_EOI_PENDING); } @@ -1807,10 +1810,22 @@ static void lateeoi_ack_dynirq(struct irq_data *data) struct irq_info *info = info_for_irq(data->irq); evtchn_port_t evtchn = info ? info->evtchn : 0; - if (VALID_EVTCHN(evtchn)) { - do_mask(info, EVT_MASK_REASON_EOI_PENDING); - ack_dynirq(data); - } + if (!VALID_EVTCHN(evtchn)) + return; + + do_mask(info, EVT_MASK_REASON_EOI_PENDING); + + if (unlikely(irqd_is_setaffinity_pending(data)) && + likely(!irqd_irq_disabled(data))) { + do_mask(info, EVT_MASK_REASON_TEMPORARY); + + clear_evtchn(evtchn); + + irq_move_masked_irq(data); + + do_unmask(info, EVT_MASK_REASON_TEMPORARY); + } else + clear_evtchn(evtchn); } static void lateeoi_mask_ack_dynirq(struct irq_data *data) diff --git a/fs/btrfs/Kconfig b/fs/btrfs/Kconfig index 68b95ad82126edcc960ba5ae618ab5a92e9f9097..520a0f6a7d9e9708e456b2fea116247f19f79430 100644 --- a/fs/btrfs/Kconfig +++ b/fs/btrfs/Kconfig @@ -18,6 +18,8 @@ config BTRFS_FS select RAID6_PQ select XOR_BLOCKS select SRCU + depends on !PPC_256K_PAGES # powerpc + depends on !PAGE_SIZE_256KB # hexagon help Btrfs is a general purpose copy-on-write filesystem with extents, diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c index 4e2cce5ca7f6a3f4a3ede8e7c5e7e123a9cde910..04422d929c232f79a9c6edf9bf555f3045ce8670 100644 --- a/fs/btrfs/delayed-inode.c +++ b/fs/btrfs/delayed-inode.c @@ -1032,12 +1032,10 @@ static int __btrfs_update_delayed_inode(struct btrfs_trans_handle *trans, nofs_flag = memalloc_nofs_save(); ret = btrfs_lookup_inode(trans, root, path, &key, mod); memalloc_nofs_restore(nofs_flag); - if (ret > 0) { - btrfs_release_path(path); - return -ENOENT; - } else if (ret < 0) { - return ret; - } + if (ret > 0) + ret = -ENOENT; + if (ret < 0) + goto out; leaf = path->nodes[0]; inode_item = btrfs_item_ptr(leaf, path->slots[0], @@ -1075,6 +1073,14 @@ err_out: btrfs_delayed_inode_release_metadata(fs_info, node, (ret < 0)); btrfs_release_delayed_inode(node); + /* + * If we fail to update the delayed inode we need to abort the + * transaction, because we could leave the inode with the improper + * counts behind. + */ + if (ret && ret != -ENOENT) + btrfs_abort_transaction(trans, ret); + return ret; search: diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 4f26dae63b64a3f8a924b3c59795541c795b18c6..4f21b8fbfd4bc24114ebef3bc8f24a79cc3bae8c 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -547,7 +547,7 @@ again: * inode has not been flagged as nocompress. This flag can * change at any time if we discover bad compression ratios. */ - if (inode_need_compress(BTRFS_I(inode), start, end)) { + if (nr_pages > 1 && inode_need_compress(BTRFS_I(inode), start, end)) { WARN_ON(pages); pages = kcalloc(nr_pages, sizeof(struct page *), GFP_NOFS); if (!pages) { @@ -8213,7 +8213,19 @@ static void btrfs_invalidatepage(struct page *page, unsigned int offset, */ wait_on_page_writeback(page); - if (offset) { + /* + * For subpage case, we have call sites like + * btrfs_punch_hole_lock_range() which passes range not aligned to + * sectorsize. + * If the range doesn't cover the full page, we don't need to and + * shouldn't clear page extent mapped, as page->private can still + * record subpage dirty bits for other part of the range. + * + * For cases that can invalidate the full even the range doesn't + * cover the full page, like invalidating the last page, we're + * still safe to wait for ordered extent to finish. + */ + if (!(offset == 0 && length == PAGE_SIZE)) { btrfs_releasepage(page, GFP_NOFS); return; } diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 9e5809118c34d24a6687c9cb55724a307af3428b..10f020ab1186f1fd049ed9cf80060bf33801ca1e 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -4080,6 +4080,17 @@ static int process_recorded_refs(struct send_ctx *sctx, int *pending_move) if (ret < 0) goto out; } else { + /* + * If we previously orphanized a directory that + * collided with a new reference that we already + * processed, recompute the current path because + * that directory may be part of the path. + */ + if (orphanized_dir) { + ret = refresh_ref_path(sctx, cur); + if (ret < 0) + goto out; + } ret = send_unlink(sctx, cur->full_path); if (ret < 0) goto out; diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 279d9262b676d46f9f77db1d63af8e324f14ed7e..3bb6b688ece522b9351383a1fa4d2db71b149ecc 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -382,7 +382,7 @@ static ssize_t btrfs_discard_bitmap_bytes_show(struct kobject *kobj, { struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); - return scnprintf(buf, PAGE_SIZE, "%lld\n", + return scnprintf(buf, PAGE_SIZE, "%llu\n", fs_info->discard_ctl.discard_bitmap_bytes); } BTRFS_ATTR(discard, discard_bitmap_bytes, btrfs_discard_bitmap_bytes_show); @@ -404,7 +404,7 @@ static ssize_t btrfs_discard_extent_bytes_show(struct kobject *kobj, { struct btrfs_fs_info *fs_info = discard_to_fs_info(kobj); - return scnprintf(buf, PAGE_SIZE, "%lld\n", + return scnprintf(buf, PAGE_SIZE, "%llu\n", fs_info->discard_ctl.discard_extent_bytes); } BTRFS_ATTR(discard, discard_extent_bytes, btrfs_discard_extent_bytes_show); diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index af2f2f8704d8bc88ad14f85f0d77f819c9109e10..8daa9e4eb1d2e8a8c45205b659e50d1aa1f299b0 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c @@ -1382,8 +1382,10 @@ int btrfs_defrag_root(struct btrfs_root *root) while (1) { trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) - return PTR_ERR(trans); + if (IS_ERR(trans)) { + ret = PTR_ERR(trans); + break; + } ret = btrfs_defrag_leaves(trans, root); diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 300951088a11c89d0e11ad5f94080a04eb357243..4b913de2f24fb58aee63c571b5c22c36f791daf8 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -6348,6 +6348,7 @@ next: error: if (wc.trans) btrfs_end_transaction(wc.trans); + clear_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags); btrfs_free_path(path); return ret; } diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 35c83f65475b2a4a7615952efacdbe0f9e662bba..3465ff95cb89f22da8f9ea63b7ddc37da3ef737d 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -78,10 +78,6 @@ static int ceph_set_page_dirty(struct page *page) struct inode *inode; struct ceph_inode_info *ci; struct ceph_snap_context *snapc; - int ret; - - if (unlikely(!mapping)) - return !TestSetPageDirty(page); if (PageDirty(page)) { dout("%p set_page_dirty %p idx %lu -- already dirty\n", @@ -127,11 +123,7 @@ static int ceph_set_page_dirty(struct page *page) page->private = (unsigned long)snapc; SetPagePrivate(page); - ret = __set_page_dirty_nobuffers(page); - WARN_ON(!PageLocked(page)); - WARN_ON(!page->mapping); - - return ret; + return __set_page_dirty_nobuffers(page); } /* @@ -1302,6 +1294,45 @@ ceph_find_incompatible(struct page *page) return NULL; } +/** + * prep_noread_page - prep a page for writing without reading first + * @page: page being prepared + * @pos: starting position for the write + * @len: length of write + * + * In some cases, write_begin doesn't need to read at all: + * - full page write + * - file is currently zero-length + * - write that lies in a page that is completely beyond EOF + * - write that covers the the page from start to EOF or beyond it + * + * If any of these criteria are met, then zero out the unwritten parts + * of the page and return true. Otherwise, return false. + */ +static bool skip_page_read(struct page *page, loff_t pos, size_t len) +{ + struct inode *inode = page->mapping->host; + loff_t i_size = i_size_read(inode); + size_t offset = offset_in_page(pos); + + /* Full page write */ + if (offset == 0 && len >= PAGE_SIZE) + return true; + + /* pos beyond last page in the file */ + if (pos - offset >= i_size) + goto zero_out; + + /* write that covers the whole page from start to EOF or beyond it */ + if (offset == 0 && (pos + len) >= i_size) + goto zero_out; + + return false; +zero_out: + zero_user_segments(page, 0, offset, offset + len, PAGE_SIZE); + return true; +} + /* * We are only allowed to write into/dirty the page if the page is * clean, or already dirty within the same snap context. @@ -1315,7 +1346,6 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping, struct ceph_snap_context *snapc; struct page *page = NULL; pgoff_t index = pos >> PAGE_SHIFT; - int pos_in_page = pos & ~PAGE_MASK; int r = 0; dout("write_begin file %p inode %p page %p %d~%d\n", file, inode, page, (int)pos, (int)len); @@ -1350,19 +1380,9 @@ static int ceph_write_begin(struct file *file, struct address_space *mapping, break; } - /* - * In some cases we don't need to read at all: - * - full page write - * - write that lies completely beyond EOF - * - write that covers the the page from start to EOF or beyond it - */ - if ((pos_in_page == 0 && len == PAGE_SIZE) || - (pos >= i_size_read(inode)) || - (pos_in_page == 0 && (pos + len) >= i_size_read(inode))) { - zero_user_segments(page, 0, pos_in_page, - pos_in_page + len, PAGE_SIZE); + /* No need to read in some cases */ + if (skip_page_read(page, pos, len)) break; - } /* * We need to read it. If we get back -EINPROGRESS, then the page was diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 209535d5b8d387389afe25fe8d54ab19fc088749..3d2e3dd4ee01da992410f566b89bec97e3aaa929 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -578,6 +578,7 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, struct ceph_inode_info *ci = ceph_inode(dir); struct inode *inode; struct timespec64 now; + struct ceph_mds_client *mdsc = ceph_sb_to_mdsc(dir->i_sb); struct ceph_vino vino = { .ino = req->r_deleg_ino, .snap = CEPH_NOSNAP }; @@ -615,8 +616,10 @@ static int ceph_finish_async_create(struct inode *dir, struct dentry *dentry, ceph_file_layout_to_legacy(lo, &in.layout); + down_read(&mdsc->snap_rwsem); ret = ceph_fill_inode(inode, NULL, &iinfo, NULL, req->r_session, req->r_fmode, NULL); + up_read(&mdsc->snap_rwsem); if (ret) { dout("%s failed to fill inode: %d\n", __func__, ret); ceph_dir_clear_complete(dir); diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 346fcdfcd3e912027272907bdf2e23b037fb1b38..57cd78e942c08fb69b86eb5c8804b600c8fd905f 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -762,6 +762,8 @@ int ceph_fill_inode(struct inode *inode, struct page *locked_page, bool new_version = false; bool fill_inline = false; + lockdep_assert_held(&mdsc->snap_rwsem); + dout("%s %p ino %llx.%llx v %llu had %llu\n", __func__, inode, ceph_vinop(inode), le64_to_cpu(info->version), ci->i_version); diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 248ee81e015164b0e1a2595af31463e7223fdabd..6599069be690ebe6d507a3ba9119dc8306e0bb31 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -979,7 +979,7 @@ struct cifs_ses { struct mutex session_mutex; struct TCP_Server_Info *server; /* pointer to server info */ int ses_count; /* reference counter */ - enum statusEnum status; + enum statusEnum status; /* updates protected by GlobalMid_Lock */ unsigned overrideSecFlg; /* if non-zero override global sec flags */ char *serverOS; /* name of operating system underlying server */ char *serverNOS; /* name of network operating system of server */ @@ -1863,6 +1863,7 @@ require use of the stronger protocol */ * list operations on pending_mid_q and oplockQ * updates to XID counters, multiplex id and SMB sequence numbers * list operations on global DnotifyReqList + * updates to ses->status * tcp_ses_lock protects: * list operations on tcp and SMB session lists * tcon->open_file_lock protects the list of open files hanging off the tcon diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index aabaebd1535f0bfc821f5abbaa3336625cb7ec8c..8ffe8063e42c1b110c824be0d348f034bab9c4ac 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -2829,9 +2829,12 @@ void cifs_put_smb_ses(struct cifs_ses *ses) spin_unlock(&cifs_tcp_ses_lock); return; } + spin_unlock(&cifs_tcp_ses_lock); + + spin_lock(&GlobalMid_Lock); if (ses->status == CifsGood) ses->status = CifsExiting; - spin_unlock(&cifs_tcp_ses_lock); + spin_unlock(&GlobalMid_Lock); cifs_free_ipc(ses); @@ -5349,7 +5352,8 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru if (!tree) return -ENOMEM; - if (!tcon->dfs_path) { + /* If it is not dfs or there was no cached dfs referral, then reconnect to same share */ + if (!tcon->dfs_path || dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl)) { if (tcon->ipc) { scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname); rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc); @@ -5359,9 +5363,6 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru goto out; } - rc = dfs_cache_noreq_find(tcon->dfs_path + 1, &ref, &tl); - if (rc) - goto out; isroot = ref.server_type == DFS_TYPE_ROOT; free_dfs_info_param(&ref); diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c index a9d15553014468cfed6617c9a4060de15eba63b7..f6ceb79a995d06b1a8f07cf60ce02ba192c562f2 100644 --- a/fs/cifs/smb2ops.c +++ b/fs/cifs/smb2ops.c @@ -3459,6 +3459,119 @@ static long smb3_punch_hole(struct file *file, struct cifs_tcon *tcon, return rc; } +static int smb3_simple_fallocate_write_range(unsigned int xid, + struct cifs_tcon *tcon, + struct cifsFileInfo *cfile, + loff_t off, loff_t len, + char *buf) +{ + struct cifs_io_parms io_parms = {0}; + int nbytes; + struct kvec iov[2]; + + io_parms.netfid = cfile->fid.netfid; + io_parms.pid = current->tgid; + io_parms.tcon = tcon; + io_parms.persistent_fid = cfile->fid.persistent_fid; + io_parms.volatile_fid = cfile->fid.volatile_fid; + io_parms.offset = off; + io_parms.length = len; + + /* iov[0] is reserved for smb header */ + iov[1].iov_base = buf; + iov[1].iov_len = io_parms.length; + return SMB2_write(xid, &io_parms, &nbytes, iov, 1); +} + +static int smb3_simple_fallocate_range(unsigned int xid, + struct cifs_tcon *tcon, + struct cifsFileInfo *cfile, + loff_t off, loff_t len) +{ + struct file_allocated_range_buffer in_data, *out_data = NULL, *tmp_data; + u32 out_data_len; + char *buf = NULL; + loff_t l; + int rc; + + in_data.file_offset = cpu_to_le64(off); + in_data.length = cpu_to_le64(len); + rc = SMB2_ioctl(xid, tcon, cfile->fid.persistent_fid, + cfile->fid.volatile_fid, + FSCTL_QUERY_ALLOCATED_RANGES, true, + (char *)&in_data, sizeof(in_data), + 1024 * sizeof(struct file_allocated_range_buffer), + (char **)&out_data, &out_data_len); + if (rc) + goto out; + /* + * It is already all allocated + */ + if (out_data_len == 0) + goto out; + + buf = kzalloc(1024 * 1024, GFP_KERNEL); + if (buf == NULL) { + rc = -ENOMEM; + goto out; + } + + tmp_data = out_data; + while (len) { + /* + * The rest of the region is unmapped so write it all. + */ + if (out_data_len == 0) { + rc = smb3_simple_fallocate_write_range(xid, tcon, + cfile, off, len, buf); + goto out; + } + + if (out_data_len < sizeof(struct file_allocated_range_buffer)) { + rc = -EINVAL; + goto out; + } + + if (off < le64_to_cpu(tmp_data->file_offset)) { + /* + * We are at a hole. Write until the end of the region + * or until the next allocated data, + * whichever comes next. + */ + l = le64_to_cpu(tmp_data->file_offset) - off; + if (len < l) + l = len; + rc = smb3_simple_fallocate_write_range(xid, tcon, + cfile, off, l, buf); + if (rc) + goto out; + off = off + l; + len = len - l; + if (len == 0) + goto out; + } + /* + * We are at a section of allocated data, just skip forward + * until the end of the data or the end of the region + * we are supposed to fallocate, whichever comes first. + */ + l = le64_to_cpu(tmp_data->length); + if (len < l) + l = len; + off += l; + len -= l; + + tmp_data = &tmp_data[1]; + out_data_len -= sizeof(struct file_allocated_range_buffer); + } + + out: + kfree(out_data); + kfree(buf); + return rc; +} + + static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, loff_t off, loff_t len, bool keep_size) { @@ -3519,6 +3632,26 @@ static long smb3_simple_falloc(struct file *file, struct cifs_tcon *tcon, } if ((keep_size == true) || (i_size_read(inode) >= off + len)) { + /* + * At this point, we are trying to fallocate an internal + * regions of a sparse file. Since smb2 does not have a + * fallocate command we have two otions on how to emulate this. + * We can either turn the entire file to become non-sparse + * which we only do if the fallocate is for virtually + * the whole file, or we can overwrite the region with zeroes + * using SMB2_write, which could be prohibitevly expensive + * if len is large. + */ + /* + * We are only trying to fallocate a small region so + * just write it with zero. + */ + if (len <= 1024 * 1024) { + rc = smb3_simple_fallocate_range(xid, tcon, cfile, + off, len); + goto out; + } + /* * Check if falloc starts within first few pages of file * and ends within a few pages of the end of file to diff --git a/fs/configfs/file.c b/fs/configfs/file.c index da8351d1e455209150954bf6cc002e5643d97870..4d0825213116a4ca800172ebdd1d21babc948aff 100644 --- a/fs/configfs/file.c +++ b/fs/configfs/file.c @@ -482,13 +482,13 @@ static int configfs_release_bin_file(struct inode *inode, struct file *file) buffer->bin_buffer_size); } up_read(&frag->frag_sem); - /* vfree on NULL is safe */ - vfree(buffer->bin_buffer); - buffer->bin_buffer = NULL; - buffer->bin_buffer_size = 0; - buffer->needs_read_fill = 1; } + vfree(buffer->bin_buffer); + buffer->bin_buffer = NULL; + buffer->bin_buffer_size = 0; + buffer->needs_read_fill = 1; + configfs_release(inode, file); return 0; } diff --git a/fs/crypto/fname.c b/fs/crypto/fname.c index 1fbe6c24d705278edbe6f54663d3ce4dfdbfadcd..9fa871e287ba33efd9b1065a0b02348d2027e7e7 100644 --- a/fs/crypto/fname.c +++ b/fs/crypto/fname.c @@ -344,13 +344,9 @@ int fscrypt_fname_disk_to_usr(const struct inode *inode, offsetof(struct fscrypt_nokey_name, sha256)); BUILD_BUG_ON(BASE64_CHARS(FSCRYPT_NOKEY_NAME_MAX) > NAME_MAX); - if (hash) { - nokey_name.dirhash[0] = hash; - nokey_name.dirhash[1] = minor_hash; - } else { - nokey_name.dirhash[0] = 0; - nokey_name.dirhash[1] = 0; - } + nokey_name.dirhash[0] = hash; + nokey_name.dirhash[1] = minor_hash; + if (iname->len <= sizeof(nokey_name.bytes)) { memcpy(nokey_name.bytes, iname->name, iname->len); size = offsetof(struct fscrypt_nokey_name, bytes[iname->len]); diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c index 31fb08d94f8741da06550af79f67d55355cbda31..9a6f9a188efb97024e96d8da78424f7eeb3518d6 100644 --- a/fs/crypto/keysetup.c +++ b/fs/crypto/keysetup.c @@ -210,15 +210,40 @@ out_unlock: return err; } +/* + * Derive a SipHash key from the given fscrypt master key and the given + * application-specific information string. + * + * Note that the KDF produces a byte array, but the SipHash APIs expect the key + * as a pair of 64-bit words. Therefore, on big endian CPUs we have to do an + * endianness swap in order to get the same results as on little endian CPUs. + */ +static int fscrypt_derive_siphash_key(const struct fscrypt_master_key *mk, + u8 context, const u8 *info, + unsigned int infolen, siphash_key_t *key) +{ + int err; + + err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, context, info, infolen, + (u8 *)key, sizeof(*key)); + if (err) + return err; + + BUILD_BUG_ON(sizeof(*key) != 16); + BUILD_BUG_ON(ARRAY_SIZE(key->key) != 2); + le64_to_cpus(&key->key[0]); + le64_to_cpus(&key->key[1]); + return 0; +} + int fscrypt_derive_dirhash_key(struct fscrypt_info *ci, const struct fscrypt_master_key *mk) { int err; - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, HKDF_CONTEXT_DIRHASH_KEY, - ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE, - (u8 *)&ci->ci_dirhash_key, - sizeof(ci->ci_dirhash_key)); + err = fscrypt_derive_siphash_key(mk, HKDF_CONTEXT_DIRHASH_KEY, + ci->ci_nonce, FSCRYPT_FILE_NONCE_SIZE, + &ci->ci_dirhash_key); if (err) return err; ci->ci_dirhash_key_initialized = true; @@ -253,10 +278,9 @@ static int fscrypt_setup_iv_ino_lblk_32_key(struct fscrypt_info *ci, if (mk->mk_ino_hash_key_initialized) goto unlock; - err = fscrypt_hkdf_expand(&mk->mk_secret.hkdf, - HKDF_CONTEXT_INODE_HASH_KEY, NULL, 0, - (u8 *)&mk->mk_ino_hash_key, - sizeof(mk->mk_ino_hash_key)); + err = fscrypt_derive_siphash_key(mk, + HKDF_CONTEXT_INODE_HASH_KEY, + NULL, 0, &mk->mk_ino_hash_key); if (err) goto unlock; /* pairs with smp_load_acquire() above */ diff --git a/fs/dax.c b/fs/dax.c index df5485b4bddf1996e67cb1df49aacadd0dc667c4..d5d7b9393bcaa119e6262b2deeb260f004e723ea 100644 --- a/fs/dax.c +++ b/fs/dax.c @@ -488,10 +488,11 @@ static void *grab_mapping_entry(struct xa_state *xas, struct address_space *mapping, unsigned int order) { unsigned long index = xas->xa_index; - bool pmd_downgrade = false; /* splitting PMD entry into PTE entries? */ + bool pmd_downgrade; /* splitting PMD entry into PTE entries? */ void *entry; retry: + pmd_downgrade = false; xas_lock_irq(xas); entry = get_unlocked_entry(xas, order); diff --git a/fs/dlm/config.c b/fs/dlm/config.c index 73e6643903af5067118c1ad93e938fa8f0b3f0d1..18a8ffcea0aa48b622f3dfb76b165d9fd80b1952 100644 --- a/fs/dlm/config.c +++ b/fs/dlm/config.c @@ -79,6 +79,9 @@ struct dlm_cluster { unsigned int cl_new_rsb_count; unsigned int cl_recover_callbacks; char cl_cluster_name[DLM_LOCKSPACE_LEN]; + + struct dlm_spaces *sps; + struct dlm_comms *cms; }; static struct dlm_cluster *config_item_to_cluster(struct config_item *i) @@ -379,6 +382,9 @@ static struct config_group *make_cluster(struct config_group *g, if (!cl || !sps || !cms) goto fail; + cl->sps = sps; + cl->cms = cms; + config_group_init_type_name(&cl->group, name, &cluster_type); config_group_init_type_name(&sps->ss_group, "spaces", &spaces_type); config_group_init_type_name(&cms->cs_group, "comms", &comms_type); @@ -428,6 +434,9 @@ static void drop_cluster(struct config_group *g, struct config_item *i) static void release_cluster(struct config_item *i) { struct dlm_cluster *cl = config_item_to_cluster(i); + + kfree(cl->sps); + kfree(cl->cms); kfree(cl); } diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 44e2716ac158003b2501e8ea3b73237370b97265..0c78fdfb1f6faaec81253a6535055cef23a0acc8 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -599,7 +599,7 @@ static void close_connection(struct connection *con, bool and_other, } if (con->othercon && and_other) { /* Will only re-enter once. */ - close_connection(con->othercon, false, true, true); + close_connection(con->othercon, false, tx, rx); } con->rx_leftover = 0; diff --git a/fs/erofs/super.c b/fs/erofs/super.c index d5a6b9b888a562bae6b30e80162be2bea7f7fc55..f31a08d86be893403a6283885fdf73bd2a0ffdd9 100644 --- a/fs/erofs/super.c +++ b/fs/erofs/super.c @@ -155,6 +155,7 @@ static int erofs_read_superblock(struct super_block *sb) goto out; } + ret = -EINVAL; blkszbits = dsb->blkszbits; /* 9(512 bytes) + LOG_SECTORS_PER_BLOCK == LOG_BLOCK_SIZE */ if (blkszbits != LOG_BLOCK_SIZE) { diff --git a/fs/exec.c b/fs/exec.c index ca89e0e3ef10f19ee0ba7243c52fa7ff130900cf..c7a4ef8df3058cf584f768b37d701e9b47f022f7 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1347,6 +1347,10 @@ int begin_new_exec(struct linux_binprm * bprm) WRITE_ONCE(me->self_exec_id, me->self_exec_id + 1); flush_signal_handlers(me, 0); + retval = set_cred_ucounts(bprm->cred); + if (retval < 0) + goto out_unlock; + /* * install the new credentials for this executable */ diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c index 916797077aad4ab45cd73c36a5012fd2653fef33..dedbc55cd48f55f1e895dea0dd56ea590bd17ae3 100644 --- a/fs/exfat/dir.c +++ b/fs/exfat/dir.c @@ -62,7 +62,7 @@ static void exfat_get_uniname_from_ext_entry(struct super_block *sb, static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_entry *dir_entry) { int i, dentries_per_clu, dentries_per_clu_bits = 0, num_ext; - unsigned int type, clu_offset; + unsigned int type, clu_offset, max_dentries; sector_t sector; struct exfat_chain dir, clu; struct exfat_uni_name uni_name; @@ -85,6 +85,8 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent dentries_per_clu = sbi->dentries_per_clu; dentries_per_clu_bits = ilog2(dentries_per_clu); + max_dentries = (unsigned int)min_t(u64, MAX_EXFAT_DENTRIES, + (u64)sbi->num_clusters << dentries_per_clu_bits); clu_offset = dentry >> dentries_per_clu_bits; exfat_chain_dup(&clu, &dir); @@ -108,7 +110,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent } } - while (clu.dir != EXFAT_EOF_CLUSTER) { + while (clu.dir != EXFAT_EOF_CLUSTER && dentry < max_dentries) { i = dentry & (dentries_per_clu - 1); for ( ; i < dentries_per_clu; i++, dentry++) { @@ -244,7 +246,7 @@ static int exfat_iterate(struct file *filp, struct dir_context *ctx) if (err) goto unlock; get_new: - if (cpos >= i_size_read(inode)) + if (ei->flags == ALLOC_NO_FAT_CHAIN && cpos >= i_size_read(inode)) goto end_of_dir; err = exfat_readdir(inode, &cpos, &de); diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 7cae226b000f7c048a4b2864195906f4614503a4..115a77b96e5e144780fe31f584a7b4fac5aca23c 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1480,6 +1480,7 @@ struct ext4_sb_info { struct kobject s_kobj; struct completion s_kobj_unregister; struct super_block *s_sb; + struct buffer_head *s_mmp_bh; /* Journaling */ struct journal_s *s_journal; @@ -3624,6 +3625,9 @@ extern struct ext4_io_end_vec *ext4_last_io_end_vec(ext4_io_end_t *io_end); /* mmp.c */ extern int ext4_multi_mount_protect(struct super_block *, ext4_fsblk_t); +/* mmp.c */ +extern void ext4_stop_mmpd(struct ext4_sb_info *sbi); + /* verity.c */ extern const struct fsverity_operations ext4_verityops; diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index e6542ba264330fde323007029d2902dba4049703..e00a35530a4e00d91326f063f34ad4321e10674d 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -825,6 +825,7 @@ void ext4_ext_tree_init(handle_t *handle, struct inode *inode) eh->eh_entries = 0; eh->eh_magic = EXT4_EXT_MAGIC; eh->eh_max = cpu_to_le16(ext4_ext_space_root(inode, 0)); + eh->eh_generation = 0; ext4_mark_inode_dirty(handle, inode); } @@ -1090,6 +1091,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, neh->eh_max = cpu_to_le16(ext4_ext_space_block(inode, 0)); neh->eh_magic = EXT4_EXT_MAGIC; neh->eh_depth = 0; + neh->eh_generation = 0; /* move remainder of path[depth] to the new leaf */ if (unlikely(path[depth].p_hdr->eh_entries != @@ -1167,6 +1169,7 @@ static int ext4_ext_split(handle_t *handle, struct inode *inode, neh->eh_magic = EXT4_EXT_MAGIC; neh->eh_max = cpu_to_le16(ext4_ext_space_block_idx(inode, 0)); neh->eh_depth = cpu_to_le16(depth - i); + neh->eh_generation = 0; fidx = EXT_FIRST_INDEX(neh); fidx->ei_block = border; ext4_idx_store_pblock(fidx, oldblock); diff --git a/fs/ext4/extents_status.c b/fs/ext4/extents_status.c index 0a729027322ddc116c35ab387528f2eba8b99133..9a3a8996aacf7356131e3ea6a12e096f3a711695 100644 --- a/fs/ext4/extents_status.c +++ b/fs/ext4/extents_status.c @@ -1574,11 +1574,9 @@ static unsigned long ext4_es_scan(struct shrinker *shrink, ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt); trace_ext4_es_shrink_scan_enter(sbi->s_sb, nr_to_scan, ret); - if (!nr_to_scan) - return ret; - nr_shrunk = __es_shrink(sbi, nr_to_scan, NULL); + ret = percpu_counter_read_positive(&sbi->s_es_stats.es_stats_shk_cnt); trace_ext4_es_shrink_scan_exit(sbi->s_sb, nr_shrunk, ret); return nr_shrunk; } diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index b294ebcb4db4bcbe538343bcd181dd020c0f3118..875af329c43ec9db36d4fed2ee17fff3bba8b730 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -402,7 +402,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g, * * We always try to spread first-level directories. * - * If there are blockgroups with both free inodes and free blocks counts + * If there are blockgroups with both free inodes and free clusters counts * not worse than average we return one with smallest directory count. * Otherwise we simply return a random group. * @@ -411,7 +411,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g, * It's OK to put directory into a group unless * it has too many directories already (max_dirs) or * it has too few free inodes left (min_inodes) or - * it has too few free blocks left (min_blocks) or + * it has too few free clusters left (min_clusters) or * Parent's group is preferred, if it doesn't satisfy these * conditions we search cyclically through the rest. If none * of the groups look good we just look for a group with more @@ -427,7 +427,7 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, ext4_group_t real_ngroups = ext4_get_groups_count(sb); int inodes_per_group = EXT4_INODES_PER_GROUP(sb); unsigned int freei, avefreei, grp_free; - ext4_fsblk_t freeb, avefreec; + ext4_fsblk_t freec, avefreec; unsigned int ndirs; int max_dirs, min_inodes; ext4_grpblk_t min_clusters; @@ -446,9 +446,8 @@ static int find_group_orlov(struct super_block *sb, struct inode *parent, freei = percpu_counter_read_positive(&sbi->s_freeinodes_counter); avefreei = freei / ngroups; - freeb = EXT4_C2B(sbi, - percpu_counter_read_positive(&sbi->s_freeclusters_counter)); - avefreec = freeb; + freec = percpu_counter_read_positive(&sbi->s_freeclusters_counter); + avefreec = freec; do_div(avefreec, ngroups); ndirs = percpu_counter_read_positive(&sbi->s_dirs_counter); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 3f11c948feb026c056c0f495e191cfa125bbe172..18a5321b5ef37d6500cb3fd9464fd3e68c13a140 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -3419,7 +3419,7 @@ retry: * i_disksize out to i_size. This could be beyond where direct I/O is * happening and thus expose allocated blocks to direct I/O reads. */ - else if ((map->m_lblk * (1 << blkbits)) >= i_size_read(inode)) + else if (((loff_t)map->m_lblk << blkbits) >= i_size_read(inode)) m_flags = EXT4_GET_BLOCKS_CREATE; else if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) m_flags = EXT4_GET_BLOCKS_IO_CREATE_EXT; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 9c390c3d7fb15fb7167b8f9a78f93aeb721d706e..d7cb7d719ee5845924146bd92c5837b4042de266 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1597,10 +1597,11 @@ static int mb_find_extent(struct ext4_buddy *e4b, int block, if (ex->fe_start + ex->fe_len > EXT4_CLUSTERS_PER_GROUP(e4b->bd_sb)) { /* Should never happen! (but apparently sometimes does?!?) */ WARN_ON(1); - ext4_error(e4b->bd_sb, "corruption or bug in mb_find_extent " - "block=%d, order=%d needed=%d ex=%u/%d/%d@%u", - block, order, needed, ex->fe_group, ex->fe_start, - ex->fe_len, ex->fe_logical); + ext4_grp_locked_error(e4b->bd_sb, e4b->bd_group, 0, 0, + "corruption or bug in mb_find_extent " + "block=%d, order=%d needed=%d ex=%u/%d/%d@%u", + block, order, needed, ex->fe_group, ex->fe_start, + ex->fe_len, ex->fe_logical); ex->fe_len = 0; ex->fe_start = 0; ex->fe_group = 0; diff --git a/fs/ext4/mmp.c b/fs/ext4/mmp.c index 68fbeedd627bc5fab86ab865fa0a739cfe3764c6..6cb598b549ca169af7bc533c87298ff369b0d539 100644 --- a/fs/ext4/mmp.c +++ b/fs/ext4/mmp.c @@ -127,9 +127,9 @@ void __dump_mmp_msg(struct super_block *sb, struct mmp_struct *mmp, */ static int kmmpd(void *data) { - struct super_block *sb = ((struct mmpd_data *) data)->sb; - struct buffer_head *bh = ((struct mmpd_data *) data)->bh; + struct super_block *sb = (struct super_block *) data; struct ext4_super_block *es = EXT4_SB(sb)->s_es; + struct buffer_head *bh = EXT4_SB(sb)->s_mmp_bh; struct mmp_struct *mmp; ext4_fsblk_t mmp_block; u32 seq = 0; @@ -245,12 +245,18 @@ static int kmmpd(void *data) retval = write_mmp_block(sb, bh); exit_thread: - EXT4_SB(sb)->s_mmp_tsk = NULL; - kfree(data); - brelse(bh); return retval; } +void ext4_stop_mmpd(struct ext4_sb_info *sbi) +{ + if (sbi->s_mmp_tsk) { + kthread_stop(sbi->s_mmp_tsk); + brelse(sbi->s_mmp_bh); + sbi->s_mmp_tsk = NULL; + } +} + /* * Get a random new sequence number but make sure it is not greater than * EXT4_MMP_SEQ_MAX. @@ -275,7 +281,6 @@ int ext4_multi_mount_protect(struct super_block *sb, struct ext4_super_block *es = EXT4_SB(sb)->s_es; struct buffer_head *bh = NULL; struct mmp_struct *mmp = NULL; - struct mmpd_data *mmpd_data; u32 seq; unsigned int mmp_check_interval = le16_to_cpu(es->s_mmp_update_interval); unsigned int wait_time = 0; @@ -364,24 +369,17 @@ skip: goto failed; } - mmpd_data = kmalloc(sizeof(*mmpd_data), GFP_KERNEL); - if (!mmpd_data) { - ext4_warning(sb, "not enough memory for mmpd_data"); - goto failed; - } - mmpd_data->sb = sb; - mmpd_data->bh = bh; + EXT4_SB(sb)->s_mmp_bh = bh; /* * Start a kernel thread to update the MMP block periodically. */ - EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, mmpd_data, "kmmpd-%.*s", + EXT4_SB(sb)->s_mmp_tsk = kthread_run(kmmpd, sb, "kmmpd-%.*s", (int)sizeof(mmp->mmp_bdevname), bdevname(bh->b_bdev, mmp->mmp_bdevname)); if (IS_ERR(EXT4_SB(sb)->s_mmp_tsk)) { EXT4_SB(sb)->s_mmp_tsk = NULL; - kfree(mmpd_data); ext4_warning(sb, "Unable to create kmmpd thread for %s.", sb->s_id); goto failed; diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 21c4ba2513ce5e85ed51f7e6d47bc8c92d8c92e3..099e4afa41e526e917275aa4bdb1455d3c521d0e 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1260,8 +1260,8 @@ static void ext4_put_super(struct super_block *sb) ext4_xattr_destroy_cache(sbi->s_ea_block_cache); sbi->s_ea_block_cache = NULL; - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); + ext4_stop_mmpd(sbi); + brelse(sbi->s_sbh); sb->s_fs_info = NULL; /* @@ -3099,8 +3099,15 @@ static void ext4_orphan_cleanup(struct super_block *sb, inode_lock(inode); truncate_inode_pages(inode->i_mapping, inode->i_size); ret = ext4_truncate(inode); - if (ret) + if (ret) { + /* + * We need to clean up the in-core orphan list + * manually if ext4_truncate() failed to get a + * transaction handle. + */ + ext4_orphan_del(NULL, inode); ext4_std_error(inode->i_sb, ret); + } inode_unlock(inode); nr_truncates++; } else { @@ -5039,6 +5046,7 @@ no_journal: ext4_msg(sb, KERN_ERR, "unable to initialize " "flex_bg meta info!"); + ret = -ENOMEM; goto failed_mount6; } @@ -5165,8 +5173,7 @@ failed_mount3a: ext4_es_unregister_shrinker(sbi); failed_mount3: del_timer_sync(&sbi->s_err_report); - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); + ext4_stop_mmpd(sbi); failed_mount2: rcu_read_lock(); group_desc = rcu_dereference(sbi->s_group_desc); @@ -5919,8 +5926,7 @@ static int ext4_remount(struct super_block *sb, int *flags, char *data) */ ext4_mark_recovery_complete(sb, es); } - if (sbi->s_mmp_tsk) - kthread_stop(sbi->s_mmp_tsk); + ext4_stop_mmpd(sbi); } else { /* Make sure we can mount this feature set readwrite */ if (ext4_has_feature_readonly(sb) || diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index bdc0f3b2d7abfe7159b24e339a82d3a42308496c..cfae2dddb0baefac84d88d15d733b4cfd67d5f0d 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -4112,6 +4112,12 @@ static int f2fs_swap_activate(struct swap_info_struct *sis, struct file *file, if (f2fs_readonly(F2FS_I_SB(inode)->sb)) return -EROFS; + if (f2fs_lfs_mode(F2FS_I_SB(inode))) { + f2fs_err(F2FS_I_SB(inode), + "Swapfile not supported in LFS mode"); + return -EINVAL; + } + ret = f2fs_convert_inline_inode(inode); if (ret) return ret; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index 69a390c6064c642f3459acf8932ceeb2357a30f4..2d7799bd30b107fe39760e79880a9daeaceaa4aa 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -3462,6 +3462,8 @@ void f2fs_destroy_garbage_collection_cache(void); */ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only); bool f2fs_space_for_roll_forward(struct f2fs_sb_info *sbi); +int __init f2fs_create_recovery_cache(void); +void f2fs_destroy_recovery_cache(void); /* * debug.c diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c index 9b38cef4d50fe4c9852a972b18ac793fefdf34dc..e02affb5c0e799fb4edf4f21eb11a6bc1c03f312 100644 --- a/fs/f2fs/gc.c +++ b/fs/f2fs/gc.c @@ -1801,6 +1801,7 @@ static void init_atgc_management(struct f2fs_sb_info *sbi) am->candidate_ratio = DEF_GC_THREAD_CANDIDATE_RATIO; am->max_candidate_count = DEF_GC_THREAD_MAX_CANDIDATE_COUNT; am->age_weight = DEF_GC_THREAD_AGE_WEIGHT; + am->age_threshold = DEF_GC_THREAD_AGE_THRESHOLD; } void f2fs_build_gc_manager(struct f2fs_sb_info *sbi) diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c index 5f7ab4f113224107429751a56090600efd27b6a4..17d0e5f4efec801b61f147c8a7301bb438250f89 100644 --- a/fs/f2fs/namei.c +++ b/fs/f2fs/namei.c @@ -153,7 +153,8 @@ fail_drop: return ERR_PTR(err); } -static inline int is_extension_exist(const unsigned char *s, const char *sub) +static inline int is_extension_exist(const unsigned char *s, const char *sub, + bool tmp_ext) { size_t slen = strlen(s); size_t sublen = strlen(sub); @@ -169,6 +170,13 @@ static inline int is_extension_exist(const unsigned char *s, const char *sub) if (slen < sublen + 2) return 0; + if (!tmp_ext) { + /* file has no temp extension */ + if (s[slen - sublen - 1] != '.') + return 0; + return !strncasecmp(s + slen - sublen, sub, sublen); + } + for (i = 1; i < slen - sublen; i++) { if (s[i] != '.') continue; @@ -194,7 +202,7 @@ static inline void set_file_temperature(struct f2fs_sb_info *sbi, struct inode * hot_count = sbi->raw_super->hot_ext_count; for (i = 0; i < cold_count + hot_count; i++) { - if (is_extension_exist(name, extlist[i])) + if (is_extension_exist(name, extlist[i], true)) break; } @@ -295,7 +303,7 @@ static void set_compress_inode(struct f2fs_sb_info *sbi, struct inode *inode, hot_count = sbi->raw_super->hot_ext_count; for (i = cold_count; i < cold_count + hot_count; i++) { - if (is_extension_exist(name, extlist[i])) { + if (is_extension_exist(name, extlist[i], false)) { up_read(&sbi->sb_lock); return; } @@ -306,7 +314,7 @@ static void set_compress_inode(struct f2fs_sb_info *sbi, struct inode *inode, ext = F2FS_OPTION(sbi).extensions; for (i = 0; i < ext_cnt; i++) { - if (!is_extension_exist(name, ext[i])) + if (!is_extension_exist(name, ext[i], false)) continue; set_compress_context(inode); diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 4f12ade6410a133c8479c0e215a468da28a6b3f2..72ce1311167913b6f32e9d80b6709a94ec654b6f 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -777,13 +777,6 @@ int f2fs_recover_fsync_data(struct f2fs_sb_info *sbi, bool check_only) quota_enabled = f2fs_enable_quota_files(sbi, s_flags & SB_RDONLY); #endif - fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", - sizeof(struct fsync_inode_entry)); - if (!fsync_entry_slab) { - err = -ENOMEM; - goto out; - } - INIT_LIST_HEAD(&inode_list); INIT_LIST_HEAD(&tmp_inode_list); INIT_LIST_HEAD(&dir_list); @@ -856,8 +849,6 @@ skip: } } - kmem_cache_destroy(fsync_entry_slab); -out: #ifdef CONFIG_QUOTA /* Turn quotas off */ if (quota_enabled) @@ -867,3 +858,17 @@ out: return ret ? ret: err; } + +int __init f2fs_create_recovery_cache(void) +{ + fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", + sizeof(struct fsync_inode_entry)); + if (!fsync_entry_slab) + return -ENOMEM; + return 0; +} + +void f2fs_destroy_recovery_cache(void) +{ + kmem_cache_destroy(fsync_entry_slab); +} diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index abc469dd9aea8fde3c1b59899c250fd835d1d9a5..c529880678878a87a30ffbd5ad61d456e645bb75 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -4027,9 +4027,12 @@ static int __init init_f2fs_fs(void) err = f2fs_create_checkpoint_caches(); if (err) goto free_segment_manager_caches; - err = f2fs_create_extent_cache(); + err = f2fs_create_recovery_cache(); if (err) goto free_checkpoint_caches; + err = f2fs_create_extent_cache(); + if (err) + goto free_recovery_cache; err = f2fs_create_garbage_collection_cache(); if (err) goto free_extent_cache; @@ -4078,6 +4081,8 @@ free_garbage_collection_cache: f2fs_destroy_garbage_collection_cache(); free_extent_cache: f2fs_destroy_extent_cache(); +free_recovery_cache: + f2fs_destroy_recovery_cache(); free_checkpoint_caches: f2fs_destroy_checkpoint_caches(); free_segment_manager_caches: @@ -4103,6 +4108,7 @@ static void __exit exit_f2fs_fs(void) f2fs_exit_sysfs(); f2fs_destroy_garbage_collection_cache(); f2fs_destroy_extent_cache(); + f2fs_destroy_recovery_cache(); f2fs_destroy_checkpoint_caches(); f2fs_destroy_segment_manager_caches(); f2fs_destroy_node_manager_caches(); @@ -4116,4 +4122,5 @@ module_exit(exit_f2fs_fs) MODULE_AUTHOR("Samsung Electronics's Praesto Team"); MODULE_DESCRIPTION("Flash Friendly File System"); MODULE_LICENSE("GPL"); +MODULE_SOFTDEP("pre: crc32"); diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 90dddb507e4afa6ee7006758ca4391f9d14c4e62..a0869194ab7390be901453abfc96b0df24c9c7e2 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -505,12 +505,19 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id) if (!isw) return; + atomic_inc(&isw_nr_in_flight); + /* find and pin the new wb */ rcu_read_lock(); memcg_css = css_from_id(new_wb_id, &memory_cgrp_subsys); - if (memcg_css) - isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC); + if (memcg_css && !css_tryget(memcg_css)) + memcg_css = NULL; rcu_read_unlock(); + if (!memcg_css) + goto out_free; + + isw->new_wb = wb_get_create(bdi, memcg_css, GFP_ATOMIC); + css_put(memcg_css); if (!isw->new_wb) goto out_free; @@ -535,11 +542,10 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id) * Let's continue after I_WB_SWITCH is guaranteed to be visible. */ call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn); - - atomic_inc(&isw_nr_in_flight); return; out_free: + atomic_dec(&isw_nr_in_flight); if (isw->new_wb) wb_put(isw->new_wb); kfree(isw); @@ -2196,28 +2202,6 @@ int dirtytime_interval_handler(struct ctl_table *table, int write, return ret; } -static noinline void block_dump___mark_inode_dirty(struct inode *inode) -{ - if (inode->i_ino || strcmp(inode->i_sb->s_id, "bdev")) { - struct dentry *dentry; - const char *name = "?"; - - dentry = d_find_alias(inode); - if (dentry) { - spin_lock(&dentry->d_lock); - name = (const char *) dentry->d_name.name; - } - printk(KERN_DEBUG - "%s(%d): dirtied inode %lu (%s) on %s\n", - current->comm, task_pid_nr(current), inode->i_ino, - name, inode->i_sb->s_id); - if (dentry) { - spin_unlock(&dentry->d_lock); - dput(dentry); - } - } -} - /** * __mark_inode_dirty - internal function * @@ -2277,9 +2261,6 @@ void __mark_inode_dirty(struct inode *inode, int flags) (dirtytime && (inode->i_state & I_DIRTY_INODE))) return; - if (unlikely(block_dump)) - block_dump___mark_inode_dirty(inode); - spin_lock(&inode->i_lock); if (dirtytime && (inode->i_state & I_DIRTY_INODE)) goto out_unlock_inode; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 588f8d1240aab377c94fc1e7aa619a1b89b181e3..4140d5c3ab5a5df18734fd12c3a6e5b406ce4b27 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -783,6 +783,7 @@ static int fuse_check_page(struct page *page) 1 << PG_uptodate | 1 << PG_lru | 1 << PG_active | + 1 << PG_workingset | 1 << PG_reclaim | 1 << PG_waiters))) { dump_page(page, "fuse: trying to steal weird page"); @@ -1275,6 +1276,15 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file, goto restart; } spin_lock(&fpq->lock); + /* + * Must not put request on fpq->io queue after having been shut down by + * fuse_abort_conn() + */ + if (!fpq->connected) { + req->out.h.error = err = -ECONNABORTED; + goto out_end; + + } list_add(&req->list, &fpq->io); spin_unlock(&fpq->lock); cs->req = req; @@ -1861,7 +1871,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud, } err = -EINVAL; - if (oh.error <= -1000 || oh.error > 0) + if (oh.error <= -512 || oh.error > 0) goto copy_finish; spin_lock(&fpq->lock); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index ffa031fe52933fd5f63c748b988f0b56c3d91376..756bbdd563e085a0c9631c363b0fffe374e7dc91 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -340,18 +340,33 @@ static struct vfsmount *fuse_dentry_automount(struct path *path) /* Initialize superblock, making @mp_fi its root */ err = fuse_fill_super_submount(sb, mp_fi); - if (err) + if (err) { + fuse_conn_put(fc); + kfree(fm); + sb->s_fs_info = NULL; goto out_put_sb; + } + + down_write(&fc->killsb); + list_add_tail(&fm->fc_entry, &fc->mounts); + up_write(&fc->killsb); sb->s_flags |= SB_ACTIVE; fsc->root = dget(sb->s_root); + + /* + * FIXME: setting SB_BORN requires a write barrier for + * super_cache_count(). We should actually come + * up with a proper ->get_tree() implementation + * for submounts and call vfs_get_tree() to take + * care of the write barrier. + */ + smp_wmb(); + sb->s_flags |= SB_BORN; + /* We are done configuring the superblock, so unlock it */ up_write(&sb->s_umount); - down_write(&fc->killsb); - list_add_tail(&fm->fc_entry, &fc->mounts); - up_write(&fc->killsb); - /* Create the submount */ mnt = vfs_create_mount(fsc); if (IS_ERR(mnt)) { diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index 16fb0184ce5e1c0e05b00add600f231d25bffdde..cfd9d03f604fee4a79cd6ad5a0bd01c8de6f6a78 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -474,8 +474,8 @@ static vm_fault_t gfs2_page_mkwrite(struct vm_fault *vmf) file_update_time(vmf->vma->vm_file); /* page is wholly or partially inside EOF */ - if (offset > size - PAGE_SIZE) - length = offset_in_page(size); + if (size - offset < PAGE_SIZE) + length = size - offset; else length = PAGE_SIZE; diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c index f2c6bbe5cdb81568bb8b4b7195536112c5192f57..ae9c5c1bdc508dd716138b4e61df23a75309c334 100644 --- a/fs/gfs2/ops_fstype.c +++ b/fs/gfs2/ops_fstype.c @@ -670,6 +670,7 @@ static int init_statfs(struct gfs2_sbd *sdp) } iput(pn); + pn = NULL; ip = GFS2_I(sdp->sd_sc_inode); error = gfs2_glock_nq_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &sdp->sd_sc_gh); diff --git a/fs/io-wq.c b/fs/io-wq.c index f72d53848dcbcb15581c674fef266b623cdfb469..8bb17b6d4de3c89cd5890bc71be956c65484dea0 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -299,7 +299,8 @@ static void io_wqe_wake_worker(struct io_wqe *wqe, struct io_wqe_acct *acct) * Most likely an attempt to queue unbounded work on an io_wq that * wasn't setup with any unbounded workers. */ - WARN_ON_ONCE(!acct->max_workers); + if (unlikely(!acct->max_workers)) + pr_warn_once("io-wq is not configured for unbound workers"); rcu_read_lock(); ret = io_wqe_activate_free_worker(wqe); @@ -1085,6 +1086,8 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) if (WARN_ON_ONCE(!data->free_work || !data->do_work)) return ERR_PTR(-EINVAL); + if (WARN_ON_ONCE(!bounded)) + return ERR_PTR(-EINVAL); wq = kzalloc(sizeof(*wq), GFP_KERNEL); if (!wq) diff --git a/fs/io_uring.c b/fs/io_uring.c index fdbaaf579cc60a0b5b1b6381a48a715f1ef1e294..42153106b7bc93a79922d62c9374f124f3a2df27 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -344,9 +344,10 @@ struct io_ring_ctx { struct socket *ring_sock; #endif - struct idr io_buffer_idr; + struct xarray io_buffers; - struct idr personality_idr; + struct xarray personalities; + u32 pers_next; struct { unsigned cached_cq_tail; @@ -1211,8 +1212,8 @@ static struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p) INIT_LIST_HEAD(&ctx->cq_overflow_list); init_completion(&ctx->ref_comp); init_completion(&ctx->sq_thread_comp); - idr_init(&ctx->io_buffer_idr); - idr_init(&ctx->personality_idr); + xa_init_flags(&ctx->io_buffers, XA_FLAGS_ALLOC1); + xa_init_flags(&ctx->personalities, XA_FLAGS_ALLOC1); mutex_init(&ctx->uring_lock); init_waitqueue_head(&ctx->wait); spin_lock_init(&ctx->completion_lock); @@ -2086,7 +2087,6 @@ static void __io_req_task_submit(struct io_kiocb *req) __io_req_task_cancel(req, -EFAULT); mutex_unlock(&ctx->uring_lock); - ctx->flags &= ~IORING_SETUP_R_DISABLED; if (ctx->flags & IORING_SETUP_SQPOLL) io_sq_thread_drop_mm(); } @@ -2770,7 +2770,7 @@ static bool io_file_supports_async(struct file *file, int rw) return true; return false; } - if (S_ISCHR(mode) || S_ISSOCK(mode)) + if (S_ISSOCK(mode)) return true; if (S_ISREG(mode)) { if (io_bdev_nowait(file->f_inode->i_sb->s_bdev) && @@ -2989,7 +2989,7 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len, lockdep_assert_held(&req->ctx->uring_lock); - head = idr_find(&req->ctx->io_buffer_idr, bgid); + head = xa_load(&req->ctx->io_buffers, bgid); if (head) { if (!list_empty(&head->list)) { kbuf = list_last_entry(&head->list, struct io_buffer, @@ -2997,7 +2997,7 @@ static struct io_buffer *io_buffer_select(struct io_kiocb *req, size_t *len, list_del(&kbuf->list); } else { kbuf = head; - idr_remove(&req->ctx->io_buffer_idr, bgid); + xa_erase(&req->ctx->io_buffers, bgid); } if (*len > kbuf->len) *len = kbuf->len; @@ -3959,7 +3959,7 @@ static int __io_remove_buffers(struct io_ring_ctx *ctx, struct io_buffer *buf, } i++; kfree(buf); - idr_remove(&ctx->io_buffer_idr, bgid); + xa_erase(&ctx->io_buffers, bgid); return i; } @@ -3977,7 +3977,7 @@ static int io_remove_buffers(struct io_kiocb *req, bool force_nonblock, lockdep_assert_held(&ctx->uring_lock); ret = -ENOENT; - head = idr_find(&ctx->io_buffer_idr, p->bgid); + head = xa_load(&ctx->io_buffers, p->bgid); if (head) ret = __io_remove_buffers(ctx, head, p->bgid, p->nbufs); if (ret < 0) @@ -4068,21 +4068,14 @@ static int io_provide_buffers(struct io_kiocb *req, bool force_nonblock, lockdep_assert_held(&ctx->uring_lock); - list = head = idr_find(&ctx->io_buffer_idr, p->bgid); + list = head = xa_load(&ctx->io_buffers, p->bgid); ret = io_add_buffers(p, &head); - if (ret < 0) - goto out; - - if (!list) { - ret = idr_alloc(&ctx->io_buffer_idr, head, p->bgid, p->bgid + 1, - GFP_KERNEL); - if (ret < 0) { + if (ret >= 0 && !list) { + ret = xa_insert(&ctx->io_buffers, p->bgid, head, GFP_KERNEL); + if (ret < 0) __io_remove_buffers(ctx, head, p->bgid, -1U); - goto out; - } } -out: if (ret < 0) req_set_fail_links(req); @@ -6629,7 +6622,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req, if (id) { struct io_identity *iod; - iod = idr_find(&ctx->personality_idr, id); + iod = xa_load(&ctx->personalities, id); if (unlikely(!iod)) return -EINVAL; refcount_inc(&iod->count); @@ -7998,6 +7991,7 @@ static void io_sq_offload_start(struct io_ring_ctx *ctx) { struct io_sq_data *sqd = ctx->sq_data; + ctx->flags &= ~IORING_SETUP_R_DISABLED; if ((ctx->flags & IORING_SETUP_SQPOLL) && sqd->thread) wake_up_process(sqd->thread); } @@ -8410,19 +8404,13 @@ static int io_eventfd_unregister(struct io_ring_ctx *ctx) return -ENXIO; } -static int __io_destroy_buffers(int id, void *p, void *data) -{ - struct io_ring_ctx *ctx = data; - struct io_buffer *buf = p; - - __io_remove_buffers(ctx, buf, id, -1U); - return 0; -} - static void io_destroy_buffers(struct io_ring_ctx *ctx) { - idr_for_each(&ctx->io_buffer_idr, __io_destroy_buffers, ctx); - idr_destroy(&ctx->io_buffer_idr); + struct io_buffer *buf; + unsigned long index; + + xa_for_each(&ctx->io_buffers, index, buf) + __io_remove_buffers(ctx, buf, index, -1U); } static void io_ring_ctx_free(struct io_ring_ctx *ctx) @@ -8445,7 +8433,6 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx) io_sqe_files_unregister(ctx); io_eventfd_unregister(ctx); io_destroy_buffers(ctx); - idr_destroy(&ctx->personality_idr); #if defined(CONFIG_UNIX) if (ctx->ring_sock) { @@ -8505,18 +8492,19 @@ static int io_uring_fasync(int fd, struct file *file, int on) return fasync_helper(fd, file, on, &ctx->cq_fasync); } -static int io_remove_personalities(int id, void *p, void *data) +static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id) { - struct io_ring_ctx *ctx = data; struct io_identity *iod; - iod = idr_remove(&ctx->personality_idr, id); + iod = xa_erase(&ctx->personalities, id); if (iod) { put_cred(iod->creds); if (refcount_dec_and_test(&iod->count)) kfree(iod); + return 0; } - return 0; + + return -EINVAL; } static void io_ring_exit_work(struct work_struct *work) @@ -8545,6 +8533,9 @@ static bool io_cancel_ctx_cb(struct io_wq_work *work, void *data) static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx) { + unsigned long index; + struct io_identify *iod; + mutex_lock(&ctx->uring_lock); percpu_ref_kill(&ctx->refs); /* if force is set, the ring is going away. always drop after that */ @@ -8565,7 +8556,8 @@ static void io_ring_ctx_wait_and_kill(struct io_ring_ctx *ctx) /* if we failed setting up the ctx, we might not have any rings */ io_iopoll_try_reap_events(ctx); - idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx); + xa_for_each(&ctx->personalities, index, iod) + io_unregister_personality(ctx, index); /* * Do this upfront, so we won't have a grace period where the ring @@ -9128,11 +9120,10 @@ out_fput: } #ifdef CONFIG_PROC_FS -static int io_uring_show_cred(int id, void *p, void *data) +static int io_uring_show_cred(struct seq_file *m, unsigned int id, + const struct io_identity *iod) { - struct io_identity *iod = p; const struct cred *cred = iod->creds; - struct seq_file *m = data; struct user_namespace *uns = seq_user_ns(m); struct group_info *gi; kernel_cap_t cap; @@ -9200,9 +9191,13 @@ static void __io_uring_show_fdinfo(struct io_ring_ctx *ctx, struct seq_file *m) seq_printf(m, "%5u: 0x%llx/%u\n", i, buf->ubuf, (unsigned int) buf->len); } - if (has_lock && !idr_is_empty(&ctx->personality_idr)) { + if (has_lock && !xa_empty(&ctx->personalities)) { + unsigned long index; + const struct io_identity *iod; + seq_printf(m, "Personalities:\n"); - idr_for_each(&ctx->personality_idr, io_uring_show_cred, m); + xa_for_each(&ctx->personalities, index, iod) + io_uring_show_cred(m, index, iod); } seq_printf(m, "PollList:\n"); spin_lock_irq(&ctx->completion_lock); @@ -9588,39 +9583,26 @@ out: static int io_register_personality(struct io_ring_ctx *ctx) { - struct io_identity *id; + struct io_identity *iod; + u32 id; int ret; - id = kmalloc(sizeof(*id), GFP_KERNEL); - if (unlikely(!id)) + iod = kmalloc(sizeof(*iod), GFP_KERNEL); + if (unlikely(!iod)) return -ENOMEM; - io_init_identity(id); - id->creds = get_current_cred(); + io_init_identity(iod); + iod->creds = get_current_cred(); - ret = idr_alloc_cyclic(&ctx->personality_idr, id, 1, USHRT_MAX, GFP_KERNEL); - if (ret < 0) { - put_cred(id->creds); - kfree(id); - } + ret = xa_alloc_cyclic(&ctx->personalities, &id, (void *)iod, + XA_LIMIT(0, USHRT_MAX), &ctx->pers_next, GFP_KERNEL); + if (!ret) + return id; + put_cred(iod->creds); + kfree(iod); return ret; } -static int io_unregister_personality(struct io_ring_ctx *ctx, unsigned id) -{ - struct io_identity *iod; - - iod = idr_remove(&ctx->personality_idr, id); - if (iod) { - put_cred(iod->creds); - if (refcount_dec_and_test(&iod->count)) - kfree(iod); - return 0; - } - - return -EINVAL; -} - static int io_register_restrictions(struct io_ring_ctx *ctx, void __user *arg, unsigned int nr_args) { diff --git a/fs/jfs/inode.c b/fs/jfs/inode.c index 6f65bfa9f18d5b629b82c3efc349107e6d2dbecf..b0eb9c85eea0c45480082328b1b142884005b097 100644 --- a/fs/jfs/inode.c +++ b/fs/jfs/inode.c @@ -151,7 +151,8 @@ void jfs_evict_inode(struct inode *inode) if (test_cflag(COMMIT_Freewmap, inode)) jfs_free_zero_link(inode); - diFree(inode); + if (JFS_SBI(inode->i_sb)->ipimap) + diFree(inode); /* * Free the inode from the quota allocation. diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 9330eff210e0c7532d7ddaafb8f165558ee85074..78fd136ac13b90e482a7141d1db59e15e770b69e 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1324,6 +1324,7 @@ int lmLogInit(struct jfs_log * log) } else { if (!uuid_equal(&logsuper->uuid, &log->uuid)) { jfs_warn("wrong uuid on JFS log device"); + rc = -EINVAL; goto errout20; } log->size = le32_to_cpu(logsuper->size); diff --git a/fs/nfs/delegation.c b/fs/nfs/delegation.c index 04bf8066980c1d9fd32b85927dbe51ac025b3512..d6ac2c4f88b6b42bb81c1010c9430c82dcf47018 100644 --- a/fs/nfs/delegation.c +++ b/fs/nfs/delegation.c @@ -75,6 +75,13 @@ void nfs_mark_delegation_referenced(struct nfs_delegation *delegation) set_bit(NFS_DELEGATION_REFERENCED, &delegation->flags); } +static void nfs_mark_return_delegation(struct nfs_server *server, + struct nfs_delegation *delegation) +{ + set_bit(NFS_DELEGATION_RETURN, &delegation->flags); + set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); +} + static bool nfs4_is_valid_delegation(const struct nfs_delegation *delegation, fmode_t flags) @@ -293,6 +300,7 @@ nfs_start_delegation_return_locked(struct nfs_inode *nfsi) goto out; spin_lock(&delegation->lock); if (!test_and_set_bit(NFS_DELEGATION_RETURNING, &delegation->flags)) { + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); /* Refcount matched in nfs_end_delegation_return() */ ret = nfs_get_delegation(delegation); } @@ -314,16 +322,17 @@ nfs_start_delegation_return(struct nfs_inode *nfsi) return delegation; } -static void -nfs_abort_delegation_return(struct nfs_delegation *delegation, - struct nfs_client *clp) +static void nfs_abort_delegation_return(struct nfs_delegation *delegation, + struct nfs_client *clp, int err) { spin_lock(&delegation->lock); clear_bit(NFS_DELEGATION_RETURNING, &delegation->flags); - set_bit(NFS_DELEGATION_RETURN, &delegation->flags); + if (err == -EAGAIN) { + set_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags); + set_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state); + } spin_unlock(&delegation->lock); - set_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state); } static struct nfs_delegation * @@ -528,7 +537,7 @@ static int nfs_end_delegation_return(struct inode *inode, struct nfs_delegation } while (err == 0); if (err) { - nfs_abort_delegation_return(delegation, clp); + nfs_abort_delegation_return(delegation, clp, err); goto out; } @@ -557,6 +566,7 @@ static bool nfs_delegation_need_return(struct nfs_delegation *delegation) if (ret) clear_bit(NFS_DELEGATION_RETURN_IF_CLOSED, &delegation->flags); if (test_bit(NFS_DELEGATION_RETURNING, &delegation->flags) || + test_bit(NFS_DELEGATION_RETURN_DELAYED, &delegation->flags) || test_bit(NFS_DELEGATION_REVOKED, &delegation->flags)) ret = false; @@ -636,6 +646,38 @@ out: return err; } +static bool nfs_server_clear_delayed_delegations(struct nfs_server *server) +{ + struct nfs_delegation *d; + bool ret = false; + + list_for_each_entry_rcu (d, &server->delegations, super_list) { + if (!test_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags)) + continue; + nfs_mark_return_delegation(server, d); + clear_bit(NFS_DELEGATION_RETURN_DELAYED, &d->flags); + ret = true; + } + return ret; +} + +static bool nfs_client_clear_delayed_delegations(struct nfs_client *clp) +{ + struct nfs_server *server; + bool ret = false; + + if (!test_and_clear_bit(NFS4CLNT_DELEGRETURN_DELAYED, &clp->cl_state)) + goto out; + rcu_read_lock(); + list_for_each_entry_rcu (server, &clp->cl_superblocks, client_link) { + if (nfs_server_clear_delayed_delegations(server)) + ret = true; + } + rcu_read_unlock(); +out: + return ret; +} + /** * nfs_client_return_marked_delegations - return previously marked delegations * @clp: nfs_client to process @@ -648,8 +690,14 @@ out: */ int nfs_client_return_marked_delegations(struct nfs_client *clp) { - return nfs_client_for_each_server(clp, - nfs_server_return_marked_delegations, NULL); + int err = nfs_client_for_each_server( + clp, nfs_server_return_marked_delegations, NULL); + if (err) + return err; + /* If a return was delayed, sleep to prevent hard looping */ + if (nfs_client_clear_delayed_delegations(clp)) + ssleep(1); + return 0; } /** @@ -764,13 +812,6 @@ static void nfs_mark_return_if_closed_delegation(struct nfs_server *server, set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); } -static void nfs_mark_return_delegation(struct nfs_server *server, - struct nfs_delegation *delegation) -{ - set_bit(NFS_DELEGATION_RETURN, &delegation->flags); - set_bit(NFS4CLNT_DELEGRETURN, &server->nfs_client->cl_state); -} - static bool nfs_server_mark_return_all_delegations(struct nfs_server *server) { struct nfs_delegation *delegation; diff --git a/fs/nfs/delegation.h b/fs/nfs/delegation.h index 9b00a0b7f8321fab75eeb6b732e9578b54086010..26f57a99da84ea49e0171ad911e8754a3771cede 100644 --- a/fs/nfs/delegation.h +++ b/fs/nfs/delegation.h @@ -36,6 +36,7 @@ enum { NFS_DELEGATION_REVOKED, NFS_DELEGATION_TEST_EXPIRED, NFS_DELEGATION_INODE_FREEING, + NFS_DELEGATION_RETURN_DELAYED, }; int nfs_inode_set_delegation(struct inode *inode, const struct cred *cred, diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 2d30a4da49fa0dedd8959c3fc4545d7ab9076764..2e894fec036b083b8431cf82883a7d06fe9b1e83 100644 --- a/fs/nfs/direct.c +++ b/fs/nfs/direct.c @@ -700,8 +700,8 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) { struct nfs_direct_req *dreq = hdr->dreq; struct nfs_commit_info cinfo; - bool request_commit = false; struct nfs_page *req = nfs_list_entry(hdr->pages.next); + int flags = NFS_ODIRECT_DONE; nfs_init_cinfo_from_dreq(&cinfo, dreq); @@ -713,15 +713,9 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) nfs_direct_count_bytes(dreq, hdr); if (hdr->good_bytes != 0 && nfs_write_need_commit(hdr)) { - switch (dreq->flags) { - case 0: + if (!dreq->flags) dreq->flags = NFS_ODIRECT_DO_COMMIT; - request_commit = true; - break; - case NFS_ODIRECT_RESCHED_WRITES: - case NFS_ODIRECT_DO_COMMIT: - request_commit = true; - } + flags = dreq->flags; } spin_unlock(&dreq->lock); @@ -729,12 +723,15 @@ static void nfs_direct_write_completion(struct nfs_pgio_header *hdr) req = nfs_list_entry(hdr->pages.next); nfs_list_remove_request(req); - if (request_commit) { + if (flags == NFS_ODIRECT_DO_COMMIT) { kref_get(&req->wb_kref); memcpy(&req->wb_verf, &hdr->verf.verifier, sizeof(req->wb_verf)); nfs_mark_request_commit(req, hdr->lseg, &cinfo, hdr->ds_commit_idx); + } else if (flags == NFS_ODIRECT_RESCHED_WRITES) { + kref_get(&req->wb_kref); + nfs_mark_request_commit(req, NULL, &cinfo, 0); } nfs_unlock_and_release_request(req); } diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index dc2cbca98fb0d983841c0956b3d4dd058431da81..9811880470a078ebabc11d48821f531c7b0a8f61 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1064,6 +1064,7 @@ EXPORT_SYMBOL_GPL(nfs_inode_attach_open_context); void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) { filp->private_data = get_nfs_open_context(ctx); + set_bit(NFS_CONTEXT_FILE_OPEN, &ctx->flags); if (list_empty(&ctx->list)) nfs_inode_attach_open_context(ctx); } @@ -1083,6 +1084,8 @@ struct nfs_open_context *nfs_find_open_context(struct inode *inode, const struct continue; if ((pos->mode & (FMODE_READ|FMODE_WRITE)) != mode) continue; + if (!test_bit(NFS_CONTEXT_FILE_OPEN, &pos->flags)) + continue; ctx = get_nfs_open_context(pos); if (ctx) break; @@ -1098,6 +1101,7 @@ void nfs_file_clear_open_context(struct file *filp) if (ctx) { struct inode *inode = d_inode(ctx->dentry); + clear_bit(NFS_CONTEXT_FILE_OPEN, &ctx->flags); /* * We fatal error on write before. Try to writeback * every page again. diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 2397ceedba8afb4df9b7ef268ff2a5741da6b70b..e1491def7124f36b3413c0816d77ff958bd62a5b 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -360,7 +360,7 @@ nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, break; case NFS3_CREATE_UNCHECKED: - goto out; + goto out_release_acls; } nfs_fattr_init(data->res.dir_attr); nfs_fattr_init(data->res.fattr); @@ -727,7 +727,7 @@ nfs3_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, break; default: status = -EINVAL; - goto out; + goto out_release_acls; } d_alias = nfs3_do_create(dir, dentry, data); diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 543d916f79abb6474eb5c05eb49f97803e634cd6..3e344bec3647b09889b113c6b568d6316b41140d 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -45,6 +45,7 @@ enum nfs4_client_state { NFS4CLNT_RECALL_RUNNING, NFS4CLNT_RECALL_ANY_LAYOUT_READ, NFS4CLNT_RECALL_ANY_LAYOUT_RW, + NFS4CLNT_DELEGRETURN_DELAYED, }; #define NFS4_RENEW_TIMEOUT 0x01 diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index 7491323a58207541cf3fe4226cbe6f1930920483..6d74f2e2de4615a14528f5696b7bdcc05cffcfc7 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -197,8 +197,11 @@ void nfs40_shutdown_client(struct nfs_client *clp) struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) { - int err; + char buf[INET6_ADDRSTRLEN + 1]; + const char *ip_addr = cl_init->ip_addr; struct nfs_client *clp = nfs_alloc_client(cl_init); + int err; + if (IS_ERR(clp)) return clp; @@ -222,6 +225,44 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) init_waitqueue_head(&clp->cl_lock_waitq); #endif INIT_LIST_HEAD(&clp->pending_cb_stateids); + + if (cl_init->minorversion != 0) + __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); + __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); + __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags); + + /* + * Set up the connection to the server before we add add to the + * global list. + */ + err = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_GSS_KRB5I); + if (err == -EINVAL) + err = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_UNIX); + if (err < 0) + goto error; + + /* If no clientaddr= option was specified, find a usable cb address */ + if (ip_addr == NULL) { + struct sockaddr_storage cb_addr; + struct sockaddr *sap = (struct sockaddr *)&cb_addr; + + err = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr)); + if (err < 0) + goto error; + err = rpc_ntop(sap, buf, sizeof(buf)); + if (err < 0) + goto error; + ip_addr = (const char *)buf; + } + strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); + + err = nfs_idmap_new(clp); + if (err < 0) { + dprintk("%s: failed to create idmapper. Error = %d\n", + __func__, err); + goto error; + } + __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); return clp; error: @@ -372,8 +413,6 @@ static int nfs4_init_client_minor_version(struct nfs_client *clp) struct nfs_client *nfs4_init_client(struct nfs_client *clp, const struct nfs_client_initdata *cl_init) { - char buf[INET6_ADDRSTRLEN + 1]; - const char *ip_addr = cl_init->ip_addr; struct nfs_client *old; int error; @@ -381,43 +420,6 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp, /* the client is initialised already */ return clp; - /* Check NFS protocol revision and initialize RPC op vector */ - clp->rpc_ops = &nfs_v4_clientops; - - if (clp->cl_minorversion != 0) - __set_bit(NFS_CS_INFINITE_SLOTS, &clp->cl_flags); - __set_bit(NFS_CS_DISCRTRY, &clp->cl_flags); - __set_bit(NFS_CS_NO_RETRANS_TIMEOUT, &clp->cl_flags); - - error = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_GSS_KRB5I); - if (error == -EINVAL) - error = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_UNIX); - if (error < 0) - goto error; - - /* If no clientaddr= option was specified, find a usable cb address */ - if (ip_addr == NULL) { - struct sockaddr_storage cb_addr; - struct sockaddr *sap = (struct sockaddr *)&cb_addr; - - error = rpc_localaddr(clp->cl_rpcclient, sap, sizeof(cb_addr)); - if (error < 0) - goto error; - error = rpc_ntop(sap, buf, sizeof(buf)); - if (error < 0) - goto error; - ip_addr = (const char *)buf; - } - strlcpy(clp->cl_ipaddr, ip_addr, sizeof(clp->cl_ipaddr)); - - error = nfs_idmap_new(clp); - if (error < 0) { - dprintk("%s: failed to create idmapper. Error = %d\n", - __func__, error); - goto error; - } - __set_bit(NFS_CS_IDMAP, &clp->cl_res_state); - error = nfs4_init_client_minor_version(clp); if (error < 0) goto error; diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c index 4d20125e982a0e0f80a3061e898a4f40b520e2e8..371665e0c154c54044c5422cbcb5e85489738b0c 100644 --- a/fs/nfs/pnfs.c +++ b/fs/nfs/pnfs.c @@ -966,10 +966,8 @@ void pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, const struct cred *cred, bool update_barrier) { - u32 oldseq, newseq, new_barrier = 0; - - oldseq = be32_to_cpu(lo->plh_stateid.seqid); - newseq = be32_to_cpu(new->seqid); + u32 oldseq = be32_to_cpu(lo->plh_stateid.seqid); + u32 newseq = be32_to_cpu(new->seqid); if (!pnfs_layout_is_valid(lo)) { pnfs_set_layout_cred(lo, cred); @@ -979,19 +977,21 @@ pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, clear_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags); return; } - if (pnfs_seqid_is_newer(newseq, oldseq)) { + + if (pnfs_seqid_is_newer(newseq, oldseq)) nfs4_stateid_copy(&lo->plh_stateid, new); - /* - * Because of wraparound, we want to keep the barrier - * "close" to the current seqids. - */ - new_barrier = newseq - atomic_read(&lo->plh_outstanding); - } - if (update_barrier) - new_barrier = be32_to_cpu(new->seqid); - else if (new_barrier == 0) + + if (update_barrier) { + pnfs_barrier_update(lo, newseq); return; - pnfs_barrier_update(lo, new_barrier); + } + /* + * Because of wraparound, we want to keep the barrier + * "close" to the current seqids. We really only want to + * get here from a layoutget call. + */ + if (atomic_read(&lo->plh_outstanding) == 1) + pnfs_barrier_update(lo, be32_to_cpu(lo->plh_stateid.seqid)); } static bool @@ -2015,7 +2015,7 @@ lookup_again: * If the layout segment list is empty, but there are outstanding * layoutget calls, then they might be subject to a layoutrecall. */ - if (list_empty(&lo->plh_segs) && + if ((list_empty(&lo->plh_segs) || !pnfs_layout_is_valid(lo)) && atomic_read(&lo->plh_outstanding) != 0) { spin_unlock(&ino->i_lock); lseg = ERR_PTR(wait_var_event_killable(&lo->plh_outstanding, @@ -2391,11 +2391,13 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) goto out_forget; } + if (!pnfs_layout_is_valid(lo) && !pnfs_is_first_layoutget(lo)) + goto out_forget; + if (nfs4_stateid_match_other(&lo->plh_stateid, &res->stateid)) { /* existing state ID, make sure the sequence number matches. */ if (pnfs_layout_stateid_blocked(lo, &res->stateid)) { - if (!pnfs_layout_is_valid(lo) && - pnfs_is_first_layoutget(lo)) + if (!pnfs_layout_is_valid(lo)) lo->plh_barrier = 0; dprintk("%s forget reply due to sequence\n", __func__); goto out_forget; @@ -2416,8 +2418,6 @@ pnfs_layout_process(struct nfs4_layoutget *lgp) goto out_forget; } else { /* We have a completely new layout */ - if (!pnfs_is_first_layoutget(lo)) - goto out_forget; pnfs_set_layout_stateid(lo, &res->stateid, lgp->cred, true); } diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index e3b25822e0bb19783e095f19a15fe7825a25c2ff..251c4a3aef9a6806468b9624197e748610de2fc6 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c @@ -791,19 +791,16 @@ out: } EXPORT_SYMBOL_GPL(nfs4_pnfs_ds_add); -static void nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds) +static int nfs4_wait_ds_connect(struct nfs4_pnfs_ds *ds) { might_sleep(); - wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING, - TASK_KILLABLE); + return wait_on_bit(&ds->ds_state, NFS4DS_CONNECTING, TASK_KILLABLE); } static void nfs4_clear_ds_conn_bit(struct nfs4_pnfs_ds *ds) { smp_mb__before_atomic(); - clear_bit(NFS4DS_CONNECTING, &ds->ds_state); - smp_mb__after_atomic(); - wake_up_bit(&ds->ds_state, NFS4DS_CONNECTING); + clear_and_wake_up_bit(NFS4DS_CONNECTING, &ds->ds_state); } static struct nfs_client *(*get_v3_ds_connect)( @@ -969,30 +966,33 @@ int nfs4_pnfs_ds_connect(struct nfs_server *mds_srv, struct nfs4_pnfs_ds *ds, { int err; -again: - err = 0; - if (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) == 0) { - if (version == 3) { - err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo, - retrans); - } else if (version == 4) { - err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo, - retrans, minor_version); - } else { - dprintk("%s: unsupported DS version %d\n", __func__, - version); - err = -EPROTONOSUPPORT; - } + do { + err = nfs4_wait_ds_connect(ds); + if (err || ds->ds_clp) + goto out; + if (nfs4_test_deviceid_unavailable(devid)) + return -ENODEV; + } while (test_and_set_bit(NFS4DS_CONNECTING, &ds->ds_state) != 0); - nfs4_clear_ds_conn_bit(ds); - } else { - nfs4_wait_ds_connect(ds); + if (ds->ds_clp) + goto connect_done; - /* what was waited on didn't connect AND didn't mark unavail */ - if (!ds->ds_clp && !nfs4_test_deviceid_unavailable(devid)) - goto again; + switch (version) { + case 3: + err = _nfs4_pnfs_v3_ds_connect(mds_srv, ds, timeo, retrans); + break; + case 4: + err = _nfs4_pnfs_v4_ds_connect(mds_srv, ds, timeo, retrans, + minor_version); + break; + default: + dprintk("%s: unsupported DS version %d\n", __func__, version); + err = -EPROTONOSUPPORT; } +connect_done: + nfs4_clear_ds_conn_bit(ds); +out: /* * At this point the ds->ds_clp should be ready, but it might have * hit an error. diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index ac20f79bbedd623444988f4eebfc35aa3f147631..80e394a2e3fd706a91a1868c0037a15302cb4ede 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -7158,7 +7158,6 @@ nfs4_client_to_reclaim(struct xdr_netobj name, struct xdr_netobj princhash, unsigned int strhashval; struct nfs4_client_reclaim *crp; - trace_nfsd_clid_reclaim(nn, name.len, name.data); crp = alloc_reclaim(); if (crp) { strhashval = clientstr_hashval(name); @@ -7208,8 +7207,6 @@ nfsd4_find_reclaim_client(struct xdr_netobj name, struct nfsd_net *nn) unsigned int strhashval; struct nfs4_client_reclaim *crp = NULL; - trace_nfsd_clid_find(nn, name.len, name.data); - strhashval = clientstr_hashval(name); list_for_each_entry(crp, &nn->reclaim_str_hashtbl[strhashval], cr_strhash) { if (compare_blob(&crp->cr_name, &name) == 0) { diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h index 99bf07800cd094d1fde643aad32374673292c511..c8ca73d69ad04f51bdedb325ceb4f43b44757fdb 100644 --- a/fs/nfsd/trace.h +++ b/fs/nfsd/trace.h @@ -368,35 +368,6 @@ DEFINE_EVENT(nfsd_net_class, nfsd_##name, \ DEFINE_NET_EVENT(grace_start); DEFINE_NET_EVENT(grace_complete); -DECLARE_EVENT_CLASS(nfsd_clid_class, - TP_PROTO(const struct nfsd_net *nn, - unsigned int namelen, - const unsigned char *namedata), - TP_ARGS(nn, namelen, namedata), - TP_STRUCT__entry( - __field(unsigned long long, boot_time) - __field(unsigned int, namelen) - __dynamic_array(unsigned char, name, namelen) - ), - TP_fast_assign( - __entry->boot_time = nn->boot_time; - __entry->namelen = namelen; - memcpy(__get_dynamic_array(name), namedata, namelen); - ), - TP_printk("boot_time=%16llx nfs4_clientid=%.*s", - __entry->boot_time, __entry->namelen, __get_str(name)) -) - -#define DEFINE_CLID_EVENT(name) \ -DEFINE_EVENT(nfsd_clid_class, nfsd_clid_##name, \ - TP_PROTO(const struct nfsd_net *nn, \ - unsigned int namelen, \ - const unsigned char *namedata), \ - TP_ARGS(nn, namelen, namedata)) - -DEFINE_CLID_EVENT(find); -DEFINE_CLID_EVENT(reclaim); - TRACE_EVENT(nfsd_clid_inuse_err, TP_PROTO(const struct nfs4_client *clp), TP_ARGS(clp), diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1ecaceebee1339716c03a24819bbea664aaf79fb..011cd570b50dfde6e843011f05c01078e9b2dad6 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1113,6 +1113,19 @@ out: } #ifdef CONFIG_NFSD_V3 +static int +nfsd_filemap_write_and_wait_range(struct nfsd_file *nf, loff_t offset, + loff_t end) +{ + struct address_space *mapping = nf->nf_file->f_mapping; + int ret = filemap_fdatawrite_range(mapping, offset, end); + + if (ret) + return ret; + filemap_fdatawait_range_keep_errors(mapping, offset, end); + return 0; +} + /* * Commit all pending writes to stable storage. * @@ -1143,10 +1156,11 @@ nfsd_commit(struct svc_rqst *rqstp, struct svc_fh *fhp, if (err) goto out; if (EX_ISSYNC(fhp->fh_export)) { - int err2; + int err2 = nfsd_filemap_write_and_wait_range(nf, offset, end); down_write(&nf->nf_rwsem); - err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); + if (!err2) + err2 = vfs_fsync_range(nf->nf_file, offset, end, 0); switch (err2) { case 0: nfsd_copy_boot_verifier(verf, net_generic(nf->nf_net, diff --git a/fs/nilfs2/sysfs.c b/fs/nilfs2/sysfs.c index 303d71430bdd170905956a38cb8a79186e03cc46..9c6c0e2e5880ae6a7c51dbf837bebdaaa52a2248 100644 --- a/fs/nilfs2/sysfs.c +++ b/fs/nilfs2/sysfs.c @@ -1053,6 +1053,7 @@ void nilfs_sysfs_delete_device_group(struct the_nilfs *nilfs) nilfs_sysfs_delete_superblock_group(nilfs); nilfs_sysfs_delete_segctor_group(nilfs); kobject_del(&nilfs->ns_dev_kobj); + kobject_put(&nilfs->ns_dev_kobj); kfree(nilfs->ns_dev_subgroups); } diff --git a/fs/ntfs/inode.c b/fs/ntfs/inode.c index e9d5c8e638b0164b79e83c4de0db04e520a05005..ea18e4a2a691df3a3679dbc56dfbf31596be21b0 100644 --- a/fs/ntfs/inode.c +++ b/fs/ntfs/inode.c @@ -477,7 +477,7 @@ err_corrupt_attr: } file_name_attr = (FILE_NAME_ATTR*)((u8*)attr + le16_to_cpu(attr->data.resident.value_offset)); - p2 = (u8*)attr + le32_to_cpu(attr->data.resident.value_length); + p2 = (u8 *)file_name_attr + le32_to_cpu(attr->data.resident.value_length); if (p2 < (u8*)attr || p2 > p) goto err_corrupt_attr; /* This attribute is ok, but is it in the $Extend directory? */ diff --git a/fs/ocfs2/filecheck.c b/fs/ocfs2/filecheck.c index 50f11bfdc8c2d5d9c2c7e8d9989edd179120c2af..82a3edc4aea4b31b95da8d3f5a9951f3f4cc1dac 100644 --- a/fs/ocfs2/filecheck.c +++ b/fs/ocfs2/filecheck.c @@ -328,11 +328,7 @@ static ssize_t ocfs2_filecheck_attr_show(struct kobject *kobj, ret = snprintf(buf + total, remain, "%lu\t\t%u\t%s\n", p->fe_ino, p->fe_done, ocfs2_filecheck_error(p->fe_status)); - if (ret < 0) { - total = ret; - break; - } - if (ret == remain) { + if (ret >= remain) { /* snprintf() didn't fit */ total = -E2BIG; break; diff --git a/fs/ocfs2/stackglue.c b/fs/ocfs2/stackglue.c index a191094694c6194fde2d5a59f91711c6f94bee19..03eacb249f379a515619f355035972d62460ee2e 100644 --- a/fs/ocfs2/stackglue.c +++ b/fs/ocfs2/stackglue.c @@ -502,11 +502,7 @@ static ssize_t ocfs2_loaded_cluster_plugins_show(struct kobject *kobj, list_for_each_entry(p, &ocfs2_stack_list, sp_list) { ret = snprintf(buf, remain, "%s\n", p->sp_name); - if (ret < 0) { - total = ret; - break; - } - if (ret == remain) { + if (ret >= remain) { /* snprintf() didn't fit */ total = -E2BIG; break; @@ -533,7 +529,7 @@ static ssize_t ocfs2_active_cluster_plugin_show(struct kobject *kobj, if (active_stack) { ret = snprintf(buf, PAGE_SIZE, "%s\n", active_stack->sp_name); - if (ret == PAGE_SIZE) + if (ret >= PAGE_SIZE) ret = -E2BIG; } spin_unlock(&ocfs2_stack_lock); diff --git a/fs/open.c b/fs/open.c index 4d7537ae59df5045c3548fabd9c28b0870d4841c..3aaaad47d9cac24c0351c8d5a86ec0b7dbd67ea4 100644 --- a/fs/open.c +++ b/fs/open.c @@ -993,12 +993,20 @@ inline struct open_how build_open_how(int flags, umode_t mode) inline int build_open_flags(const struct open_how *how, struct open_flags *op) { - int flags = how->flags; + u64 flags = how->flags; + u64 strip = FMODE_NONOTIFY | O_CLOEXEC; int lookup_flags = 0; int acc_mode = ACC_MODE(flags); - /* Must never be set by userspace */ - flags &= ~(FMODE_NONOTIFY | O_CLOEXEC); + BUILD_BUG_ON_MSG(upper_32_bits(VALID_OPEN_FLAGS), + "struct open_flags doesn't yet handle flags > 32 bits"); + + /* + * Strip flags that either shouldn't be set by userspace like + * FMODE_NONOTIFY or that aren't relevant in determining struct + * open_flags like O_CLOEXEC. + */ + flags &= ~strip; /* * Older syscalls implicitly clear all of the invalid flags or argument diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index ee5efdc35cc1e337ab8e849372a69167faa8f07a..2f2e430461b2141cb76d6d1c210d9c7f8bdc7b48 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -209,7 +209,7 @@ static int orangefs_statfs(struct dentry *dentry, struct kstatfs *buf) buf->f_bavail = (sector_t) new_op->downcall.resp.statfs.blocks_avail; buf->f_files = (sector_t) new_op->downcall.resp.statfs.files_total; buf->f_ffree = (sector_t) new_op->downcall.resp.statfs.files_avail; - buf->f_frsize = sb->s_blocksize; + buf->f_frsize = 0; out_op_release: op_release(new_op); diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 3cec6fbef725ed3e3122cf8dffbbd057be5c47b8..3931f60e421f76378fddfba004880f2de740bf02 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -829,7 +829,7 @@ static int show_smap(struct seq_file *m, void *v) __show_smap(m, &mss, false); seq_printf(m, "THPeligible: %d\n", - transparent_hugepage_enabled(vma)); + transparent_hugepage_active(vma)); if (arch_pkeys_enabled()) seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma)); diff --git a/fs/pstore/Kconfig b/fs/pstore/Kconfig index e16a49ebfe546dbecf0e64c8e5838a180161ebb2..8efe60487b486be7f3861090147ba554d170eaaa 100644 --- a/fs/pstore/Kconfig +++ b/fs/pstore/Kconfig @@ -165,6 +165,7 @@ config PSTORE_BLK tristate "Log panic/oops to a block device" depends on PSTORE depends on BLOCK + depends on BROKEN select PSTORE_ZONE default n help diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index e98f99338f8f8b992b51f5f313adcb9ce5b3fca6..df5fc12a6ceed6fcdf182277b1afec0962d60fd7 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -2760,6 +2760,20 @@ int journal_init(struct super_block *sb, const char *j_dev_name, goto free_and_return; } + /* + * Sanity check to see if journal first block is correct. + * If journal first block is invalid it can cause + * zeroing important superblock members. + */ + if (!SB_ONDISK_JOURNAL_DEVICE(sb) && + SB_ONDISK_JOURNAL_1st_BLOCK(sb) < SB_JOURNAL_1st_RESERVED_BLOCK(sb)) { + reiserfs_warning(sb, "journal-1393", + "journal 1st super block is invalid: 1st reserved block %d, but actual 1st block is %d", + SB_JOURNAL_1st_RESERVED_BLOCK(sb), + SB_ONDISK_JOURNAL_1st_BLOCK(sb)); + goto free_and_return; + } + if (journal_init_dev(sb, journal, j_dev_name) != 0) { reiserfs_warning(sb, "sh-462", "unable to initialize journal device"); diff --git a/fs/seq_file.c b/fs/seq_file.c index 03a369ccd28c342dad3e2bf815642aa8ade08f9e..472714716be69a984a327fb00ebb3f93abdf9cf0 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -32,6 +32,9 @@ static void seq_set_overflow(struct seq_file *m) static void *seq_buf_alloc(unsigned long size) { + if (unlikely(size > MAX_RW_COUNT)) + return NULL; + return kvmalloc(size, GFP_KERNEL_ACCOUNT); } diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c index 08fde777c32473546d612bac949c6eee63400e1d..ad90a3a64293eb648d1929ed1e9d66aea29f6611 100644 --- a/fs/ubifs/dir.c +++ b/fs/ubifs/dir.c @@ -1335,7 +1335,10 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, goto out_release; } + spin_lock(&whiteout->i_lock); whiteout->i_state |= I_LINKABLE; + spin_unlock(&whiteout->i_lock); + whiteout_ui = ubifs_inode(whiteout); whiteout_ui->data = dev; whiteout_ui->data_len = ubifs_encode_dev(dev, MKDEV(0, 0)); @@ -1428,7 +1431,11 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry, inc_nlink(whiteout); mark_inode_dirty(whiteout); + + spin_lock(&whiteout->i_lock); whiteout->i_state &= ~I_LINKABLE; + spin_unlock(&whiteout->i_lock); + iput(whiteout); } diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index 091c2ad8f21113ac7f04f9b8d89e59b57027880d..7274bd23881b2dc256a769608c224f2eeb8fc91d 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -881,7 +881,8 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode) struct inode *xino; struct ubifs_dent_node *xent, *pxent = NULL; - if (ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) { + if (ui->xattr_cnt > ubifs_xattr_max_cnt(c)) { + err = -EPERM; ubifs_err(c, "Cannot delete inode, it has too much xattrs!"); goto out_release; } diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index dacbb999ae34d4c7ae97dfec95339e9df4e07578..cfd46753a685656b75eef1cf74b1e2e5da46277c 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -275,6 +275,7 @@ static struct inode *ubifs_alloc_inode(struct super_block *sb) memset((void *)ui + sizeof(struct inode), 0, sizeof(struct ubifs_inode) - sizeof(struct inode)); mutex_init(&ui->ui_mutex); + init_rwsem(&ui->xattr_sem); spin_lock_init(&ui->ui_lock); return &ui->vfs_inode; }; diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h index 4ffd832e3b93706e2dc05efd508462843725c266..e7e48f3b179ab3133fb837fbe134fc3363f20c6d 100644 --- a/fs/ubifs/ubifs.h +++ b/fs/ubifs/ubifs.h @@ -356,6 +356,7 @@ struct ubifs_gced_idx_leb { * @ui_mutex: serializes inode write-back with the rest of VFS operations, * serializes "clean <-> dirty" state changes, serializes bulk-read, * protects @dirty, @bulk_read, @ui_size, and @xattr_size + * @xattr_sem: serilizes write operations (remove|set|create) on xattr * @ui_lock: protects @synced_i_size * @synced_i_size: synchronized size of inode, i.e. the value of inode size * currently stored on the flash; used only for regular file @@ -409,6 +410,7 @@ struct ubifs_inode { unsigned int bulk_read:1; unsigned int compr_type:2; struct mutex ui_mutex; + struct rw_semaphore xattr_sem; spinlock_t ui_lock; loff_t synced_i_size; loff_t ui_size; diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c index a0b9b349efe65a27471b2e2cc0fe78480b056d80..17745f5462f02e863988991b33a546bd2c35b830 100644 --- a/fs/ubifs/xattr.c +++ b/fs/ubifs/xattr.c @@ -285,6 +285,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value, if (!xent) return -ENOMEM; + down_write(&ubifs_inode(host)->xattr_sem); /* * The extended attribute entries are stored in LNC, so multiple * look-ups do not involve reading the flash. @@ -319,6 +320,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value, iput(inode); out_free: + up_write(&ubifs_inode(host)->xattr_sem); kfree(xent); return err; } @@ -341,18 +343,19 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf, if (!xent) return -ENOMEM; + down_read(&ubifs_inode(host)->xattr_sem); xent_key_init(c, &key, host->i_ino, &nm); err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); if (err) { if (err == -ENOENT) err = -ENODATA; - goto out_unlock; + goto out_cleanup; } inode = iget_xattr(c, le64_to_cpu(xent->inum)); if (IS_ERR(inode)) { err = PTR_ERR(inode); - goto out_unlock; + goto out_cleanup; } ui = ubifs_inode(inode); @@ -374,7 +377,8 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf, out_iput: mutex_unlock(&ui->ui_mutex); iput(inode); -out_unlock: +out_cleanup: + up_read(&ubifs_inode(host)->xattr_sem); kfree(xent); return err; } @@ -406,16 +410,21 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) dbg_gen("ino %lu ('%pd'), buffer size %zd", host->i_ino, dentry, size); + down_read(&host_ui->xattr_sem); len = host_ui->xattr_names + host_ui->xattr_cnt; - if (!buffer) + if (!buffer) { /* * We should return the minimum buffer size which will fit a * null-terminated list of all the extended attribute names. */ - return len; + err = len; + goto out_err; + } - if (len > size) - return -ERANGE; + if (len > size) { + err = -ERANGE; + goto out_err; + } lowest_xent_key(c, &key, host->i_ino); while (1) { @@ -437,8 +446,9 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) pxent = xent; key_read(c, &xent->key, &key); } - kfree(pxent); + up_read(&host_ui->xattr_sem); + if (err != -ENOENT) { ubifs_err(c, "cannot find next direntry, error %d", err); return err; @@ -446,6 +456,10 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) ubifs_assert(c, written <= size); return written; + +out_err: + up_read(&host_ui->xattr_sem); + return err; } static int remove_xattr(struct ubifs_info *c, struct inode *host, @@ -498,12 +512,13 @@ int ubifs_purge_xattrs(struct inode *host) struct fscrypt_name nm = {0}; int err; - if (ubifs_inode(host)->xattr_cnt < ubifs_xattr_max_cnt(c)) + if (ubifs_inode(host)->xattr_cnt <= ubifs_xattr_max_cnt(c)) return 0; ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion", host->i_ino); + down_write(&ubifs_inode(host)->xattr_sem); lowest_xent_key(c, &key, host->i_ino); while (1) { xent = ubifs_tnc_next_ent(c, &key, &nm); @@ -523,7 +538,7 @@ int ubifs_purge_xattrs(struct inode *host) ubifs_ro_mode(c, err); kfree(pxent); kfree(xent); - return err; + goto out_err; } ubifs_assert(c, ubifs_inode(xino)->xattr); @@ -535,7 +550,7 @@ int ubifs_purge_xattrs(struct inode *host) kfree(xent); iput(xino); ubifs_err(c, "cannot remove xattr, error %d", err); - return err; + goto out_err; } iput(xino); @@ -544,14 +559,19 @@ int ubifs_purge_xattrs(struct inode *host) pxent = xent; key_read(c, &xent->key, &key); } - kfree(pxent); + up_write(&ubifs_inode(host)->xattr_sem); + if (err != -ENOENT) { ubifs_err(c, "cannot find next direntry, error %d", err); return err; } return 0; + +out_err: + up_write(&ubifs_inode(host)->xattr_sem); + return err; } /** @@ -594,6 +614,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name) if (!xent) return -ENOMEM; + down_write(&ubifs_inode(host)->xattr_sem); xent_key_init(c, &key, host->i_ino, &nm); err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); if (err) { @@ -618,6 +639,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name) iput(inode); out_free: + up_write(&ubifs_inode(host)->xattr_sem); kfree(xent); return err; } diff --git a/fs/udf/namei.c b/fs/udf/namei.c index e169d8fe35b543f0a36bb2ce3950d25eaf0b819d..f4a72ff8cf959b25a66599a042592d4bbab8bfcf 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -932,6 +932,10 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, iinfo->i_location.partitionReferenceNum, 0); epos.bh = udf_tgetblk(sb, block); + if (unlikely(!epos.bh)) { + err = -ENOMEM; + goto out_no_entry; + } lock_buffer(epos.bh); memset(epos.bh->b_data, 0x00, bsize); set_buffer_uptodate(epos.bh); diff --git a/include/asm-generic/preempt.h b/include/asm-generic/preempt.h index d683f5e6d7913be7746e375908265b827d1b74c2..b4d43a4af5f794e9f7a0094cd002610fa1beb6d0 100644 --- a/include/asm-generic/preempt.h +++ b/include/asm-generic/preempt.h @@ -29,7 +29,7 @@ static __always_inline void preempt_count_set(int pc) } while (0) #define init_idle_preempt_count(p, cpu) do { \ - task_thread_info(p)->preempt_count = PREEMPT_ENABLED; \ + task_thread_info(p)->preempt_count = PREEMPT_DISABLED; \ } while (0) static __always_inline void set_preempt_need_resched(void) diff --git a/include/clocksource/timer-ti-dm.h b/include/clocksource/timer-ti-dm.h index 4c61dade8835f5d994afda3e08b34cc2842e18e4..f6da8a1326398d45409415354880cf35e3f06956 100644 --- a/include/clocksource/timer-ti-dm.h +++ b/include/clocksource/timer-ti-dm.h @@ -74,6 +74,7 @@ #define OMAP_TIMER_ERRATA_I103_I767 0x80000000 struct timer_regs { + u32 ocp_cfg; u32 tidr; u32 tier; u32 twer; diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h index 0a288dddcf5bef74c90f170a685f96f8a9438839..25806141db59197270238d11c086f32647687595 100644 --- a/include/crypto/internal/hash.h +++ b/include/crypto/internal/hash.h @@ -75,13 +75,7 @@ void crypto_unregister_ahashes(struct ahash_alg *algs, int count); int ahash_register_instance(struct crypto_template *tmpl, struct ahash_instance *inst); -int shash_no_setkey(struct crypto_shash *tfm, const u8 *key, - unsigned int keylen); - -static inline bool crypto_shash_alg_has_setkey(struct shash_alg *alg) -{ - return alg->setkey != shash_no_setkey; -} +bool crypto_shash_alg_has_setkey(struct shash_alg *alg); static inline bool crypto_shash_alg_needs_key(struct shash_alg *alg) { diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h index b7285268402612cee29c22e0859b052b635a0a16..23b2ca1c2d238973a1d85fca62db8a7304e647b7 100644 --- a/include/dt-bindings/clock/imx8mq-clock.h +++ b/include/dt-bindings/clock/imx8mq-clock.h @@ -405,25 +405,6 @@ #define IMX8MQ_VIDEO2_PLL1_REF_SEL 266 -#define IMX8MQ_SYS1_PLL_40M_CG 267 -#define IMX8MQ_SYS1_PLL_80M_CG 268 -#define IMX8MQ_SYS1_PLL_100M_CG 269 -#define IMX8MQ_SYS1_PLL_133M_CG 270 -#define IMX8MQ_SYS1_PLL_160M_CG 271 -#define IMX8MQ_SYS1_PLL_200M_CG 272 -#define IMX8MQ_SYS1_PLL_266M_CG 273 -#define IMX8MQ_SYS1_PLL_400M_CG 274 -#define IMX8MQ_SYS1_PLL_800M_CG 275 -#define IMX8MQ_SYS2_PLL_50M_CG 276 -#define IMX8MQ_SYS2_PLL_100M_CG 277 -#define IMX8MQ_SYS2_PLL_125M_CG 278 -#define IMX8MQ_SYS2_PLL_166M_CG 279 -#define IMX8MQ_SYS2_PLL_200M_CG 280 -#define IMX8MQ_SYS2_PLL_250M_CG 281 -#define IMX8MQ_SYS2_PLL_333M_CG 282 -#define IMX8MQ_SYS2_PLL_500M_CG 283 -#define IMX8MQ_SYS2_PLL_1000M_CG 284 - #define IMX8MQ_CLK_GPU_CORE 285 #define IMX8MQ_CLK_GPU_SHADER 286 #define IMX8MQ_CLK_M4_CORE 287 diff --git a/include/keys/system_keyring.h b/include/keys/system_keyring.h index fb8b07daa9d15519370e1731b8cf4c726bf83a17..875e002a41804726f712948e5ed9acb1c7402706 100644 --- a/include/keys/system_keyring.h +++ b/include/keys/system_keyring.h @@ -31,6 +31,7 @@ extern int restrict_link_by_builtin_and_secondary_trusted( #define restrict_link_by_builtin_and_secondary_trusted restrict_link_by_builtin_trusted #endif +extern struct pkcs7_message *pkcs7; #ifdef CONFIG_SYSTEM_BLACKLIST_KEYRING extern int mark_hash_blacklisted(const char *hash); extern int is_hash_blacklisted(const u8 *hash, size_t hash_len, @@ -49,6 +50,20 @@ static inline int is_binary_blacklisted(const u8 *hash, size_t hash_len) } #endif +#ifdef CONFIG_SYSTEM_REVOCATION_LIST +extern int add_key_to_revocation_list(const char *data, size_t size); +extern int is_key_on_revocation_list(struct pkcs7_message *pkcs7); +#else +static inline int add_key_to_revocation_list(const char *data, size_t size) +{ + return 0; +} +static inline int is_key_on_revocation_list(struct pkcs7_message *pkcs7) +{ + return -ENOKEY; +} +#endif + #ifdef CONFIG_IMA_BLACKLIST_KEYRING extern struct key *ima_blacklist_keyring; diff --git a/include/linux/bio.h b/include/linux/bio.h index c6d765382926441c5945a9ab3970c8ac7aa38c70..23b7a73cd7575815f936c1203351873f21a86868 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -38,9 +38,6 @@ #define bio_offset(bio) bio_iter_offset((bio), (bio)->bi_iter) #define bio_iovec(bio) bio_iter_iovec((bio), (bio)->bi_iter) -#define bio_multiple_segments(bio) \ - ((bio)->bi_iter.bi_size != bio_iovec(bio).bv_len) - #define bvec_iter_sectors(iter) ((iter).bi_size >> 9) #define bvec_iter_end_sector(iter) ((iter).bi_sector + bvec_iter_sectors((iter))) @@ -252,7 +249,7 @@ static inline void bio_clear_flag(struct bio *bio, unsigned int bit) static inline void bio_get_first_bvec(struct bio *bio, struct bio_vec *bv) { - *bv = bio_iovec(bio); + *bv = mp_bvec_iter_bvec(bio->bi_io_vec, bio->bi_iter); } static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv) @@ -260,10 +257,9 @@ static inline void bio_get_last_bvec(struct bio *bio, struct bio_vec *bv) struct bvec_iter iter = bio->bi_iter; int idx; - if (unlikely(!bio_multiple_segments(bio))) { - *bv = bio_iovec(bio); - return; - } + bio_get_first_bvec(bio, bv); + if (bv->bv_len == bio->bi_iter.bi_size) + return; /* this bio only has a single bvec */ bio_advance_iter(bio, &iter, iter.bi_size); diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h index 86d143db65231649af215c30dfc24814f0d38349..83a3ebff74560cff37fad91bb6536146a1541481 100644 --- a/include/linux/clocksource.h +++ b/include/linux/clocksource.h @@ -131,7 +131,7 @@ struct clocksource { #define CLOCK_SOURCE_UNSTABLE 0x40 #define CLOCK_SOURCE_SUSPEND_NONSTOP 0x80 #define CLOCK_SOURCE_RESELECT 0x100 - +#define CLOCK_SOURCE_VERIFY_PERCPU 0x200 /* simplify initialization of mask field */ #define CLOCKSOURCE_MASK(bits) GENMASK_ULL((bits) - 1, 0) diff --git a/include/linux/compiler-clang.h b/include/linux/compiler-clang.h index 189149de77a9d34097741b9777a7c6a31f1516f8..9ba951e3a6c22f81d049fb7932164655606bba00 100644 --- a/include/linux/compiler-clang.h +++ b/include/linux/compiler-clang.h @@ -23,6 +23,12 @@ /* all clang versions usable with the kernel support KASAN ABI version 5 */ #define KASAN_ABI_VERSION 5 +/* + * Note: Checking __has_feature(*_sanitizer) is only true if the feature is + * enabled. Therefore it is not required to additionally check defined(CONFIG_*) + * to avoid adding redundant attributes in other configurations. + */ + #if __has_feature(address_sanitizer) || __has_feature(hwaddress_sanitizer) /* Emulate GCC's __SANITIZE_ADDRESS__ flag */ #define __SANITIZE_ADDRESS__ @@ -55,6 +61,17 @@ #define __no_sanitize_undefined #endif +/* + * Support for __has_feature(coverage_sanitizer) was added in Clang 13 together + * with no_sanitize("coverage"). Prior versions of Clang support coverage + * instrumentation, but cannot be queried for support by the preprocessor. + */ +#if __has_feature(coverage_sanitizer) +#define __no_sanitize_coverage __attribute__((no_sanitize("coverage"))) +#else +#define __no_sanitize_coverage +#endif + /* * Not all versions of clang implement the type-generic versions * of the builtin overflow checkers. Fortunately, clang implements diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 555ab0fddbef7dc937a178e49621598736408c05..4cf524ccab43020d7adb70b3e523a2268d153953 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -137,6 +137,12 @@ #define __no_sanitize_undefined #endif +#if defined(CONFIG_KCOV) && __has_attribute(__no_sanitize_coverage__) +#define __no_sanitize_coverage __attribute__((no_sanitize_coverage)) +#else +#define __no_sanitize_coverage +#endif + #if GCC_VERSION >= 50100 #define COMPILER_HAS_GENERIC_BUILTIN_OVERFLOW 1 #endif diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h index ac3fa37a84f940450ab7f6ff3cc619647838c598..2a1c202baa1fe3d403a7a22a83239bb5b4f6e8b3 100644 --- a/include/linux/compiler_types.h +++ b/include/linux/compiler_types.h @@ -205,7 +205,7 @@ struct ftrace_likely_data { /* Section for code which can't be instrumented at all */ #define noinstr \ noinline notrace __attribute((__section__(".noinstr.text"))) \ - __no_kcsan __no_sanitize_address + __no_kcsan __no_sanitize_address __no_sanitize_coverage #endif /* __KERNEL__ */ diff --git a/include/linux/cred.h b/include/linux/cred.h index 18639c069263fbe79dfd5a36163c656dca5da220..ad160e5fe5c6466defd4faa4de10308faae7b119 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h @@ -144,6 +144,7 @@ struct cred { #endif struct user_struct *user; /* real user ID subscription */ struct user_namespace *user_ns; /* user_ns the caps and keyrings are relative to. */ + struct ucounts *ucounts; struct group_info *group_info; /* supplementary groups for euid/fsgid */ /* RCU deletion */ union { @@ -170,6 +171,7 @@ extern int set_security_override_from_ctx(struct cred *, const char *); extern int set_create_files_as(struct cred *, struct inode *); extern int cred_fscmp(const struct cred *, const struct cred *); extern void __init cred_init(void); +extern int set_cred_ucounts(struct cred *); /* * check for validity of credentials diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h index 2915f56ad4214f1586df36665feb16f3b97336ca..edb5c186b0b7ae6a52c0ac19f84141f7cbc72f5f 100644 --- a/include/linux/debug_locks.h +++ b/include/linux/debug_locks.h @@ -27,8 +27,10 @@ extern int debug_locks_off(void); int __ret = 0; \ \ if (!oops_in_progress && unlikely(c)) { \ + instrumentation_begin(); \ if (debug_locks_off() && !debug_locks_silent) \ WARN(1, "DEBUG_LOCKS_WARN_ON(%s)", #c); \ + instrumentation_end(); \ __ret = 1; \ } \ __ret; \ diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 0365aa97f8e734b447bcd59267198b69c30bd076..e72787731a5b26341e9d2e0be527e879c795dfab 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -7,43 +7,37 @@ #include <linux/fs.h> /* only for vma_is_dax() */ -extern vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf); -extern int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, - pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr, - struct vm_area_struct *vma); -extern void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd); -extern int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm, - pud_t *dst_pud, pud_t *src_pud, unsigned long addr, - struct vm_area_struct *vma); +vm_fault_t do_huge_pmd_anonymous_page(struct vm_fault *vmf); +int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pmd_t *dst_pmd, pmd_t *src_pmd, unsigned long addr, + struct vm_area_struct *vma); +void huge_pmd_set_accessed(struct vm_fault *vmf, pmd_t orig_pmd); +int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm, + pud_t *dst_pud, pud_t *src_pud, unsigned long addr, + struct vm_area_struct *vma); #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD -extern void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud); +void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud); #else static inline void huge_pud_set_accessed(struct vm_fault *vmf, pud_t orig_pud) { } #endif -extern vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd); -extern struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, - unsigned long addr, - pmd_t *pmd, - unsigned int flags); -extern bool madvise_free_huge_pmd(struct mmu_gather *tlb, - struct vm_area_struct *vma, - pmd_t *pmd, unsigned long addr, unsigned long next); -extern int zap_huge_pmd(struct mmu_gather *tlb, - struct vm_area_struct *vma, - pmd_t *pmd, unsigned long addr); -extern int zap_huge_pud(struct mmu_gather *tlb, - struct vm_area_struct *vma, - pud_t *pud, unsigned long addr); -extern bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, - unsigned long new_addr, - pmd_t *old_pmd, pmd_t *new_pmd); -extern int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, - unsigned long addr, pgprot_t newprot, - unsigned long cp_flags); +vm_fault_t do_huge_pmd_wp_page(struct vm_fault *vmf, pmd_t orig_pmd); +struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, + unsigned long addr, pmd_t *pmd, + unsigned int flags); +bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, + pmd_t *pmd, unsigned long addr, unsigned long next); +int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, pmd_t *pmd, + unsigned long addr); +int zap_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, pud_t *pud, + unsigned long addr); +bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr, + unsigned long new_addr, pmd_t *old_pmd, pmd_t *new_pmd); +int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, + pgprot_t newprot, unsigned long cp_flags); vm_fault_t vmf_insert_pfn_pmd_prot(struct vm_fault *vmf, pfn_t pfn, pgprot_t pgprot, bool write); @@ -84,6 +78,7 @@ static inline vm_fault_t vmf_insert_pfn_pud(struct vm_fault *vmf, pfn_t pfn, } enum transparent_hugepage_flag { + TRANSPARENT_HUGEPAGE_NEVER_DAX, TRANSPARENT_HUGEPAGE_FLAG, TRANSPARENT_HUGEPAGE_REQ_MADV_FLAG, TRANSPARENT_HUGEPAGE_DEFRAG_DIRECT_FLAG, @@ -100,13 +95,13 @@ enum transparent_hugepage_flag { struct kobject; struct kobj_attribute; -extern ssize_t single_hugepage_flag_store(struct kobject *kobj, - struct kobj_attribute *attr, - const char *buf, size_t count, - enum transparent_hugepage_flag flag); -extern ssize_t single_hugepage_flag_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf, - enum transparent_hugepage_flag flag); +ssize_t single_hugepage_flag_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count, + enum transparent_hugepage_flag flag); +ssize_t single_hugepage_flag_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf, + enum transparent_hugepage_flag flag); extern struct kobj_attribute shmem_enabled_attr; #define HPAGE_PMD_ORDER (HPAGE_PMD_SHIFT-PAGE_SHIFT) @@ -123,29 +118,53 @@ extern struct kobj_attribute shmem_enabled_attr; extern unsigned long transparent_hugepage_flags; +static inline bool transhuge_vma_suitable(struct vm_area_struct *vma, + unsigned long haddr) +{ + /* Don't have to check pgoff for anonymous vma */ + if (!vma_is_anonymous(vma)) { + if (!IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff, + HPAGE_PMD_NR)) + return false; + } + + if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end) + return false; + return true; +} + +static inline bool transhuge_vma_enabled(struct vm_area_struct *vma, + unsigned long vm_flags) +{ + /* Explicitly disabled through madvise. */ + if ((vm_flags & VM_NOHUGEPAGE) || + test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) + return false; + return true; +} + /* * to be used on vmas which are known to support THP. - * Use transparent_hugepage_enabled otherwise + * Use transparent_hugepage_active otherwise */ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma) { - if (vma->vm_flags & VM_NOHUGEPAGE) + + /* + * If the hardware/firmware marked hugepage support disabled. + */ + if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_NEVER_DAX)) return false; - if (vma_is_temporary_stack(vma)) + if (!transhuge_vma_enabled(vma, vma->vm_flags)) return false; - if (test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) + if (vma_is_temporary_stack(vma)) return false; if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_FLAG)) return true; - /* - * For dax vmas, try to always use hugepage mappings. If the kernel does - * not support hugepages, fsdax mappings will fallback to PAGE_SIZE - * mappings, and device-dax namespaces, that try to guarantee a given - * mapping size, will fail to enable - */ + if (vma_is_dax(vma)) return true; @@ -156,35 +175,17 @@ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma) return false; } -bool transparent_hugepage_enabled(struct vm_area_struct *vma); - -#define HPAGE_CACHE_INDEX_MASK (HPAGE_PMD_NR - 1) - -static inline bool transhuge_vma_suitable(struct vm_area_struct *vma, - unsigned long haddr) -{ - /* Don't have to check pgoff for anonymous vma */ - if (!vma_is_anonymous(vma)) { - if (((vma->vm_start >> PAGE_SHIFT) & HPAGE_CACHE_INDEX_MASK) != - (vma->vm_pgoff & HPAGE_CACHE_INDEX_MASK)) - return false; - } - - if (haddr < vma->vm_start || haddr + HPAGE_PMD_SIZE > vma->vm_end) - return false; - return true; -} +bool transparent_hugepage_active(struct vm_area_struct *vma); #define transparent_hugepage_use_zero_page() \ (transparent_hugepage_flags & \ (1<<TRANSPARENT_HUGEPAGE_USE_ZERO_PAGE_FLAG)) -extern unsigned long thp_get_unmapped_area(struct file *filp, - unsigned long addr, unsigned long len, unsigned long pgoff, - unsigned long flags); +unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr, + unsigned long len, unsigned long pgoff, unsigned long flags); -extern void prep_transhuge_page(struct page *page); -extern void free_transhuge_page(struct page *page); +void prep_transhuge_page(struct page *page); +void free_transhuge_page(struct page *page); bool is_transparent_hugepage(struct page *page); bool can_split_huge_page(struct page *page, int *pextra_pins); @@ -222,16 +223,12 @@ void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud, __split_huge_pud(__vma, __pud, __address); \ } while (0) -extern int hugepage_madvise(struct vm_area_struct *vma, - unsigned long *vm_flags, int advice); -extern void vma_adjust_trans_huge(struct vm_area_struct *vma, - unsigned long start, - unsigned long end, - long adjust_next); -extern spinlock_t *__pmd_trans_huge_lock(pmd_t *pmd, - struct vm_area_struct *vma); -extern spinlock_t *__pud_trans_huge_lock(pud_t *pud, - struct vm_area_struct *vma); +int hugepage_madvise(struct vm_area_struct *vma, unsigned long *vm_flags, + int advice); +void vma_adjust_trans_huge(struct vm_area_struct *vma, unsigned long start, + unsigned long end, long adjust_next); +spinlock_t *__pmd_trans_huge_lock(pmd_t *pmd, struct vm_area_struct *vma); +spinlock_t *__pud_trans_huge_lock(pud_t *pud, struct vm_area_struct *vma); static inline int is_swap_pmd(pmd_t pmd) { @@ -294,9 +291,10 @@ struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr, struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, pud_t *pud, int flags, struct dev_pagemap **pgmap); -extern vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd); +vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf, pmd_t orig_pmd); extern struct page *huge_zero_page; +extern unsigned long huge_zero_pfn; static inline bool is_huge_zero_page(struct page *page) { @@ -305,7 +303,7 @@ static inline bool is_huge_zero_page(struct page *page) static inline bool is_huge_zero_pmd(pmd_t pmd) { - return is_huge_zero_page(pmd_page(pmd)); + return READ_ONCE(huge_zero_pfn) == pmd_pfn(pmd) && pmd_present(pmd); } static inline bool is_huge_zero_pud(pud_t pud) @@ -364,7 +362,7 @@ static inline bool __transparent_hugepage_enabled(struct vm_area_struct *vma) return false; } -static inline bool transparent_hugepage_enabled(struct vm_area_struct *vma) +static inline bool transparent_hugepage_active(struct vm_area_struct *vma) { return false; } @@ -375,6 +373,12 @@ static inline bool transhuge_vma_suitable(struct vm_area_struct *vma, return false; } +static inline bool transhuge_vma_enabled(struct vm_area_struct *vma, + unsigned long vm_flags) +{ + return false; +} + static inline void prep_transhuge_page(struct page *page) {} static inline bool is_transparent_hugepage(struct page *page) @@ -451,6 +455,11 @@ static inline bool is_huge_zero_page(struct page *page) return false; } +static inline bool is_huge_zero_pmd(pmd_t pmd) +{ + return false; +} + static inline bool is_huge_zero_pud(pud_t pud) { return false; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index b5807f23caf80458a6238d286c4deec6fd21fe07..5b68c9787f7c2ae832a9daaf0f2e6456d0591024 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -628,17 +628,6 @@ static inline int hstate_index(struct hstate *h) return h - hstates; } -pgoff_t __basepage_index(struct page *page); - -/* Return page->index in PAGE_SIZE units */ -static inline pgoff_t basepage_index(struct page *page) -{ - if (!PageCompound(page)) - return page->index; - - return __basepage_index(page); -} - extern int dissolve_free_huge_page(struct page *page); extern int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn); @@ -871,11 +860,6 @@ static inline int hstate_index(struct hstate *h) return 0; } -static inline pgoff_t basepage_index(struct page *page) -{ - return page->index; -} - static inline int dissolve_free_huge_page(struct page *page) { return 0; diff --git a/include/linux/iio/common/cros_ec_sensors_core.h b/include/linux/iio/common/cros_ec_sensors_core.h index c9b80be82440f87b8820fb82fee7db9f0ea83172..f82857bd693fdfde7959a6be091927e7de2909bb 100644 --- a/include/linux/iio/common/cros_ec_sensors_core.h +++ b/include/linux/iio/common/cros_ec_sensors_core.h @@ -77,7 +77,7 @@ struct cros_ec_sensors_core_state { u16 scale; } calib[CROS_EC_SENSOR_MAX_AXIS]; s8 sign[CROS_EC_SENSOR_MAX_AXIS]; - u8 samples[CROS_EC_SAMPLE_SIZE]; + u8 samples[CROS_EC_SAMPLE_SIZE] __aligned(8); int (*read_ec_sensors_data)(struct iio_dev *indio_dev, unsigned long scan_mask, s16 *data); diff --git a/include/linux/mfd/abx500/ux500_chargalg.h b/include/linux/mfd/abx500/ux500_chargalg.h index 9b97d284d0ce87c3e5f21f0c38caf1ff4aae1676..bc3819dc33e120a7af4476357f42e2e8c9af3729 100644 --- a/include/linux/mfd/abx500/ux500_chargalg.h +++ b/include/linux/mfd/abx500/ux500_chargalg.h @@ -15,7 +15,7 @@ * - POWER_SUPPLY_TYPE_USB, * because only them store as drv_data pointer to struct ux500_charger. */ -#define psy_to_ux500_charger(x) power_supply_get_drvdata(psy) +#define psy_to_ux500_charger(x) power_supply_get_drvdata(x) /* Forward declaration */ struct ux500_charger; diff --git a/include/linux/mm.h b/include/linux/mm.h index 5106db3ad1ce34d6e368ea6031eca1489f3e5cf0..289c26f055cdd7c91beb3e4b034f9d5d2f243aa1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1648,6 +1648,7 @@ struct zap_details { struct address_space *check_mapping; /* Check page->mapping if set */ pgoff_t first_index; /* Lowest page->index to unmap */ pgoff_t last_index; /* Highest page->index to unmap */ + struct page *single_page; /* Locked page to be unmapped */ }; struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, @@ -1695,6 +1696,7 @@ extern vm_fault_t handle_mm_fault(struct vm_area_struct *vma, extern int fixup_user_fault(struct mm_struct *mm, unsigned long address, unsigned int fault_flags, bool *unlocked); +void unmap_mapping_page(struct page *page); void unmap_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t nr, bool even_cows); void unmap_mapping_range(struct address_space *mapping, @@ -1715,6 +1717,7 @@ static inline int fixup_user_fault(struct mm_struct *mm, unsigned long address, BUG(); return -EFAULT; } +static inline void unmap_mapping_page(struct page *page) { } static inline void unmap_mapping_pages(struct address_space *mapping, pgoff_t start, pgoff_t nr, bool even_cows) { } static inline void unmap_mapping_range(struct address_space *mapping, diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h index 2ad72d2c8cc528a2103556eeadd657389f5ece35..5d0767cb424aaa3478c8c35e97fe1a723c95b53a 100644 --- a/include/linux/mmdebug.h +++ b/include/linux/mmdebug.h @@ -37,6 +37,18 @@ void dump_mm(const struct mm_struct *mm); BUG(); \ } \ } while (0) +#define VM_WARN_ON_ONCE_PAGE(cond, page) ({ \ + static bool __section(".data.once") __warned; \ + int __ret_warn_once = !!(cond); \ + \ + if (unlikely(__ret_warn_once && !__warned)) { \ + dump_page(page, "VM_WARN_ON_ONCE_PAGE(" __stringify(cond)")");\ + __warned = true; \ + WARN_ON(1); \ + } \ + unlikely(__ret_warn_once); \ +}) + #define VM_WARN_ON(cond) (void)WARN_ON(cond) #define VM_WARN_ON_ONCE(cond) (void)WARN_ON_ONCE(cond) #define VM_WARN_ONCE(cond, format...) (void)WARN_ONCE(cond, format) @@ -48,6 +60,7 @@ void dump_mm(const struct mm_struct *mm); #define VM_BUG_ON_MM(cond, mm) VM_BUG_ON(cond) #define VM_WARN_ON(cond) BUILD_BUG_ON_INVALID(cond) #define VM_WARN_ON_ONCE(cond) BUILD_BUG_ON_INVALID(cond) +#define VM_WARN_ON_ONCE_PAGE(cond, page) BUILD_BUG_ON_INVALID(cond) #define VM_WARN_ONCE(cond, format...) BUILD_BUG_ON_INVALID(cond) #define VM_WARN(cond, format...) BUILD_BUG_ON_INVALID(cond) #endif diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h index 823a0eb7cb67f0c4d71d6421a33eae2fe1a27615..4b338f1eb547145794bfda51e786a102ca32b088 100644 --- a/include/linux/netdev_features.h +++ b/include/linux/netdev_features.h @@ -88,7 +88,7 @@ enum { /* * Add your fresh new feature above and remember to update - * netdev_features_strings[] in net/core/ethtool.c and maybe + * netdev_features_strings[] in net/ethtool/common.c and maybe * some feature mask #defines below. Please also describe it * in Documentation/networking/netdev-features.rst. */ diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index a2c6455ea3fae92a7bf44ae5089e47d06b7c0148..91a6525a98cb7e0848b2be237538ef70b3d44a6c 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -79,6 +79,7 @@ struct nfs_open_context { #define NFS_CONTEXT_RESEND_WRITES (1) #define NFS_CONTEXT_BAD (2) #define NFS_CONTEXT_UNLOCK (3) +#define NFS_CONTEXT_FILE_OPEN (4) int error; struct list_head list; diff --git a/include/linux/of_mdio.h b/include/linux/of_mdio.h index cfe8c607a628d04010859a1b56663167ef6540a7..f56c6a9230ac8733677aaf1b323e42df2180adc5 100644 --- a/include/linux/of_mdio.h +++ b/include/linux/of_mdio.h @@ -75,6 +75,13 @@ static inline int of_mdiobus_register(struct mii_bus *mdio, struct device_node * return mdiobus_register(mdio); } +static inline int devm_of_mdiobus_register(struct device *dev, + struct mii_bus *mdio, + struct device_node *np) +{ + return devm_mdiobus_register(dev, mdio); +} + static inline struct mdio_device *of_mdio_find_device(struct device_node *np) { return NULL; diff --git a/include/linux/pagemap.h b/include/linux/pagemap.h index b032f094a7827f99e0bc934d60570bea6c3a0b95..fcb3f040102af2d5c71afacb31f8f8140260ae25 100644 --- a/include/linux/pagemap.h +++ b/include/linux/pagemap.h @@ -501,7 +501,7 @@ static inline struct page *read_mapping_page(struct address_space *mapping, } /* - * Get index of the page with in radix-tree + * Get index of the page within radix-tree (but not for hugetlb pages). * (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE) */ static inline pgoff_t page_to_index(struct page *page) @@ -520,15 +520,16 @@ static inline pgoff_t page_to_index(struct page *page) return pgoff; } +extern pgoff_t hugetlb_basepage_index(struct page *page); + /* - * Get the offset in PAGE_SIZE. - * (TODO: hugepage should have ->index in PAGE_SIZE) + * Get the offset in PAGE_SIZE (even for hugetlb pages). + * (TODO: hugetlb pages should have ->index in PAGE_SIZE) */ static inline pgoff_t page_to_pgoff(struct page *page) { - if (unlikely(PageHeadHuge(page))) - return page->index << compound_order(page); - + if (unlikely(PageHuge(page))) + return hugetlb_basepage_index(page); return page_to_index(page); } diff --git a/include/linux/prandom.h b/include/linux/prandom.h index bbf4b4ad61dfda9dc66da325d9a29d3b9e6cbf09..056d31317e4990a6f3f25041be076a9db289d846 100644 --- a/include/linux/prandom.h +++ b/include/linux/prandom.h @@ -111,7 +111,7 @@ static inline u32 __seed(u32 x, u32 m) */ static inline void prandom_seed_state(struct rnd_state *state, u64 seed) { - u32 i = (seed >> 32) ^ (seed << 10) ^ seed; + u32 i = ((seed >> 32) ^ (seed << 10) ^ seed) & 0xffffffffUL; state->s1 = __seed(i, 2U); state->s2 = __seed(i, 8U); diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index c5adba5e79e7ec4499f0ae0afa827373a47a4f49..7d12c76e8fa459002850f734e4295a36a5ace93f 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -308,7 +308,7 @@ static inline int rcu_read_lock_any_held(void) #define RCU_LOCKDEP_WARN(c, s) \ do { \ static bool __section(".data.unlikely") __warned; \ - if (debug_lockdep_rcu_enabled() && !__warned && (c)) { \ + if ((c) && debug_lockdep_rcu_enabled() && !__warned) { \ __warned = true; \ lockdep_rcu_suspicious(__FILE__, __LINE__, s); \ } \ diff --git a/include/linux/rmap.h b/include/linux/rmap.h index def5c62c93b3beb40555b20e49eabeac7fec748c..8d04e7deedc66be25c7de941f962d0816fd41053 100644 --- a/include/linux/rmap.h +++ b/include/linux/rmap.h @@ -91,6 +91,7 @@ enum ttu_flags { TTU_SPLIT_HUGE_PMD = 0x4, /* split huge PMD if any */ TTU_IGNORE_MLOCK = 0x8, /* ignore mlock */ + TTU_SYNC = 0x10, /* avoid racy checks with PVMW_SYNC */ TTU_IGNORE_HWPOISON = 0x20, /* corrupted page is recoverable */ TTU_BATCH_FLUSH = 0x40, /* Batch TLB flushes where possible * and caller guarantees they will diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 4b6a8234d7fc237434a15c6df38e618e264f0146..657640015b335c8e21e15e223ecb88c3aa2cd475 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -525,6 +525,17 @@ static inline int kill_cad_pid(int sig, int priv) #define SEND_SIG_NOINFO ((struct kernel_siginfo *) 0) #define SEND_SIG_PRIV ((struct kernel_siginfo *) 1) +static inline int __on_sig_stack(unsigned long sp) +{ +#ifdef CONFIG_STACK_GROWSUP + return sp >= current->sas_ss_sp && + sp - current->sas_ss_sp < current->sas_ss_size; +#else + return sp > current->sas_ss_sp && + sp - current->sas_ss_sp <= current->sas_ss_size; +#endif +} + /* * True if we are on the alternate signal stack. */ @@ -542,13 +553,7 @@ static inline int on_sig_stack(unsigned long sp) if (current->sas_ss_flags & SS_AUTODISARM) return 0; -#ifdef CONFIG_STACK_GROWSUP - return sp >= current->sas_ss_sp && - sp - current->sas_ss_sp < current->sas_ss_size; -#else - return sp > current->sas_ss_sp && - sp - current->sas_ss_sp <= current->sas_ss_size; -#endif + return __on_sig_stack(sp); } static inline int sas_ss_flags(unsigned long sp) diff --git a/include/linux/swap.h b/include/linux/swap.h index fbc6805358da0c1f7a1cfd7e331928f5e00ad98f..dfabf4660a67031eeedec671ffc3630353f04cfc 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -503,6 +503,15 @@ static inline struct swap_info_struct *swp_swap_info(swp_entry_t entry) return NULL; } +static inline struct swap_info_struct *get_swap_device(swp_entry_t entry) +{ + return NULL; +} + +static inline void put_swap_device(struct swap_info_struct *si) +{ +} + #define swap_address_space(entry) (NULL) #define get_nr_swap_pages() 0L #define total_swap_pages 0L diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index 966ed898032746b58ad79caead930f66292a9148..e4c5df71f0e7479834f7e55e8f1c12e6fa9331a0 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -41,7 +41,17 @@ extern int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, void *data, int prio); extern int +tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, void *data, + int prio); +extern int tracepoint_probe_unregister(struct tracepoint *tp, void *probe, void *data); +static inline int +tracepoint_probe_register_may_exist(struct tracepoint *tp, void *probe, + void *data) +{ + return tracepoint_probe_register_prio_may_exist(tp, probe, data, + TRACEPOINT_DEFAULT_PRIO); +} extern void for_each_kernel_tracepoint(void (*fct)(struct tracepoint *tp, void *priv), void *priv); diff --git a/include/linux/user_namespace.h b/include/linux/user_namespace.h index 7616c7bf4b241069f4cf31e994f04b872524e566..e1bd560da1cd4c5242d59c30527102faadda8069 100644 --- a/include/linux/user_namespace.h +++ b/include/linux/user_namespace.h @@ -101,11 +101,15 @@ struct ucounts { }; extern struct user_namespace init_user_ns; +extern struct ucounts init_ucounts; bool setup_userns_sysctls(struct user_namespace *ns); void retire_userns_sysctls(struct user_namespace *ns); struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, enum ucount_type type); void dec_ucount(struct ucounts *ucounts, enum ucount_type type); +struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid); +struct ucounts *get_ucounts(struct ucounts *ucounts); +void put_ucounts(struct ucounts *ucounts); #ifdef CONFIG_USER_NS diff --git a/include/linux/wait.h b/include/linux/wait.h index 27fb99cfeb026932b6e26d70334a4ed5389551e3..f8b0704968a1eda2f90618efa5d53f4a00b60c01 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -1126,7 +1126,7 @@ do { \ * Waitqueues which are removed from the waitqueue_head at wakeup time */ void prepare_to_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); -void prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); +bool prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); long prepare_to_wait_event(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state); void finish_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry); long wait_woken(struct wait_queue_entry *wq_entry, unsigned mode, long timeout); diff --git a/include/media/hevc-ctrls.h b/include/media/hevc-ctrls.h index 1009cf0891cc6ce52165db19e5eb9d329a13eb1b..a3b650ab00f663baf39a6f229978578fafe8aefa 100644 --- a/include/media/hevc-ctrls.h +++ b/include/media/hevc-ctrls.h @@ -81,7 +81,7 @@ struct v4l2_ctrl_hevc_sps { __u64 flags; }; -#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 0) +#define V4L2_HEVC_PPS_FLAG_DEPENDENT_SLICE_SEGMENT_ENABLED (1ULL << 0) #define V4L2_HEVC_PPS_FLAG_OUTPUT_FLAG_PRESENT (1ULL << 1) #define V4L2_HEVC_PPS_FLAG_SIGN_DATA_HIDING_ENABLED (1ULL << 2) #define V4L2_HEVC_PPS_FLAG_CABAC_INIT_PRESENT (1ULL << 3) @@ -160,6 +160,7 @@ struct v4l2_hevc_pred_weight_table { #define V4L2_HEVC_SLICE_PARAMS_FLAG_USE_INTEGER_MV (1ULL << 6) #define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_DEBLOCKING_FILTER_DISABLED (1ULL << 7) #define V4L2_HEVC_SLICE_PARAMS_FLAG_SLICE_LOOP_FILTER_ACROSS_SLICES_ENABLED (1ULL << 8) +#define V4L2_HEVC_SLICE_PARAMS_FLAG_DEPENDENT_SLICE_SEGMENT (1ULL << 9) struct v4l2_ctrl_hevc_slice_params { __u32 bit_size; diff --git a/include/media/media-dev-allocator.h b/include/media/media-dev-allocator.h index b35ea6062596b420c901c924288bbdadffbbb655..2ab54d426c644f82c1947b7ac8c97d541ee3a17c 100644 --- a/include/media/media-dev-allocator.h +++ b/include/media/media-dev-allocator.h @@ -19,7 +19,7 @@ struct usb_device; -#if defined(CONFIG_MEDIA_CONTROLLER) && defined(CONFIG_USB) +#if defined(CONFIG_MEDIA_CONTROLLER) && IS_ENABLED(CONFIG_USB) /** * media_device_usb_allocate() - Allocate and return struct &media device * diff --git a/include/media/v4l2-async.h b/include/media/v4l2-async.h index d6e31234826f35cc201dc4edc1bf747192e5cc2a..92cd9f038fed8cb6798fadb46d9c51164e6c8988 100644 --- a/include/media/v4l2-async.h +++ b/include/media/v4l2-async.h @@ -189,9 +189,11 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, * * @notif: pointer to &struct v4l2_async_notifier * @endpoint: local endpoint pointing to the remote sub-device to be matched - * @asd: Async sub-device struct allocated by the caller. The &struct - * v4l2_async_subdev shall be the first member of the driver's async - * sub-device struct, i.e. both begin at the same memory address. + * @asd_struct_size: size of the driver's async sub-device struct, including + * sizeof(struct v4l2_async_subdev). The &struct + * v4l2_async_subdev shall be the first member of + * the driver's async sub-device struct, i.e. both + * begin at the same memory address. * * Gets the remote endpoint of a given local endpoint, set it up for fwnode * matching and adds the async sub-device to the notifier's @asd_list. The @@ -199,13 +201,12 @@ v4l2_async_notifier_add_fwnode_subdev(struct v4l2_async_notifier *notifier, * notifier cleanup time. * * This is just like @v4l2_async_notifier_add_fwnode_subdev, but with the - * exception that the fwnode refers to a local endpoint, not the remote one, and - * the function relies on the caller to allocate the async sub-device struct. + * exception that the fwnode refers to a local endpoint, not the remote one. */ -int +struct v4l2_async_subdev * v4l2_async_notifier_add_fwnode_remote_subdev(struct v4l2_async_notifier *notif, struct fwnode_handle *endpoint, - struct v4l2_async_subdev *asd); + unsigned int asd_struct_size); /** * v4l2_async_notifier_add_i2c_subdev - Allocate and add an i2c async diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h index e9aeda38d307a482e84dbec6880c1214a9729d7d..b966b75939bf6ebf432ea738fd0f48b72980a8c5 100644 --- a/include/media/v4l2-subdev.h +++ b/include/media/v4l2-subdev.h @@ -163,6 +163,9 @@ struct v4l2_subdev_io_pin_config { * @s_gpio: set GPIO pins. Very simple right now, might need to be extended with * a direction argument if needed. * + * @command: called by in-kernel drivers in order to call functions internal + * to subdev drivers driver that have a separate callback. + * * @ioctl: called at the end of ioctl() syscall handler at the V4L2 core. * used to provide support for private ioctls used on the driver. * @@ -195,6 +198,7 @@ struct v4l2_subdev_core_ops { int (*load_fw)(struct v4l2_subdev *sd); int (*reset)(struct v4l2_subdev *sd, u32 val); int (*s_gpio)(struct v4l2_subdev *sd, u32 val); + long (*command)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); long (*ioctl)(struct v4l2_subdev *sd, unsigned int cmd, void *arg); #ifdef CONFIG_COMPAT long (*compat_ioctl32)(struct v4l2_subdev *sd, unsigned int cmd, diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 6da4b3c5dd55d96fa32f80374d3c7293eb4e0f23..243de74e118e76d51fb3ad00f5b70ea27ad5f882 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1773,13 +1773,15 @@ struct hci_cp_ext_adv_set { __u8 max_events; } __packed; +#define HCI_MAX_EXT_AD_LENGTH 251 + #define HCI_OP_LE_SET_EXT_ADV_DATA 0x2037 struct hci_cp_le_set_ext_adv_data { __u8 handle; __u8 operation; __u8 frag_pref; __u8 length; - __u8 data[HCI_MAX_AD_LENGTH]; + __u8 data[]; } __packed; #define HCI_OP_LE_SET_EXT_SCAN_RSP_DATA 0x2038 @@ -1788,7 +1790,7 @@ struct hci_cp_le_set_ext_scan_rsp_data { __u8 operation; __u8 frag_pref; __u8 length; - __u8 data[HCI_MAX_AD_LENGTH]; + __u8 data[]; } __packed; #define LE_SET_ADV_DATA_OP_COMPLETE 0x03 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index df611c8b6b5955a4fbe0395ca627a517e5c06755..e534dff2874e1b044833984d1214d42a3c952dc1 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -226,9 +226,9 @@ struct adv_info { __u16 remaining_time; __u16 duration; __u16 adv_data_len; - __u8 adv_data[HCI_MAX_AD_LENGTH]; + __u8 adv_data[HCI_MAX_EXT_AD_LENGTH]; __u16 scan_rsp_len; - __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; + __u8 scan_rsp_data[HCI_MAX_EXT_AD_LENGTH]; __s8 tx_power; bdaddr_t random_addr; bool rpa_expired; @@ -523,9 +523,9 @@ struct hci_dev { DECLARE_BITMAP(dev_flags, __HCI_NUM_FLAGS); __s8 adv_tx_power; - __u8 adv_data[HCI_MAX_AD_LENGTH]; + __u8 adv_data[HCI_MAX_EXT_AD_LENGTH]; __u8 adv_data_len; - __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; + __u8 scan_rsp_data[HCI_MAX_EXT_AD_LENGTH]; __u8 scan_rsp_data_len; struct list_head adv_instances; diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 123b1e9ea304a190f89409e5c3619835200635a1..161b909790389834863b12baa4ed03fbb71e90d1 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -312,12 +312,14 @@ flow_action_mixed_hw_stats_check(const struct flow_action *action, if (flow_offload_has_one_action(action)) return true; - flow_action_for_each(i, action_entry, action) { - if (i && action_entry->hw_stats != last_hw_stats) { - NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported"); - return false; + if (action) { + flow_action_for_each(i, action_entry, action) { + if (i && action_entry->hw_stats != last_hw_stats) { + NL_SET_ERR_MSG_MOD(extack, "Mixing HW stats types for actions is not supported"); + return false; + } + last_hw_stats = action_entry->hw_stats; } - last_hw_stats = action_entry->hw_stats; } return true; } diff --git a/include/net/ip.h b/include/net/ip.h index 2d6b985d11ccaa75827b3a15ac3f898d7a193242..5538e54d4620c04aaab1781391b44d59a2ea894d 100644 --- a/include/net/ip.h +++ b/include/net/ip.h @@ -31,6 +31,7 @@ #include <net/flow.h> #include <net/flow_dissector.h> #include <net/netns/hash.h> +#include <net/lwtunnel.h> #define IPV4_MAX_PMTU 65535U /* RFC 2675, Section 5.1 */ #define IPV4_MIN_MTU 68 /* RFC 791 */ @@ -445,22 +446,25 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst, /* 'forwarding = true' case should always honour route mtu */ mtu = dst_metric_raw(dst, RTAX_MTU); - if (mtu) - return mtu; + if (!mtu) + mtu = min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU); - return min(READ_ONCE(dst->dev->mtu), IP_MAX_MTU); + return mtu - lwtunnel_headroom(dst->lwtstate, mtu); } static inline unsigned int ip_skb_dst_mtu(struct sock *sk, const struct sk_buff *skb) { + unsigned int mtu; + if (!sk || !sk_fullsock(sk) || ip_sk_use_pmtu(sk)) { bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; return ip_dst_mtu_maybe_forward(skb_dst(skb), forwarding); } - return min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); + mtu = min(READ_ONCE(skb_dst(skb)->dev->mtu), IP_MAX_MTU); + return mtu - lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); } struct dst_metrics *ip_fib_metrics_init(struct net *net, struct nlattr *fc_mx, diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 2a5277758379e5da10d33faaf4637ccef070fbc6..37a7fb1969d6c722c9b32f9927c67fc82cf33d20 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h @@ -264,11 +264,18 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb, static inline int ip6_skb_dst_mtu(struct sk_buff *skb) { + int mtu; + struct ipv6_pinfo *np = skb->sk && !dev_recursion_level() ? inet6_sk(skb->sk) : NULL; - return (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) ? - skb_dst(skb)->dev->mtu : dst_mtu(skb_dst(skb)); + if (np && np->pmtudisc >= IPV6_PMTUDISC_PROBE) { + mtu = READ_ONCE(skb_dst(skb)->dev->mtu); + mtu -= lwtunnel_headroom(skb_dst(skb)->lwtstate, mtu); + } else + mtu = dst_mtu(skb_dst(skb)); + + return mtu; } static inline bool ip6_sk_accept_pmtu(const struct sock *sk) @@ -316,7 +323,7 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) if (dst_metric_locked(dst, RTAX_MTU)) { mtu = dst_metric_raw(dst, RTAX_MTU); if (mtu) - return mtu; + goto out; } mtu = IPV6_MIN_MTU; @@ -326,7 +333,8 @@ static inline unsigned int ip6_dst_mtu_forward(const struct dst_entry *dst) mtu = idev->cnf.mtu6; rcu_read_unlock(); - return mtu; +out: + return mtu - lwtunnel_headroom(dst->lwtstate, mtu); } u32 ip6_mtu_from_fib6(const struct fib6_result *res, diff --git a/include/net/macsec.h b/include/net/macsec.h index 52874cdfe2260169cd2978f5343d9e86e5785d96..d6fa6b97f6efa347ea24653dfced8456576e7102 100644 --- a/include/net/macsec.h +++ b/include/net/macsec.h @@ -241,7 +241,7 @@ struct macsec_context { struct macsec_rx_sc *rx_sc; struct { unsigned char assoc_num; - u8 key[MACSEC_KEYID_LEN]; + u8 key[MACSEC_MAX_KEY_LEN]; union { struct macsec_rx_sa *rx_sa; struct macsec_tx_sa *tx_sa; diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index e79bba4d97a3b0b51010d254552563b2d3d1bddb..712eb08699fb224ce0229cc62adfccf4ad2ab22b 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -179,6 +179,12 @@ static inline bool qdisc_run_begin(struct Qdisc *qdisc) */ smp_mb__before_atomic(); + /* Paired with smp_mb__after_atomic() to make sure + * STATE_MISSED checking is synchronized with clearing + * in pfifo_fast_dequeue(). + */ + smp_mb__before_atomic(); + /* If the MISSED flag is set, it means other thread has * set the MISSED flag before second spin_trylock(), so * we can return false here to avoid multi cpus doing diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 0bdff38eb4bb7087239990fb7a084365b140860b..51d698f2656fc17ac6d376fc8ca1eee99b3d0b46 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h @@ -458,7 +458,7 @@ struct sctp_af { int saddr); void (*from_sk) (union sctp_addr *, struct sock *sk); - void (*from_addr_param) (union sctp_addr *, + bool (*from_addr_param) (union sctp_addr *, union sctp_addr_param *, __be16 port, int iif); int (*to_addr_param) (const union sctp_addr *, diff --git a/include/net/sock.h b/include/net/sock.h index f68184b8c0aa5caba412a5d5c3ce8b3f9ce1944b..3c7addf9515090703051be2c4f3cbbf971835610 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1900,7 +1900,8 @@ static inline u32 net_tx_rndhash(void) static inline void sk_set_txhash(struct sock *sk) { - sk->sk_txhash = net_tx_rndhash(); + /* This pairs with READ_ONCE() in skb_set_hash_from_sk() */ + WRITE_ONCE(sk->sk_txhash, net_tx_rndhash()); } static inline bool sk_rethink_txhash(struct sock *sk) @@ -2172,9 +2173,12 @@ static inline void sock_poll_wait(struct file *filp, struct socket *sock, static inline void skb_set_hash_from_sk(struct sk_buff *skb, struct sock *sk) { - if (sk->sk_txhash) { + /* This pairs with WRITE_ONCE() in sk_set_txhash() */ + u32 txhash = READ_ONCE(sk->sk_txhash); + + if (txhash) { skb->l4_hash = 1; - skb->hash = sk->sk_txhash; + skb->hash = txhash; } } @@ -2232,8 +2236,13 @@ struct sk_buff *sock_dequeue_err_skb(struct sock *sk); static inline int sock_error(struct sock *sk) { int err; - if (likely(!sk->sk_err)) + + /* Avoid an atomic operation for the common case. + * This is racy since another cpu/thread can change sk_err under us. + */ + if (likely(data_race(!sk->sk_err))) return 0; + err = xchg(&sk->sk_err, 0); return -err; } diff --git a/include/net/tc_act/tc_vlan.h b/include/net/tc_act/tc_vlan.h index f051046ba034420a45188df0ba8bc7e5b257163c..f94b8bc26f9ec5ede1523c4e0a92bc79ac0a506e 100644 --- a/include/net/tc_act/tc_vlan.h +++ b/include/net/tc_act/tc_vlan.h @@ -16,6 +16,7 @@ struct tcf_vlan_params { u16 tcfv_push_vid; __be16 tcfv_push_proto; u8 tcfv_push_prio; + bool tcfv_push_prio_exists; struct rcu_head rcu; }; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index c58a6d4eb61033d222dd22c2242e321f286b3d93..6232a5f048bde66a35c056d08ea6421de3cdeb05 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1546,6 +1546,7 @@ void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si); void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si); u32 xfrm_replay_seqhi(struct xfrm_state *x, __be32 net_seq); int xfrm_init_replay(struct xfrm_state *x); +u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu); u32 xfrm_state_mtu(struct xfrm_state *x, int mtu); int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload); int xfrm_init_state(struct xfrm_state *x); diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h index eaa8386dbc630b3d30c9b8b1f76d4e18a538d9f5..7a9a23e7a604a97ee63466197cefedebed82d64d 100644 --- a/include/net/xsk_buff_pool.h +++ b/include/net/xsk_buff_pool.h @@ -147,11 +147,16 @@ static inline bool xp_desc_crosses_non_contig_pg(struct xsk_buff_pool *pool, { bool cross_pg = (addr & (PAGE_SIZE - 1)) + len > PAGE_SIZE; - if (pool->dma_pages_cnt && cross_pg) { + if (likely(!cross_pg)) + return false; + + if (pool->dma_pages_cnt) { return !(pool->dma_pages[addr >> PAGE_SHIFT] & XSK_NEXT_PG_CONTIG_MASK); } - return false; + + /* skb path */ + return addr + len > pool->addrs_cnt; } static inline u64 xp_aligned_extract_addr(struct xsk_buff_pool *pool, u64 addr) diff --git a/include/scsi/fc/fc_ms.h b/include/scsi/fc/fc_ms.h index 9e273fed0a85fccfefac6bb8460d0b76396763ba..800d53dc94705eee89833e7db341a179490e14a5 100644 --- a/include/scsi/fc/fc_ms.h +++ b/include/scsi/fc/fc_ms.h @@ -63,8 +63,8 @@ enum fc_fdmi_hba_attr_type { * HBA Attribute Length */ #define FC_FDMI_HBA_ATTR_NODENAME_LEN 8 -#define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 80 -#define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 80 +#define FC_FDMI_HBA_ATTR_MANUFACTURER_LEN 64 +#define FC_FDMI_HBA_ATTR_SERIALNUMBER_LEN 64 #define FC_FDMI_HBA_ATTR_MODEL_LEN 256 #define FC_FDMI_HBA_ATTR_MODELDESCR_LEN 256 #define FC_FDMI_HBA_ATTR_HARDWAREVERSION_LEN 256 diff --git a/include/scsi/libiscsi.h b/include/scsi/libiscsi.h index b3bbd10eb3f0797ee7acb0acd75fae37b8910b13..2b5f97224f69365ab1ec2f3529cb5f4cfcdf8d61 100644 --- a/include/scsi/libiscsi.h +++ b/include/scsi/libiscsi.h @@ -195,12 +195,6 @@ struct iscsi_conn { unsigned long suspend_tx; /* suspend Tx */ unsigned long suspend_rx; /* suspend Rx */ - /* abort */ - wait_queue_head_t ehwait; /* used in eh_abort() */ - struct iscsi_tm tmhdr; - struct timer_list tmf_timer; - int tmf_state; /* see TMF_INITIAL, etc.*/ - /* negotiated params */ unsigned max_recv_dlength; /* initiator_max_recv_dsl*/ unsigned max_xmit_dlength; /* target_max_recv_dsl */ @@ -270,6 +264,11 @@ struct iscsi_session { * and recv lock. */ struct mutex eh_mutex; + /* abort */ + wait_queue_head_t ehwait; /* used in eh_abort() */ + struct iscsi_tm tmhdr; + struct timer_list tmf_timer; + int tmf_state; /* see TMF_INITIAL, etc.*/ /* iSCSI session-wide sequencing */ uint32_t cmdsn; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 8a26a2ffa95234e9ce1a31492af236f774f71244..f28bb20d627134b7d072562cd4f816c824eabac7 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -193,6 +193,7 @@ enum iscsi_connection_state { ISCSI_CONN_UP = 0, ISCSI_CONN_DOWN, ISCSI_CONN_FAILED, + ISCSI_CONN_BOUND, }; struct iscsi_cls_conn { @@ -433,6 +434,8 @@ extern void iscsi_remove_session(struct iscsi_cls_session *session); extern void iscsi_free_session(struct iscsi_cls_session *session); extern struct iscsi_cls_conn *iscsi_create_conn(struct iscsi_cls_session *sess, int dd_size, uint32_t cid); +extern void iscsi_put_conn(struct iscsi_cls_conn *conn); +extern void iscsi_get_conn(struct iscsi_cls_conn *conn); extern int iscsi_destroy_conn(struct iscsi_cls_conn *conn); extern void iscsi_unblock_session(struct iscsi_cls_session *session); extern void iscsi_block_session(struct iscsi_cls_session *session); diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index cde753bb2093562d4dd837821d98362e2c9659e0..13772f039c8dc1996a9625a73d8e526189d5e24d 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -223,7 +223,7 @@ enum tunable_id { ETHTOOL_PFC_PREVENTION_TOUT, /* timeout in msecs */ /* * Add your fresh new tunable attribute above and remember to update - * tunable_strings[] in net/core/ethtool.c + * tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_TUNABLE_COUNT, }; @@ -287,7 +287,7 @@ enum phy_tunable_id { ETHTOOL_PHY_EDPD, /* * Add your fresh new phy tunable attribute above and remember to update - * phy_tunable_strings[] in net/core/ethtool.c + * phy_tunable_strings[] in net/ethtool/common.c */ __ETHTOOL_PHY_TUNABLE_COUNT, }; diff --git a/init/main.c b/init/main.c index b4449544390ca14f7b96a87d77aafc79af250070..dd26a42e80a87cf613982e6cf70a1293440d8529 100644 --- a/init/main.c +++ b/init/main.c @@ -914,11 +914,7 @@ asmlinkage __visible void __init __no_sanitize_address start_kernel(void) * time - but meanwhile we still have a functioning scheduler. */ sched_init(); - /* - * Disable preemption - early bootup scheduling is extremely - * fragile until we cpu_idle() for the first time. - */ - preempt_disable(); + if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n")) local_irq_disable(); diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index 182e162f8fd0b6c66c7c5ec724b6c78dc6a7f40c..239c6b3b5993484baea9efd35fe485e0f4be5b04 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1395,29 +1395,54 @@ static u64 ___bpf_prog_run(u64 *regs, const struct bpf_insn *insn, u64 *stack) select_insn: goto *jumptable[insn->code]; - /* ALU */ -#define ALU(OPCODE, OP) \ - ALU64_##OPCODE##_X: \ - DST = DST OP SRC; \ - CONT; \ - ALU_##OPCODE##_X: \ - DST = (u32) DST OP (u32) SRC; \ - CONT; \ - ALU64_##OPCODE##_K: \ - DST = DST OP IMM; \ - CONT; \ - ALU_##OPCODE##_K: \ - DST = (u32) DST OP (u32) IMM; \ + /* Explicitly mask the register-based shift amounts with 63 or 31 + * to avoid undefined behavior. Normally this won't affect the + * generated code, for example, in case of native 64 bit archs such + * as x86-64 or arm64, the compiler is optimizing the AND away for + * the interpreter. In case of JITs, each of the JIT backends compiles + * the BPF shift operations to machine instructions which produce + * implementation-defined results in such a case; the resulting + * contents of the register may be arbitrary, but program behaviour + * as a whole remains defined. In other words, in case of JIT backends, + * the AND must /not/ be added to the emitted LSH/RSH/ARSH translation. + */ + /* ALU (shifts) */ +#define SHT(OPCODE, OP) \ + ALU64_##OPCODE##_X: \ + DST = DST OP (SRC & 63); \ + CONT; \ + ALU_##OPCODE##_X: \ + DST = (u32) DST OP ((u32) SRC & 31); \ + CONT; \ + ALU64_##OPCODE##_K: \ + DST = DST OP IMM; \ + CONT; \ + ALU_##OPCODE##_K: \ + DST = (u32) DST OP (u32) IMM; \ + CONT; + /* ALU (rest) */ +#define ALU(OPCODE, OP) \ + ALU64_##OPCODE##_X: \ + DST = DST OP SRC; \ + CONT; \ + ALU_##OPCODE##_X: \ + DST = (u32) DST OP (u32) SRC; \ + CONT; \ + ALU64_##OPCODE##_K: \ + DST = DST OP IMM; \ + CONT; \ + ALU_##OPCODE##_K: \ + DST = (u32) DST OP (u32) IMM; \ CONT; - ALU(ADD, +) ALU(SUB, -) ALU(AND, &) ALU(OR, |) - ALU(LSH, <<) - ALU(RSH, >>) ALU(XOR, ^) ALU(MUL, *) + SHT(LSH, <<) + SHT(RSH, >>) +#undef SHT #undef ALU ALU_NEG: DST = (u32) -DST; @@ -1442,13 +1467,13 @@ select_insn: insn++; CONT; ALU_ARSH_X: - DST = (u64) (u32) (((s32) DST) >> SRC); + DST = (u64) (u32) (((s32) DST) >> (SRC & 31)); CONT; ALU_ARSH_K: DST = (u64) (u32) (((s32) DST) >> IMM); CONT; ALU64_ARSH_X: - (*(s64 *) &DST) >>= SRC; + (*(s64 *) &DST) >>= (SRC & 63); CONT; ALU64_ARSH_K: (*(s64 *) &DST) >>= IMM; diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c index add0b34f2b3403e89199abc779df31bfaf0c448a..f9913bc65ef8d7a34feea4261a1cab351ce66a26 100644 --- a/kernel/bpf/ringbuf.c +++ b/kernel/bpf/ringbuf.c @@ -8,6 +8,7 @@ #include <linux/vmalloc.h> #include <linux/wait.h> #include <linux/poll.h> +#include <linux/kmemleak.h> #include <uapi/linux/btf.h> #define RINGBUF_CREATE_FLAG_MASK (BPF_F_NUMA_NODE) @@ -109,6 +110,7 @@ static struct bpf_ringbuf *bpf_ringbuf_area_alloc(size_t data_sz, int numa_node) rb = vmap(pages, nr_meta_pages + 2 * nr_data_pages, VM_ALLOC | VM_USERMAP, PAGE_KERNEL); if (rb) { + kmemleak_not_leak(pages); rb->pages = pages; rb->nr_pages = nr_pages; return rb; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e97724e36dfb52262a230faccb4e64cfd4d5cf7a..bf6798fb23319d471401a15e373ff2b0b8a75314 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -10532,7 +10532,7 @@ static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u32 len } } -static void adjust_poke_descs(struct bpf_prog *prog, u32 len) +static void adjust_poke_descs(struct bpf_prog *prog, u32 off, u32 len) { struct bpf_jit_poke_descriptor *tab = prog->aux->poke_tab; int i, sz = prog->aux->size_poke_tab; @@ -10540,6 +10540,8 @@ static void adjust_poke_descs(struct bpf_prog *prog, u32 len) for (i = 0; i < sz; i++) { desc = &tab[i]; + if (desc->insn_idx <= off) + continue; desc->insn_idx += len - 1; } } @@ -10560,7 +10562,7 @@ static struct bpf_prog *bpf_patch_insn_data(struct bpf_verifier_env *env, u32 of if (adjust_insn_aux_data(env, new_prog, off, len)) return NULL; adjust_subprog_starts(env, off, len); - adjust_poke_descs(new_prog, len); + adjust_poke_descs(new_prog, off, len); return new_prog; } diff --git a/kernel/cgroup/cgroup-v1.c b/kernel/cgroup/cgroup-v1.c index f6dddb3a8f4a298889d77a7763bcb57fa1ce005d..04eb28f7735fb7974764438fc27b4c3972aa3f7d 100644 --- a/kernel/cgroup/cgroup-v1.c +++ b/kernel/cgroup/cgroup-v1.c @@ -912,6 +912,8 @@ int cgroup1_parse_param(struct fs_context *fc, struct fs_parameter *param) opt = fs_parse(fc, cgroup1_fs_parameters, param, &result); if (opt == -ENOPARAM) { if (strcmp(param->key, "source") == 0) { + if (param->type != fs_value_is_string) + return invalf(fc, "Non-string source"); if (fc->source) return invalf(fc, "Multiple sources not supported"); fc->source = param->string; diff --git a/kernel/cpu.c b/kernel/cpu.c index 2b8d7a5db3837078388c42ecd09900748c3ad913..67c22941b5f275e05fe4e2de549e427f1435b96f 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -32,6 +32,7 @@ #include <linux/relay.h> #include <linux/slab.h> #include <linux/percpu-rwsem.h> +#include <linux/cpuset.h> #include <trace/events/power.h> #define CREATE_TRACE_POINTS @@ -814,6 +815,52 @@ void __init cpuhp_threads_init(void) kthread_unpark(this_cpu_read(cpuhp_state.thread)); } +/* + * + * Serialize hotplug trainwrecks outside of the cpu_hotplug_lock + * protected region. + * + * The operation is still serialized against concurrent CPU hotplug via + * cpu_add_remove_lock, i.e. CPU map protection. But it is _not_ + * serialized against other hotplug related activity like adding or + * removing of state callbacks and state instances, which invoke either the + * startup or the teardown callback of the affected state. + * + * This is required for subsystems which are unfixable vs. CPU hotplug and + * evade lock inversion problems by scheduling work which has to be + * completed _before_ cpu_up()/_cpu_down() returns. + * + * Don't even think about adding anything to this for any new code or even + * drivers. It's only purpose is to keep existing lock order trainwrecks + * working. + * + * For cpu_down() there might be valid reasons to finish cleanups which are + * not required to be done under cpu_hotplug_lock, but that's a different + * story and would be not invoked via this. + */ +static void cpu_up_down_serialize_trainwrecks(bool tasks_frozen) +{ + /* + * cpusets delegate hotplug operations to a worker to "solve" the + * lock order problems. Wait for the worker, but only if tasks are + * _not_ frozen (suspend, hibernate) as that would wait forever. + * + * The wait is required because otherwise the hotplug operation + * returns with inconsistent state, which could even be observed in + * user space when a new CPU is brought up. The CPU plug uevent + * would be delivered and user space reacting on it would fail to + * move tasks to the newly plugged CPU up to the point where the + * work has finished because up to that point the newly plugged CPU + * is not assignable in cpusets/cgroups. On unplug that's not + * necessarily a visible issue, but it is still inconsistent state, + * which is the real problem which needs to be "fixed". This can't + * prevent the transient state between scheduling the work and + * returning from waiting for it. + */ + if (!tasks_frozen) + cpuset_wait_for_hotplug(); +} + #ifdef CONFIG_HOTPLUG_CPU #ifndef arch_clear_mm_cpumask_cpu #define arch_clear_mm_cpumask_cpu(cpu, mm) cpumask_clear_cpu(cpu, mm_cpumask(mm)) @@ -1051,6 +1098,7 @@ out: */ lockup_detector_cleanup(); arch_smt_update(); + cpu_up_down_serialize_trainwrecks(tasks_frozen); return ret; } @@ -1247,6 +1295,7 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen, enum cpuhp_state target) out: cpus_write_unlock(); arch_smt_update(); + cpu_up_down_serialize_trainwrecks(tasks_frozen); return ret; } diff --git a/kernel/cred.c b/kernel/cred.c index 421b1149c6516004221159824dc6c18770db64e6..098213d4a39c3de3636fa1e0cef0ba82484e14f1 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -60,6 +60,7 @@ struct cred init_cred = { .user = INIT_USER, .user_ns = &init_user_ns, .group_info = &init_groups, + .ucounts = &init_ucounts, }; static inline void set_cred_subscribers(struct cred *cred, int n) @@ -119,6 +120,8 @@ static void put_cred_rcu(struct rcu_head *rcu) if (cred->group_info) put_group_info(cred->group_info); free_uid(cred->user); + if (cred->ucounts) + put_ucounts(cred->ucounts); put_user_ns(cred->user_ns); kmem_cache_free(cred_jar, cred); } @@ -222,6 +225,7 @@ struct cred *cred_alloc_blank(void) #ifdef CONFIG_DEBUG_CREDENTIALS new->magic = CRED_MAGIC; #endif + new->ucounts = get_ucounts(&init_ucounts); if (security_cred_alloc_blank(new, GFP_KERNEL_ACCOUNT) < 0) goto error; @@ -284,6 +288,11 @@ struct cred *prepare_creds(void) if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0) goto error; + + new->ucounts = get_ucounts(new->ucounts); + if (!new->ucounts) + goto error; + validate_creds(new); return new; @@ -363,6 +372,9 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) ret = create_user_ns(new); if (ret < 0) goto error_put; + ret = set_cred_ucounts(new); + if (ret < 0) + goto error_put; } #ifdef CONFIG_KEYS @@ -653,6 +665,31 @@ int cred_fscmp(const struct cred *a, const struct cred *b) } EXPORT_SYMBOL(cred_fscmp); +int set_cred_ucounts(struct cred *new) +{ + struct task_struct *task = current; + const struct cred *old = task->real_cred; + struct ucounts *old_ucounts = new->ucounts; + + if (new->user == old->user && new->user_ns == old->user_ns) + return 0; + + /* + * This optimization is needed because alloc_ucounts() uses locks + * for table lookups. + */ + if (old_ucounts && old_ucounts->ns == new->user_ns && uid_eq(old_ucounts->uid, new->euid)) + return 0; + + if (!(new->ucounts = alloc_ucounts(new->user_ns, new->euid))) + return -EAGAIN; + + if (old_ucounts) + put_ucounts(old_ucounts); + + return 0; +} + /* * initialise the credentials stuff */ @@ -719,6 +756,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) if (security_prepare_creds(new, old, GFP_KERNEL_ACCOUNT) < 0) goto error; + new->ucounts = get_ucounts(new->ucounts); + if (!new->ucounts) + goto error; + put_cred(old); validate_creds(new); return new; diff --git a/kernel/fork.c b/kernel/fork.c index 7c044d377926cc1bf015c7db550b28e873f4cdf6..096945ef49ad75dee51951832270f07a1dbf10ce 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2392,7 +2392,7 @@ static inline void init_idle_pids(struct task_struct *idle) } } -struct task_struct *fork_idle(int cpu) +struct task_struct * __init fork_idle(int cpu) { struct task_struct *task; struct kernel_clone_args args = { @@ -2960,6 +2960,12 @@ int ksys_unshare(unsigned long unshare_flags) if (err) goto bad_unshare_cleanup_cred; + if (new_cred) { + err = set_cred_ucounts(new_cred); + if (err) + goto bad_unshare_cleanup_cred; + } + if (new_fs || new_fd || do_sysvsem || new_cred || new_nsproxy) { if (do_sysvsem) { /* diff --git a/kernel/futex.c b/kernel/futex.c index 3136aba177720f4050a5771a11b06f76f121c936..98a6e1b80bfe462e9174dca612c3c6a010440a0b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -35,7 +35,6 @@ #include <linux/jhash.h> #include <linux/pagemap.h> #include <linux/syscalls.h> -#include <linux/hugetlb.h> #include <linux/freezer.h> #include <linux/memblock.h> #include <linux/fault-inject.h> @@ -652,7 +651,7 @@ again: key->both.offset |= FUT_OFF_INODE; /* inode-based key */ key->shared.i_seq = get_inode_sequence_number(inode); - key->shared.pgoff = basepage_index(tail); + key->shared.pgoff = page_to_pgoff(tail); rcu_read_unlock(); } diff --git a/kernel/jump_label.c b/kernel/jump_label.c index a0c325664190be9025fdd58e582483213b6880ff..4ae693ce71a417a77ba995c8d1566e537dd170ae 100644 --- a/kernel/jump_label.c +++ b/kernel/jump_label.c @@ -316,14 +316,16 @@ static int addr_conflict(struct jump_entry *entry, void *start, void *end) } static int __jump_label_text_reserved(struct jump_entry *iter_start, - struct jump_entry *iter_stop, void *start, void *end) + struct jump_entry *iter_stop, void *start, void *end, bool init) { struct jump_entry *iter; iter = iter_start; while (iter < iter_stop) { - if (addr_conflict(iter, start, end)) - return 1; + if (init || !jump_entry_is_init(iter)) { + if (addr_conflict(iter, start, end)) + return 1; + } iter++; } @@ -561,7 +563,7 @@ static int __jump_label_mod_text_reserved(void *start, void *end) ret = __jump_label_text_reserved(mod->jump_entries, mod->jump_entries + mod->num_jump_entries, - start, end); + start, end, mod->state == MODULE_STATE_COMING); module_put(mod); @@ -786,8 +788,9 @@ early_initcall(jump_label_init_module); */ int jump_label_text_reserved(void *start, void *end) { + bool init = system_state < SYSTEM_RUNNING; int ret = __jump_label_text_reserved(__start___jump_table, - __stop___jump_table, start, end); + __stop___jump_table, start, end, init); if (ret) return ret; diff --git a/kernel/kthread.c b/kernel/kthread.c index 5edf7e19ab2626ccd6e85e7cd4bc07240c87ed56..9825cf89c614db62ef49b85c160b47123e9d2429 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -1044,8 +1044,38 @@ void kthread_flush_work(struct kthread_work *work) EXPORT_SYMBOL_GPL(kthread_flush_work); /* - * This function removes the work from the worker queue. Also it makes sure - * that it won't get queued later via the delayed work's timer. + * Make sure that the timer is neither set nor running and could + * not manipulate the work list_head any longer. + * + * The function is called under worker->lock. The lock is temporary + * released but the timer can't be set again in the meantime. + */ +static void kthread_cancel_delayed_work_timer(struct kthread_work *work, + unsigned long *flags) +{ + struct kthread_delayed_work *dwork = + container_of(work, struct kthread_delayed_work, work); + struct kthread_worker *worker = work->worker; + + /* + * del_timer_sync() must be called to make sure that the timer + * callback is not running. The lock must be temporary released + * to avoid a deadlock with the callback. In the meantime, + * any queuing is blocked by setting the canceling counter. + */ + work->canceling++; + raw_spin_unlock_irqrestore(&worker->lock, *flags); + del_timer_sync(&dwork->timer); + raw_spin_lock_irqsave(&worker->lock, *flags); + work->canceling--; +} + +/* + * This function removes the work from the worker queue. + * + * It is called under worker->lock. The caller must make sure that + * the timer used by delayed work is not running, e.g. by calling + * kthread_cancel_delayed_work_timer(). * * The work might still be in use when this function finishes. See the * current_work proceed by the worker. @@ -1053,28 +1083,8 @@ EXPORT_SYMBOL_GPL(kthread_flush_work); * Return: %true if @work was pending and successfully canceled, * %false if @work was not pending */ -static bool __kthread_cancel_work(struct kthread_work *work, bool is_dwork, - unsigned long *flags) +static bool __kthread_cancel_work(struct kthread_work *work) { - /* Try to cancel the timer if exists. */ - if (is_dwork) { - struct kthread_delayed_work *dwork = - container_of(work, struct kthread_delayed_work, work); - struct kthread_worker *worker = work->worker; - - /* - * del_timer_sync() must be called to make sure that the timer - * callback is not running. The lock must be temporary released - * to avoid a deadlock with the callback. In the meantime, - * any queuing is blocked by setting the canceling counter. - */ - work->canceling++; - raw_spin_unlock_irqrestore(&worker->lock, *flags); - del_timer_sync(&dwork->timer); - raw_spin_lock_irqsave(&worker->lock, *flags); - work->canceling--; - } - /* * Try to remove the work from a worker list. It might either * be from worker->work_list or from worker->delayed_work_list. @@ -1097,14 +1107,14 @@ static bool __kthread_cancel_work(struct kthread_work *work, bool is_dwork, * modify @dwork's timer so that it expires after @delay. If @delay is zero, * @work is guaranteed to be queued immediately. * - * Return: %true if @dwork was pending and its timer was modified, - * %false otherwise. + * Return: %false if @dwork was idle and queued, %true otherwise. * * A special case is when the work is being canceled in parallel. * It might be caused either by the real kthread_cancel_delayed_work_sync() * or yet another kthread_mod_delayed_work() call. We let the other command - * win and return %false here. The caller is supposed to synchronize these - * operations a reasonable way. + * win and return %true here. The return value can be used for reference + * counting and the number of queued works stays the same. Anyway, the caller + * is supposed to synchronize these operations a reasonable way. * * This function is safe to call from any context including IRQ handler. * See __kthread_cancel_work() and kthread_delayed_work_timer_fn() @@ -1116,22 +1126,39 @@ bool kthread_mod_delayed_work(struct kthread_worker *worker, { struct kthread_work *work = &dwork->work; unsigned long flags; - int ret = false; + int ret; raw_spin_lock_irqsave(&worker->lock, flags); /* Do not bother with canceling when never queued. */ - if (!work->worker) + if (!work->worker) { + ret = false; goto fast_queue; + } /* Work must not be used with >1 worker, see kthread_queue_work() */ WARN_ON_ONCE(work->worker != worker); - /* Do not fight with another command that is canceling this work. */ - if (work->canceling) + /* + * Temporary cancel the work but do not fight with another command + * that is canceling the work as well. + * + * It is a bit tricky because of possible races with another + * mod_delayed_work() and cancel_delayed_work() callers. + * + * The timer must be canceled first because worker->lock is released + * when doing so. But the work can be removed from the queue (list) + * only when it can be queued again so that the return value can + * be used for reference counting. + */ + kthread_cancel_delayed_work_timer(work, &flags); + if (work->canceling) { + /* The number of works in the queue does not change. */ + ret = true; goto out; + } + ret = __kthread_cancel_work(work); - ret = __kthread_cancel_work(work, true, &flags); fast_queue: __kthread_queue_delayed_work(worker, dwork, delay); out: @@ -1153,7 +1180,10 @@ static bool __kthread_cancel_work_sync(struct kthread_work *work, bool is_dwork) /* Work must not be used with >1 worker, see kthread_queue_work(). */ WARN_ON_ONCE(work->worker != worker); - ret = __kthread_cancel_work(work, is_dwork, &flags); + if (is_dwork) + kthread_cancel_delayed_work_timer(work, &flags); + + ret = __kthread_cancel_work(work); if (worker->current_work != work) goto out_fast; diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 858b96b438cee38c90cc18739c71bdad061212a5..8ae9d7abebc086c641c439b7dc33f49118b0448b 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -842,7 +842,7 @@ static int count_matching_names(struct lock_class *new_class) } /* used from NMI context -- must be lockless */ -static __always_inline struct lock_class * +static noinstr struct lock_class * look_up_lock_class(const struct lockdep_map *lock, unsigned int subclass) { struct lockdep_subclass_key *key; @@ -850,12 +850,14 @@ look_up_lock_class(const struct lockdep_map *lock, unsigned int subclass) struct lock_class *class; if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) { + instrumentation_begin(); debug_locks_off(); printk(KERN_ERR "BUG: looking up invalid subclass: %u\n", subclass); printk(KERN_ERR "turning off the locking correctness validator.\n"); dump_stack(); + instrumentation_end(); return NULL; } @@ -2295,7 +2297,56 @@ static void print_lock_class_header(struct lock_class *class, int depth) } /* - * printk the shortest lock dependencies from @start to @end in reverse order: + * Dependency path printing: + * + * After BFS we get a lock dependency path (linked via ->parent of lock_list), + * printing out each lock in the dependency path will help on understanding how + * the deadlock could happen. Here are some details about dependency path + * printing: + * + * 1) A lock_list can be either forwards or backwards for a lock dependency, + * for a lock dependency A -> B, there are two lock_lists: + * + * a) lock_list in the ->locks_after list of A, whose ->class is B and + * ->links_to is A. In this case, we can say the lock_list is + * "A -> B" (forwards case). + * + * b) lock_list in the ->locks_before list of B, whose ->class is A + * and ->links_to is B. In this case, we can say the lock_list is + * "B <- A" (bacwards case). + * + * The ->trace of both a) and b) point to the call trace where B was + * acquired with A held. + * + * 2) A "helper" lock_list is introduced during BFS, this lock_list doesn't + * represent a certain lock dependency, it only provides an initial entry + * for BFS. For example, BFS may introduce a "helper" lock_list whose + * ->class is A, as a result BFS will search all dependencies starting with + * A, e.g. A -> B or A -> C. + * + * The notation of a forwards helper lock_list is like "-> A", which means + * we should search the forwards dependencies starting with "A", e.g A -> B + * or A -> C. + * + * The notation of a bacwards helper lock_list is like "<- B", which means + * we should search the backwards dependencies ending with "B", e.g. + * B <- A or B <- C. + */ + +/* + * printk the shortest lock dependencies from @root to @leaf in reverse order. + * + * We have a lock dependency path as follow: + * + * @root @leaf + * | | + * V V + * ->parent ->parent + * | lock_list | <--------- | lock_list | ... | lock_list | <--------- | lock_list | + * | -> L1 | | L1 -> L2 | ... |Ln-2 -> Ln-1| | Ln-1 -> Ln| + * + * , so it's natural that we start from @leaf and print every ->class and + * ->trace until we reach the @root. */ static void __used print_shortest_lock_dependencies(struct lock_list *leaf, @@ -2323,6 +2374,61 @@ print_shortest_lock_dependencies(struct lock_list *leaf, } while (entry && (depth >= 0)); } +/* + * printk the shortest lock dependencies from @leaf to @root. + * + * We have a lock dependency path (from a backwards search) as follow: + * + * @leaf @root + * | | + * V V + * ->parent ->parent + * | lock_list | ---------> | lock_list | ... | lock_list | ---------> | lock_list | + * | L2 <- L1 | | L3 <- L2 | ... | Ln <- Ln-1 | | <- Ln | + * + * , so when we iterate from @leaf to @root, we actually print the lock + * dependency path L1 -> L2 -> .. -> Ln in the non-reverse order. + * + * Another thing to notice here is that ->class of L2 <- L1 is L1, while the + * ->trace of L2 <- L1 is the call trace of L2, in fact we don't have the call + * trace of L1 in the dependency path, which is alright, because most of the + * time we can figure out where L1 is held from the call trace of L2. + */ +static void __used +print_shortest_lock_dependencies_backwards(struct lock_list *leaf, + struct lock_list *root) +{ + struct lock_list *entry = leaf; + const struct lock_trace *trace = NULL; + int depth; + + /*compute depth from generated tree by BFS*/ + depth = get_lock_depth(leaf); + + do { + print_lock_class_header(entry->class, depth); + if (trace) { + printk("%*s ... acquired at:\n", depth, ""); + print_lock_trace(trace, 2); + printk("\n"); + } + + /* + * Record the pointer to the trace for the next lock_list + * entry, see the comments for the function. + */ + trace = entry->trace; + + if (depth == 0 && (entry != root)) { + printk("lockdep:%s bad path found in chain graph\n", __func__); + break; + } + + entry = get_lock_parent(entry); + depth--; + } while (entry && (depth >= 0)); +} + static void print_irq_lock_scenario(struct lock_list *safe_entry, struct lock_list *unsafe_entry, @@ -2440,7 +2546,7 @@ print_bad_irq_dependency(struct task_struct *curr, prev_root->trace = save_trace(); if (!prev_root->trace) return; - print_shortest_lock_dependencies(backwards_entry, prev_root); + print_shortest_lock_dependencies_backwards(backwards_entry, prev_root); pr_warn("\nthe dependencies between the lock to be acquired"); pr_warn(" and %s-irq-unsafe lock:\n", irqclass); @@ -2658,8 +2764,18 @@ static int check_irq_usage(struct task_struct *curr, struct held_lock *prev, * Step 3: we found a bad match! Now retrieve a lock from the backward * list whose usage mask matches the exclusive usage mask from the * lock found on the forward list. + * + * Note, we should only keep the LOCKF_ENABLED_IRQ_ALL bits, considering + * the follow case: + * + * When trying to add A -> B to the graph, we find that there is a + * hardirq-safe L, that L -> ... -> A, and another hardirq-unsafe M, + * that B -> ... -> M. However M is **softirq-safe**, if we use exact + * invert bits of M's usage_mask, we will find another lock N that is + * **softirq-unsafe** and N -> ... -> A, however N -> .. -> M will not + * cause a inversion deadlock. */ - backward_mask = original_mask(target_entry1->class->usage_mask); + backward_mask = original_mask(target_entry1->class->usage_mask & LOCKF_ENABLED_IRQ_ALL); ret = find_usage_backwards(&this, backward_mask, &target_entry); if (bfs_error(ret)) { @@ -4510,7 +4626,7 @@ static int check_wait_context(struct task_struct *curr, struct held_lock *next) short curr_inner; int depth; - if (!curr->lockdep_depth || !next_inner || next->trylock) + if (!next_inner || next->trylock) return 0; if (!next_outer) diff --git a/kernel/module.c b/kernel/module.c index 908d46abe1656e8ebb330cda4f7cca97bfe34d8a..185b2655bc206b35b07cc2bf5866adc9af462a1f 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -272,9 +272,18 @@ static void module_assert_mutex_or_preempt(void) #endif } +#ifdef CONFIG_MODULE_SIG static bool sig_enforce = IS_ENABLED(CONFIG_MODULE_SIG_FORCE); module_param(sig_enforce, bool_enable_only, 0644); +void set_module_sig_enforced(void) +{ + sig_enforce = true; +} +#else +#define sig_enforce false +#endif + /* * Export sig_enforce kernel cmdline parameter to allow other subsystems rely * on that instead of directly to CONFIG_MODULE_SIG_FORCE config. @@ -285,11 +294,6 @@ bool is_module_sig_enforced(void) } EXPORT_SYMBOL(is_module_sig_enforced); -void set_module_sig_enforced(void) -{ - sig_enforce = true; -} - /* Block module loading/unloading? */ int modules_disabled = 0; core_param(nomodule, modules_disabled, bint, 0); diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h index e01cba5e4b5290c5f59790cad95b1dbab4c3a060..fcf95d1eec69ab1bb70612bae2d59a410bdc43c6 100644 --- a/kernel/rcu/rcu.h +++ b/kernel/rcu/rcu.h @@ -308,6 +308,8 @@ static inline void rcu_init_levelspread(int *levelspread, const int *levelcnt) } } +extern void rcu_init_geometry(void); + /* Returns a pointer to the first leaf rcu_node structure. */ #define rcu_first_leaf_node() (rcu_state.level[rcu_num_lvls - 1]) diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c index c13348ee80a5a204f1e36dc60e0028667d364790..68ceac3878445ddaf13aae465706ff4932cb7e74 100644 --- a/kernel/rcu/srcutree.c +++ b/kernel/rcu/srcutree.c @@ -90,6 +90,9 @@ static void init_srcu_struct_nodes(struct srcu_struct *ssp, bool is_static) struct srcu_node *snp; struct srcu_node *snp_first; + /* Initialize geometry if it has not already been initialized. */ + rcu_init_geometry(); + /* Work out the overall tree geometry. */ ssp->level[0] = &ssp->node[0]; for (i = 1; i < rcu_num_lvls; i++) diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c index 61e250cdd7c9c2335b9c52844319c8b3361bdb5d..8c3ba0185082dbb1c715c523283578b64f402c5b 100644 --- a/kernel/rcu/tree.c +++ b/kernel/rcu/tree.c @@ -2837,7 +2837,6 @@ static int __init rcu_spawn_core_kthreads(void) "%s: Could not start rcuc kthread, OOM is now expected behavior\n", __func__); return 0; } -early_initcall(rcu_spawn_core_kthreads); /* * Handle any core-RCU processing required by a call_rcu() invocation. @@ -4273,6 +4272,7 @@ static int __init rcu_spawn_gp_kthread(void) wake_up_process(t); rcu_spawn_nocb_kthreads(); rcu_spawn_boost_kthreads(); + rcu_spawn_core_kthreads(); return 0; } early_initcall(rcu_spawn_gp_kthread); @@ -4383,11 +4383,25 @@ static void __init rcu_init_one(void) * replace the definitions in tree.h because those are needed to size * the ->node array in the rcu_state structure. */ -static void __init rcu_init_geometry(void) +void rcu_init_geometry(void) { ulong d; int i; + static unsigned long old_nr_cpu_ids; int rcu_capacity[RCU_NUM_LVLS]; + static bool initialized; + + if (initialized) { + /* + * Warn if setup_nr_cpu_ids() had not yet been invoked, + * unless nr_cpus_ids == NR_CPUS, in which case who cares? + */ + WARN_ON_ONCE(old_nr_cpu_ids != nr_cpu_ids); + return; + } + + old_nr_cpu_ids = nr_cpu_ids; + initialized = true; /* * Initialize any unspecified boot parameters. diff --git a/kernel/rcu/update.c b/kernel/rcu/update.c index 39334d2d2b37991f1801a9ee8bf179db21d7fb0e..849f0aa99333bd8a4f0da858854c5e8afc2d93d1 100644 --- a/kernel/rcu/update.c +++ b/kernel/rcu/update.c @@ -275,7 +275,7 @@ EXPORT_SYMBOL_GPL(rcu_callback_map); noinstr int notrace debug_lockdep_rcu_enabled(void) { - return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && debug_locks && + return rcu_scheduler_active != RCU_SCHEDULER_INACTIVE && READ_ONCE(debug_locks) && current->lockdep_recursion == 0; } EXPORT_SYMBOL_GPL(debug_lockdep_rcu_enabled); diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 57b2362518849f54766d835cd7378f4d50b4b858..679562d2f55d1c23b406c8296ffc16a938f97865 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1063,9 +1063,10 @@ static void uclamp_sync_util_min_rt_default(void) static inline struct uclamp_se uclamp_tg_restrict(struct task_struct *p, enum uclamp_id clamp_id) { + /* Copy by value as we could modify it */ struct uclamp_se uc_req = p->uclamp_req[clamp_id]; #ifdef CONFIG_UCLAMP_TASK_GROUP - struct uclamp_se uc_max; + unsigned int tg_min, tg_max, value; /* * Tasks in autogroups or root task group will be @@ -1076,9 +1077,11 @@ uclamp_tg_restrict(struct task_struct *p, enum uclamp_id clamp_id) if (task_group(p) == &root_task_group) return uc_req; - uc_max = task_group(p)->uclamp[clamp_id]; - if (uc_req.value > uc_max.value || !uc_req.user_defined) - return uc_max; + tg_min = task_group(p)->uclamp[UCLAMP_MIN].value; + tg_max = task_group(p)->uclamp[UCLAMP_MAX].value; + value = uc_req.value; + value = clamp(value, tg_min, tg_max); + uclamp_se_set(&uc_req, value, false); #endif return uc_req; @@ -1277,8 +1280,9 @@ static inline void uclamp_rq_dec(struct rq *rq, struct task_struct *p) } static inline void -uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id) +uclamp_update_active(struct task_struct *p) { + enum uclamp_id clamp_id; struct rq_flags rf; struct rq *rq; @@ -1298,9 +1302,11 @@ uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id) * affecting a valid clamp bucket, the next time it's enqueued, * it will already see the updated clamp bucket value. */ - if (p->uclamp[clamp_id].active) { - uclamp_rq_dec_id(rq, p, clamp_id); - uclamp_rq_inc_id(rq, p, clamp_id); + for_each_clamp_id(clamp_id) { + if (p->uclamp[clamp_id].active) { + uclamp_rq_dec_id(rq, p, clamp_id); + uclamp_rq_inc_id(rq, p, clamp_id); + } } task_rq_unlock(rq, p, &rf); @@ -1308,20 +1314,14 @@ uclamp_update_active(struct task_struct *p, enum uclamp_id clamp_id) #ifdef CONFIG_UCLAMP_TASK_GROUP static inline void -uclamp_update_active_tasks(struct cgroup_subsys_state *css, - unsigned int clamps) +uclamp_update_active_tasks(struct cgroup_subsys_state *css) { - enum uclamp_id clamp_id; struct css_task_iter it; struct task_struct *p; css_task_iter_start(css, 0, &it); - while ((p = css_task_iter_next(&it))) { - for_each_clamp_id(clamp_id) { - if ((0x1 << clamp_id) & clamps) - uclamp_update_active(p, clamp_id); - } - } + while ((p = css_task_iter_next(&it))) + uclamp_update_active(p); css_task_iter_end(&it); } @@ -6512,7 +6512,7 @@ void show_state_filter(unsigned long state_filter) * NOTE: this function does not set the idle thread's NEED_RESCHED * flag, to make booting more robust. */ -void init_idle(struct task_struct *idle, int cpu) +void __init init_idle(struct task_struct *idle, int cpu) { struct rq *rq = cpu_rq(cpu); unsigned long flags; @@ -7607,7 +7607,11 @@ static int cpu_cgroup_css_online(struct cgroup_subsys_state *css) #ifdef CONFIG_UCLAMP_TASK_GROUP /* Propagate the effective uclamp value for the new group */ + mutex_lock(&uclamp_mutex); + rcu_read_lock(); cpu_util_update_eff(css); + rcu_read_unlock(); + mutex_unlock(&uclamp_mutex); #endif return 0; @@ -7697,6 +7701,9 @@ static void cpu_util_update_eff(struct cgroup_subsys_state *css) enum uclamp_id clamp_id; unsigned int clamps; + lockdep_assert_held(&uclamp_mutex); + SCHED_WARN_ON(!rcu_read_lock_held()); + css_for_each_descendant_pre(css, top_css) { uc_parent = css_tg(css)->parent ? css_tg(css)->parent->uclamp : NULL; @@ -7729,7 +7736,7 @@ static void cpu_util_update_eff(struct cgroup_subsys_state *css) } /* Immediately update descendants RUNNABLE tasks */ - uclamp_update_active_tasks(css, clamps); + uclamp_update_active_tasks(css); } } diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c index 8d06d1f4e2f7b8ed09c9ef81b637559d1ef27440..6b98c1fe6e7f8c4a0a87c873132f5da48dc22367 100644 --- a/kernel/sched/deadline.c +++ b/kernel/sched/deadline.c @@ -2470,6 +2470,8 @@ static void switched_to_dl(struct rq *rq, struct task_struct *p) check_preempt_curr_dl(rq, p, 0); else resched_curr(rq); + } else { + update_dl_rq_load_avg(rq_clock_pelt(rq), rq, 0); } } diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index d6e1c90de570a4b47c5b584af68d1c172302e6c0..32c0905bca84973fea5e1a7a40510a406f34a90c 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -3141,7 +3141,7 @@ void reweight_task(struct task_struct *p, int prio) * * tg->weight * grq->load.weight * ge->load.weight = ----------------------------- (1) - * \Sum grq->load.weight + * \Sum grq->load.weight * * Now, because computing that sum is prohibitively expensive to compute (been * there, done that) we approximate it with this average stuff. The average @@ -3155,7 +3155,7 @@ void reweight_task(struct task_struct *p, int prio) * * tg->weight * grq->avg.load_avg * ge->load.weight = ------------------------------ (3) - * tg->load_avg + * tg->load_avg * * Where: tg->load_avg ~= \Sum grq->avg.load_avg * @@ -3171,7 +3171,7 @@ void reweight_task(struct task_struct *p, int prio) * * tg->weight * grq->load.weight * ge->load.weight = ----------------------------- = tg->weight (4) - * grp->load.weight + * grp->load.weight * * That is, the sum collapses because all other CPUs are idle; the UP scenario. * @@ -3190,7 +3190,7 @@ void reweight_task(struct task_struct *p, int prio) * * tg->weight * grq->load.weight * ge->load.weight = ----------------------------- (6) - * tg_load_avg' + * tg_load_avg' * * Where: * @@ -3672,15 +3672,15 @@ update_cfs_rq_load_avg(u64 now, struct cfs_rq *cfs_rq) r = removed_load; sub_positive(&sa->load_avg, r); - sub_positive(&sa->load_sum, r * divider); + sa->load_sum = sa->load_avg * divider; r = removed_util; sub_positive(&sa->util_avg, r); - sub_positive(&sa->util_sum, r * divider); + sa->util_sum = sa->util_avg * divider; r = removed_runnable; sub_positive(&sa->runnable_avg, r); - sub_positive(&sa->runnable_sum, r * divider); + sa->runnable_sum = sa->runnable_avg * divider; /* * removed_runnable is the unweighted version of removed_load so we diff --git a/kernel/sched/psi.c b/kernel/sched/psi.c index 651218ded981707a720b5a287a421c2dc73af23f..d50a31ecedeec33b785b8b09565041927934962a 100644 --- a/kernel/sched/psi.c +++ b/kernel/sched/psi.c @@ -179,6 +179,8 @@ struct psi_group psi_system = { static void psi_avgs_work(struct work_struct *work); +static void poll_timer_fn(struct timer_list *t); + static void group_init(struct psi_group *group) { int cpu; @@ -198,6 +200,8 @@ static void group_init(struct psi_group *group) memset(group->polling_total, 0, sizeof(group->polling_total)); group->polling_next_update = ULLONG_MAX; group->polling_until = 0; + init_waitqueue_head(&group->poll_wait); + timer_setup(&group->poll_timer, poll_timer_fn, 0); rcu_assign_pointer(group->poll_task, NULL); } @@ -1126,9 +1130,7 @@ struct psi_trigger *psi_trigger_create(struct psi_group *group, return ERR_CAST(task); } atomic_set(&group->poll_wakeup, 0); - init_waitqueue_head(&group->poll_wait); wake_up_process(task); - timer_setup(&group->poll_timer, poll_timer_fn, 0); rcu_assign_pointer(group->poll_task, task); } @@ -1180,6 +1182,7 @@ static void psi_trigger_destroy(struct kref *ref) group->poll_task, lockdep_is_held(&group->trigger_lock)); rcu_assign_pointer(group->poll_task, NULL); + del_timer(&group->poll_timer); } } @@ -1192,17 +1195,14 @@ static void psi_trigger_destroy(struct kref *ref) */ synchronize_rcu(); /* - * Destroy the kworker after releasing trigger_lock to prevent a + * Stop kthread 'psimon' after releasing trigger_lock to prevent a * deadlock while waiting for psi_poll_work to acquire trigger_lock */ if (task_to_destroy) { /* * After the RCU grace period has expired, the worker * can no longer be found through group->poll_task. - * But it might have been already scheduled before - * that - deschedule it cleanly before destroying it. */ - del_timer_sync(&group->poll_timer); kthread_stop(task_to_destroy); } kfree(t); diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c index 49ec096a8aa1f3bdb456e9b8355529554db4deae..b5cf418e2e3feca37defee4214fae140af66a833 100644 --- a/kernel/sched/rt.c +++ b/kernel/sched/rt.c @@ -2291,13 +2291,20 @@ void __init init_sched_rt_class(void) static void switched_to_rt(struct rq *rq, struct task_struct *p) { /* - * If we are already running, then there's nothing - * that needs to be done. But if we are not running - * we may need to preempt the current running task. - * If that current running task is also an RT task + * If we are running, update the avg_rt tracking, as the running time + * will now on be accounted into the latter. + */ + if (task_current(rq, p)) { + update_rt_rq_load_avg(rq_clock_pelt(rq), rq, 0); + return; + } + + /* + * If we are not running we may need to preempt the current + * running task. If that current running task is also an RT task * then see if we can move to another run queue. */ - if (task_on_rq_queued(p) && rq->curr != p) { + if (task_on_rq_queued(p)) { #ifdef CONFIG_SMP if (p->nr_cpus_allowed > 1 && rq->rt.overloaded) rt_queue_push_tasks(rq); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index fdebfcbdfca94ba766c10399f7cfeeb3f8b69cb5..39112ac7ab3476b65521b9eabba072b0fa404806 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2422,20 +2422,27 @@ static __always_inline unsigned long uclamp_rq_util_with(struct rq *rq, unsigned long util, struct task_struct *p) { - unsigned long min_util; - unsigned long max_util; + unsigned long min_util = 0; + unsigned long max_util = 0; if (!static_branch_likely(&sched_uclamp_used)) return util; - min_util = READ_ONCE(rq->uclamp[UCLAMP_MIN].value); - max_util = READ_ONCE(rq->uclamp[UCLAMP_MAX].value); - if (p) { - min_util = max(min_util, uclamp_eff_value(p, UCLAMP_MIN)); - max_util = max(max_util, uclamp_eff_value(p, UCLAMP_MAX)); + min_util = uclamp_eff_value(p, UCLAMP_MIN); + max_util = uclamp_eff_value(p, UCLAMP_MAX); + + /* + * Ignore last runnable task's max clamp, as this task will + * reset it. Similarly, no need to read the rq's min clamp. + */ + if (rq->uclamp_flags & UCLAMP_FLAG_IDLE) + goto out; } + min_util = max_t(unsigned long, min_util, READ_ONCE(rq->uclamp[UCLAMP_MIN].value)); + max_util = max_t(unsigned long, max_util, READ_ONCE(rq->uclamp[UCLAMP_MAX].value)); +out: /* * Since CPU's {min,max}_util clamps are MAX aggregated considering * RUNNABLE tasks with _different_ clamps, we can end up with an diff --git a/kernel/sched/wait.c b/kernel/sched/wait.c index 01f5d3020589de0e85ed2fa706c30bc0be547687..21005b980a6b76b3275a9676ae760091e3e2fe89 100644 --- a/kernel/sched/wait.c +++ b/kernel/sched/wait.c @@ -249,17 +249,22 @@ prepare_to_wait(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_ent } EXPORT_SYMBOL(prepare_to_wait); -void +/* Returns true if we are the first waiter in the queue, false otherwise. */ +bool prepare_to_wait_exclusive(struct wait_queue_head *wq_head, struct wait_queue_entry *wq_entry, int state) { unsigned long flags; + bool was_empty = false; wq_entry->flags |= WQ_FLAG_EXCLUSIVE; spin_lock_irqsave(&wq_head->lock, flags); - if (list_empty(&wq_entry->entry)) + if (list_empty(&wq_entry->entry)) { + was_empty = list_empty(&wq_head->head); __add_wait_queue_entry_tail(wq_head, wq_entry); + } set_current_state(state); spin_unlock_irqrestore(&wq_head->lock, flags); + return was_empty; } EXPORT_SYMBOL(prepare_to_wait_exclusive); diff --git a/kernel/smpboot.c b/kernel/smpboot.c index f25208e8df8365e090cedf887638b3e0b00e92bc..e4163042c4d6658d4fcf192bfcac04e8c2ddb5cf 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -33,7 +33,6 @@ struct task_struct *idle_thread_get(unsigned int cpu) if (!tsk) return ERR_PTR(-ENOMEM); - init_idle(tsk, cpu); return tsk; } diff --git a/kernel/static_call.c b/kernel/static_call.c index f59089a1223191e2789366e5a5becaeed1dc625a..b62a0c41c9050dde7e09259da9e01cf6fef306eb 100644 --- a/kernel/static_call.c +++ b/kernel/static_call.c @@ -292,13 +292,15 @@ static int addr_conflict(struct static_call_site *site, void *start, void *end) static int __static_call_text_reserved(struct static_call_site *iter_start, struct static_call_site *iter_stop, - void *start, void *end) + void *start, void *end, bool init) { struct static_call_site *iter = iter_start; while (iter < iter_stop) { - if (addr_conflict(iter, start, end)) - return 1; + if (init || !static_call_is_init(iter)) { + if (addr_conflict(iter, start, end)) + return 1; + } iter++; } @@ -324,7 +326,7 @@ static int __static_call_mod_text_reserved(void *start, void *end) ret = __static_call_text_reserved(mod->static_call_sites, mod->static_call_sites + mod->num_static_call_sites, - start, end); + start, end, mod->state == MODULE_STATE_COMING); module_put(mod); @@ -459,8 +461,9 @@ static inline int __static_call_mod_text_reserved(void *start, void *end) int static_call_text_reserved(void *start, void *end) { + bool init = system_state < SYSTEM_RUNNING; int ret = __static_call_text_reserved(__start_static_call_sites, - __stop_static_call_sites, start, end); + __stop_static_call_sites, start, end, init); if (ret) return ret; diff --git a/kernel/sys.c b/kernel/sys.c index a730c03ee607cc5941628ed6fc1800f512d41467..0670e824e0197ae70f6d92b681f5448af60864ee 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -552,6 +552,10 @@ long __sys_setreuid(uid_t ruid, uid_t euid) if (retval < 0) goto error; + retval = set_cred_ucounts(new); + if (retval < 0) + goto error; + return commit_creds(new); error: @@ -610,6 +614,10 @@ long __sys_setuid(uid_t uid) if (retval < 0) goto error; + retval = set_cred_ucounts(new); + if (retval < 0) + goto error; + return commit_creds(new); error: @@ -685,6 +693,10 @@ long __sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) if (retval < 0) goto error; + retval = set_cred_ucounts(new); + if (retval < 0) + goto error; + return commit_creds(new); error: diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c index 02441ead3c3bb05d3a2828e567775e0d374df5b6..74492f08660c4da4696458a7e9d21e50961bc653 100644 --- a/kernel/time/clocksource.c +++ b/kernel/time/clocksource.c @@ -124,6 +124,13 @@ static void __clocksource_change_rating(struct clocksource *cs, int rating); #define WATCHDOG_INTERVAL (HZ >> 1) #define WATCHDOG_THRESHOLD (NSEC_PER_SEC >> 4) +/* + * Maximum permissible delay between two readouts of the watchdog + * clocksource surrounding a read of the clocksource being validated. + * This delay could be due to SMIs, NMIs, or to VCPU preemptions. + */ +#define WATCHDOG_MAX_SKEW (100 * NSEC_PER_USEC) + static void clocksource_watchdog_work(struct work_struct *work) { /* @@ -184,12 +191,99 @@ void clocksource_mark_unstable(struct clocksource *cs) spin_unlock_irqrestore(&watchdog_lock, flags); } +static ulong max_cswd_read_retries = 3; +module_param(max_cswd_read_retries, ulong, 0644); + +static bool cs_watchdog_read(struct clocksource *cs, u64 *csnow, u64 *wdnow) +{ + unsigned int nretries; + u64 wd_end, wd_delta; + int64_t wd_delay; + + for (nretries = 0; nretries <= max_cswd_read_retries; nretries++) { + local_irq_disable(); + *wdnow = watchdog->read(watchdog); + *csnow = cs->read(cs); + wd_end = watchdog->read(watchdog); + local_irq_enable(); + + wd_delta = clocksource_delta(wd_end, *wdnow, watchdog->mask); + wd_delay = clocksource_cyc2ns(wd_delta, watchdog->mult, + watchdog->shift); + if (wd_delay <= WATCHDOG_MAX_SKEW) { + if (nretries > 1 || nretries >= max_cswd_read_retries) { + pr_warn("timekeeping watchdog on CPU%d: %s retried %d times before success\n", + smp_processor_id(), watchdog->name, nretries); + } + return true; + } + } + + pr_warn("timekeeping watchdog on CPU%d: %s read-back delay of %lldns, attempt %d, marking unstable\n", + smp_processor_id(), watchdog->name, wd_delay, nretries); + return false; +} + +static u64 csnow_mid; +static cpumask_t cpus_ahead; +static cpumask_t cpus_behind; + +static void clocksource_verify_one_cpu(void *csin) +{ + struct clocksource *cs = (struct clocksource *)csin; + + csnow_mid = cs->read(cs); +} + +static void clocksource_verify_percpu(struct clocksource *cs) +{ + int64_t cs_nsec, cs_nsec_max = 0, cs_nsec_min = LLONG_MAX; + u64 csnow_begin, csnow_end; + int cpu, testcpu; + s64 delta; + + cpumask_clear(&cpus_ahead); + cpumask_clear(&cpus_behind); + preempt_disable(); + testcpu = smp_processor_id(); + pr_warn("Checking clocksource %s synchronization from CPU %d.\n", cs->name, testcpu); + for_each_online_cpu(cpu) { + if (cpu == testcpu) + continue; + csnow_begin = cs->read(cs); + smp_call_function_single(cpu, clocksource_verify_one_cpu, cs, 1); + csnow_end = cs->read(cs); + delta = (s64)((csnow_mid - csnow_begin) & cs->mask); + if (delta < 0) + cpumask_set_cpu(cpu, &cpus_behind); + delta = (csnow_end - csnow_mid) & cs->mask; + if (delta < 0) + cpumask_set_cpu(cpu, &cpus_ahead); + delta = clocksource_delta(csnow_end, csnow_begin, cs->mask); + cs_nsec = clocksource_cyc2ns(delta, cs->mult, cs->shift); + if (cs_nsec > cs_nsec_max) + cs_nsec_max = cs_nsec; + if (cs_nsec < cs_nsec_min) + cs_nsec_min = cs_nsec; + } + preempt_enable(); + if (!cpumask_empty(&cpus_ahead)) + pr_warn(" CPUs %*pbl ahead of CPU %d for clocksource %s.\n", + cpumask_pr_args(&cpus_ahead), testcpu, cs->name); + if (!cpumask_empty(&cpus_behind)) + pr_warn(" CPUs %*pbl behind CPU %d for clocksource %s.\n", + cpumask_pr_args(&cpus_behind), testcpu, cs->name); + if (!cpumask_empty(&cpus_ahead) || !cpumask_empty(&cpus_behind)) + pr_warn(" CPU %d check durations %lldns - %lldns for clocksource %s.\n", + testcpu, cs_nsec_min, cs_nsec_max, cs->name); +} + static void clocksource_watchdog(struct timer_list *unused) { - struct clocksource *cs; u64 csnow, wdnow, cslast, wdlast, delta; - int64_t wd_nsec, cs_nsec; int next_cpu, reset_pending; + int64_t wd_nsec, cs_nsec; + struct clocksource *cs; spin_lock(&watchdog_lock); if (!watchdog_running) @@ -206,10 +300,11 @@ static void clocksource_watchdog(struct timer_list *unused) continue; } - local_irq_disable(); - csnow = cs->read(cs); - wdnow = watchdog->read(watchdog); - local_irq_enable(); + if (!cs_watchdog_read(cs, &csnow, &wdnow)) { + /* Clock readout unreliable, so give it up. */ + __clocksource_unstable(cs); + continue; + } /* Clocksource initialized ? */ if (!(cs->flags & CLOCK_SOURCE_WATCHDOG) || @@ -407,6 +502,12 @@ static int __clocksource_watchdog_kthread(void) unsigned long flags; int select = 0; + /* Do any required per-CPU skew verification. */ + if (curr_clocksource && + curr_clocksource->flags & CLOCK_SOURCE_UNSTABLE && + curr_clocksource->flags & CLOCK_SOURCE_VERIFY_PERCPU) + clocksource_verify_percpu(curr_clocksource); + spin_lock_irqsave(&watchdog_lock, flags); list_for_each_entry_safe(cs, tmp, &watchdog_list, wd_list) { if (cs->flags & CLOCK_SOURCE_UNSTABLE) { diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 01710831fd02fc1652fca87c01d57782358a2ae1..216329c23f18aca189fefd4718a31ef16e589592 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2106,7 +2106,8 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog * if (prog->aux->max_tp_access > btp->writable_size) return -EINVAL; - return tracepoint_probe_register(tp, (void *)btp->bpf_func, prog); + return tracepoint_probe_register_may_exist(tp, (void *)btp->bpf_func, + prog); } int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index b09c598065019fd69285e77a40be871eab7b3104..ee84891bacfac5aa5e7221c53e2b4fec4b61da92 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2181,8 +2181,15 @@ void tracing_reset_all_online_cpus(void) } } +/* + * The tgid_map array maps from pid to tgid; i.e. the value stored at index i + * is the tgid last observed corresponding to pid=i. + */ static int *tgid_map; +/* The maximum valid index into tgid_map. */ +static size_t tgid_map_max; + #define SAVED_CMDLINES_DEFAULT 128 #define NO_CMDLINE_MAP UINT_MAX static arch_spinlock_t trace_cmdline_lock = __ARCH_SPIN_LOCK_UNLOCKED; @@ -2455,24 +2462,41 @@ void trace_find_cmdline(int pid, char comm[]) preempt_enable(); } +static int *trace_find_tgid_ptr(int pid) +{ + /* + * Pairs with the smp_store_release in set_tracer_flag() to ensure that + * if we observe a non-NULL tgid_map then we also observe the correct + * tgid_map_max. + */ + int *map = smp_load_acquire(&tgid_map); + + if (unlikely(!map || pid > tgid_map_max)) + return NULL; + + return &map[pid]; +} + int trace_find_tgid(int pid) { - if (unlikely(!tgid_map || !pid || pid > PID_MAX_DEFAULT)) - return 0; + int *ptr = trace_find_tgid_ptr(pid); - return tgid_map[pid]; + return ptr ? *ptr : 0; } static int trace_save_tgid(struct task_struct *tsk) { + int *ptr; + /* treat recording of idle task as a success */ if (!tsk->pid) return 1; - if (unlikely(!tgid_map || tsk->pid > PID_MAX_DEFAULT)) + ptr = trace_find_tgid_ptr(tsk->pid); + if (!ptr) return 0; - tgid_map[tsk->pid] = tsk->tgid; + *ptr = tsk->tgid; return 1; } @@ -4847,6 +4871,8 @@ int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set) int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled) { + int *map; + if ((mask == TRACE_ITER_RECORD_TGID) || (mask == TRACE_ITER_RECORD_CMD)) lockdep_assert_held(&event_mutex); @@ -4869,10 +4895,19 @@ int set_tracer_flag(struct trace_array *tr, unsigned int mask, int enabled) trace_event_enable_cmd_record(enabled); if (mask == TRACE_ITER_RECORD_TGID) { - if (!tgid_map) - tgid_map = kvcalloc(PID_MAX_DEFAULT + 1, - sizeof(*tgid_map), - GFP_KERNEL); + if (!tgid_map) { + tgid_map_max = pid_max; + map = kvcalloc(tgid_map_max + 1, sizeof(*tgid_map), + GFP_KERNEL); + + /* + * Pairs with smp_load_acquire() in + * trace_find_tgid_ptr() to ensure that if it observes + * the tgid_map we just allocated then it also observes + * the corresponding tgid_map_max value. + */ + smp_store_release(&tgid_map, map); + } if (!tgid_map) { tr->trace_flags &= ~TRACE_ITER_RECORD_TGID; return -ENOMEM; @@ -5284,37 +5319,16 @@ static const struct file_operations tracing_readme_fops = { static void *saved_tgids_next(struct seq_file *m, void *v, loff_t *pos) { - int *ptr = v; + int pid = ++(*pos); - if (*pos || m->count) - ptr++; - - (*pos)++; - - for (; ptr <= &tgid_map[PID_MAX_DEFAULT]; ptr++) { - if (trace_find_tgid(*ptr)) - return ptr; - } - - return NULL; + return trace_find_tgid_ptr(pid); } static void *saved_tgids_start(struct seq_file *m, loff_t *pos) { - void *v; - loff_t l = 0; + int pid = *pos; - if (!tgid_map) - return NULL; - - v = &tgid_map[0]; - while (l <= *pos) { - v = saved_tgids_next(m, v, &l); - if (!v) - return NULL; - } - - return v; + return trace_find_tgid_ptr(pid); } static void saved_tgids_stop(struct seq_file *m, void *v) @@ -5323,9 +5337,14 @@ static void saved_tgids_stop(struct seq_file *m, void *v) static int saved_tgids_show(struct seq_file *m, void *v) { - int pid = (int *)v - tgid_map; + int *entry = (int *)v; + int pid = entry - tgid_map; + int tgid = *entry; + + if (tgid == 0) + return SEQ_SKIP; - seq_printf(m, "%d %d\n", pid, trace_find_tgid(pid)); + seq_printf(m, "%d %d\n", pid, tgid); return 0; } diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c index 96c3f86b81c5f63279d4d358d74b3dfb108acfff..49d886b328dc1a0901fe28d844a447293a0eb50d 100644 --- a/kernel/trace/trace_events_hist.c +++ b/kernel/trace/trace_events_hist.c @@ -1539,6 +1539,13 @@ static int contains_operator(char *str) switch (*op) { case '-': + /* + * Unfortunately, the modifier ".sym-offset" + * can confuse things. + */ + if (op - str >= 4 && !strncmp(op - 4, ".sym-offset", 11)) + return FIELD_OP_NONE; + if (*str == '-') field_op = FIELD_OP_UNARY_MINUS; else @@ -1666,7 +1673,9 @@ static struct hist_field *create_hist_field(struct hist_trigger_data *hist_data, if (WARN_ON_ONCE(!field)) goto out; - if (is_string_field(field)) { + /* Pointers to strings are just pointers and dangerous to dereference */ + if (is_string_field(field) && + (field->filter_type != FILTER_PTR_STRING)) { flags |= HIST_FIELD_FL_STRING; hist_field->size = MAX_FILTER_STR_VAL; @@ -4462,8 +4471,6 @@ static inline void add_to_key(char *compound_key, void *key, field = key_field->field; if (field->filter_type == FILTER_DYN_STRING) size = *(u32 *)(rec + field->offset) >> 16; - else if (field->filter_type == FILTER_PTR_STRING) - size = strlen(key); else if (field->filter_type == FILTER_STATIC_STRING) size = field->size; diff --git a/kernel/tracepoint.c b/kernel/tracepoint.c index 3e261482296cf2c13d03cdf4d5c66bb959baf6f6..f8b161edca5eaa6e5869d202694fb362aeb42020 100644 --- a/kernel/tracepoint.c +++ b/kernel/tracepoint.c @@ -294,7 +294,8 @@ static void tracepoint_update_call(struct tracepoint *tp, struct tracepoint_func * Add the probe function to a tracepoint. */ static int tracepoint_add_func(struct tracepoint *tp, - struct tracepoint_func *func, int prio) + struct tracepoint_func *func, int prio, + bool warn) { struct tracepoint_func *old, *tp_funcs; int ret; @@ -309,7 +310,7 @@ static int tracepoint_add_func(struct tracepoint *tp, lockdep_is_held(&tracepoints_mutex)); old = func_add(&tp_funcs, func, prio); if (IS_ERR(old)) { - WARN_ON_ONCE(PTR_ERR(old) != -ENOMEM); + WARN_ON_ONCE(warn && PTR_ERR(old) != -ENOMEM); return PTR_ERR(old); } @@ -364,6 +365,32 @@ static int tracepoint_remove_func(struct tracepoint *tp, return 0; } +/** + * tracepoint_probe_register_prio_may_exist - Connect a probe to a tracepoint with priority + * @tp: tracepoint + * @probe: probe handler + * @data: tracepoint data + * @prio: priority of this function over other registered functions + * + * Same as tracepoint_probe_register_prio() except that it will not warn + * if the tracepoint is already registered. + */ +int tracepoint_probe_register_prio_may_exist(struct tracepoint *tp, void *probe, + void *data, int prio) +{ + struct tracepoint_func tp_func; + int ret; + + mutex_lock(&tracepoints_mutex); + tp_func.func = probe; + tp_func.data = data; + tp_func.prio = prio; + ret = tracepoint_add_func(tp, &tp_func, prio, false); + mutex_unlock(&tracepoints_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(tracepoint_probe_register_prio_may_exist); + /** * tracepoint_probe_register_prio - Connect a probe to a tracepoint with priority * @tp: tracepoint @@ -387,7 +414,7 @@ int tracepoint_probe_register_prio(struct tracepoint *tp, void *probe, tp_func.func = probe; tp_func.data = data; tp_func.prio = prio; - ret = tracepoint_add_func(tp, &tp_func, prio); + ret = tracepoint_add_func(tp, &tp_func, prio, true); mutex_unlock(&tracepoints_mutex); return ret; } diff --git a/kernel/ucount.c b/kernel/ucount.c index 11b1596e2542a5e28061cb31201e2a89bf66e936..9894795043c4229d19d583241dd9b51c0a14efb9 100644 --- a/kernel/ucount.c +++ b/kernel/ucount.c @@ -8,6 +8,12 @@ #include <linux/kmemleak.h> #include <linux/user_namespace.h> +struct ucounts init_ucounts = { + .ns = &init_user_ns, + .uid = GLOBAL_ROOT_UID, + .count = 1, +}; + #define UCOUNTS_HASHTABLE_BITS 10 static struct hlist_head ucounts_hashtable[(1 << UCOUNTS_HASHTABLE_BITS)]; static DEFINE_SPINLOCK(ucounts_lock); @@ -125,7 +131,15 @@ static struct ucounts *find_ucounts(struct user_namespace *ns, kuid_t uid, struc return NULL; } -static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid) +static void hlist_add_ucounts(struct ucounts *ucounts) +{ + struct hlist_head *hashent = ucounts_hashentry(ucounts->ns, ucounts->uid); + spin_lock_irq(&ucounts_lock); + hlist_add_head(&ucounts->node, hashent); + spin_unlock_irq(&ucounts_lock); +} + +struct ucounts *alloc_ucounts(struct user_namespace *ns, kuid_t uid) { struct hlist_head *hashent = ucounts_hashentry(ns, uid); struct ucounts *ucounts, *new; @@ -160,7 +174,26 @@ static struct ucounts *get_ucounts(struct user_namespace *ns, kuid_t uid) return ucounts; } -static void put_ucounts(struct ucounts *ucounts) +struct ucounts *get_ucounts(struct ucounts *ucounts) +{ + unsigned long flags; + + if (!ucounts) + return NULL; + + spin_lock_irqsave(&ucounts_lock, flags); + if (ucounts->count == INT_MAX) { + WARN_ONCE(1, "ucounts: counter has reached its maximum value"); + ucounts = NULL; + } else { + ucounts->count += 1; + } + spin_unlock_irqrestore(&ucounts_lock, flags); + + return ucounts; +} + +void put_ucounts(struct ucounts *ucounts) { unsigned long flags; @@ -194,7 +227,7 @@ struct ucounts *inc_ucount(struct user_namespace *ns, kuid_t uid, { struct ucounts *ucounts, *iter, *bad; struct user_namespace *tns; - ucounts = get_ucounts(ns, uid); + ucounts = alloc_ucounts(ns, uid); for (iter = ucounts; iter; iter = tns->ucounts) { int max; tns = iter->ns; @@ -237,6 +270,7 @@ static __init int user_namespace_sysctl_init(void) BUG_ON(!user_header); BUG_ON(!setup_userns_sysctls(&init_user_ns)); #endif + hlist_add_ucounts(&init_ucounts); return 0; } subsys_initcall(user_namespace_sysctl_init); diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index ce396ea4de60891b4040da0c04e0facf96b81332..8206a13c81ebcdcd21d9aa0467e86293185da4bf 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -1340,6 +1340,9 @@ static int userns_install(struct nsset *nsset, struct ns_common *ns) put_user_ns(cred->user_ns); set_cred_user_ns(cred, get_user_ns(user_ns)); + if (set_cred_ucounts(cred) < 0) + return -EINVAL; + return 0; } diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index dcf4a9028e1653f77d98ed3d4e48ac29b96a0901..5b7f88a2876dbe5b6ce3e376aba491ad71677d75 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1302,7 +1302,6 @@ config LOCKDEP bool depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT select STACKTRACE - depends on FRAME_POINTER || MIPS || PPC || S390 || MICROBLAZE || ARM || ARC || X86 select KALLSYMS select KALLSYMS_ALL diff --git a/lib/debug_locks.c b/lib/debug_locks.c index 06d3135bd184c498ae02a60a9da4b5ba502e442d..a75ee30b77cb8dd70d792d36e17ec74b0385852f 100644 --- a/lib/debug_locks.c +++ b/lib/debug_locks.c @@ -36,7 +36,7 @@ EXPORT_SYMBOL_GPL(debug_locks_silent); /* * Generic 'turn off all lock debugging' function: */ -noinstr int debug_locks_off(void) +int debug_locks_off(void) { if (debug_locks && __debug_locks_off()) { if (!debug_locks_silent) { diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c index c0cfcfd486be00a5887b930b967c3d61b6f0a0b6..e6327391b6b66350af40846c0c48733de04ce291 100644 --- a/lib/decompress_unlz4.c +++ b/lib/decompress_unlz4.c @@ -112,6 +112,9 @@ STATIC inline int INIT unlz4(u8 *input, long in_len, error("data corrupted"); goto exit_2; } + } else if (size < 4) { + /* empty or end-of-file */ + goto exit_3; } chunksize = get_unaligned_le32(inp); @@ -125,6 +128,10 @@ STATIC inline int INIT unlz4(u8 *input, long in_len, continue; } + if (!fill && chunksize == 0) { + /* empty or end-of-file */ + goto exit_3; + } if (posp) *posp += 4; @@ -184,6 +191,7 @@ STATIC inline int INIT unlz4(u8 *input, long in_len, } } +exit_3: ret = 0; exit_2: if (!input) diff --git a/lib/iov_iter.c b/lib/iov_iter.c index f0b2ccb1bb0182694733683501b55dc4d7dc2bb2..537bfdc8cd095f724c86c7a0798bfd1a45121b13 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -434,7 +434,7 @@ int iov_iter_fault_in_readable(struct iov_iter *i, size_t bytes) int err; struct iovec v; - if (!(i->type & (ITER_BVEC|ITER_KVEC))) { + if (iter_is_iovec(i)) { iterate_iovec(i, bytes, v, iov, skip, ({ err = fault_in_pages_readable(v.iov_base, v.iov_len); if (unlikely(err)) @@ -922,9 +922,12 @@ size_t copy_page_to_iter(struct page *page, size_t offset, size_t bytes, size_t wanted = copy_to_iter(kaddr + offset, bytes, i); kunmap_atomic(kaddr); return wanted; - } else if (unlikely(iov_iter_is_discard(i))) + } else if (unlikely(iov_iter_is_discard(i))) { + if (unlikely(i->count < bytes)) + bytes = i->count; + i->count -= bytes; return bytes; - else if (likely(!iov_iter_is_pipe(i))) + } else if (likely(!iov_iter_is_pipe(i))) return copy_page_to_iter_iovec(page, offset, bytes, i); else return copy_page_to_iter_pipe(page, offset, bytes, i); diff --git a/lib/kstrtox.c b/lib/kstrtox.c index a14ccf90505525f91658ac10281726524ec28936..8504526541c138e27f4e00aa83124d65e58c5e59 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -39,20 +39,22 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) /* * Convert non-negative integer string representation in explicitly given radix - * to an integer. + * to an integer. A maximum of max_chars characters will be converted. + * * Return number of characters consumed maybe or-ed with overflow bit. * If overflow occurs, result integer (incorrect) is still returned. * * Don't you dare use this function. */ -unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p) +unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p, + size_t max_chars) { unsigned long long res; unsigned int rv; res = 0; rv = 0; - while (1) { + while (max_chars--) { unsigned int c = *s; unsigned int lc = c | 0x20; /* don't tolower() this line */ unsigned int val; @@ -82,6 +84,11 @@ unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long return rv; } +unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p) +{ + return _parse_integer_limit(s, base, p, INT_MAX); +} + static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) { unsigned long long _res; diff --git a/lib/kstrtox.h b/lib/kstrtox.h index 3b4637bcd2540d7c4244363016c8d75ec604fd98..158c400ca8658e0d44c195a80a5628edb507ca5e 100644 --- a/lib/kstrtox.h +++ b/lib/kstrtox.h @@ -4,6 +4,8 @@ #define KSTRTOX_OVERFLOW (1U << 31) const char *_parse_integer_fixup_radix(const char *s, unsigned int *base); +unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *res, + size_t max_chars); unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *res); #endif diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c index a899b3f0e2e53ee25485fbddef4b5ae2778e9f18..76c52b0b76d382bbca024263d5c7eaa35c6d22d9 100644 --- a/lib/locking-selftest.c +++ b/lib/locking-selftest.c @@ -186,6 +186,7 @@ static void init_shared_classes(void) #define HARDIRQ_ENTER() \ local_irq_disable(); \ __irq_enter(); \ + lockdep_hardirq_threaded(); \ WARN_ON(!in_irq()); #define HARDIRQ_EXIT() \ diff --git a/lib/math/rational.c b/lib/math/rational.c index 9781d521963d145261a9b3d7e1cacfb5c3cbe5e6..c0ab51d8fbb98d17514ae63bf2b700d40f3cb752 100644 --- a/lib/math/rational.c +++ b/lib/math/rational.c @@ -12,6 +12,7 @@ #include <linux/compiler.h> #include <linux/export.h> #include <linux/minmax.h> +#include <linux/limits.h> /* * calculate best rational approximation for a given fraction @@ -78,13 +79,18 @@ void rational_best_approximation( * found below as 't'. */ if ((n2 > max_numerator) || (d2 > max_denominator)) { - unsigned long t = min((max_numerator - n0) / n1, - (max_denominator - d0) / d1); + unsigned long t = ULONG_MAX; - /* This tests if the semi-convergent is closer - * than the previous convergent. + if (d1) + t = (max_denominator - d0) / d1; + if (n1) + t = min(t, (max_numerator - n0) / n1); + + /* This tests if the semi-convergent is closer than the previous + * convergent. If d1 is zero there is no previous convergent as this + * is the 1st iteration, so always choose the semi-convergent. */ - if (2u * t > a || (2u * t == a && d0 * dp > d1 * d)) { + if (!d1 || 2u * t > a || (2u * t == a && d0 * dp > d1 * d)) { n1 = n0 + t * n1; d1 = d0 + t * d1; } diff --git a/lib/seq_buf.c b/lib/seq_buf.c index 707453f5d58ee056010684f19b80756cbeb00c9e..6dafde851333759ebb3afde4d75967f35d539178 100644 --- a/lib/seq_buf.c +++ b/lib/seq_buf.c @@ -229,8 +229,10 @@ int seq_buf_putmem_hex(struct seq_buf *s, const void *mem, WARN_ON(s->size == 0); + BUILD_BUG_ON(MAX_MEMHEX_BYTES * 2 >= HEX_CHARS); + while (len) { - start_len = min(len, HEX_CHARS - 1); + start_len = min(len, MAX_MEMHEX_BYTES); #ifdef __BIG_ENDIAN for (i = 0, j = 0; i < start_len; i++) { #else @@ -243,12 +245,14 @@ int seq_buf_putmem_hex(struct seq_buf *s, const void *mem, break; /* j increments twice per loop */ - len -= j / 2; hex[j++] = ' '; seq_buf_putmem(s, hex, j); if (seq_buf_has_overflowed(s)) return -1; + + len -= start_len; + data += start_len; } return 0; } diff --git a/lib/vsprintf.c b/lib/vsprintf.c index fd0fde639ec9154f49b6ef3570efda169c0292ac..8ade1a86d8187d358be59b4b81487b66680c1e88 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -53,6 +53,31 @@ #include <linux/string_helpers.h> #include "kstrtox.h" +static unsigned long long simple_strntoull(const char *startp, size_t max_chars, + char **endp, unsigned int base) +{ + const char *cp; + unsigned long long result = 0ULL; + size_t prefix_chars; + unsigned int rv; + + cp = _parse_integer_fixup_radix(startp, &base); + prefix_chars = cp - startp; + if (prefix_chars < max_chars) { + rv = _parse_integer_limit(cp, base, &result, max_chars - prefix_chars); + /* FIXME */ + cp += (rv & ~KSTRTOX_OVERFLOW); + } else { + /* Field too short for prefix + digit, skip over without converting */ + cp = startp + max_chars; + } + + if (endp) + *endp = (char *)cp; + + return result; +} + /** * simple_strtoull - convert a string to an unsigned long long * @cp: The start of the string @@ -63,18 +88,7 @@ */ unsigned long long simple_strtoull(const char *cp, char **endp, unsigned int base) { - unsigned long long result; - unsigned int rv; - - cp = _parse_integer_fixup_radix(cp, &base); - rv = _parse_integer(cp, base, &result); - /* FIXME */ - cp += (rv & ~KSTRTOX_OVERFLOW); - - if (endp) - *endp = (char *)cp; - - return result; + return simple_strntoull(cp, INT_MAX, endp, base); } EXPORT_SYMBOL(simple_strtoull); @@ -109,6 +123,21 @@ long simple_strtol(const char *cp, char **endp, unsigned int base) } EXPORT_SYMBOL(simple_strtol); +static long long simple_strntoll(const char *cp, size_t max_chars, char **endp, + unsigned int base) +{ + /* + * simple_strntoull() safely handles receiving max_chars==0 in the + * case cp[0] == '-' && max_chars == 1. + * If max_chars == 0 we can drop through and pass it to simple_strntoull() + * and the content of *cp is irrelevant. + */ + if (*cp == '-' && max_chars > 0) + return -simple_strntoull(cp + 1, max_chars - 1, endp, base); + + return simple_strntoull(cp, max_chars, endp, base); +} + /** * simple_strtoll - convert a string to a signed long long * @cp: The start of the string @@ -119,10 +148,7 @@ EXPORT_SYMBOL(simple_strtol); */ long long simple_strtoll(const char *cp, char **endp, unsigned int base) { - if (*cp == '-') - return -simple_strtoull(cp + 1, endp, base); - - return simple_strtoull(cp, endp, base); + return simple_strntoll(cp, INT_MAX, endp, base); } EXPORT_SYMBOL(simple_strtoll); @@ -3442,25 +3468,13 @@ int vsscanf(const char *buf, const char *fmt, va_list args) break; if (is_sign) - val.s = qualifier != 'L' ? - simple_strtol(str, &next, base) : - simple_strtoll(str, &next, base); + val.s = simple_strntoll(str, + field_width >= 0 ? field_width : INT_MAX, + &next, base); else - val.u = qualifier != 'L' ? - simple_strtoul(str, &next, base) : - simple_strtoull(str, &next, base); - - if (field_width > 0 && next - str > field_width) { - if (base == 0) - _parse_integer_fixup_radix(str, &base); - while (next - str > field_width) { - if (is_sign) - val.s = div_s64(val.s, base); - else - val.u = div_u64(val.u, base); - --next; - } - } + val.u = simple_strntoull(str, + field_width >= 0 ? field_width : INT_MAX, + &next, base); switch (qualifier) { case 'H': /* that's 'hh' in format */ diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c index 750bfef26be37fa641077adc2a78bb09089b047c..12ebc97e8b4354c72edf35f96239e3b53919dc76 100644 --- a/mm/debug_vm_pgtable.c +++ b/mm/debug_vm_pgtable.c @@ -58,11 +58,23 @@ #define RANDOM_ORVALUE (GENMASK(BITS_PER_LONG - 1, 0) & ~ARCH_SKIP_MASK) #define RANDOM_NZVALUE GENMASK(7, 0) -static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot) +static void __init pte_basic_tests(unsigned long pfn, int idx) { + pgprot_t prot = protection_map[idx]; pte_t pte = pfn_pte(pfn, prot); + unsigned long val = idx, *ptr = &val; + + pr_debug("Validating PTE basic (%pGv)\n", ptr); + + /* + * This test needs to be executed after the given page table entry + * is created with pfn_pte() to make sure that protection_map[idx] + * does not have the dirty bit enabled from the beginning. This is + * important for platforms like arm64 where (!PTE_RDONLY) indicate + * dirty bit being set. + */ + WARN_ON(pte_dirty(pte_wrprotect(pte))); - pr_debug("Validating PTE basic\n"); WARN_ON(!pte_same(pte, pte)); WARN_ON(!pte_young(pte_mkyoung(pte_mkold(pte)))); WARN_ON(!pte_dirty(pte_mkdirty(pte_mkclean(pte)))); @@ -70,6 +82,8 @@ static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot) WARN_ON(pte_young(pte_mkold(pte_mkyoung(pte)))); WARN_ON(pte_dirty(pte_mkclean(pte_mkdirty(pte)))); WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte)))); + WARN_ON(pte_dirty(pte_wrprotect(pte_mkclean(pte)))); + WARN_ON(!pte_dirty(pte_wrprotect(pte_mkdirty(pte)))); } static void __init pte_advanced_tests(struct mm_struct *mm, @@ -129,14 +143,28 @@ static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot) } #ifdef CONFIG_TRANSPARENT_HUGEPAGE -static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) +static void __init pmd_basic_tests(unsigned long pfn, int idx) { - pmd_t pmd = pfn_pmd(pfn, prot); + pgprot_t prot = protection_map[idx]; + unsigned long val = idx, *ptr = &val; + pmd_t pmd; if (!has_transparent_hugepage()) return; - pr_debug("Validating PMD basic\n"); + pr_debug("Validating PMD basic (%pGv)\n", ptr); + pmd = pfn_pmd(pfn, prot); + + /* + * This test needs to be executed after the given page table entry + * is created with pfn_pmd() to make sure that protection_map[idx] + * does not have the dirty bit enabled from the beginning. This is + * important for platforms like arm64 where (!PTE_RDONLY) indicate + * dirty bit being set. + */ + WARN_ON(pmd_dirty(pmd_wrprotect(pmd))); + + WARN_ON(!pmd_same(pmd, pmd)); WARN_ON(!pmd_young(pmd_mkyoung(pmd_mkold(pmd)))); WARN_ON(!pmd_dirty(pmd_mkdirty(pmd_mkclean(pmd)))); @@ -144,6 +172,8 @@ static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) WARN_ON(pmd_young(pmd_mkold(pmd_mkyoung(pmd)))); WARN_ON(pmd_dirty(pmd_mkclean(pmd_mkdirty(pmd)))); WARN_ON(pmd_write(pmd_wrprotect(pmd_mkwrite(pmd)))); + WARN_ON(pmd_dirty(pmd_wrprotect(pmd_mkclean(pmd)))); + WARN_ON(!pmd_dirty(pmd_wrprotect(pmd_mkdirty(pmd)))); /* * A huge page does not point to next level page table * entry. Hence this must qualify as pmd_bad(). @@ -156,7 +186,7 @@ static void __init pmd_advanced_tests(struct mm_struct *mm, unsigned long pfn, unsigned long vaddr, pgprot_t prot, pgtable_t pgtable) { - pmd_t pmd = pfn_pmd(pfn, prot); + pmd_t pmd; if (!has_transparent_hugepage()) return; @@ -203,9 +233,14 @@ static void __init pmd_advanced_tests(struct mm_struct *mm, static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot) { - pmd_t pmd = pfn_pmd(pfn, prot); + pmd_t pmd; + + if (!has_transparent_hugepage()) + return; pr_debug("Validating PMD leaf\n"); + pmd = pfn_pmd(pfn, prot); + /* * PMD based THP is a leaf entry. */ @@ -238,30 +273,51 @@ static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot) static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot) { - pmd_t pmd = pfn_pmd(pfn, prot); + pmd_t pmd; if (!IS_ENABLED(CONFIG_NUMA_BALANCING)) return; + if (!has_transparent_hugepage()) + return; + pr_debug("Validating PMD saved write\n"); + pmd = pfn_pmd(pfn, prot); WARN_ON(!pmd_savedwrite(pmd_mk_savedwrite(pmd_clear_savedwrite(pmd)))); WARN_ON(pmd_savedwrite(pmd_clear_savedwrite(pmd_mk_savedwrite(pmd)))); } #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD -static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) +static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { - pud_t pud = pfn_pud(pfn, prot); + pgprot_t prot = protection_map[idx]; + unsigned long val = idx, *ptr = &val; + pud_t pud; if (!has_transparent_hugepage()) return; - pr_debug("Validating PUD basic\n"); + pr_debug("Validating PUD basic (%pGv)\n", ptr); + pud = pfn_pud(pfn, prot); + + /* + * This test needs to be executed after the given page table entry + * is created with pfn_pud() to make sure that protection_map[idx] + * does not have the dirty bit enabled from the beginning. This is + * important for platforms like arm64 where (!PTE_RDONLY) indicate + * dirty bit being set. + */ + WARN_ON(pud_dirty(pud_wrprotect(pud))); + WARN_ON(!pud_same(pud, pud)); WARN_ON(!pud_young(pud_mkyoung(pud_mkold(pud)))); + WARN_ON(!pud_dirty(pud_mkdirty(pud_mkclean(pud)))); + WARN_ON(pud_dirty(pud_mkclean(pud_mkdirty(pud)))); WARN_ON(!pud_write(pud_mkwrite(pud_wrprotect(pud)))); WARN_ON(pud_write(pud_wrprotect(pud_mkwrite(pud)))); WARN_ON(pud_young(pud_mkold(pud_mkyoung(pud)))); + WARN_ON(pud_dirty(pud_wrprotect(pud_mkclean(pud)))); + WARN_ON(!pud_dirty(pud_wrprotect(pud_mkdirty(pud)))); if (mm_pmd_folded(mm)) return; @@ -278,7 +334,7 @@ static void __init pud_advanced_tests(struct mm_struct *mm, unsigned long pfn, unsigned long vaddr, pgprot_t prot) { - pud_t pud = pfn_pud(pfn, prot); + pud_t pud; if (!has_transparent_hugepage()) return; @@ -287,6 +343,7 @@ static void __init pud_advanced_tests(struct mm_struct *mm, /* Align the address wrt HPAGE_PUD_SIZE */ vaddr &= HPAGE_PUD_MASK; + pud = pfn_pud(pfn, prot); set_pud_at(mm, vaddr, pudp, pud); pudp_set_wrprotect(mm, vaddr, pudp); pud = READ_ONCE(*pudp); @@ -325,9 +382,13 @@ static void __init pud_advanced_tests(struct mm_struct *mm, static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { - pud_t pud = pfn_pud(pfn, prot); + pud_t pud; + + if (!has_transparent_hugepage()) + return; pr_debug("Validating PUD leaf\n"); + pud = pfn_pud(pfn, prot); /* * PUD based THP is a leaf entry. */ @@ -359,7 +420,7 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) #endif /* !CONFIG_HAVE_ARCH_HUGE_VMAP */ #else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ -static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { } +static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { } static void __init pud_advanced_tests(struct mm_struct *mm, struct vm_area_struct *vma, pud_t *pudp, unsigned long pfn, unsigned long vaddr, @@ -372,8 +433,8 @@ static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot) } #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ #else /* !CONFIG_TRANSPARENT_HUGEPAGE */ -static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) { } -static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { } +static void __init pmd_basic_tests(unsigned long pfn, int idx) { } +static void __init pud_basic_tests(struct mm_struct *mm, unsigned long pfn, int idx) { } static void __init pmd_advanced_tests(struct mm_struct *mm, struct vm_area_struct *vma, pmd_t *pmdp, unsigned long pfn, unsigned long vaddr, @@ -609,12 +670,16 @@ static void __init pte_protnone_tests(unsigned long pfn, pgprot_t prot) #ifdef CONFIG_TRANSPARENT_HUGEPAGE static void __init pmd_protnone_tests(unsigned long pfn, pgprot_t prot) { - pmd_t pmd = pmd_mkhuge(pfn_pmd(pfn, prot)); + pmd_t pmd; if (!IS_ENABLED(CONFIG_NUMA_BALANCING)) return; + if (!has_transparent_hugepage()) + return; + pr_debug("Validating PMD protnone\n"); + pmd = pmd_mkhuge(pfn_pmd(pfn, prot)); WARN_ON(!pmd_protnone(pmd)); WARN_ON(!pmd_present(pmd)); } @@ -634,18 +699,26 @@ static void __init pte_devmap_tests(unsigned long pfn, pgprot_t prot) #ifdef CONFIG_TRANSPARENT_HUGEPAGE static void __init pmd_devmap_tests(unsigned long pfn, pgprot_t prot) { - pmd_t pmd = pfn_pmd(pfn, prot); + pmd_t pmd; + + if (!has_transparent_hugepage()) + return; pr_debug("Validating PMD devmap\n"); + pmd = pfn_pmd(pfn, prot); WARN_ON(!pmd_devmap(pmd_mkdevmap(pmd))); } #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD static void __init pud_devmap_tests(unsigned long pfn, pgprot_t prot) { - pud_t pud = pfn_pud(pfn, prot); + pud_t pud; + + if (!has_transparent_hugepage()) + return; pr_debug("Validating PUD devmap\n"); + pud = pfn_pud(pfn, prot); WARN_ON(!pud_devmap(pud_mkdevmap(pud))); } #else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ @@ -688,25 +761,33 @@ static void __init pte_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot) #ifdef CONFIG_TRANSPARENT_HUGEPAGE static void __init pmd_soft_dirty_tests(unsigned long pfn, pgprot_t prot) { - pmd_t pmd = pfn_pmd(pfn, prot); + pmd_t pmd; if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY)) return; + if (!has_transparent_hugepage()) + return; + pr_debug("Validating PMD soft dirty\n"); + pmd = pfn_pmd(pfn, prot); WARN_ON(!pmd_soft_dirty(pmd_mksoft_dirty(pmd))); WARN_ON(pmd_soft_dirty(pmd_clear_soft_dirty(pmd))); } static void __init pmd_swap_soft_dirty_tests(unsigned long pfn, pgprot_t prot) { - pmd_t pmd = pfn_pmd(pfn, prot); + pmd_t pmd; if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY) || !IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION)) return; + if (!has_transparent_hugepage()) + return; + pr_debug("Validating PMD swap soft dirty\n"); + pmd = pfn_pmd(pfn, prot); WARN_ON(!pmd_swp_soft_dirty(pmd_swp_mksoft_dirty(pmd))); WARN_ON(pmd_swp_soft_dirty(pmd_swp_clear_soft_dirty(pmd))); } @@ -735,6 +816,9 @@ static void __init pmd_swap_tests(unsigned long pfn, pgprot_t prot) swp_entry_t swp; pmd_t pmd; + if (!has_transparent_hugepage()) + return; + pr_debug("Validating PMD swap\n"); pmd = pfn_pmd(pfn, prot); swp = __pmd_to_swp_entry(pmd); @@ -899,6 +983,7 @@ static int __init debug_vm_pgtable(void) unsigned long vaddr, pte_aligned, pmd_aligned; unsigned long pud_aligned, p4d_aligned, pgd_aligned; spinlock_t *ptl = NULL; + int idx; pr_info("Validating architecture page table helpers\n"); prot = vm_get_page_prot(VMFLAGS); @@ -963,9 +1048,25 @@ static int __init debug_vm_pgtable(void) saved_pmdp = pmd_offset(pudp, 0UL); saved_ptep = pmd_pgtable(pmd); - pte_basic_tests(pte_aligned, prot); - pmd_basic_tests(pmd_aligned, prot); - pud_basic_tests(pud_aligned, prot); + /* + * Iterate over the protection_map[] to make sure that all + * the basic page table transformation validations just hold + * true irrespective of the starting protection value for a + * given page table entry. + */ + for (idx = 0; idx < ARRAY_SIZE(protection_map); idx++) { + pte_basic_tests(pte_aligned, idx); + pmd_basic_tests(pmd_aligned, idx); + pud_basic_tests(mm, pud_aligned, idx); + } + + /* + * Both P4D and PGD level tests are very basic which do not + * involve creating page table entries from the protection + * value and the given pfn. Hence just keep them out from + * the above iteration for now to save some test execution + * time. + */ p4d_basic_tests(p4d_aligned, prot); pgd_basic_tests(pgd_aligned, prot); diff --git a/mm/gup.c b/mm/gup.c index c2826f3afe722d608a82d5011a6263ac98148a89..6cb7d8ae56f66f101500182d9f8987c89e9748ff 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -44,6 +44,23 @@ static void hpage_pincount_sub(struct page *page, int refs) atomic_sub(refs, compound_pincount_ptr(page)); } +/* Equivalent to calling put_page() @refs times. */ +static void put_page_refs(struct page *page, int refs) +{ +#ifdef CONFIG_DEBUG_VM + if (VM_WARN_ON_ONCE_PAGE(page_ref_count(page) < refs, page)) + return; +#endif + + /* + * Calling put_page() for each ref is unnecessarily slow. Only the last + * ref needs a put_page(). + */ + if (refs > 1) + page_ref_sub(page, refs - 1); + put_page(page); +} + /* * Return the compound head page with ref appropriately incremented, * or NULL if that failed. @@ -56,6 +73,21 @@ static inline struct page *try_get_compound_head(struct page *page, int refs) return NULL; if (unlikely(!page_cache_add_speculative(head, refs))) return NULL; + + /* + * At this point we have a stable reference to the head page; but it + * could be that between the compound_head() lookup and the refcount + * increment, the compound page was split, in which case we'd end up + * holding a reference on a page that has nothing to do with the page + * we were given anymore. + * So now that the head page is stable, recheck that the pages still + * belong together. + */ + if (unlikely(compound_head(page) != head)) { + put_page_refs(head, refs); + return NULL; + } + return head; } @@ -95,6 +127,14 @@ static __maybe_unused struct page *try_grab_compound_head(struct page *page, is_migrate_cma_page(page)) return NULL; + /* + * CAUTION: Don't use compound_head() on the page before this + * point, the result won't be stable. + */ + page = try_get_compound_head(page, refs); + if (!page) + return NULL; + /* * When pinning a compound page of order > 1 (which is what * hpage_pincount_available() checks for), use an exact count to @@ -103,15 +143,10 @@ static __maybe_unused struct page *try_grab_compound_head(struct page *page, * However, be sure to *also* increment the normal page refcount * field at least once, so that the page really is pinned. */ - if (!hpage_pincount_available(page)) - refs *= GUP_PIN_COUNTING_BIAS; - - page = try_get_compound_head(page, refs); - if (!page) - return NULL; - if (hpage_pincount_available(page)) hpage_pincount_add(page, refs); + else + page_ref_add(page, refs * (GUP_PIN_COUNTING_BIAS - 1)); mod_node_page_state(page_pgdat(page), NR_FOLL_PIN_ACQUIRED, orig_refs); @@ -135,14 +170,7 @@ static void put_compound_head(struct page *page, int refs, unsigned int flags) refs *= GUP_PIN_COUNTING_BIAS; } - VM_BUG_ON_PAGE(page_ref_count(page) < refs, page); - /* - * Calling put_page() for each ref is unnecessarily slow. Only the last - * ref needs a put_page(). - */ - if (refs > 1) - page_ref_sub(page, refs - 1); - put_page(page); + put_page_refs(page, refs); } /** diff --git a/mm/huge_memory.c b/mm/huge_memory.c index d9ade23ac2b22b1e501fd9909f32bf7dcec11982..9fe622ff2fc4ad972bad3b04fdfefd40eedd44a4 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -61,8 +61,16 @@ static struct shrinker deferred_split_shrinker; static atomic_t huge_zero_refcount; struct page *huge_zero_page __read_mostly; +unsigned long huge_zero_pfn __read_mostly = ~0UL; -bool transparent_hugepage_enabled(struct vm_area_struct *vma) +static inline bool file_thp_enabled(struct vm_area_struct *vma) +{ + return transhuge_vma_enabled(vma, vma->vm_flags) && vma->vm_file && + !inode_is_open_for_write(vma->vm_file->f_inode) && + (vma->vm_flags & VM_EXEC); +} + +bool transparent_hugepage_active(struct vm_area_struct *vma) { /* The addr is used to check if the vma size fits */ unsigned long addr = (vma->vm_end & HPAGE_PMD_MASK) - HPAGE_PMD_SIZE; @@ -73,6 +81,8 @@ bool transparent_hugepage_enabled(struct vm_area_struct *vma) return __transparent_hugepage_enabled(vma); if (vma_is_shmem(vma)) return shmem_huge_enabled(vma); + if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS)) + return file_thp_enabled(vma); return false; } @@ -97,6 +107,7 @@ retry: __free_pages(zero_page, compound_order(zero_page)); goto retry; } + WRITE_ONCE(huge_zero_pfn, page_to_pfn(zero_page)); /* We take additional reference here. It will be put back by shrinker */ atomic_set(&huge_zero_refcount, 2); @@ -146,6 +157,7 @@ static unsigned long shrink_huge_zero_page_scan(struct shrinker *shrink, if (atomic_cmpxchg(&huge_zero_refcount, 1, 0) == 1) { struct page *zero_page = xchg(&huge_zero_page, NULL); BUG_ON(zero_page == NULL); + WRITE_ONCE(huge_zero_pfn, ~0UL); __free_pages(zero_page, compound_order(zero_page)); return HPAGE_PMD_NR; } @@ -372,7 +384,11 @@ static int __init hugepage_init(void) struct kobject *hugepage_kobj; if (!has_transparent_hugepage()) { - transparent_hugepage_flags = 0; + /* + * Hardware doesn't support hugepages, hence disable + * DAX PMD support. + */ + transparent_hugepage_flags = 1 << TRANSPARENT_HUGEPAGE_NEVER_DAX; return -EINVAL; } @@ -1588,7 +1604,7 @@ bool madvise_free_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, * If other processes are mapping this page, we couldn't discard * the page unless they all do MADV_FREE so let's skip the page. */ - if (page_mapcount(page) != 1) + if (total_mapcount(page) != 1) goto out; if (!trylock_page(page)) @@ -2031,7 +2047,7 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, count_vm_event(THP_SPLIT_PMD); if (!vma_is_anonymous(vma)) { - _pmd = pmdp_huge_clear_flush_notify(vma, haddr, pmd); + old_pmd = pmdp_huge_clear_flush_notify(vma, haddr, pmd); /* * We are going to unmap this huge page. So * just go ahead and zap it @@ -2040,16 +2056,25 @@ static void __split_huge_pmd_locked(struct vm_area_struct *vma, pmd_t *pmd, zap_deposited_table(mm, pmd); if (vma_is_special_huge(vma)) return; - page = pmd_page(_pmd); - if (!PageDirty(page) && pmd_dirty(_pmd)) - set_page_dirty(page); - if (!PageReferenced(page) && pmd_young(_pmd)) - SetPageReferenced(page); - page_remove_rmap(page, true); - put_page(page); + if (unlikely(is_pmd_migration_entry(old_pmd))) { + swp_entry_t entry; + + entry = pmd_to_swp_entry(old_pmd); + page = migration_entry_to_page(entry); + } else { + page = pmd_page(old_pmd); + if (!PageDirty(page) && pmd_dirty(old_pmd)) + set_page_dirty(page); + if (!PageReferenced(page) && pmd_young(old_pmd)) + SetPageReferenced(page); + page_remove_rmap(page, true); + put_page(page); + } add_mm_counter(mm, mm_counter_file(page), -HPAGE_PMD_NR); return; - } else if (pmd_trans_huge(*pmd) && is_huge_zero_pmd(*pmd)) { + } + + if (is_huge_zero_pmd(*pmd)) { /* * FIXME: Do we want to invalidate secondary mmu by calling * mmu_notifier_invalidate_range() see comments below inside @@ -2330,17 +2355,17 @@ void vma_adjust_trans_huge(struct vm_area_struct *vma, static void unmap_page(struct page *page) { - enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | + enum ttu_flags ttu_flags = TTU_IGNORE_MLOCK | TTU_SYNC | TTU_RMAP_LOCKED | TTU_SPLIT_HUGE_PMD; - bool unmap_success; VM_BUG_ON_PAGE(!PageHead(page), page); if (PageAnon(page)) ttu_flags |= TTU_SPLIT_FREEZE; - unmap_success = try_to_unmap(page, ttu_flags); - VM_BUG_ON_PAGE(!unmap_success, page); + try_to_unmap(page, ttu_flags); + + VM_WARN_ON_ONCE_PAGE(page_mapped(page), page); } static void remap_page(struct page *page, unsigned int nr) @@ -2630,7 +2655,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) struct deferred_split *ds_queue = get_deferred_split_queue(head); struct anon_vma *anon_vma = NULL; struct address_space *mapping = NULL; - int count, mapcount, extra_pins, ret; + int extra_pins, ret; unsigned long flags; pgoff_t end; @@ -2690,7 +2715,6 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) } unmap_page(head); - VM_BUG_ON_PAGE(compound_mapcount(head), head); /* prevent PageLRU to go away from under us, and freeze lru stats */ spin_lock_irqsave(&pgdata->lru_lock, flags); @@ -2709,9 +2733,7 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) /* Prevent deferred_split_scan() touching ->_refcount */ spin_lock(&ds_queue->split_queue_lock); - count = page_count(head); - mapcount = total_mapcount(head); - if (!mapcount && page_ref_freeze(head, 1 + extra_pins)) { + if (page_ref_freeze(head, 1 + extra_pins)) { if (!list_empty(page_deferred_list(head))) { ds_queue->split_queue_len--; list_del(page_deferred_list(head)); @@ -2727,16 +2749,9 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) __split_huge_page(page, list, end, flags); ret = 0; } else { - if (IS_ENABLED(CONFIG_DEBUG_VM) && mapcount) { - pr_alert("total_mapcount: %u, page_count(): %u\n", - mapcount, count); - if (PageTail(page)) - dump_page(head, NULL); - dump_page(page, "total_mapcount(head) > 0"); - BUG(); - } spin_unlock(&ds_queue->split_queue_lock); -fail: if (mapping) +fail: + if (mapping) xa_unlock(&mapping->i_pages); spin_unlock_irqrestore(&pgdata->lru_lock, flags); remap_page(head, thp_nr_pages(head)); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index bc1006a32733851d8eb45433db3cd95f75e2bdd8..fa6b0ac6c280dee90ebfae12943dcf82552a6b18 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1252,8 +1252,7 @@ static void destroy_compound_gigantic_page(struct page *page, struct page *p = page + 1; atomic_set(compound_mapcount_ptr(page), 0); - if (hpage_pincount_available(page)) - atomic_set(compound_pincount_ptr(page), 0); + atomic_set(compound_pincount_ptr(page), 0); for (i = 1; i < nr_pages; i++, p = mem_map_next(p, page, i)) { clear_compound_head(p); @@ -1316,8 +1315,6 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask, return alloc_contig_pages(nr_pages, gfp_mask, nid, nodemask); } -static void prep_new_huge_page(struct hstate *h, struct page *page, int nid); -static void prep_compound_gigantic_page(struct page *page, unsigned int order); #else /* !CONFIG_CONTIG_ALLOC */ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask, int nid, nodemask_t *nodemask) @@ -1583,9 +1580,7 @@ static void prep_compound_gigantic_page(struct page *page, unsigned int order) set_compound_head(p, page); } atomic_set(compound_mapcount_ptr(page), -1); - - if (hpage_pincount_available(page)) - atomic_set(compound_pincount_ptr(page), 0); + atomic_set(compound_pincount_ptr(page), 0); } /* @@ -1635,15 +1630,12 @@ struct address_space *hugetlb_page_mapping_lock_write(struct page *hpage) return NULL; } -pgoff_t __basepage_index(struct page *page) +pgoff_t hugetlb_basepage_index(struct page *page) { struct page *page_head = compound_head(page); pgoff_t index = page_index(page_head); unsigned long compound_idx; - if (!PageHuge(page_head)) - return page_index(page); - if (compound_order(page_head) >= MAX_ORDER) compound_idx = page_to_pfn(page) - page_to_pfn(page_head); else @@ -2484,16 +2476,10 @@ found: return 1; } -static void __init prep_compound_huge_page(struct page *page, - unsigned int order) -{ - if (unlikely(order > (MAX_ORDER - 1))) - prep_compound_gigantic_page(page, order); - else - prep_compound_page(page, order); -} - -/* Put bootmem huge pages into the standard lists after mem_map is up */ +/* + * Put bootmem huge pages into the standard lists after mem_map is up. + * Note: This only applies to gigantic (order > MAX_ORDER) pages. + */ static void __init gather_bootmem_prealloc(void) { struct huge_bootmem_page *m; @@ -2502,20 +2488,19 @@ static void __init gather_bootmem_prealloc(void) struct page *page = virt_to_page(m); struct hstate *h = m->hstate; + VM_BUG_ON(!hstate_is_gigantic(h)); WARN_ON(page_count(page) != 1); - prep_compound_huge_page(page, h->order); + prep_compound_gigantic_page(page, huge_page_order(h)); WARN_ON(PageReserved(page)); prep_new_huge_page(h, page, page_to_nid(page)); put_page(page); /* free it into the hugepage allocator */ /* - * If we had gigantic hugepages allocated at boot time, we need - * to restore the 'stolen' pages to totalram_pages in order to - * fix confusing memory reports from free(1) and another - * side-effects, like CommitLimit going negative. + * We need to restore the 'stolen' pages to totalram_pages + * in order to fix confusing memory reports from free(1) and + * other side-effects, like CommitLimit going negative. */ - if (hstate_is_gigantic(h)) - adjust_managed_page_count(page, 1 << h->order); + adjust_managed_page_count(page, pages_per_huge_page(h)); cond_resched(); } } diff --git a/mm/internal.h b/mm/internal.h index c43ccdddb0f6e92e712dfd2dafe144018e7a4440..840b8a330b9acf5c87e976214a7dd25f0aef685a 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -379,27 +379,52 @@ static inline void mlock_migrate_page(struct page *newpage, struct page *page) extern pmd_t maybe_pmd_mkwrite(pmd_t pmd, struct vm_area_struct *vma); /* - * At what user virtual address is page expected in @vma? + * At what user virtual address is page expected in vma? + * Returns -EFAULT if all of the page is outside the range of vma. + * If page is a compound head, the entire compound page is considered. */ static inline unsigned long -__vma_address(struct page *page, struct vm_area_struct *vma) +vma_address(struct page *page, struct vm_area_struct *vma) { - pgoff_t pgoff = page_to_pgoff(page); - return vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); + pgoff_t pgoff; + unsigned long address; + + VM_BUG_ON_PAGE(PageKsm(page), page); /* KSM page->index unusable */ + pgoff = page_to_pgoff(page); + if (pgoff >= vma->vm_pgoff) { + address = vma->vm_start + + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); + /* Check for address beyond vma (or wrapped through 0?) */ + if (address < vma->vm_start || address >= vma->vm_end) + address = -EFAULT; + } else if (PageHead(page) && + pgoff + compound_nr(page) - 1 >= vma->vm_pgoff) { + /* Test above avoids possibility of wrap to 0 on 32-bit */ + address = vma->vm_start; + } else { + address = -EFAULT; + } + return address; } +/* + * Then at what user virtual address will none of the page be found in vma? + * Assumes that vma_address() already returned a good starting address. + * If page is a compound head, the entire compound page is considered. + */ static inline unsigned long -vma_address(struct page *page, struct vm_area_struct *vma) +vma_address_end(struct page *page, struct vm_area_struct *vma) { - unsigned long start, end; - - start = __vma_address(page, vma); - end = start + thp_size(page) - PAGE_SIZE; - - /* page should be within @vma mapping range */ - VM_BUG_ON_VMA(end < vma->vm_start || start >= vma->vm_end, vma); - - return max(start, vma->vm_start); + pgoff_t pgoff; + unsigned long address; + + VM_BUG_ON_PAGE(PageKsm(page), page); /* KSM page->index unusable */ + pgoff = page_to_pgoff(page) + compound_nr(page); + address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); + /* Check for address beyond vma (or wrapped through 0?) */ + if (address < vma->vm_start || address > vma->vm_end) + address = vma->vm_end; + return address; } static inline struct file *maybe_unlock_mmap_for_io(struct vm_fault *vmf, diff --git a/mm/khugepaged.c b/mm/khugepaged.c index a6238118ac4c77d4d83b614db2bc97958a08644b..ee88125785638ae3293f0d9f04b5dab55eae95cf 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -440,9 +440,7 @@ static inline int khugepaged_test_exit(struct mm_struct *mm) static bool hugepage_vma_check(struct vm_area_struct *vma, unsigned long vm_flags) { - /* Explicitly disabled through madvise. */ - if ((vm_flags & VM_NOHUGEPAGE) || - test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) + if (!transhuge_vma_enabled(vma, vm_flags)) return false; /* Enabled via shmem mount options or sysfs settings. */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 8d9f5fa4c6d398c9992d9b97834a5db852769afc..92bf987d0a4102af78e514f75b70ebb3c780ce8f 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2898,12 +2898,20 @@ static void commit_charge(struct page *page, struct mem_cgroup *memcg) } #ifdef CONFIG_MEMCG_KMEM +/* + * The allocated objcg pointers array is not accounted directly. + * Moreover, it should not come from DMA buffer and is not readily + * reclaimable. So those GFP bits should be masked off. + */ +#define OBJCGS_CLEAR_MASK (__GFP_DMA | __GFP_RECLAIMABLE | __GFP_ACCOUNT) + int memcg_alloc_page_obj_cgroups(struct page *page, struct kmem_cache *s, gfp_t gfp) { unsigned int objects = objs_per_slab_page(s, page); void *vec; + gfp &= ~OBJCGS_CLEAR_MASK; vec = kcalloc_node(objects, sizeof(struct obj_cgroup *), gfp, page_to_nid(page)); if (!vec) diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 25fb82320e3d5d77ccc3af45dbffa8176a55d376..01445ddff58d80e6be202ef4a342763e2afb6ccf 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -1856,11 +1856,11 @@ static int __soft_offline_page(struct page *page) pr_info("soft offline: %#lx: %s migration failed %d, type %lx (%pGp)\n", pfn, msg_page[huge], ret, page->flags, &page->flags); if (ret > 0) - ret = -EIO; + ret = -EBUSY; } } else { - pr_info("soft offline: %#lx: %s isolation failed: %d, page count %d, type %lx (%pGp)\n", - pfn, msg_page[huge], ret, page_count(page), page->flags, &page->flags); + pr_info("soft offline: %#lx: %s isolation failed, page count %d, type %lx (%pGp)\n", + pfn, msg_page[huge], page_count(page), page->flags, &page->flags); ret = -EBUSY; } return ret; diff --git a/mm/memory.c b/mm/memory.c index b70bd3ba338887bf27403b6eff98cfdf00a4295c..0a905e0a7e6720242f60195f864b2be07dc7b6bd 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1355,7 +1355,18 @@ static inline unsigned long zap_pmd_range(struct mmu_gather *tlb, else if (zap_huge_pmd(tlb, vma, pmd, addr)) goto next; /* fall through */ + } else if (details && details->single_page && + PageTransCompound(details->single_page) && + next - addr == HPAGE_PMD_SIZE && pmd_none(*pmd)) { + spinlock_t *ptl = pmd_lock(tlb->mm, pmd); + /* + * Take and drop THP pmd lock so that we cannot return + * prematurely, while zap_huge_pmd() has cleared *pmd, + * but not yet decremented compound_mapcount(). + */ + spin_unlock(ptl); } + /* * Here there can be other concurrent MADV_DONTNEED or * trans huge page faults running, and if the pmd is @@ -3185,6 +3196,36 @@ static inline void unmap_mapping_range_tree(struct rb_root_cached *root, } } +/** + * unmap_mapping_page() - Unmap single page from processes. + * @page: The locked page to be unmapped. + * + * Unmap this page from any userspace process which still has it mmaped. + * Typically, for efficiency, the range of nearby pages has already been + * unmapped by unmap_mapping_pages() or unmap_mapping_range(). But once + * truncation or invalidation holds the lock on a page, it may find that + * the page has been remapped again: and then uses unmap_mapping_page() + * to unmap it finally. + */ +void unmap_mapping_page(struct page *page) +{ + struct address_space *mapping = page->mapping; + struct zap_details details = { }; + + VM_BUG_ON(!PageLocked(page)); + VM_BUG_ON(PageTail(page)); + + details.check_mapping = mapping; + details.first_index = page->index; + details.last_index = page->index + thp_nr_pages(page) - 1; + details.single_page = page; + + i_mmap_lock_write(mapping); + if (unlikely(!RB_EMPTY_ROOT(&mapping->i_mmap.rb_root))) + unmap_mapping_range_tree(&mapping->i_mmap, &details); + i_mmap_unlock_write(mapping); +} + /** * unmap_mapping_pages() - Unmap pages from processes. * @mapping: The address space containing pages to be unmapped. @@ -3261,6 +3302,7 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) { struct vm_area_struct *vma = vmf->vma; struct page *page = NULL, *swapcache; + struct swap_info_struct *si = NULL; swp_entry_t entry; pte_t pte; int locked; @@ -3288,14 +3330,16 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) goto out; } + /* Prevent swapoff from happening to us. */ + si = get_swap_device(entry); + if (unlikely(!si)) + goto out; delayacct_set_flag(DELAYACCT_PF_SWAPIN); page = lookup_swap_cache(entry, vma, vmf->address); swapcache = page; if (!page) { - struct swap_info_struct *si = swp_swap_info(entry); - if (data_race(si->flags & SWP_SYNCHRONOUS_IO) && __swap_count(entry) == 1) { /* skip swapcache */ @@ -3466,6 +3510,8 @@ vm_fault_t do_swap_page(struct vm_fault *vmf) unlock: pte_unmap_unlock(vmf->pte, vmf->ptl); out: + if (si) + put_swap_device(si); return ret; out_nomap: pte_unmap_unlock(vmf->pte, vmf->ptl); @@ -3477,6 +3523,8 @@ out_release: unlock_page(swapcache); put_page(swapcache); } + if (si) + put_swap_device(si); return ret; } diff --git a/mm/migrate.c b/mm/migrate.c index 7982256a51250f290e9959e2837d05324832dce1..278e6f3fa62ce13143ca9848c79f634bd5701d31 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -326,6 +326,7 @@ void __migration_entry_wait(struct mm_struct *mm, pte_t *ptep, goto out; page = migration_entry_to_page(entry); + page = compound_head(page); /* * Once page cache replacement of page migration started, page_count diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 81cc7fdc9c8fd44f2ed64411f0c51a5b9f82668a..e30d88efd7fbb63dc177a2926b1ca759f187bd37 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -7788,31 +7788,24 @@ static void calculate_totalreserve_pages(void) static void setup_per_zone_lowmem_reserve(void) { struct pglist_data *pgdat; - enum zone_type j, idx; + enum zone_type i, j; for_each_online_pgdat(pgdat) { - for (j = 0; j < MAX_NR_ZONES; j++) { - struct zone *zone = pgdat->node_zones + j; - unsigned long managed_pages = zone_managed_pages(zone); - - zone->lowmem_reserve[j] = 0; + for (i = 0; i < MAX_NR_ZONES - 1; i++) { + struct zone *zone = &pgdat->node_zones[i]; + int ratio = sysctl_lowmem_reserve_ratio[i]; + bool clear = !ratio || !zone_managed_pages(zone); + unsigned long managed_pages = 0; - idx = j; - while (idx) { - struct zone *lower_zone; + for (j = i + 1; j < MAX_NR_ZONES; j++) { + struct zone *upper_zone = &pgdat->node_zones[j]; - idx--; - lower_zone = pgdat->node_zones + idx; + managed_pages += zone_managed_pages(upper_zone); - if (!sysctl_lowmem_reserve_ratio[idx] || - !zone_managed_pages(lower_zone)) { - lower_zone->lowmem_reserve[j] = 0; - continue; - } else { - lower_zone->lowmem_reserve[j] = - managed_pages / sysctl_lowmem_reserve_ratio[idx]; - } - managed_pages += zone_managed_pages(lower_zone); + if (clear) + zone->lowmem_reserve[j] = 0; + else + zone->lowmem_reserve[j] = managed_pages / ratio; } } } diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c index 5e77b269c330a29a6c5bebdf963bdcd0b08d3780..610ebbee787ccb5d9f373995ae856b360b56e71c 100644 --- a/mm/page_vma_mapped.c +++ b/mm/page_vma_mapped.c @@ -115,6 +115,13 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw) return pfn_is_match(pvmw->page, pfn); } +static void step_forward(struct page_vma_mapped_walk *pvmw, unsigned long size) +{ + pvmw->address = (pvmw->address + size) & ~(size - 1); + if (!pvmw->address) + pvmw->address = ULONG_MAX; +} + /** * page_vma_mapped_walk - check if @pvmw->page is mapped in @pvmw->vma at * @pvmw->address @@ -143,6 +150,7 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw) { struct mm_struct *mm = pvmw->vma->vm_mm; struct page *page = pvmw->page; + unsigned long end; pgd_t *pgd; p4d_t *p4d; pud_t *pud; @@ -152,10 +160,11 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw) if (pvmw->pmd && !pvmw->pte) return not_found(pvmw); - if (pvmw->pte) - goto next_pte; + if (unlikely(PageHuge(page))) { + /* The only possible mapping was handled on last iteration */ + if (pvmw->pte) + return not_found(pvmw); - if (unlikely(PageHuge(pvmw->page))) { /* when pud is not present, pte will be NULL */ pvmw->pte = huge_pte_offset(mm, pvmw->address, page_size(page)); if (!pvmw->pte) @@ -167,78 +176,108 @@ bool page_vma_mapped_walk(struct page_vma_mapped_walk *pvmw) return not_found(pvmw); return true; } -restart: - pgd = pgd_offset(mm, pvmw->address); - if (!pgd_present(*pgd)) - return false; - p4d = p4d_offset(pgd, pvmw->address); - if (!p4d_present(*p4d)) - return false; - pud = pud_offset(p4d, pvmw->address); - if (!pud_present(*pud)) - return false; - pvmw->pmd = pmd_offset(pud, pvmw->address); + /* - * Make sure the pmd value isn't cached in a register by the - * compiler and used as a stale value after we've observed a - * subsequent update. + * Seek to next pte only makes sense for THP. + * But more important than that optimization, is to filter out + * any PageKsm page: whose page->index misleads vma_address() + * and vma_address_end() to disaster. */ - pmde = READ_ONCE(*pvmw->pmd); - if (pmd_trans_huge(pmde) || is_pmd_migration_entry(pmde)) { - pvmw->ptl = pmd_lock(mm, pvmw->pmd); - if (likely(pmd_trans_huge(*pvmw->pmd))) { - if (pvmw->flags & PVMW_MIGRATION) - return not_found(pvmw); - if (pmd_page(*pvmw->pmd) != page) - return not_found(pvmw); - return true; - } else if (!pmd_present(*pvmw->pmd)) { - if (thp_migration_supported()) { - if (!(pvmw->flags & PVMW_MIGRATION)) + end = PageTransCompound(page) ? + vma_address_end(page, pvmw->vma) : + pvmw->address + PAGE_SIZE; + if (pvmw->pte) + goto next_pte; +restart: + do { + pgd = pgd_offset(mm, pvmw->address); + if (!pgd_present(*pgd)) { + step_forward(pvmw, PGDIR_SIZE); + continue; + } + p4d = p4d_offset(pgd, pvmw->address); + if (!p4d_present(*p4d)) { + step_forward(pvmw, P4D_SIZE); + continue; + } + pud = pud_offset(p4d, pvmw->address); + if (!pud_present(*pud)) { + step_forward(pvmw, PUD_SIZE); + continue; + } + + pvmw->pmd = pmd_offset(pud, pvmw->address); + /* + * Make sure the pmd value isn't cached in a register by the + * compiler and used as a stale value after we've observed a + * subsequent update. + */ + pmde = READ_ONCE(*pvmw->pmd); + + if (pmd_trans_huge(pmde) || is_pmd_migration_entry(pmde)) { + pvmw->ptl = pmd_lock(mm, pvmw->pmd); + pmde = *pvmw->pmd; + if (likely(pmd_trans_huge(pmde))) { + if (pvmw->flags & PVMW_MIGRATION) return not_found(pvmw); - if (is_migration_entry(pmd_to_swp_entry(*pvmw->pmd))) { - swp_entry_t entry = pmd_to_swp_entry(*pvmw->pmd); + if (pmd_page(pmde) != page) + return not_found(pvmw); + return true; + } + if (!pmd_present(pmde)) { + swp_entry_t entry; - if (migration_entry_to_page(entry) != page) - return not_found(pvmw); - return true; - } + if (!thp_migration_supported() || + !(pvmw->flags & PVMW_MIGRATION)) + return not_found(pvmw); + entry = pmd_to_swp_entry(pmde); + if (!is_migration_entry(entry) || + migration_entry_to_page(entry) != page) + return not_found(pvmw); + return true; } - return not_found(pvmw); - } else { /* THP pmd was split under us: handle on pte level */ spin_unlock(pvmw->ptl); pvmw->ptl = NULL; + } else if (!pmd_present(pmde)) { + /* + * If PVMW_SYNC, take and drop THP pmd lock so that we + * cannot return prematurely, while zap_huge_pmd() has + * cleared *pmd but not decremented compound_mapcount(). + */ + if ((pvmw->flags & PVMW_SYNC) && + PageTransCompound(page)) { + spinlock_t *ptl = pmd_lock(mm, pvmw->pmd); + + spin_unlock(ptl); + } + step_forward(pvmw, PMD_SIZE); + continue; } - } else if (!pmd_present(pmde)) { - return false; - } - if (!map_pte(pvmw)) - goto next_pte; - while (1) { + if (!map_pte(pvmw)) + goto next_pte; +this_pte: if (check_pte(pvmw)) return true; next_pte: - /* Seek to next pte only makes sense for THP */ - if (!PageTransHuge(pvmw->page) || PageHuge(pvmw->page)) - return not_found(pvmw); do { pvmw->address += PAGE_SIZE; - if (pvmw->address >= pvmw->vma->vm_end || - pvmw->address >= - __vma_address(pvmw->page, pvmw->vma) + - thp_size(pvmw->page)) + if (pvmw->address >= end) return not_found(pvmw); /* Did we cross page table boundary? */ - if (pvmw->address % PMD_SIZE == 0) { - pte_unmap(pvmw->pte); + if ((pvmw->address & (PMD_SIZE - PAGE_SIZE)) == 0) { if (pvmw->ptl) { spin_unlock(pvmw->ptl); pvmw->ptl = NULL; } + pte_unmap(pvmw->pte); + pvmw->pte = NULL; goto restart; - } else { - pvmw->pte++; + } + pvmw->pte++; + if ((pvmw->flags & PVMW_SYNC) && !pvmw->ptl) { + pvmw->ptl = pte_lockptr(mm, pvmw->pmd); + spin_lock(pvmw->ptl); } } while (pte_none(*pvmw->pte)); @@ -246,7 +285,10 @@ next_pte: pvmw->ptl = pte_lockptr(mm, pvmw->pmd); spin_lock(pvmw->ptl); } - } + goto this_pte; + } while (pvmw->address < end); + + return false; } /** @@ -265,14 +307,10 @@ int page_mapped_in_vma(struct page *page, struct vm_area_struct *vma) .vma = vma, .flags = PVMW_SYNC, }; - unsigned long start, end; - - start = __vma_address(page, vma); - end = start + thp_size(page) - PAGE_SIZE; - if (unlikely(end < vma->vm_start || start >= vma->vm_end)) + pvmw.address = vma_address(page, vma); + if (pvmw.address == -EFAULT) return 0; - pvmw.address = max(start, vma->vm_start); if (!page_vma_mapped_walk(&pvmw)) return 0; page_vma_mapped_walk_done(&pvmw); diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c index 9578db83e312f85ff727c7fdfb19b1780aa86db1..4e640baf979488acc90a7b4c8dc1aa4b8d00f037 100644 --- a/mm/pgtable-generic.c +++ b/mm/pgtable-generic.c @@ -135,8 +135,8 @@ pmd_t pmdp_huge_clear_flush(struct vm_area_struct *vma, unsigned long address, { pmd_t pmd; VM_BUG_ON(address & ~HPAGE_PMD_MASK); - VM_BUG_ON((pmd_present(*pmdp) && !pmd_trans_huge(*pmdp) && - !pmd_devmap(*pmdp)) || !pmd_present(*pmdp)); + VM_BUG_ON(pmd_present(*pmdp) && !pmd_trans_huge(*pmdp) && + !pmd_devmap(*pmdp)); pmd = pmdp_huge_get_and_clear(vma->vm_mm, address, pmdp); flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE); return pmd; diff --git a/mm/rmap.c b/mm/rmap.c index 6657000b18d41bf5db76845401233d22ec8fd3aa..14f84f70c5571879f58336c763d1888a2060415e 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -700,7 +700,6 @@ static bool should_defer_flush(struct mm_struct *mm, enum ttu_flags flags) */ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) { - unsigned long address; if (PageAnon(page)) { struct anon_vma *page__anon_vma = page_anon_vma(page); /* @@ -710,15 +709,13 @@ unsigned long page_address_in_vma(struct page *page, struct vm_area_struct *vma) if (!vma->anon_vma || !page__anon_vma || vma->anon_vma->root != page__anon_vma->root) return -EFAULT; - } else if (page->mapping) { - if (!vma->vm_file || vma->vm_file->f_mapping != page->mapping) - return -EFAULT; - } else + } else if (!vma->vm_file) { return -EFAULT; - address = __vma_address(page, vma); - if (unlikely(address < vma->vm_start || address >= vma->vm_end)) + } else if (vma->vm_file->f_mapping != compound_head(page)->mapping) { return -EFAULT; - return address; + } + + return vma_address(page, vma); } pmd_t *mm_find_pmd(struct mm_struct *mm, unsigned long address) @@ -912,7 +909,7 @@ static bool page_mkclean_one(struct page *page, struct vm_area_struct *vma, */ mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_PAGE, 0, vma, vma->vm_mm, address, - min(vma->vm_end, address + page_size(page))); + vma_address_end(page, vma)); mmu_notifier_invalidate_range_start(&range); while (page_vma_mapped_walk(&pvmw)) { @@ -1385,6 +1382,15 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, struct mmu_notifier_range range; enum ttu_flags flags = (enum ttu_flags)(long)arg; + /* + * When racing against e.g. zap_pte_range() on another cpu, + * in between its ptep_get_and_clear_full() and page_remove_rmap(), + * try_to_unmap() may return false when it is about to become true, + * if page table locking is skipped: use TTU_SYNC to wait for that. + */ + if (flags & TTU_SYNC) + pvmw.flags = PVMW_SYNC; + /* munlock has nothing to gain from examining un-locked vmas */ if ((flags & TTU_MUNLOCK) && !(vma->vm_flags & VM_LOCKED)) return true; @@ -1406,9 +1412,10 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, * Note that the page can not be free in this function as call of * try_to_unmap() must hold a reference on the page. */ + range.end = PageKsm(page) ? + address + PAGE_SIZE : vma_address_end(page, vma); mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma, vma->vm_mm, - address, - min(vma->vm_end, address + page_size(page))); + address, range.end); if (PageHuge(page)) { /* * If sharing is possible, start and end will be adjusted @@ -1716,9 +1723,9 @@ static bool invalid_migration_vma(struct vm_area_struct *vma, void *arg) return vma_is_temporary_stack(vma); } -static int page_mapcount_is_zero(struct page *page) +static int page_not_mapped(struct page *page) { - return !total_mapcount(page); + return !page_mapped(page); } /** @@ -1736,7 +1743,7 @@ bool try_to_unmap(struct page *page, enum ttu_flags flags) struct rmap_walk_control rwc = { .rmap_one = try_to_unmap_one, .arg = (void *)flags, - .done = page_mapcount_is_zero, + .done = page_not_mapped, .anon_lock = page_lock_anon_vma_read, }; @@ -1757,14 +1764,15 @@ bool try_to_unmap(struct page *page, enum ttu_flags flags) else rmap_walk(page, &rwc); - return !page_mapcount(page) ? true : false; + /* + * When racing against e.g. zap_pte_range() on another cpu, + * in between its ptep_get_and_clear_full() and page_remove_rmap(), + * try_to_unmap() may return false when it is about to become true, + * if page table locking is skipped: use TTU_SYNC to wait for that. + */ + return !page_mapcount(page); } -static int page_not_mapped(struct page *page) -{ - return !page_mapped(page); -}; - /** * try_to_munlock - try to munlock a page * @page: the page to be munlocked @@ -1859,6 +1867,7 @@ static void rmap_walk_anon(struct page *page, struct rmap_walk_control *rwc, struct vm_area_struct *vma = avc->vma; unsigned long address = vma_address(page, vma); + VM_BUG_ON_VMA(address == -EFAULT, vma); cond_resched(); if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) @@ -1913,6 +1922,7 @@ static void rmap_walk_file(struct page *page, struct rmap_walk_control *rwc, pgoff_start, pgoff_end) { unsigned long address = vma_address(page, vma); + VM_BUG_ON_VMA(address == -EFAULT, vma); cond_resched(); if (rwc->invalid_vma && rwc->invalid_vma(vma, rwc->arg)) diff --git a/mm/shmem.c b/mm/shmem.c index 6e487bf555f9ea937be9b96d38f4192f9da59dee..96df61c8af65344c1712d7b20b0b1afc3c4509ae 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1698,7 +1698,8 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index, struct address_space *mapping = inode->i_mapping; struct shmem_inode_info *info = SHMEM_I(inode); struct mm_struct *charge_mm = vma ? vma->vm_mm : current->mm; - struct page *page; + struct swap_info_struct *si; + struct page *page = NULL; swp_entry_t swap; int error; @@ -1706,6 +1707,12 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index, swap = radix_to_swp_entry(*pagep); *pagep = NULL; + /* Prevent swapoff from happening to us. */ + si = get_swap_device(swap); + if (!si) { + error = EINVAL; + goto failed; + } /* Look it up and read it in.. */ page = lookup_swap_cache(swap, NULL, 0); if (!page) { @@ -1767,6 +1774,8 @@ static int shmem_swapin_page(struct inode *inode, pgoff_t index, swap_free(swap); *pagep = page; + if (si) + put_swap_device(si); return 0; failed: if (!shmem_confirm_swap(mapping, index, swap)) @@ -1777,6 +1786,9 @@ unlock: put_page(page); } + if (si) + put_swap_device(si); + return error; } @@ -4080,8 +4092,7 @@ bool shmem_huge_enabled(struct vm_area_struct *vma) loff_t i_size; pgoff_t off; - if ((vma->vm_flags & VM_NOHUGEPAGE) || - test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags)) + if (!transhuge_vma_enabled(vma, vma->vm_flags)) return false; if (shmem_huge == SHMEM_HUGE_FORCE) return true; diff --git a/mm/slab.h b/mm/slab.h index e258ffcfb0ef2e6c88f31d4e2d66cdcf1a534ec6..944e8b2040ae21acbf63b7db87925cbded14caae 100644 --- a/mm/slab.h +++ b/mm/slab.h @@ -326,7 +326,6 @@ static inline void memcg_slab_post_alloc_hook(struct kmem_cache *s, if (!memcg_kmem_enabled() || !objcg) return; - flags &= ~__GFP_ACCOUNT; for (i = 0; i < size; i++) { if (likely(p[i])) { page = virt_to_head_page(p[i]); diff --git a/mm/truncate.c b/mm/truncate.c index 960edf5803ca97fa22e94d65ff76be49b8d4be3b..8914ca4ce4b1e0ce930d5e5ae37d74b05f8fe1af 100644 --- a/mm/truncate.c +++ b/mm/truncate.c @@ -173,13 +173,10 @@ void do_invalidatepage(struct page *page, unsigned int offset, * its lock, b) when a concurrent invalidate_mapping_pages got there first and * c) when tmpfs swizzles a page between a tmpfs inode and swapper_space. */ -static void -truncate_cleanup_page(struct address_space *mapping, struct page *page) +static void truncate_cleanup_page(struct page *page) { - if (page_mapped(page)) { - unsigned int nr = thp_nr_pages(page); - unmap_mapping_pages(mapping, page->index, nr, false); - } + if (page_mapped(page)) + unmap_mapping_page(page); if (page_has_private(page)) do_invalidatepage(page, 0, thp_size(page)); @@ -224,7 +221,7 @@ int truncate_inode_page(struct address_space *mapping, struct page *page) if (page->mapping != mapping) return -EIO; - truncate_cleanup_page(mapping, page); + truncate_cleanup_page(page); delete_from_page_cache(page); return 0; } @@ -362,7 +359,7 @@ void truncate_inode_pages_range(struct address_space *mapping, pagevec_add(&locked_pvec, page); } for (i = 0; i < pagevec_count(&locked_pvec); i++) - truncate_cleanup_page(mapping, locked_pvec.pages[i]); + truncate_cleanup_page(locked_pvec.pages[i]); delete_from_page_cache_batch(mapping, &locked_pvec); for (i = 0; i < pagevec_count(&locked_pvec); i++) unlock_page(locked_pvec.pages[i]); @@ -737,6 +734,16 @@ int invalidate_inode_pages2_range(struct address_space *mapping, continue; } + if (!did_range_unmap && page_mapped(page)) { + /* + * If page is mapped, before taking its lock, + * zap the rest of the file in one hit. + */ + unmap_mapping_pages(mapping, index, + (1 + end - index), false); + did_range_unmap = 1; + } + lock_page(page); WARN_ON(page_to_index(page) != index); if (page->mapping != mapping) { @@ -744,23 +751,11 @@ int invalidate_inode_pages2_range(struct address_space *mapping, continue; } wait_on_page_writeback(page); - if (page_mapped(page)) { - if (!did_range_unmap) { - /* - * Zap the rest of the file in one hit. - */ - unmap_mapping_pages(mapping, index, - (1 + end - index), false); - did_range_unmap = 1; - } else { - /* - * Just zap this page - */ - unmap_mapping_pages(mapping, index, - 1, false); - } - } + + if (page_mapped(page)) + unmap_mapping_page(page); BUG_ON(page_mapped(page)); + ret2 = do_launder_page(mapping, page); if (ret2 == 0) { if (!invalidate_complete_page2(mapping, page)) diff --git a/mm/z3fold.c b/mm/z3fold.c index 8ae944eeb8e20de6560146c87c13512b5e2e5c31..912ac9a64a155d1cd14a30eefb2bfa8700815715 100644 --- a/mm/z3fold.c +++ b/mm/z3fold.c @@ -1063,6 +1063,7 @@ static void z3fold_destroy_pool(struct z3fold_pool *pool) destroy_workqueue(pool->compact_wq); destroy_workqueue(pool->release_wq); z3fold_unregister_migration(pool); + free_percpu(pool->unbuddied); kfree(pool); } @@ -1386,7 +1387,7 @@ static int z3fold_reclaim_page(struct z3fold_pool *pool, unsigned int retries) if (zhdr->foreign_handles || test_and_set_bit(PAGE_CLAIMED, &page->private)) { if (kref_put(&zhdr->refcount, - release_z3fold_page)) + release_z3fold_page_locked)) atomic64_dec(&pool->pages_nr); else z3fold_page_unlock(zhdr); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 86ebfc6ae6986195f0a16f353210d3cdcb1004b6..0854f1b35683ca7e057842d47915e82207cd05d8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1713,14 +1713,6 @@ int hci_dev_do_close(struct hci_dev *hdev) BT_DBG("%s %p", hdev->name, hdev); - if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && - !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && - test_bit(HCI_UP, &hdev->flags)) { - /* Execute vendor specific shutdown routine */ - if (hdev->shutdown) - hdev->shutdown(hdev); - } - cancel_delayed_work(&hdev->power_off); hci_request_cancel_all(hdev); @@ -1796,6 +1788,14 @@ int hci_dev_do_close(struct hci_dev *hdev) clear_bit(HCI_INIT, &hdev->flags); } + if (!hci_dev_test_flag(hdev, HCI_UNREGISTER) && + !hci_dev_test_flag(hdev, HCI_USER_CHANNEL) && + test_bit(HCI_UP, &hdev->flags)) { + /* Execute vendor specific shutdown routine */ + if (hdev->shutdown) + hdev->shutdown(hdev); + } + /* flush cmd work */ flush_work(&hdev->cmd_work); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4676e4b0be2bf38315093e127bbf25cf8cb12f0a..e59ae24a8f17f350aaa4c02e6910a6c2b9130db1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4360,12 +4360,12 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode); - switch (conn->setting & SCO_AIRMODE_MASK) { - case SCO_AIRMODE_CVSD: + switch (ev->air_mode) { + case 0x02: if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD); break; - case SCO_AIRMODE_TRANSP: + case 0x03: if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_TRANSP); break; @@ -5256,8 +5256,19 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); - if (ev->status) + if (ev->status) { + struct adv_info *adv; + + adv = hci_find_adv_instance(hdev, ev->handle); + if (!adv) + return; + + /* Remove advertising as it has been terminated */ + hci_remove_adv_instance(hdev, ev->handle); + mgmt_advertising_removed(NULL, hdev, ev->handle); + return; + } conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle)); if (conn) { @@ -5401,7 +5412,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, struct hci_conn *conn; bool match; u32 flags; - u8 *ptr, real_len; + u8 *ptr; switch (type) { case LE_ADV_IND: @@ -5432,14 +5443,10 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, break; } - real_len = ptr - data; - - /* Adjust for actual length */ - if (len != real_len) { - bt_dev_err_ratelimited(hdev, "advertising data len corrected %u -> %u", - len, real_len); - len = real_len; - } + /* Adjust for actual length. This handles the case when remote + * device is advertising with incorrect data length. + */ + len = ptr - data; /* If the direct address is present, then this report is from * a LE Direct Advertising Report event. In that case it is diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 161ea93a5382849acf817384dab756732420a158..1a94ed2f8a4f8ebe72a706f01f9472b67b3e92e6 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1060,9 +1060,10 @@ static u8 get_adv_instance_scan_rsp_len(struct hci_dev *hdev, u8 instance) if (!adv_instance) return 0; - /* TODO: Take into account the "appearance" and "local-name" flags here. - * These are currently being ignored as they are not supported. - */ + if (adv_instance->flags & MGMT_ADV_FLAG_APPEARANCE || + adv_instance->flags & MGMT_ADV_FLAG_LOCAL_NAME) + return 1; + return adv_instance->scan_rsp_len; } @@ -1595,33 +1596,33 @@ void __hci_req_update_scan_rsp_data(struct hci_request *req, u8 instance) return; if (ext_adv_capable(hdev)) { - struct hci_cp_le_set_ext_scan_rsp_data cp; + struct { + struct hci_cp_le_set_ext_scan_rsp_data cp; + u8 data[HCI_MAX_EXT_AD_LENGTH]; + } pdu; - memset(&cp, 0, sizeof(cp)); + memset(&pdu, 0, sizeof(pdu)); - /* Extended scan response data doesn't allow a response to be - * set if the instance isn't scannable. - */ - if (get_adv_instance_scan_rsp_len(hdev, instance)) + if (instance) len = create_instance_scan_rsp_data(hdev, instance, - cp.data); + pdu.data); else - len = 0; + len = create_default_scan_rsp_data(hdev, pdu.data); if (hdev->scan_rsp_data_len == len && - !memcmp(cp.data, hdev->scan_rsp_data, len)) + !memcmp(pdu.data, hdev->scan_rsp_data, len)) return; - memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data)); + memcpy(hdev->scan_rsp_data, pdu.data, len); hdev->scan_rsp_data_len = len; - cp.handle = instance; - cp.length = len; - cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; - cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; + pdu.cp.handle = instance; + pdu.cp.length = len; + pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; + pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; - hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, sizeof(cp), - &cp); + hci_req_add(req, HCI_OP_LE_SET_EXT_SCAN_RSP_DATA, + sizeof(pdu.cp) + len, &pdu.cp); } else { struct hci_cp_le_set_scan_rsp_data cp; @@ -1744,26 +1745,30 @@ void __hci_req_update_adv_data(struct hci_request *req, u8 instance) return; if (ext_adv_capable(hdev)) { - struct hci_cp_le_set_ext_adv_data cp; + struct { + struct hci_cp_le_set_ext_adv_data cp; + u8 data[HCI_MAX_EXT_AD_LENGTH]; + } pdu; - memset(&cp, 0, sizeof(cp)); + memset(&pdu, 0, sizeof(pdu)); - len = create_instance_adv_data(hdev, instance, cp.data); + len = create_instance_adv_data(hdev, instance, pdu.data); /* There's nothing to do if the data hasn't changed */ if (hdev->adv_data_len == len && - memcmp(cp.data, hdev->adv_data, len) == 0) + memcmp(pdu.data, hdev->adv_data, len) == 0) return; - memcpy(hdev->adv_data, cp.data, sizeof(cp.data)); + memcpy(hdev->adv_data, pdu.data, len); hdev->adv_data_len = len; - cp.length = len; - cp.handle = instance; - cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; - cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; + pdu.cp.length = len; + pdu.cp.handle = instance; + pdu.cp.operation = LE_SET_ADV_DATA_OP_COMPLETE; + pdu.cp.frag_pref = LE_SET_ADV_DATA_NO_FRAG; - hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, sizeof(cp), &cp); + hci_req_add(req, HCI_OP_LE_SET_EXT_ADV_DATA, + sizeof(pdu.cp) + len, &pdu.cp); } else { struct hci_cp_le_set_adv_data cp; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cdc3863371739f4c8dd6c25e1689a011f2dca892..0ddbc415ce156f948ce8ccd3727c953736072ff0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6055,7 +6055,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, struct l2cap_ecred_conn_rsp *rsp = (void *) data; struct hci_conn *hcon = conn->hcon; u16 mtu, mps, credits, result; - struct l2cap_chan *chan; + struct l2cap_chan *chan, *tmp; int err = 0, sec_level; int i = 0; @@ -6074,7 +6074,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, cmd_len -= sizeof(*rsp); - list_for_each_entry(chan, &conn->chan_l, list) { + list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { u16 dcid; if (chan->ident != cmd->ident || @@ -6237,7 +6237,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) { - struct l2cap_chan *chan; + struct l2cap_chan *chan, *tmp; struct l2cap_ecred_conn_rsp *rsp = (void *) data; u16 result; @@ -6251,7 +6251,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, if (!result) return 0; - list_for_each_entry(chan, &conn->chan_l, list) { + list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { if (chan->ident != cmd->ident) continue; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 12d7b368b428e84a4a3866e40182db7c006732a7..31a585fe0c7c61eb3296dab064668ca82f9bb4ab 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -247,12 +247,15 @@ static const u8 mgmt_status_table[] = { MGMT_STATUS_TIMEOUT, /* Instant Passed */ MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */ MGMT_STATUS_FAILED, /* Transaction Collision */ + MGMT_STATUS_FAILED, /* Reserved for future use */ MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */ MGMT_STATUS_REJECTED, /* QoS Rejected */ MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */ MGMT_STATUS_REJECTED, /* Insufficient Security */ MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */ + MGMT_STATUS_FAILED, /* Reserved for future use */ MGMT_STATUS_BUSY, /* Role Switch Pending */ + MGMT_STATUS_FAILED, /* Reserved for future use */ MGMT_STATUS_FAILED, /* Slot Violation */ MGMT_STATUS_FAILED, /* Role Switch Failed */ MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */ @@ -4035,6 +4038,8 @@ static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data, hci_dev_lock(hdev); + memset(&rp, 0, sizeof(rp)); + if (cp->addr.type == BDADDR_BREDR) { br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist, &cp->addr.bdaddr, @@ -7350,6 +7355,9 @@ static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data, for (i = 0, cur_len = 0; i < len; i += (cur_len + 1)) { cur_len = data[i]; + if (!cur_len) + continue; + if (data[i + 1] == EIR_FLAGS && (!is_adv_data || flags_managed(adv_flags))) return false; diff --git a/net/bpfilter/main.c b/net/bpfilter/main.c index 05e1cfc1e5cd114c544e224cea28d530f70243a7..291a925462463df20df39534041c71c421aa6db1 100644 --- a/net/bpfilter/main.c +++ b/net/bpfilter/main.c @@ -57,7 +57,7 @@ int main(void) { debug_f = fopen("/dev/kmsg", "w"); setvbuf(debug_f, 0, _IOLBF, 0); - fprintf(debug_f, "Started bpfilter\n"); + fprintf(debug_f, "<5>Started bpfilter\n"); loop(); fclose(debug_f); return 0; diff --git a/net/bridge/br_mrp.c b/net/bridge/br_mrp.c index d1336a7ad7ff2da8386e00f3ec9c49b27373b723..3259f5480127a37f88b62ffa6500e8c9a9c4f0b7 100644 --- a/net/bridge/br_mrp.c +++ b/net/bridge/br_mrp.c @@ -607,8 +607,7 @@ int br_mrp_set_ring_state(struct net_bridge *br, if (!mrp) return -EINVAL; - if (mrp->ring_state == BR_MRP_RING_STATE_CLOSED && - state->ring_state != BR_MRP_RING_STATE_CLOSED) + if (mrp->ring_state != state->ring_state) mrp->ring_transitions++; mrp->ring_state = state->ring_state; @@ -690,8 +689,7 @@ int br_mrp_set_in_state(struct net_bridge *br, struct br_mrp_in_state *state) if (!mrp) return -EINVAL; - if (mrp->in_state == BR_MRP_IN_STATE_CLOSED && - state->in_state != BR_MRP_IN_STATE_CLOSED) + if (mrp->in_state != state->in_state) mrp->in_transitions++; mrp->in_state = state->in_state; diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 5015ece7adf7a072d8f8bb636dcf9aad44eb7159..e5328a2777ecd038d1b0474166e89cce4b956999 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c @@ -2998,7 +2998,9 @@ static void br_multicast_pim(struct net_bridge *br, pim_hdr_type(pimhdr) != PIM_TYPE_HELLO) return; + spin_lock(&br->multicast_lock); br_multicast_mark_router(br, port); + spin_unlock(&br->multicast_lock); } static int br_ip4_multicast_mrd_rcv(struct net_bridge *br, @@ -3009,7 +3011,9 @@ static int br_ip4_multicast_mrd_rcv(struct net_bridge *br, igmp_hdr(skb)->type != IGMP_MRDISC_ADV) return -ENOMSG; + spin_lock(&br->multicast_lock); br_multicast_mark_router(br, port); + spin_unlock(&br->multicast_lock); return 0; } @@ -3077,7 +3081,9 @@ static void br_ip6_multicast_mrd_rcv(struct net_bridge *br, if (icmp6_hdr(skb)->icmp6_type != ICMPV6_MRDISC_ADV) return; + spin_lock(&br->multicast_lock); br_multicast_mark_router(br, port); + spin_unlock(&br->multicast_lock); } static int br_multicast_ipv6_rcv(struct net_bridge *br, diff --git a/net/can/bcm.c b/net/can/bcm.c index f3e4d9528fa38787563ddbdce0375e1f417436d8..0928a39c4423bcbca3d03fffc493950162aecb37 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -785,6 +785,7 @@ static int bcm_delete_rx_op(struct list_head *ops, struct bcm_msg_head *mh, bcm_rx_handler, op); list_del(&op->list); + synchronize_rcu(); bcm_remove_op(op); return 1; /* done */ } @@ -1533,9 +1534,13 @@ static int bcm_release(struct socket *sock) REGMASK(op->can_id), bcm_rx_handler, op); - bcm_remove_op(op); } + synchronize_rcu(); + + list_for_each_entry_safe(op, next, &bo->rx_ops, list) + bcm_remove_op(op); + #if IS_ENABLED(CONFIG_PROC_FS) /* remove procfs entry */ if (net->can.bcmproc_dir && bo->bcm_proc_read) diff --git a/net/can/gw.c b/net/can/gw.c index 6b790b6ff8d2653298535b71bd5aeabcd5a0b545..cbb46d3aa963442e0b4319de0bf7e61b4e8c77de 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -534,6 +534,7 @@ static int cgw_notifier(struct notifier_block *nb, if (gwj->src.dev == dev || gwj->dst.dev == dev) { hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); + synchronize_rcu(); kmem_cache_free(cgw_cache, gwj); } } @@ -1092,6 +1093,7 @@ static void cgw_remove_all_jobs(struct net *net) hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) { hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); + synchronize_rcu(); kmem_cache_free(cgw_cache, gwj); } } @@ -1160,6 +1162,7 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); + synchronize_rcu(); kmem_cache_free(cgw_cache, gwj); err = 0; break; diff --git a/net/can/isotp.c b/net/can/isotp.c index 1adefb14527d85b034c60d2cb71c48b1ee4e8088..5fc28f190677bee615a60a6bbb85341b5251b291 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -1023,9 +1023,6 @@ static int isotp_release(struct socket *sock) lock_sock(sk); - hrtimer_cancel(&so->txtimer); - hrtimer_cancel(&so->rxtimer); - /* remove current filters & unregister */ if (so->bound) { if (so->ifindex) { @@ -1037,10 +1034,14 @@ static int isotp_release(struct socket *sock) SINGLE_MASK(so->rxid), isotp_rcv, sk); dev_put(dev); + synchronize_rcu(); } } } + hrtimer_cancel(&so->txtimer); + hrtimer_cancel(&so->rxtimer); + so->ifindex = 0; so->bound = 0; diff --git a/net/can/j1939/main.c b/net/can/j1939/main.c index e52330f628c9fac69500f13343a429b080e61bf9..6884d18f919c74c2df226a1bbcaf2c29fcbeb05c 100644 --- a/net/can/j1939/main.c +++ b/net/can/j1939/main.c @@ -193,6 +193,10 @@ static void j1939_can_rx_unregister(struct j1939_priv *priv) can_rx_unregister(dev_net(ndev), ndev, J1939_CAN_ID, J1939_CAN_MASK, j1939_can_recv, priv); + /* The last reference of priv is dropped by the RCU deferred + * j1939_sk_sock_destruct() of the last socket, so we can + * safely drop this reference here. + */ j1939_priv_put(priv); } diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c index 56aa66147d5acb2020ef46e2677545c73bb705fb..e1a399821238f028f73a26a85bf43255f69af2d2 100644 --- a/net/can/j1939/socket.c +++ b/net/can/j1939/socket.c @@ -398,6 +398,9 @@ static int j1939_sk_init(struct sock *sk) atomic_set(&jsk->skb_pending, 0); spin_lock_init(&jsk->sk_session_queue_lock); INIT_LIST_HEAD(&jsk->sk_session_queue); + + /* j1939_sk_sock_destruct() depends on SOCK_RCU_FREE flag */ + sock_set_flag(sk, SOCK_RCU_FREE); sk->sk_destruct = j1939_sk_sock_destruct; sk->sk_protocol = CAN_J1939; @@ -673,7 +676,7 @@ static int j1939_sk_setsockopt(struct socket *sock, int level, int optname, switch (optname) { case SO_J1939_FILTER: - if (!sockptr_is_null(optval)) { + if (!sockptr_is_null(optval) && optlen != 0) { struct j1939_filter *f; int c; diff --git a/net/core/dev.c b/net/core/dev.c index 73d7b423211b5e0fb9e8896fc1ab1955e24f9bb8..127f0c08207b58f75b87154c1951fc48de75f807 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6456,11 +6456,18 @@ EXPORT_SYMBOL(napi_schedule_prep); * __napi_schedule_irqoff - schedule for receive * @n: entry to schedule * - * Variant of __napi_schedule() assuming hard irqs are masked + * Variant of __napi_schedule() assuming hard irqs are masked. + * + * On PREEMPT_RT enabled kernels this maps to __napi_schedule() + * because the interrupt disabled assumption might not be true + * due to force-threaded interrupts and spinlock substitution. */ void __napi_schedule_irqoff(struct napi_struct *n) { - ____napi_schedule(this_cpu_ptr(&softnet_data), n); + if (!IS_ENABLED(CONFIG_PREEMPT_RT)) + ____napi_schedule(this_cpu_ptr(&softnet_data), n); + else + __napi_schedule(n); } EXPORT_SYMBOL(__napi_schedule_irqoff); diff --git a/net/core/filter.c b/net/core/filter.c index ef6bdbb63ecbba0c140aa3a6138f73888a66a8eb..7ea752af7894d791f9f4c54e05f2d93cb6170f63 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -3266,8 +3266,6 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb) shinfo->gso_type |= SKB_GSO_TCPV6; } - /* Due to IPv6 header, MSS needs to be downgraded. */ - skb_decrease_gso_size(shinfo, len_diff); /* Header must be checked, and gso_segs recomputed. */ shinfo->gso_type |= SKB_GSO_DODGY; shinfo->gso_segs = 0; @@ -3307,8 +3305,6 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb) shinfo->gso_type |= SKB_GSO_TCPV4; } - /* Due to IPv4 header, MSS can be upgraded. */ - skb_increase_gso_size(shinfo, len_diff); /* Header must be checked, and gso_segs recomputed. */ shinfo->gso_type |= SKB_GSO_DODGY; shinfo->gso_segs = 0; diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 2917af3f5ac191e62416eb4bff1f92f17d1acf71..68ff19af195c6db1e6983aadbd17e73762498d34 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -1421,7 +1421,7 @@ static int ethtool_get_any_eeprom(struct net_device *dev, void __user *useraddr, if (eeprom.offset + eeprom.len > total_len) return -EINVAL; - data = kmalloc(PAGE_SIZE, GFP_USER); + data = kzalloc(PAGE_SIZE, GFP_USER); if (!data) return -ENOMEM; @@ -1486,7 +1486,7 @@ static int ethtool_set_eeprom(struct net_device *dev, void __user *useraddr) if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) return -EINVAL; - data = kmalloc(PAGE_SIZE, GFP_USER); + data = kzalloc(PAGE_SIZE, GFP_USER); if (!data) return -ENOMEM; @@ -1765,7 +1765,7 @@ static int ethtool_self_test(struct net_device *dev, char __user *useraddr) return -EFAULT; test.len = test_len; - data = kmalloc_array(test_len, sizeof(u64), GFP_USER); + data = kcalloc(test_len, sizeof(u64), GFP_USER); if (!data) return -ENOMEM; @@ -2281,7 +2281,7 @@ static int ethtool_get_tunable(struct net_device *dev, void __user *useraddr) ret = ethtool_tunable_valid(&tuna); if (ret) return ret; - data = kmalloc(tuna.len, GFP_USER); + data = kzalloc(tuna.len, GFP_USER); if (!data) return -ENOMEM; ret = ops->get_tunable(dev, &tuna, data); @@ -2473,7 +2473,7 @@ static int get_phy_tunable(struct net_device *dev, void __user *useraddr) ret = ethtool_phy_tunable_valid(&tuna); if (ret) return ret; - data = kmalloc(tuna.len, GFP_USER); + data = kzalloc(tuna.len, GFP_USER); if (!data) return -ENOMEM; if (phy_drv_tunable) { diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index b7260c8cef2e5dea4c34b80e6728f85805dc40e9..8267349afe231aca3269b4d24be025fb9b08cbf3 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -572,7 +572,7 @@ int inet_dgram_connect(struct socket *sock, struct sockaddr *uaddr, return err; } - if (!inet_sk(sk)->inet_num && inet_autobind(sk)) + if (data_race(!inet_sk(sk)->inet_num) && inet_autobind(sk)) return -EAGAIN; return sk->sk_prot->connect(sk, uaddr, addr_len); } @@ -799,7 +799,7 @@ int inet_send_prepare(struct sock *sk) sock_rps_record_flow(sk); /* We may need to bind the socket. */ - if (!inet_sk(sk)->inet_num && !sk->sk_prot->no_autobind && + if (data_race(!inet_sk(sk)->inet_num) && !sk->sk_prot->no_autobind && inet_autobind(sk)) return -EAGAIN; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 123a6d39438f8dc04c4745c7063c8ba22ec50b7a..7c185977742974829dfb02b8068b8ddb2bc350e6 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1989,7 +1989,7 @@ static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla) return -EAFNOSUPPORT; if (nla_parse_nested_deprecated(tb, IFLA_INET_MAX, nla, NULL, NULL) < 0) - BUG(); + return -EINVAL; if (tb[IFLA_INET_CONF]) { nla_for_each_nested(a, tb[IFLA_INET_CONF], rem) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 4b834bbf95e074d215d32bc6354fe83e2db2dc34..ed9857b2875dcfbd302f96711396419cc83d10eb 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -673,7 +673,7 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); u32 padto; - padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); + padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached)); if (skb->len < padto) esp.tfclen = padto - skb->len; } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 84bb707bd88d84218b9b67996ed26f7c1423ade1..647bceab56c2d56470488865912b0e69b43bb9bc 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -371,6 +371,8 @@ static int __fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, fl4.flowi4_proto = 0; fl4.fl4_sport = 0; fl4.fl4_dport = 0; + } else { + swap(fl4.fl4_sport, fl4.fl4_dport); } if (fib_lookup(net, &fl4, &res, 0)) diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 97975bed491addd6bfbe461298a1ce7264f845d7..560d5dc43562936667c2cb023311e2188864465a 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -1053,7 +1053,7 @@ static int __ip_append_data(struct sock *sk, unsigned int datalen; unsigned int fraglen; unsigned int fraggap; - unsigned int alloclen; + unsigned int alloclen, alloc_extra; unsigned int pagedlen; struct sk_buff *skb_prev; alloc_new_skb: @@ -1073,35 +1073,39 @@ alloc_new_skb: fraglen = datalen + fragheaderlen; pagedlen = 0; + alloc_extra = hh_len + 15; + alloc_extra += exthdrlen; + + /* The last fragment gets additional space at tail. + * Note, with MSG_MORE we overallocate on fragments, + * because we have no idea what fragment will be + * the last. + */ + if (datalen == length + fraggap) + alloc_extra += rt->dst.trailer_len; + if ((flags & MSG_MORE) && !(rt->dst.dev->features&NETIF_F_SG)) alloclen = mtu; - else if (!paged) + else if (!paged && + (fraglen + alloc_extra < SKB_MAX_ALLOC || + !(rt->dst.dev->features & NETIF_F_SG))) alloclen = fraglen; else { alloclen = min_t(int, fraglen, MAX_HEADER); pagedlen = fraglen - alloclen; } - alloclen += exthdrlen; - - /* The last fragment gets additional space at tail. - * Note, with MSG_MORE we overallocate on fragments, - * because we have no idea what fragment will be - * the last. - */ - if (datalen == length + fraggap) - alloclen += rt->dst.trailer_len; + alloclen += alloc_extra; if (transhdrlen) { - skb = sock_alloc_send_skb(sk, - alloclen + hh_len + 15, + skb = sock_alloc_send_skb(sk, alloclen, (flags & MSG_DONTWAIT), &err); } else { skb = NULL; if (refcount_read(&sk->sk_wmem_alloc) + wmem_alloc_delta <= 2 * sk->sk_sndbuf) - skb = alloc_skb(alloclen + hh_len + 15, + skb = alloc_skb(alloclen, sk->sk_allocation); if (unlikely(!skb)) err = -ENOBUFS; diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 248856b301c4570268b006b691889ce9ac74cd09..8ce8b7300b9d3eaa47a56096a43498518176598a 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -952,6 +952,7 @@ bool ping_rcv(struct sk_buff *skb) struct sock *sk; struct net *net = dev_net(skb->dev); struct icmphdr *icmph = icmp_hdr(skb); + bool rc = false; /* We assume the packet has already been checked by icmp_rcv */ @@ -966,14 +967,15 @@ bool ping_rcv(struct sk_buff *skb) struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); pr_debug("rcv on socket %p\n", sk); - if (skb2) - ping_queue_rcv_skb(sk, skb2); + if (skb2 && !ping_queue_rcv_skb(sk, skb2)) + rc = true; sock_put(sk); - return true; } - pr_debug("no socket, dropping\n"); - return false; + if (!rc) + pr_debug("no socket, dropping\n"); + + return rc; } EXPORT_SYMBOL_GPL(ping_rcv); diff --git a/net/ipv4/route.c b/net/ipv4/route.c index e968bb47d5bd8adaf5955ab5288f0f4112eee88e..e15c1d8b7c8de089f02e7f1383dc30128e68d906 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1327,7 +1327,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) mtu = dst_metric_raw(dst, RTAX_MTU); if (mtu) - return mtu; + goto out; mtu = READ_ONCE(dst->dev->mtu); @@ -1336,6 +1336,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) mtu = 576; } +out: mtu = min_t(unsigned int, mtu, IP_MAX_MTU); return mtu - lwtunnel_headroom(dst->lwtstate, mtu); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index fac5c1469ceee232e3aaed0669fa3bdcdfb851b3..4d4b641c204d44ca77e0eddf87631762b04e4404 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2802,8 +2802,17 @@ static void tcp_process_loss(struct sock *sk, int flag, int num_dupack, *rexmit = REXMIT_LOST; } +static bool tcp_force_fast_retransmit(struct sock *sk) +{ + struct tcp_sock *tp = tcp_sk(sk); + + return after(tcp_highest_sack_seq(tp), + tp->snd_una + tp->reordering * tp->mss_cache); +} + /* Undo during fast recovery after partial ACK. */ -static bool tcp_try_undo_partial(struct sock *sk, u32 prior_snd_una) +static bool tcp_try_undo_partial(struct sock *sk, u32 prior_snd_una, + bool *do_lost) { struct tcp_sock *tp = tcp_sk(sk); @@ -2828,7 +2837,9 @@ static bool tcp_try_undo_partial(struct sock *sk, u32 prior_snd_una) tcp_undo_cwnd_reduction(sk, true); NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPPARTIALUNDO); tcp_try_keep_open(sk); - return true; + } else { + /* Partial ACK arrived. Force fast retransmit. */ + *do_lost = tcp_force_fast_retransmit(sk); } return false; } @@ -2852,14 +2863,6 @@ static void tcp_identify_packet_loss(struct sock *sk, int *ack_flag) } } -static bool tcp_force_fast_retransmit(struct sock *sk) -{ - struct tcp_sock *tp = tcp_sk(sk); - - return after(tcp_highest_sack_seq(tp), - tp->snd_una + tp->reordering * tp->mss_cache); -} - /* Process an event, which can update packets-in-flight not trivially. * Main goal of this function is to calculate new estimate for left_out, * taking into account both packets sitting in receiver's buffer and @@ -2929,17 +2932,21 @@ static void tcp_fastretrans_alert(struct sock *sk, const u32 prior_snd_una, if (!(flag & FLAG_SND_UNA_ADVANCED)) { if (tcp_is_reno(tp)) tcp_add_reno_sack(sk, num_dupack, ece_ack); - } else { - if (tcp_try_undo_partial(sk, prior_snd_una)) - return; - /* Partial ACK arrived. Force fast retransmit. */ - do_lost = tcp_force_fast_retransmit(sk); - } - if (tcp_try_undo_dsack(sk)) { - tcp_try_keep_open(sk); + } else if (tcp_try_undo_partial(sk, prior_snd_una, &do_lost)) return; - } + + if (tcp_try_undo_dsack(sk)) + tcp_try_keep_open(sk); + tcp_identify_packet_loss(sk, ack_flag); + if (icsk->icsk_ca_state != TCP_CA_Recovery) { + if (!tcp_time_to_recover(sk, flag)) + return; + /* Undo reverts the recovery state. If loss is evident, + * starts a new recovery (e.g. reordering then loss); + */ + tcp_enter_recovery(sk, ece_ack); + } break; case TCP_CA_Loss: tcp_process_loss(sk, flag, num_dupack, rexmit); diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 4c881f5d9080c389bd6422a15385d21d91e021b7..884d430e23cb36c3888618e7b7dd1ce8bae11764 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -5799,7 +5799,7 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) return -EAFNOSUPPORT; if (nla_parse_nested_deprecated(tb, IFLA_INET6_MAX, nla, NULL, NULL) < 0) - BUG(); + return -EINVAL; if (tb[IFLA_INET6_TOKEN]) { err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 4071cb7c7a154a335b6044b1429739b82de553ae..8d001f665fb15da8f171d81e6a9040b4a05e2460 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -708,7 +708,7 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb) struct xfrm_dst *dst = (struct xfrm_dst *)skb_dst(skb); u32 padto; - padto = min(x->tfcpad, xfrm_state_mtu(x, dst->child_mtu_cached)); + padto = min(x->tfcpad, __xfrm_state_mtu(x, dst->child_mtu_cached)); if (skb->len < padto) esp.tfclen = padto - skb->len; } diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 374105e4394f85396f2604f45f29caa1eeb59e92..4932dea9820ba83a085392f01d02ed445834d7ea 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c @@ -135,18 +135,23 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, len -= 2; while (len > 0) { - int optlen = nh[off + 1] + 2; - int i; + int optlen, i; - switch (nh[off]) { - case IPV6_TLV_PAD1: - optlen = 1; + if (nh[off] == IPV6_TLV_PAD1) { padlen++; if (padlen > 7) goto bad; - break; + off++; + len--; + continue; + } + if (len < 2) + goto bad; + optlen = nh[off + 1] + 2; + if (optlen > len) + goto bad; - case IPV6_TLV_PADN: + if (nh[off] == IPV6_TLV_PADN) { /* RFC 2460 states that the purpose of PadN is * to align the containing header to multiples * of 8. 7 is therefore the highest valid value. @@ -163,12 +168,7 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, if (nh[off + i] != 0) goto bad; } - break; - - default: /* Other TLV code so scan list */ - if (optlen > len) - goto bad; - + } else { tlv_count++; if (tlv_count > max_count) goto bad; @@ -188,7 +188,6 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs, return false; padlen = 0; - break; } off += optlen; len -= optlen; @@ -306,7 +305,7 @@ fail_and_free: #endif if (ip6_parse_tlv(tlvprocdestopt_lst, skb, - init_net.ipv6.sysctl.max_dst_opts_cnt)) { + net->ipv6.sysctl.max_dst_opts_cnt)) { skb->transport_header += extlen; opt = IP6CB(skb); #if IS_ENABLED(CONFIG_IPV6_MIP6) @@ -1041,7 +1040,7 @@ fail_and_free: opt->flags |= IP6SKB_HOPBYHOP; if (ip6_parse_tlv(tlvprochopopt_lst, skb, - init_net.ipv6.sysctl.max_hbh_opts_cnt)) { + net->ipv6.sysctl.max_hbh_opts_cnt)) { skb->transport_header += extlen; opt = IP6CB(skb); opt->nhoff = sizeof(struct ipv6hdr); diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 077d43af8226bd202be878885eaaf274776bf648..e889655ca0e2042c903ae5a5bfe4a39aa537af76 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1554,7 +1554,7 @@ emsgsize: unsigned int datalen; unsigned int fraglen; unsigned int fraggap; - unsigned int alloclen; + unsigned int alloclen, alloc_extra; unsigned int pagedlen; alloc_new_skb: /* There's no room in the current skb */ @@ -1581,17 +1581,28 @@ alloc_new_skb: fraglen = datalen + fragheaderlen; pagedlen = 0; + alloc_extra = hh_len; + alloc_extra += dst_exthdrlen; + alloc_extra += rt->dst.trailer_len; + + /* We just reserve space for fragment header. + * Note: this may be overallocation if the message + * (without MSG_MORE) fits into the MTU. + */ + alloc_extra += sizeof(struct frag_hdr); + if ((flags & MSG_MORE) && !(rt->dst.dev->features&NETIF_F_SG)) alloclen = mtu; - else if (!paged) + else if (!paged && + (fraglen + alloc_extra < SKB_MAX_ALLOC || + !(rt->dst.dev->features & NETIF_F_SG))) alloclen = fraglen; else { alloclen = min_t(int, fraglen, MAX_HEADER); pagedlen = fraglen - alloclen; } - - alloclen += dst_exthdrlen; + alloclen += alloc_extra; if (datalen != length + fraggap) { /* @@ -1601,30 +1612,21 @@ alloc_new_skb: datalen += rt->dst.trailer_len; } - alloclen += rt->dst.trailer_len; fraglen = datalen + fragheaderlen; - /* - * We just reserve space for fragment header. - * Note: this may be overallocation if the message - * (without MSG_MORE) fits into the MTU. - */ - alloclen += sizeof(struct frag_hdr); - copy = datalen - transhdrlen - fraggap - pagedlen; if (copy < 0) { err = -EINVAL; goto error; } if (transhdrlen) { - skb = sock_alloc_send_skb(sk, - alloclen + hh_len, + skb = sock_alloc_send_skb(sk, alloclen, (flags & MSG_DONTWAIT), &err); } else { skb = NULL; if (refcount_read(&sk->sk_wmem_alloc) + wmem_alloc_delta <= 2 * sk->sk_sndbuf) - skb = alloc_skb(alloclen + hh_len, + skb = alloc_skb(alloclen, sk->sk_allocation); if (unlikely(!skb)) err = -ENOBUFS; diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 42ca2d05c480dec3d612fd7f5ce1967d4da640dc..08441f06afd482066fa1381f8f0d1fb436a1d73d 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -1270,8 +1270,6 @@ route_lookup: if (max_headroom > dev->needed_headroom) dev->needed_headroom = max_headroom; - skb_set_inner_ipproto(skb, proto); - err = ip6_tnl_encap(skb, t, &proto, fl6); if (err) return err; @@ -1408,6 +1406,8 @@ ipxip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev, if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6)) return -1; + skb_set_inner_ipproto(skb, protocol); + err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu, protocol); if (err != 0) { diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index af36acc1a6448104ca6c71854e84b1a4bab4b3ea..2880dc7d9a491682bfea59757593d07178874b56 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c @@ -15,29 +15,11 @@ static u32 __ipv6_select_ident(struct net *net, const struct in6_addr *dst, const struct in6_addr *src) { - const struct { - struct in6_addr dst; - struct in6_addr src; - } __aligned(SIPHASH_ALIGNMENT) combined = { - .dst = *dst, - .src = *src, - }; - u32 hash, id; - - /* Note the following code is not safe, but this is okay. */ - if (unlikely(siphash_key_is_zero(&net->ipv4.ip_id_key))) - get_random_bytes(&net->ipv4.ip_id_key, - sizeof(net->ipv4.ip_id_key)); - - hash = siphash(&combined, sizeof(combined), &net->ipv4.ip_id_key); - - /* Treat id of 0 as unset and if we get 0 back from ip_idents_reserve, - * set the hight order instead thus minimizing possible future - * collisions. - */ - id = ip_idents_reserve(hash, 1); - if (unlikely(!id)) - id = 1 << 31; + u32 id; + + do { + id = prandom_u32(); + } while (!id); return id; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index be40f6b16199f7829acd76c7a7814f277b0cdb51..a83f0c2fcdf77c4a8ec26c32740e380c2024a851 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1445,7 +1445,7 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata) rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (WARN_ON_ONCE(!chanctx_conf)) { + if (!chanctx_conf) { rcu_read_unlock(); return NULL; } diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 6d3220c66931aa95d1b19986846c92b8ccb3c6f5..142bb28199c4832a3052300b671bcb8daf099f61 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1094,11 +1094,6 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local, struct ieee80211_hdr_3addr *nullfunc; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; - /* Don't send NDPs when STA is connected HE */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !(ifmgd->flags & IEEE80211_STA_DISABLE_HE)) - return; - skb = ieee80211_nullfunc_get(&local->hw, &sdata->vif, !ieee80211_hw_check(&local->hw, DOESNT_SUPPORT_QOS_NDP)); if (!skb) @@ -1130,10 +1125,6 @@ static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local, if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION)) return; - /* Don't send NDPs when connected HE */ - if (!(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) - return; - skb = dev_alloc_skb(local->hw.extra_tx_headroom + 30); if (!skb) return; @@ -4019,10 +4010,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, if (elems.mbssid_config_ie) bss_conf->profile_periodicity = elems.mbssid_config_ie->profile_periodicity; + else + bss_conf->profile_periodicity = 0; if (elems.ext_capab_len >= 11 && (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) bss_conf->ema_ap = true; + else + bss_conf->ema_ap = false; /* continue assoc process */ ifmgd->assoc_data->timeout = jiffies; @@ -5749,12 +5744,16 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, beacon_ies->data, beacon_ies->len); if (elem && elem->datalen >= 3) sdata->vif.bss_conf.profile_periodicity = elem->data[2]; + else + sdata->vif.bss_conf.profile_periodicity = 0; elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, beacon_ies->data, beacon_ies->len); if (elem && elem->datalen >= 11 && (elem->data[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) sdata->vif.bss_conf.ema_ap = true; + else + sdata->vif.bss_conf.ema_ap = false; } else { assoc_data->timeout = jiffies; assoc_data->timeout_started = true; diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ef8ff0bc66f17f07c053f7a08a90866d21db8097..38b5695c2a0c83bcbb57a1ca9cd1052c98d6aa27 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2250,17 +2250,15 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) sc = le16_to_cpu(hdr->seq_ctrl); frag = sc & IEEE80211_SCTL_FRAG; - if (is_multicast_ether_addr(hdr->addr1)) { - I802_DEBUG_INC(rx->local->dot11MulticastReceivedFrameCount); - goto out_no_led; - } - if (rx->sta) cache = &rx->sta->frags; if (likely(!ieee80211_has_morefrags(fc) && frag == 0)) goto out; + if (is_multicast_ether_addr(hdr->addr1)) + return RX_DROP_MONITOR; + I802_DEBUG_INC(rx->local->rx_handlers_fragments); if (skb_linearize(rx->skb)) @@ -2386,7 +2384,6 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx) out: ieee80211_led_rx(rx->local); - out_no_led: if (rx->sta) rx->sta->rx_stats.packets++; return RX_CONTINUE; diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f2fb69da9b6e1e945387253aa46154454c7d6ba1..e18c3855f6161c0044100d063acd5beddc4e8a47 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1398,11 +1398,6 @@ static void ieee80211_send_null_response(struct sta_info *sta, int tid, struct ieee80211_tx_info *info; struct ieee80211_chanctx_conf *chanctx_conf; - /* Don't send NDPs when STA is connected HE */ - if (sdata->vif.type == NL80211_IFTYPE_STATION && - !(sdata->u.mgd.flags & IEEE80211_STA_DISABLE_HE)) - return; - if (qos) { fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_QOS_NULLFUNC | @@ -2093,10 +2088,9 @@ static struct ieee80211_sta_rx_stats * sta_get_last_rx_stats(struct sta_info *sta) { struct ieee80211_sta_rx_stats *stats = &sta->rx_stats; - struct ieee80211_local *local = sta->local; int cpu; - if (!ieee80211_hw_check(&local->hw, USES_RSS)) + if (!sta->pcpu_rx_stats) return stats; for_each_possible_cpu(cpu) { @@ -2196,9 +2190,7 @@ static void sta_set_tidstats(struct sta_info *sta, int cpu; if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { - if (!ieee80211_hw_check(&local->hw, USES_RSS)) - tidstats->rx_msdu += - sta_get_tidstats_msdu(&sta->rx_stats, tid); + tidstats->rx_msdu += sta_get_tidstats_msdu(&sta->rx_stats, tid); if (sta->pcpu_rx_stats) { for_each_possible_cpu(cpu) { @@ -2277,7 +2269,6 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, sinfo->rx_beacon = sdata->u.mgd.count_beacon_signal; drv_sta_statistics(local, sdata, &sta->sta, sinfo); - sinfo->filled |= BIT_ULL(NL80211_STA_INFO_INACTIVE_TIME) | BIT_ULL(NL80211_STA_INFO_STA_FLAGS) | BIT_ULL(NL80211_STA_INFO_BSS_PARAM) | @@ -2312,8 +2303,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo, if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_RX_BYTES64) | BIT_ULL(NL80211_STA_INFO_RX_BYTES)))) { - if (!ieee80211_hw_check(&local->hw, USES_RSS)) - sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats); + sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats); if (sta->pcpu_rx_stats) { for_each_possible_cpu(cpu) { diff --git a/net/mac80211/util.c b/net/mac80211/util.c index d8f9fb0646a4d2fe1f5c44642e62e4e1d84c108b..fbf56a203c0e89daa0acbf5d8fefc9826dad997a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -954,7 +954,7 @@ static void ieee80211_parse_extension_element(u32 *crc, switch (elem->data[0]) { case WLAN_EID_EXT_HE_MU_EDCA: - if (len == sizeof(*elems->mu_edca_param_set)) { + if (len >= sizeof(*elems->mu_edca_param_set)) { elems->mu_edca_param_set = data; if (crc) *crc = crc32_be(*crc, (void *)elem, @@ -975,7 +975,7 @@ static void ieee80211_parse_extension_element(u32 *crc, } break; case WLAN_EID_EXT_UORA: - if (len == 1) + if (len >= 1) elems->uora_element = data; break; case WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME: @@ -983,7 +983,7 @@ static void ieee80211_parse_extension_element(u32 *crc, elems->max_channel_switch_time = data; break; case WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION: - if (len == sizeof(*elems->mbssid_config_ie)) + if (len >= sizeof(*elems->mbssid_config_ie)) elems->mbssid_config_ie = data; break; case WLAN_EID_EXT_HE_SPR: @@ -992,7 +992,7 @@ static void ieee80211_parse_extension_element(u32 *crc, elems->he_spr = data; break; case WLAN_EID_EXT_HE_6GHZ_CAPA: - if (len == sizeof(*elems->he_6ghz_capa)) + if (len >= sizeof(*elems->he_6ghz_capa)) elems->he_6ghz_capa = data; break; } @@ -1081,14 +1081,14 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, switch (id) { case WLAN_EID_LINK_ID: - if (elen + 2 != sizeof(struct ieee80211_tdls_lnkie)) { + if (elen + 2 < sizeof(struct ieee80211_tdls_lnkie)) { elem_parse_failed = true; break; } elems->lnk_id = (void *)(pos - 2); break; case WLAN_EID_CHAN_SWITCH_TIMING: - if (elen != sizeof(struct ieee80211_ch_switch_timing)) { + if (elen < sizeof(struct ieee80211_ch_switch_timing)) { elem_parse_failed = true; break; } @@ -1251,7 +1251,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, elems->sec_chan_offs = (void *)pos; break; case WLAN_EID_CHAN_SWITCH_PARAM: - if (elen != + if (elen < sizeof(*elems->mesh_chansw_params_ie)) { elem_parse_failed = true; break; @@ -1260,7 +1260,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, break; case WLAN_EID_WIDE_BW_CHANNEL_SWITCH: if (!action || - elen != sizeof(*elems->wide_bw_chansw_ie)) { + elen < sizeof(*elems->wide_bw_chansw_ie)) { elem_parse_failed = true; break; } @@ -1279,7 +1279,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH, pos, elen); if (ie) { - if (ie[1] == sizeof(*elems->wide_bw_chansw_ie)) + if (ie[1] >= sizeof(*elems->wide_bw_chansw_ie)) elems->wide_bw_chansw_ie = (void *)(ie + 2); else @@ -1323,7 +1323,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, elems->cisco_dtpc_elem = pos; break; case WLAN_EID_ADDBA_EXT: - if (elen != sizeof(struct ieee80211_addba_ext_ie)) { + if (elen < sizeof(struct ieee80211_addba_ext_ie)) { elem_parse_failed = true; break; } @@ -1349,7 +1349,7 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, elem, elems); break; case WLAN_EID_S1G_CAPABILITIES: - if (elen == sizeof(*elems->s1g_capab)) + if (elen >= sizeof(*elems->s1g_capab)) elems->s1g_capab = (void *)pos; else elem_parse_failed = true; diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c index 851fb3d8c791dee975bb1ac709dc49a9c27419bf..bba5696fee36d5c9873ee9719bec224dacbaec3b 100644 --- a/net/mptcp/subflow.c +++ b/net/mptcp/subflow.c @@ -338,15 +338,15 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) goto do_reset; } + if (!mptcp_finish_join(sk)) + goto do_reset; + subflow_generate_hmac(subflow->local_key, subflow->remote_key, subflow->local_nonce, subflow->remote_nonce, hmac); memcpy(subflow->hmac, hmac, MPTCPOPT_HMAC_LEN); - if (!mptcp_finish_join(sk)) - goto do_reset; - subflow->mp_join = 1; MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX); } else if (mptcp_check_fallback(sk)) { diff --git a/net/mptcp/token.c b/net/mptcp/token.c index feb4b9ffd46258fed457742a25cbfbde8e0e87d4..0691a4883f3ab13d24992602b9645cd1ab0f3616 100644 --- a/net/mptcp/token.c +++ b/net/mptcp/token.c @@ -156,9 +156,6 @@ int mptcp_token_new_connect(struct sock *sk) int retries = TOKEN_MAX_RETRIES; struct token_bucket *bucket; - pr_debug("ssk=%p, local_key=%llu, token=%u, idsn=%llu\n", - sk, subflow->local_key, subflow->token, subflow->idsn); - again: mptcp_crypto_key_gen_sha(&subflow->local_key, &subflow->token, &subflow->idsn); @@ -172,6 +169,9 @@ again: goto again; } + pr_debug("ssk=%p, local_key=%llu, token=%u, idsn=%llu\n", + sk, subflow->local_key, subflow->token, subflow->idsn); + WRITE_ONCE(msk->token, subflow->token); __sk_nulls_add_node_rcu((struct sock *)msk, &bucket->msk_chain); bucket->chain_len++; diff --git a/net/netfilter/nf_tables_offload.c b/net/netfilter/nf_tables_offload.c index 2b00f7f47693be9dc1c000bef3beace1a8715129..9ce776175214c9c2271ed73fe4cdccf956887dde 100644 --- a/net/netfilter/nf_tables_offload.c +++ b/net/netfilter/nf_tables_offload.c @@ -54,15 +54,10 @@ static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx, struct nft_flow_rule *flow) { struct nft_flow_match *match = &flow->match; - struct nft_offload_ethertype ethertype; - - if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_CONTROL) && - match->key.basic.n_proto != htons(ETH_P_8021Q) && - match->key.basic.n_proto != htons(ETH_P_8021AD)) - return; - - ethertype.value = match->key.basic.n_proto; - ethertype.mask = match->mask.basic.n_proto; + struct nft_offload_ethertype ethertype = { + .value = match->key.basic.n_proto, + .mask = match->mask.basic.n_proto, + }; if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_VLAN) && (match->key.vlan.vlan_tpid == htons(ETH_P_8021Q) || @@ -76,7 +71,9 @@ static void nft_flow_rule_transfer_vlan(struct nft_offload_ctx *ctx, match->dissector.offset[FLOW_DISSECTOR_KEY_CVLAN] = offsetof(struct nft_flow_key, cvlan); match->dissector.used_keys |= BIT(FLOW_DISSECTOR_KEY_CVLAN); - } else { + } else if (match->dissector.used_keys & BIT(FLOW_DISSECTOR_KEY_BASIC) && + (match->key.basic.n_proto == htons(ETH_P_8021Q) || + match->key.basic.n_proto == htons(ETH_P_8021AD))) { match->key.basic.n_proto = match->key.vlan.vlan_tpid; match->mask.basic.n_proto = match->mask.vlan.vlan_tpid; match->key.vlan.vlan_tpid = ethertype.value; diff --git a/net/netfilter/nft_exthdr.c b/net/netfilter/nft_exthdr.c index 3c48cdc8935df7030e983581c56bd0957d71175f..faa0844c01fb8b895c70c40bab782c378775e63d 100644 --- a/net/netfilter/nft_exthdr.c +++ b/net/netfilter/nft_exthdr.c @@ -42,6 +42,9 @@ static void nft_exthdr_ipv6_eval(const struct nft_expr *expr, unsigned int offset = 0; int err; + if (pkt->skb->protocol != htons(ETH_P_IPV6)) + goto err; + err = ipv6_find_hdr(pkt->skb, &offset, priv->type, NULL, NULL); if (priv->flags & NFT_EXTHDR_F_PRESENT) { nft_reg_store8(dest, err >= 0); diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c index c261d57a666ab6b70ff87246a4ce0b6b53433e67..2c957629ea66072358b0333ff796b8d246766835 100644 --- a/net/netfilter/nft_osf.c +++ b/net/netfilter/nft_osf.c @@ -28,6 +28,11 @@ static void nft_osf_eval(const struct nft_expr *expr, struct nft_regs *regs, struct nf_osf_data data; struct tcphdr _tcph; + if (pkt->tprot != IPPROTO_TCP) { + regs->verdict.code = NFT_BREAK; + return; + } + tcp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(struct tcphdr), &_tcph); if (!tcp) { diff --git a/net/netfilter/nft_tproxy.c b/net/netfilter/nft_tproxy.c index d67f83a0958d3661aa470a8892e1507386b87195..242222dc52c3c882b9ec70fd3ec8bc522bcc9b72 100644 --- a/net/netfilter/nft_tproxy.c +++ b/net/netfilter/nft_tproxy.c @@ -30,6 +30,12 @@ static void nft_tproxy_eval_v4(const struct nft_expr *expr, __be16 tport = 0; struct sock *sk; + if (pkt->tprot != IPPROTO_TCP && + pkt->tprot != IPPROTO_UDP) { + regs->verdict.code = NFT_BREAK; + return; + } + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr); if (!hp) { regs->verdict.code = NFT_BREAK; @@ -91,7 +97,8 @@ static void nft_tproxy_eval_v6(const struct nft_expr *expr, memset(&taddr, 0, sizeof(taddr)); - if (!pkt->tprot_set) { + if (pkt->tprot != IPPROTO_TCP && + pkt->tprot != IPPROTO_UDP) { regs->verdict.code = NFT_BREAK; return; } diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index eb1d66d20afbbfcf834db5a7f38f9b2f9be54a1f..02a97bca1a1a2e5e0446702a6a0bd66717a511e1 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c @@ -76,6 +76,7 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { static int netlbl_mgmt_add_common(struct genl_info *info, struct netlbl_audit *audit_info) { + void *pmap = NULL; int ret_val = -EINVAL; struct netlbl_domaddr_map *addrmap = NULL; struct cipso_v4_doi *cipsov4 = NULL; @@ -175,6 +176,7 @@ static int netlbl_mgmt_add_common(struct genl_info *info, ret_val = -ENOMEM; goto add_free_addrmap; } + pmap = map; map->list.addr = addr->s_addr & mask->s_addr; map->list.mask = mask->s_addr; map->list.valid = 1; @@ -183,10 +185,8 @@ static int netlbl_mgmt_add_common(struct genl_info *info, map->def.cipso = cipsov4; ret_val = netlbl_af4list_add(&map->list, &addrmap->list4); - if (ret_val != 0) { - kfree(map); - goto add_free_addrmap; - } + if (ret_val != 0) + goto add_free_map; entry->family = AF_INET; entry->def.type = NETLBL_NLTYPE_ADDRSELECT; @@ -223,6 +223,7 @@ static int netlbl_mgmt_add_common(struct genl_info *info, ret_val = -ENOMEM; goto add_free_addrmap; } + pmap = map; map->list.addr = *addr; map->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; map->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; @@ -235,10 +236,8 @@ static int netlbl_mgmt_add_common(struct genl_info *info, map->def.calipso = calipso; ret_val = netlbl_af6list_add(&map->list, &addrmap->list6); - if (ret_val != 0) { - kfree(map); - goto add_free_addrmap; - } + if (ret_val != 0) + goto add_free_map; entry->family = AF_INET6; entry->def.type = NETLBL_NLTYPE_ADDRSELECT; @@ -248,10 +247,12 @@ static int netlbl_mgmt_add_common(struct genl_info *info, ret_val = netlbl_domhsh_add(entry, audit_info); if (ret_val != 0) - goto add_free_addrmap; + goto add_free_map; return 0; +add_free_map: + kfree(pmap); add_free_addrmap: kfree(addrmap); add_doi_put_def: diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ddb68aa836f71692f0759f144c48a5d4f0b70173..08144559eed56ea19a5ceb1c2cc349caf1040aea 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2682,7 +2682,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) } if (likely(saddr == NULL)) { dev = packet_cached_dev_get(po); - proto = po->num; + proto = READ_ONCE(po->num); } else { err = -EINVAL; if (msg->msg_namelen < sizeof(struct sockaddr_ll)) @@ -2895,7 +2895,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) if (likely(saddr == NULL)) { dev = packet_cached_dev_get(po); - proto = po->num; + proto = READ_ONCE(po->num); } else { err = -EINVAL; if (msg->msg_namelen < sizeof(struct sockaddr_ll)) @@ -3033,10 +3033,13 @@ static int packet_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); - if (po->tx_ring.pg_vec) + /* Reading tx_ring.pg_vec without holding pg_vec_lock is racy. + * tpacket_snd() will redo the check safely. + */ + if (data_race(po->tx_ring.pg_vec)) return tpacket_snd(po, msg); - else - return packet_snd(sock, msg, len); + + return packet_snd(sock, msg, len); } /* @@ -3167,7 +3170,7 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, /* prevents packet_notifier() from calling * register_prot_hook() */ - po->num = 0; + WRITE_ONCE(po->num, 0); __unregister_prot_hook(sk, true); rcu_read_lock(); dev_curr = po->prot_hook.dev; @@ -3177,17 +3180,17 @@ static int packet_do_bind(struct sock *sk, const char *name, int ifindex, } BUG_ON(po->running); - po->num = proto; + WRITE_ONCE(po->num, proto); po->prot_hook.type = proto; if (unlikely(unlisted)) { dev_put(dev); po->prot_hook.dev = NULL; - po->ifindex = -1; + WRITE_ONCE(po->ifindex, -1); packet_cached_dev_reset(po); } else { po->prot_hook.dev = dev; - po->ifindex = dev ? dev->ifindex : 0; + WRITE_ONCE(po->ifindex, dev ? dev->ifindex : 0); packet_cached_dev_assign(po, dev); } } @@ -3501,7 +3504,7 @@ static int packet_getname_spkt(struct socket *sock, struct sockaddr *uaddr, uaddr->sa_family = AF_PACKET; memset(uaddr->sa_data, 0, sizeof(uaddr->sa_data)); rcu_read_lock(); - dev = dev_get_by_index_rcu(sock_net(sk), pkt_sk(sk)->ifindex); + dev = dev_get_by_index_rcu(sock_net(sk), READ_ONCE(pkt_sk(sk)->ifindex)); if (dev) strlcpy(uaddr->sa_data, dev->name, sizeof(uaddr->sa_data)); rcu_read_unlock(); @@ -3516,16 +3519,18 @@ static int packet_getname(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct packet_sock *po = pkt_sk(sk); DECLARE_SOCKADDR(struct sockaddr_ll *, sll, uaddr); + int ifindex; if (peer) return -EOPNOTSUPP; + ifindex = READ_ONCE(po->ifindex); sll->sll_family = AF_PACKET; - sll->sll_ifindex = po->ifindex; - sll->sll_protocol = po->num; + sll->sll_ifindex = ifindex; + sll->sll_protocol = READ_ONCE(po->num); sll->sll_pkttype = 0; rcu_read_lock(); - dev = dev_get_by_index_rcu(sock_net(sk), po->ifindex); + dev = dev_get_by_index_rcu(sock_net(sk), ifindex); if (dev) { sll->sll_hatype = dev->type; sll->sll_halen = dev->addr_len; @@ -4104,7 +4109,7 @@ static int packet_notifier(struct notifier_block *this, } if (msg == NETDEV_UNREGISTER) { packet_cached_dev_reset(po); - po->ifindex = -1; + WRITE_ONCE(po->ifindex, -1); if (po->prot_hook.dev) dev_put(po->prot_hook.dev); po->prot_hook.dev = NULL; @@ -4410,7 +4415,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, was_running = po->running; num = po->num; if (was_running) { - po->num = 0; + WRITE_ONCE(po->num, 0); __unregister_prot_hook(sk, false); } spin_unlock(&po->bind_lock); @@ -4445,7 +4450,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, spin_lock(&po->bind_lock); if (was_running) { - po->num = num; + WRITE_ONCE(po->num, num); register_prot_hook(sk); } spin_unlock(&po->bind_lock); @@ -4613,8 +4618,8 @@ static int packet_seq_show(struct seq_file *seq, void *v) s, refcount_read(&s->sk_refcnt), s->sk_type, - ntohs(po->num), - po->ifindex, + ntohs(READ_ONCE(po->num)), + READ_ONCE(po->ifindex), po->running, atomic_read(&s->sk_rmem_alloc), from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)), diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b8559c88243188a7ddcf42419562f82235feda0e..e760d4a38fafd34866f6e143c53b8641b875b986 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -783,8 +783,10 @@ void qrtr_ns_init(void) } qrtr_ns.workqueue = alloc_workqueue("qrtr_ns_handler", WQ_UNBOUND, 1); - if (!qrtr_ns.workqueue) + if (!qrtr_ns.workqueue) { + ret = -ENOMEM; goto err_sock; + } qrtr_ns.sock->sk->sk_data_ready = qrtr_ns_data_ready; diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 88e14cfeb5d5222354b68104c80800b76bc7f786..f613299ca7f0a668cc2c7579a4f0515e16af1d78 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -333,7 +333,8 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, } mutex_unlock(&idrinfo->lock); - if (nla_put_u32(skb, TCA_FCNT, n_i)) + ret = nla_put_u32(skb, TCA_FCNT, n_i); + if (ret) goto nla_put_failure; nla_nest_end(skb, nest); diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c index 1cac3c6fbb49c8376cec7851f7206474bcca2461..a108469c664f7b74821ac6a72f5284d12c3ed60e 100644 --- a/net/sched/act_vlan.c +++ b/net/sched/act_vlan.c @@ -70,7 +70,7 @@ static int tcf_vlan_act(struct sk_buff *skb, const struct tc_action *a, /* replace the vid */ tci = (tci & ~VLAN_VID_MASK) | p->tcfv_push_vid; /* replace prio bits, if tcfv_push_prio specified */ - if (p->tcfv_push_prio) { + if (p->tcfv_push_prio_exists) { tci &= ~VLAN_PRIO_MASK; tci |= p->tcfv_push_prio << VLAN_PRIO_SHIFT; } @@ -121,6 +121,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, struct tc_action_net *tn = net_generic(net, vlan_net_id); struct nlattr *tb[TCA_VLAN_MAX + 1]; struct tcf_chain *goto_ch = NULL; + bool push_prio_exists = false; struct tcf_vlan_params *p; struct tc_vlan *parm; struct tcf_vlan *v; @@ -189,7 +190,8 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, push_proto = htons(ETH_P_8021Q); } - if (tb[TCA_VLAN_PUSH_VLAN_PRIORITY]) + push_prio_exists = !!tb[TCA_VLAN_PUSH_VLAN_PRIORITY]; + if (push_prio_exists) push_prio = nla_get_u8(tb[TCA_VLAN_PUSH_VLAN_PRIORITY]); break; case TCA_VLAN_ACT_POP_ETH: @@ -241,6 +243,7 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, p->tcfv_action = action; p->tcfv_push_vid = push_vid; p->tcfv_push_prio = push_prio; + p->tcfv_push_prio_exists = push_prio_exists || action == TCA_VLAN_ACT_PUSH; p->tcfv_push_proto = push_proto; if (action == TCA_VLAN_ACT_PUSH_ETH) { diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index a281da07bb1d27f57492ce14efddf1078358b71c..30090794b7912a29b9c6be868e8af2da6355b0a5 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -1532,7 +1532,7 @@ static inline int __tcf_classify(struct sk_buff *skb, u32 *last_executed_chain) { #ifdef CONFIG_NET_CLS_ACT - const int max_reclassify_loop = 4; + const int max_reclassify_loop = 16; const struct tcf_proto *first_tp; int limit = 0; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index c4007b9cd16d6a200d943e3e0536d6b20022ba77..5b274534264c2de4c1325efa3f388099f32cd7ee 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -304,7 +304,7 @@ static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp) int i, err = 0; cp->perfect = kcalloc(cp->hash, sizeof(struct tcindex_filter_result), - GFP_KERNEL); + GFP_KERNEL | __GFP_NOWARN); if (!cp->perfect) return -ENOMEM; diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 6335230a971e21233bb1758b57ae72fff41ce6fc..ade2d6ddc91483a51e3e3057f51b1e1e75707dd1 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c @@ -485,11 +485,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, if (cl->qdisc != &noop_qdisc) qdisc_hash_add(cl->qdisc, true); - sch_tree_lock(sch); - qdisc_class_hash_insert(&q->clhash, &cl->common); - sch_tree_unlock(sch); - - qdisc_class_hash_grow(sch, &q->clhash); set_change_agg: sch_tree_lock(sch); @@ -507,8 +502,11 @@ set_change_agg: } if (existing) qfq_deact_rm_from_agg(q, cl); + else + qdisc_class_hash_insert(&q->clhash, &cl->common); qfq_add_to_agg(q, new_agg, cl); sch_tree_unlock(sch); + qdisc_class_hash_grow(sch, &q->clhash); *arg = (unsigned long)cl; return 0; diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 53e5ed79f63f34f6d237b5d0683925fe9c49f4a9..59e653b528b1faec6c6fcf73f0dd42633880e08d 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c @@ -270,22 +270,19 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list, rawaddr = (union sctp_addr_param *)raw_addr_list; af = sctp_get_af_specific(param_type2af(param->type)); - if (unlikely(!af)) { + if (unlikely(!af) || + !af->from_addr_param(&addr, rawaddr, htons(port), 0)) { retval = -EINVAL; - sctp_bind_addr_clean(bp); - break; + goto out_err; } - af->from_addr_param(&addr, rawaddr, htons(port), 0); if (sctp_bind_addr_state(bp, &addr) != -1) goto next; retval = sctp_add_bind_addr(bp, &addr, sizeof(addr), SCTP_ADDR_SRC, gfp); - if (retval) { + if (retval) /* Can't finish building the list, clean up. */ - sctp_bind_addr_clean(bp); - break; - } + goto out_err; next: len = ntohs(param->length); @@ -294,6 +291,12 @@ next: } return retval; + +out_err: + if (retval) + sctp_bind_addr_clean(bp); + + return retval; } /******************************************************************** diff --git a/net/sctp/input.c b/net/sctp/input.c index d508f6f3dd08a33419c010d7944f9f70cacdd700..f72bff93745c44be0dbfa29e754f2872a7d874c2 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c @@ -1131,7 +1131,8 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net, if (!af) continue; - af->from_addr_param(paddr, params.addr, sh->source, 0); + if (!af->from_addr_param(paddr, params.addr, sh->source, 0)) + continue; asoc = __sctp_lookup_association(net, laddr, paddr, transportp); if (asoc) @@ -1174,7 +1175,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( if (unlikely(!af)) return NULL; - af->from_addr_param(&paddr, param, peer_port, 0); + if (af->from_addr_param(&paddr, param, peer_port, 0)) + return NULL; return __sctp_lookup_association(net, laddr, &paddr, transportp); } @@ -1245,7 +1247,7 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net, ch = (struct sctp_chunkhdr *)ch_end; chunk_num++; - } while (ch_end < skb_tail_pointer(skb)); + } while (ch_end + sizeof(*ch) < skb_tail_pointer(skb)); return asoc; } diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index c8074f435d3ef0e22211fd5fe7e5495a64be3ad1..d594b949ae82fa3cbe921926bba322e4b5599c4f 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -530,15 +530,20 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) } /* Initialize a sctp_addr from an address parameter. */ -static void sctp_v6_from_addr_param(union sctp_addr *addr, +static bool sctp_v6_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, __be16 port, int iif) { + if (ntohs(param->v6.param_hdr.length) < sizeof(struct sctp_ipv6addr_param)) + return false; + addr->v6.sin6_family = AF_INET6; addr->v6.sin6_port = port; addr->v6.sin6_flowinfo = 0; /* BUG */ addr->v6.sin6_addr = param->v6.addr; addr->v6.sin6_scope_id = iif; + + return true; } /* Initialize an address parameter from a sctp_addr and return the length diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 25833238fe93c565c7ad09c39269d2aa75507aae..47fb87ce489fc4fc66a723e8f968755751d16aeb 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -253,14 +253,19 @@ static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk) } /* Initialize a sctp_addr from an address parameter. */ -static void sctp_v4_from_addr_param(union sctp_addr *addr, +static bool sctp_v4_from_addr_param(union sctp_addr *addr, union sctp_addr_param *param, __be16 port, int iif) { + if (ntohs(param->v4.param_hdr.length) < sizeof(struct sctp_ipv4addr_param)) + return false; + addr->v4.sin_family = AF_INET; addr->v4.sin_port = port; addr->v4.sin_addr.s_addr = param->v4.addr.s_addr; memset(addr->v4.sin_zero, 0, sizeof(addr->v4.sin_zero)); + + return true; } /* Initialize an address parameter from a sctp_addr and return the length diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b9d6babe287022e4c694613f4802c1340634d6df..7411fa44282144fd48c53c1fd4005b46c9bb2a06 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2329,11 +2329,13 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, /* Process the initialization parameters. */ sctp_walk_params(param, peer_init, init_hdr.params) { - if (!src_match && (param.p->type == SCTP_PARAM_IPV4_ADDRESS || - param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { + if (!src_match && + (param.p->type == SCTP_PARAM_IPV4_ADDRESS || + param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { af = sctp_get_af_specific(param_type2af(param.p->type)); - af->from_addr_param(&addr, param.addr, - chunk->sctp_hdr->source, 0); + if (!af->from_addr_param(&addr, param.addr, + chunk->sctp_hdr->source, 0)) + continue; if (sctp_cmp_addr_exact(sctp_source(chunk), &addr)) src_match = 1; } @@ -2514,7 +2516,8 @@ static int sctp_process_param(struct sctp_association *asoc, break; do_addr_param: af = sctp_get_af_specific(param_type2af(param.p->type)); - af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); + if (!af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0)) + break; scope = sctp_scope(peer_addr); if (sctp_in_scope(net, &addr, scope)) if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) @@ -2615,15 +2618,13 @@ do_addr_param: addr_param = param.v + sizeof(struct sctp_addip_param); af = sctp_get_af_specific(param_type2af(addr_param->p.type)); - if (af == NULL) + if (!af) break; - af->from_addr_param(&addr, addr_param, - htons(asoc->peer.port), 0); + if (!af->from_addr_param(&addr, addr_param, + htons(asoc->peer.port), 0)) + break; - /* if the address is invalid, we can't process it. - * XXX: see spec for what to do. - */ if (!af->addr_valid(&addr, NULL, NULL)) break; @@ -3037,7 +3038,8 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, if (unlikely(!af)) return SCTP_ERROR_DNS_FAILED; - af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0); + if (!af->from_addr_param(&addr, addr_param, htons(asoc->peer.port), 0)) + return SCTP_ERROR_DNS_FAILED; /* ADDIP 4.2.1 This parameter MUST NOT contain a broadcast * or multicast address. @@ -3314,7 +3316,8 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, /* We have checked the packet before, so we do not check again. */ af = sctp_get_af_specific(param_type2af(addr_param->p.type)); - af->from_addr_param(&addr, addr_param, htons(bp->port), 0); + if (!af->from_addr_param(&addr, addr_param, htons(bp->port), 0)) + return; switch (asconf_param->param_hdr.type) { case SCTP_PARAM_ADD_IP: diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 39ed0e0afe6d9bc25069659e853fbde29326a062..c045f63d11fa649bbc317906775faf0dbf56f42f 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -591,11 +591,21 @@ static struct rpc_task *__rpc_find_next_queued_priority(struct rpc_wait_queue *q struct list_head *q; struct rpc_task *task; + /* + * Service the privileged queue. + */ + q = &queue->tasks[RPC_NR_PRIORITY - 1]; + if (queue->maxpriority > RPC_PRIORITY_PRIVILEGED && !list_empty(q)) { + task = list_first_entry(q, struct rpc_task, u.tk_wait.list); + goto out; + } + /* * Service a batch of tasks from a single owner. */ q = &queue->tasks[queue->priority]; - if (!list_empty(q) && --queue->nr) { + if (!list_empty(q) && queue->nr) { + queue->nr--; task = list_first_entry(q, struct rpc_task, u.tk_wait.list); goto out; } diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index c56a66cdf4ac80d8cab6cd72c90fd86155013e3b..9c0f71e82d978c795367f849c074c4bdc347e568 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c @@ -1680,7 +1680,8 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock) err = kernel_bind(sock, (struct sockaddr *)&myaddr, transport->xprt.addrlen); if (err == 0) { - transport->srcport = port; + if (transport->xprt.reuseport) + transport->srcport = port; break; } last = port; diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index d4beca895992db6ea45b9e1776f3f2b916be0313..593846d252143c09eccd05a5e1192f92ca9dd36a 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c @@ -699,7 +699,7 @@ int tipc_bcast_init(struct net *net) spin_lock_init(&tipc_net(net)->bclock); if (!tipc_link_bc_create(net, 0, 0, NULL, - FB_MTU, + one_page_mtu, BCLINK_WIN_DEFAULT, BCLINK_WIN_DEFAULT, 0, diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 88a3ed80094cd43d73f0c02c0d97268f06daee35..91dcf648d32bbc704d4f233d2a160946c1e0b4df 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c @@ -44,12 +44,15 @@ #define MAX_FORWARD_SIZE 1024 #ifdef CONFIG_TIPC_CRYPTO #define BUF_HEADROOM ALIGN(((LL_MAX_HEADER + 48) + EHDR_MAX_SIZE), 16) -#define BUF_TAILROOM (TIPC_AES_GCM_TAG_SIZE) +#define BUF_OVERHEAD (BUF_HEADROOM + TIPC_AES_GCM_TAG_SIZE) #else #define BUF_HEADROOM (LL_MAX_HEADER + 48) -#define BUF_TAILROOM 16 +#define BUF_OVERHEAD BUF_HEADROOM #endif +const int one_page_mtu = PAGE_SIZE - SKB_DATA_ALIGN(BUF_OVERHEAD) - + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); + static unsigned int align(unsigned int i) { return (i + 3) & ~3u; @@ -67,13 +70,8 @@ static unsigned int align(unsigned int i) struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp) { struct sk_buff *skb; -#ifdef CONFIG_TIPC_CRYPTO - unsigned int buf_size = (BUF_HEADROOM + size + BUF_TAILROOM + 3) & ~3u; -#else - unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; -#endif - skb = alloc_skb_fclone(buf_size, gfp); + skb = alloc_skb_fclone(BUF_OVERHEAD + size, gfp); if (skb) { skb_reserve(skb, BUF_HEADROOM); skb_put(skb, size); @@ -395,7 +393,8 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, if (unlikely(!skb)) { if (pktmax != MAX_MSG_SIZE) return -ENOMEM; - rc = tipc_msg_build(mhdr, m, offset, dsz, FB_MTU, list); + rc = tipc_msg_build(mhdr, m, offset, dsz, + one_page_mtu, list); if (rc != dsz) return rc; if (tipc_msg_assemble(list)) diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 5d64596ba98775d5dfe2d2d4918bcc11273d485b..64ae4c4c44f8cdaabca9ca9430dc8be1b5048564 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h @@ -99,9 +99,10 @@ struct plist; #define MAX_H_SIZE 60 /* Largest possible TIPC header size */ #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE) -#define FB_MTU 3744 #define TIPC_MEDIA_INFO_OFFSET 5 +extern const int one_page_mtu; + struct tipc_skb_cb { union { struct { diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c index 3abe5257f75772039f382ea53660a5bc8adf8e98..15395683b8e2a360dd451e08e0297180528ac2d0 100644 --- a/net/tls/tls_sw.c +++ b/net/tls/tls_sw.c @@ -1154,7 +1154,7 @@ static int tls_sw_do_sendpage(struct sock *sk, struct page *page, int ret = 0; bool eor; - eor = !(flags & (MSG_MORE | MSG_SENDPAGE_NOTLAST)); + eor = !(flags & MSG_SENDPAGE_NOTLAST); sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); /* Call the sk_stream functions to manage the sndbuf mem. */ diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index cf86c1376b1a48b4c49aa3650632aaf396e09dc9..326250513570eeba572b14281fd586e7a99de3c5 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -1352,7 +1352,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, if (signal_pending(current)) { err = sock_intr_errno(timeout); - sk->sk_state = TCP_CLOSE; + sk->sk_state = sk->sk_state == TCP_ESTABLISHED ? TCP_CLOSING : TCP_CLOSE; sock->state = SS_UNCONNECTED; vsock_transport_cancel_pkt(vsk); goto out_wait; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index daf3f29c7f0cc44c61e26b88e426c4eb65221b69..8fb0478888fb29de7fe602727df86ddf79e06e61 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -4625,11 +4625,10 @@ static int nl80211_parse_tx_bitrate_mask(struct genl_info *info, sband->ht_cap.mcs.rx_mask, sizeof(mask->control[i].ht_mcs)); - if (!sband->vht_cap.vht_supported) - continue; - - vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); - vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs); + if (sband->vht_cap.vht_supported) { + vht_tx_mcs_map = le16_to_cpu(sband->vht_cap.vht_mcs.tx_mcs_map); + vht_build_mcs_mask(vht_tx_mcs_map, mask->control[i].vht_mcs); + } he_cap = ieee80211_get_he_iftype_cap(sband, wdev->iftype); if (!he_cap) diff --git a/net/wireless/util.c b/net/wireless/util.c index 2731267fd0f9ea85f4a9568600767a9e35d6ec25..4fb8d1b14e76aa80b4d788d1605e5b4ae67e40d9 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -1059,6 +1059,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, case NL80211_IFTYPE_MESH_POINT: /* mesh should be handled? */ break; + case NL80211_IFTYPE_OCB: + cfg80211_leave_ocb(rdev, dev); + break; default: break; } diff --git a/net/wireless/wext-spy.c b/net/wireless/wext-spy.c index 33bef22e44e9511a825d4b84ba52f05a1c2dfb08..b379a03716539764e5c708f132dae17632bcc3e9 100644 --- a/net/wireless/wext-spy.c +++ b/net/wireless/wext-spy.c @@ -120,8 +120,8 @@ int iw_handler_set_thrspy(struct net_device * dev, return -EOPNOTSUPP; /* Just do it */ - memcpy(&(spydata->spy_thr_low), &(threshold->low), - 2 * sizeof(struct iw_quality)); + spydata->spy_thr_low = threshold->low; + spydata->spy_thr_high = threshold->high; /* Clear flag */ memset(spydata->spy_thr_under, '\0', sizeof(spydata->spy_thr_under)); @@ -147,8 +147,8 @@ int iw_handler_get_thrspy(struct net_device * dev, return -EOPNOTSUPP; /* Just do it */ - memcpy(&(threshold->low), &(spydata->spy_thr_low), - 2 * sizeof(struct iw_quality)); + threshold->low = spydata->spy_thr_low; + threshold->high = spydata->spy_thr_high; return 0; } @@ -173,10 +173,10 @@ static void iw_send_thrspy_event(struct net_device * dev, memcpy(threshold.addr.sa_data, address, ETH_ALEN); threshold.addr.sa_family = ARPHRD_ETHER; /* Copy stats */ - memcpy(&(threshold.qual), wstats, sizeof(struct iw_quality)); + threshold.qual = *wstats; /* Copy also thresholds */ - memcpy(&(threshold.low), &(spydata->spy_thr_low), - 2 * sizeof(struct iw_quality)); + threshold.low = spydata->spy_thr_low; + threshold.high = spydata->spy_thr_high; /* Send event to user space */ wireless_send_event(dev, SIOCGIWTHRSPY, &wrqu, (char *) &threshold); diff --git a/net/xdp/xsk_queue.h b/net/xdp/xsk_queue.h index be9fd5a720117d3c4b438bca72ecde4732ac6b28..3c7ce60fe9a5a23bdb7d347e29fd4de672f7e10a 100644 --- a/net/xdp/xsk_queue.h +++ b/net/xdp/xsk_queue.h @@ -126,12 +126,15 @@ static inline bool xskq_cons_read_addr_unchecked(struct xsk_queue *q, u64 *addr) static inline bool xp_aligned_validate_desc(struct xsk_buff_pool *pool, struct xdp_desc *desc) { - u64 chunk; - - if (desc->len > pool->chunk_size) - return false; + u64 chunk, chunk_end; chunk = xp_aligned_extract_addr(pool, desc->addr); + if (likely(desc->len)) { + chunk_end = xp_aligned_extract_addr(pool, desc->addr + desc->len - 1); + if (chunk != chunk_end) + return false; + } + if (chunk >= pool->addrs_cnt) return false; diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 6d6917b68856fc7f544961d018a23a2c13bc63d9..e843b0d9e2a61c16551be51f69bc441ccad4f921 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -268,6 +268,7 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x, xso->num_exthdrs = 0; xso->flags = 0; xso->dev = NULL; + xso->real_dev = NULL; dev_put(dev); if (err != -EOPNOTSUPP) diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index e4cb0ff4dcf413227676d9adf62c9ac2898d5e9a..ac907b9d32d1e7b0c33f5eb1ce2f6a1b033a966b 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -711,15 +711,8 @@ out: static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) { #if IS_ENABLED(CONFIG_IPV6) - unsigned int ptr = 0; int err; - if (x->outer_mode.encap == XFRM_MODE_BEET && - ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL, NULL) >= 0) { - net_warn_ratelimited("BEET mode doesn't support inner IPv6 fragments\n"); - return -EAFNOSUPPORT; - } - err = xfrm6_tunnel_check_size(skb); if (err) return err; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 77499abd9f99208acf4efa3753f0f77293d7ec40..c158e70e8ae1020eb63dd09b632dd38a4037138a 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2516,7 +2516,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x) } EXPORT_SYMBOL(xfrm_state_delete_tunnel); -u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) +u32 __xfrm_state_mtu(struct xfrm_state *x, int mtu) { const struct xfrm_type *type = READ_ONCE(x->type); struct crypto_aead *aead; @@ -2547,7 +2547,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) return ((mtu - x->props.header_len - crypto_aead_authsize(aead) - net_adj) & ~(blksize - 1)) + net_adj - 2; } -EXPORT_SYMBOL_GPL(xfrm_state_mtu); +EXPORT_SYMBOL_GPL(__xfrm_state_mtu); + +u32 xfrm_state_mtu(struct xfrm_state *x, int mtu) +{ + mtu = __xfrm_state_mtu(x, mtu); + + if (x->props.family == AF_INET6 && mtu < IPV6_MIN_MTU) + return IPV6_MIN_MTU; + + return mtu; +} int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) { diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d0c32a8fcc4a99aaf023694486f4c0bd8efb91c4..45f86a97eaf26133a0aaf9f0411396329524b5f1 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -580,6 +580,20 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, copy_from_user_state(x, p); + if (attrs[XFRMA_ENCAP]) { + x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), + sizeof(*x->encap), GFP_KERNEL); + if (x->encap == NULL) + goto error; + } + + if (attrs[XFRMA_COADDR]) { + x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), + sizeof(*x->coaddr), GFP_KERNEL); + if (x->coaddr == NULL) + goto error; + } + if (attrs[XFRMA_SA_EXTRA_FLAGS]) x->props.extra_flags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]); @@ -600,23 +614,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net, attrs[XFRMA_ALG_COMP]))) goto error; - if (attrs[XFRMA_ENCAP]) { - x->encap = kmemdup(nla_data(attrs[XFRMA_ENCAP]), - sizeof(*x->encap), GFP_KERNEL); - if (x->encap == NULL) - goto error; - } - if (attrs[XFRMA_TFCPAD]) x->tfcpad = nla_get_u32(attrs[XFRMA_TFCPAD]); - if (attrs[XFRMA_COADDR]) { - x->coaddr = kmemdup(nla_data(attrs[XFRMA_COADDR]), - sizeof(*x->coaddr), GFP_KERNEL); - if (x->coaddr == NULL) - goto error; - } - xfrm_mark_get(attrs, &x->mark); xfrm_smark_init(attrs, &x->props.smark); diff --git a/samples/bpf/xdp_redirect_user.c b/samples/bpf/xdp_redirect_user.c index 9ca2bf457cdaefe387e49b458e05defed7d9ba37..3c92adc2a7bd0c906fdc7aa8ba7c3dfa895b20c0 100644 --- a/samples/bpf/xdp_redirect_user.c +++ b/samples/bpf/xdp_redirect_user.c @@ -131,7 +131,7 @@ int main(int argc, char **argv) if (!(xdp_flags & XDP_FLAGS_SKB_MODE)) xdp_flags |= XDP_FLAGS_DRV_MODE; - if (optind == argc) { + if (optind + 2 != argc) { printf("usage: %s <IFNAME|IFINDEX>_IN <IFNAME|IFINDEX>_OUT\n", argv[0]); return 1; } @@ -219,5 +219,5 @@ int main(int argc, char **argv) poll_stats(2, ifindex_out); out: - return 0; + return ret; } diff --git a/scripts/Makefile b/scripts/Makefile index c36106bce80ee273342558186ca3399b91eb72f1..9adb6d247818f1355e2e478256022cd10afd05f2 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -14,6 +14,7 @@ hostprogs-always-$(CONFIG_ASN1) += asn1_compiler hostprogs-always-$(CONFIG_MODULE_SIG_FORMAT) += sign-file hostprogs-always-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert +hostprogs-always-$(CONFIG_SYSTEM_REVOCATION_LIST) += extract-cert HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 4c058f12dd73cb6d2d3832788f25daa9d2b413d6..8bd4e673383f3269b6a53bd1bc1c704a8723ada8 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -275,7 +275,8 @@ define rule_as_o_S endef # Built-in and composite module parts -$(obj)/%.o: $(src)/%.c $(recordmcount_source) $(objtool_dep) FORCE +.SECONDEXPANSION: +$(obj)/%.o: $(src)/%.c $(recordmcount_source) $$(objtool_dep) FORCE $(call if_changed_rule,cc_o_c) $(call cmd,force_checksrc) @@ -356,7 +357,7 @@ cmd_modversions_S = \ fi endif -$(obj)/%.o: $(src)/%.S $(objtool_dep) FORCE +$(obj)/%.o: $(src)/%.S $$(objtool_dep) FORCE $(call if_changed_rule,as_o_S) targets += $(filter-out $(subdir-builtin), $(real-obj-y)) diff --git a/scripts/recordmcount.h b/scripts/recordmcount.h index f9b19524da1122ee1d004d7b5b4fef0e6d8c7c09..1e9baa5c4fc6ef2fac1385584cf6bc3b9428f35c 100644 --- a/scripts/recordmcount.h +++ b/scripts/recordmcount.h @@ -192,15 +192,20 @@ static unsigned int get_symindex(Elf_Sym const *sym, Elf32_Word const *symtab, Elf32_Word const *symtab_shndx) { unsigned long offset; + unsigned short shndx = w2(sym->st_shndx); int index; - if (sym->st_shndx != SHN_XINDEX) - return w2(sym->st_shndx); + if (shndx > SHN_UNDEF && shndx < SHN_LORESERVE) + return shndx; - offset = (unsigned long)sym - (unsigned long)symtab; - index = offset / sizeof(*sym); + if (shndx == SHN_XINDEX) { + offset = (unsigned long)sym - (unsigned long)symtab; + index = offset / sizeof(*sym); - return w(symtab_shndx[index]); + return w(symtab_shndx[index]); + } + + return 0; } static unsigned int get_shnum(Elf_Ehdr const *ehdr, Elf_Shdr const *shdr0) diff --git a/scripts/tools-support-relr.sh b/scripts/tools-support-relr.sh index 45e8aa360b45745e7134a24c32e0c4343a6c3303..cb55878bd5b815a031d883de9a8600feef8ab39d 100755 --- a/scripts/tools-support-relr.sh +++ b/scripts/tools-support-relr.sh @@ -7,7 +7,8 @@ trap "rm -f $tmp_file.o $tmp_file $tmp_file.bin" EXIT cat << "END" | $CC -c -x c - -o $tmp_file.o >/dev/null 2>&1 void *p = &p; END -$LD $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr -o $tmp_file +$LD $tmp_file.o -shared -Bsymbolic --pack-dyn-relocs=relr \ + --use-android-relr-tags -o $tmp_file # Despite printing an error message, GNU nm still exits with exit code 0 if it # sees a relr section. So we need to check that nothing is printed to stderr. diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index 76d19146d74bc34ecfc04536a404a302ddffea44..f1ca3cac9b86115a4f4101578a5c94765252dc7b 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -521,7 +521,7 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) } /* - * evm_inode_init_security - initializes security.evm + * evm_inode_init_security - initializes security.evm HMAC value */ int evm_inode_init_security(struct inode *inode, const struct xattr *lsm_xattr, @@ -530,7 +530,8 @@ int evm_inode_init_security(struct inode *inode, struct evm_xattr *xattr_data; int rc; - if (!evm_key_loaded() || !evm_protected_xattr(lsm_xattr->name)) + if (!(evm_initialized & EVM_INIT_HMAC) || + !evm_protected_xattr(lsm_xattr->name)) return 0; xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); diff --git a/security/integrity/evm/evm_secfs.c b/security/integrity/evm/evm_secfs.c index cfc3075769bb0ddcf543128a2fb2eb0854342fbc..bc10c945f3ed548a3ec5e33dcea1ed8397042ffa 100644 --- a/security/integrity/evm/evm_secfs.c +++ b/security/integrity/evm/evm_secfs.c @@ -66,12 +66,13 @@ static ssize_t evm_read_key(struct file *filp, char __user *buf, static ssize_t evm_write_key(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - int i, ret; + unsigned int i; + int ret; if (!capable(CAP_SYS_ADMIN) || (evm_initialized & EVM_SETUP_COMPLETE)) return -EPERM; - ret = kstrtoint_from_user(buf, count, 0, &i); + ret = kstrtouint_from_user(buf, count, 0, &i); if (ret) return ret; @@ -80,12 +81,12 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf, if (!i || (i & ~EVM_INIT_MASK) != 0) return -EINVAL; - /* Don't allow a request to freshly enable metadata writes if - * keys are loaded. + /* + * Don't allow a request to enable metadata writes if + * an HMAC key is loaded. */ if ((i & EVM_ALLOW_METADATA_WRITES) && - ((evm_initialized & EVM_KEY_MASK) != 0) && - !(evm_initialized & EVM_ALLOW_METADATA_WRITES)) + (evm_initialized & EVM_INIT_HMAC) != 0) return -EPERM; if (i & EVM_INIT_HMAC) { diff --git a/security/integrity/platform_certs/keyring_handler.c b/security/integrity/platform_certs/keyring_handler.c index c5ba695c10e3a5afd1633fc5bd765c0f1bf7a303..5604bd57c99077d8238cde7b5e6335a13cf16dce 100644 --- a/security/integrity/platform_certs/keyring_handler.c +++ b/security/integrity/platform_certs/keyring_handler.c @@ -55,6 +55,15 @@ static __init void uefi_blacklist_binary(const char *source, uefi_blacklist_hash(source, data, len, "bin:", 4); } +/* + * Add an X509 cert to the revocation list. + */ +static __init void uefi_revocation_list_x509(const char *source, + const void *data, size_t len) +{ + add_key_to_revocation_list(data, len); +} + /* * Return the appropriate handler for particular signature list types found in * the UEFI db and MokListRT tables. @@ -76,5 +85,7 @@ __init efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type) return uefi_blacklist_x509_tbs; if (efi_guidcmp(*sig_type, efi_cert_sha256_guid) == 0) return uefi_blacklist_binary; + if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) + return uefi_revocation_list_x509; return 0; } diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c index ee4b4c666854f6b40f5664acf20a10bc641c7448..f290f78c3f3012976a15d507cd26f195230a7fd0 100644 --- a/security/integrity/platform_certs/load_uefi.c +++ b/security/integrity/platform_certs/load_uefi.c @@ -132,8 +132,9 @@ static int __init load_moklist_certs(void) static int __init load_uefi_certs(void) { efi_guid_t secure_var = EFI_IMAGE_SECURITY_DATABASE_GUID; - void *db = NULL, *dbx = NULL; - unsigned long dbsize = 0, dbxsize = 0; + efi_guid_t mok_var = EFI_SHIM_LOCK_GUID; + void *db = NULL, *dbx = NULL, *mokx = NULL; + unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0; efi_status_t status; int rc = 0; @@ -175,6 +176,21 @@ static int __init load_uefi_certs(void) kfree(dbx); } + mokx = get_cert_list(L"MokListXRT", &mok_var, &mokxsize, &status); + if (!mokx) { + if (status == EFI_NOT_FOUND) + pr_debug("mokx variable wasn't found\n"); + else + pr_info("Couldn't get mokx list\n"); + } else { + rc = parse_efi_signature_list("UEFI:MokListXRT", + mokx, mokxsize, + get_handler_for_dbx); + if (rc) + pr_err("Couldn't parse mokx signatures %d\n", rc); + kfree(mokx); + } + /* Load the MokListRT certs */ rc = load_moklist_certs(); diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 3c05827608b6a8d5ccf3ec480047e2e5b8200bbf..884a014ce2b85a6437478b49c523c3425adedacc 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c @@ -297,26 +297,27 @@ static struct avc_xperms_decision_node struct avc_xperms_decision_node *xpd_node; struct extended_perms_decision *xpd; - xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, GFP_NOWAIT); + xpd_node = kmem_cache_zalloc(avc_xperms_decision_cachep, + GFP_NOWAIT | __GFP_NOWARN); if (!xpd_node) return NULL; xpd = &xpd_node->xpd; if (which & XPERMS_ALLOWED) { xpd->allowed = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->allowed) goto error; } if (which & XPERMS_AUDITALLOW) { xpd->auditallow = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->auditallow) goto error; } if (which & XPERMS_DONTAUDIT) { xpd->dontaudit = kmem_cache_zalloc(avc_xperms_data_cachep, - GFP_NOWAIT); + GFP_NOWAIT | __GFP_NOWARN); if (!xpd->dontaudit) goto error; } @@ -344,7 +345,7 @@ static struct avc_xperms_node *avc_xperms_alloc(void) { struct avc_xperms_node *xp_node; - xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT); + xp_node = kmem_cache_zalloc(avc_xperms_cachep, GFP_NOWAIT | __GFP_NOWARN); if (!xp_node) return xp_node; INIT_LIST_HEAD(&xp_node->xpd_head); @@ -500,7 +501,7 @@ static struct avc_node *avc_alloc_node(struct selinux_avc *avc) { struct avc_node *node; - node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT); + node = kmem_cache_zalloc(avc_node_cachep, GFP_NOWAIT | __GFP_NOWARN); if (!node) goto out; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 334299357e715c5f09a0323fe71675b150527a52..b88c1a953833464ed9baa3c3f4a518c354b7affa 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -855,6 +855,8 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, if (format == SMK_FIXED24_FMT && (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)) return -EINVAL; + if (count > PAGE_SIZE) + return -EINVAL; data = memdup_user_nul(buf, count); if (IS_ERR(data)) diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c index 7985dd8198b6c4ae066d38041aeb3d45c6947ab8..99e1728b52ae4658149ec0aebd13117c58f1170d 100644 --- a/sound/ac97/bus.c +++ b/sound/ac97/bus.c @@ -520,7 +520,7 @@ static int ac97_bus_remove(struct device *dev) struct ac97_codec_driver *adrv = to_ac97_driver(dev->driver); int ret; - ret = pm_runtime_get_sync(dev); + ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; diff --git a/sound/firewire/Kconfig b/sound/firewire/Kconfig index 9897bd26a438852603d28b6f96a6f4f801754451..12664c3a14141b767e6cc2981f7c1f45c8102280 100644 --- a/sound/firewire/Kconfig +++ b/sound/firewire/Kconfig @@ -38,7 +38,7 @@ config SND_OXFW * Mackie(Loud) Onyx 1640i (former model) * Mackie(Loud) Onyx Satellite * Mackie(Loud) Tapco Link.Firewire - * Mackie(Loud) d.4 pro + * Mackie(Loud) d.2 pro/d.4 pro (built-in FireWire card with OXFW971 ASIC) * Mackie(Loud) U.420/U.420d * TASCAM FireOne * Stanton Controllers & Systems 1 Deck/Mixer @@ -84,7 +84,7 @@ config SND_BEBOB * PreSonus FIREBOX/FIREPOD/FP10/Inspire1394 * BridgeCo RDAudio1/Audio5 * Mackie Onyx 1220/1620/1640 (FireWire I/O Card) - * Mackie d.2 (FireWire Option) and d.2 Pro + * Mackie d.2 (optional FireWire card with DM1000 ASIC) * Stanton FinalScratch 2 (ScratchAmp) * Tascam IF-FW/DM * Behringer XENIX UFX 1204/1604 @@ -110,6 +110,7 @@ config SND_BEBOB * M-Audio Ozonic/NRV10/ProfireLightBridge * M-Audio FireWire 1814/ProjectMix IO * Digidesign Mbox 2 Pro + * ToneWeal FW66 To compile this driver as a module, choose M here: the module will be called snd-bebob. diff --git a/sound/firewire/amdtp-stream.c b/sound/firewire/amdtp-stream.c index 5805c5de39fbf7fc8c4011aa2e9433e4ab367ae1..7a282d8e71485473f0c75b62c5cddae89f5d317f 100644 --- a/sound/firewire/amdtp-stream.c +++ b/sound/firewire/amdtp-stream.c @@ -1404,14 +1404,17 @@ int amdtp_domain_start(struct amdtp_domain *d, unsigned int ir_delay_cycle) unsigned int queue_size; struct amdtp_stream *s; int cycle; + bool found = false; int err; // Select an IT context as IRQ target. list_for_each_entry(s, &d->streams, list) { - if (s->direction == AMDTP_OUT_STREAM) + if (s->direction == AMDTP_OUT_STREAM) { + found = true; break; + } } - if (!s) + if (!found) return -ENXIO; d->irq_target = s; diff --git a/sound/firewire/bebob/bebob.c b/sound/firewire/bebob/bebob.c index daeecfa8b9aac3e6666de77fcf4d31cb91264dbb..67fa0f2178b018e642694184d0e7dd9fb640e2c6 100644 --- a/sound/firewire/bebob/bebob.c +++ b/sound/firewire/bebob/bebob.c @@ -59,6 +59,7 @@ static DECLARE_BITMAP(devices_used, SNDRV_CARDS); #define VEN_MAUDIO1 0x00000d6c #define VEN_MAUDIO2 0x000007f5 #define VEN_DIGIDESIGN 0x00a07e +#define OUI_SHOUYO 0x002327 #define MODEL_FOCUSRITE_SAFFIRE_BOTH 0x00000000 #define MODEL_MAUDIO_AUDIOPHILE_BOTH 0x00010060 @@ -387,7 +388,7 @@ static const struct ieee1394_device_id bebob_id_table[] = { SND_BEBOB_DEV_ENTRY(VEN_BRIDGECO, 0x00010049, &spec_normal), /* Mackie, Onyx 1220/1620/1640 (Firewire I/O Card) */ SND_BEBOB_DEV_ENTRY(VEN_MACKIE2, 0x00010065, &spec_normal), - // Mackie, d.2 (Firewire option card) and d.2 Pro (the card is built-in). + // Mackie, d.2 (optional Firewire card with DM1000). SND_BEBOB_DEV_ENTRY(VEN_MACKIE1, 0x00010067, &spec_normal), /* Stanton, ScratchAmp */ SND_BEBOB_DEV_ENTRY(VEN_STANTON, 0x00000001, &spec_normal), @@ -486,6 +487,8 @@ static const struct ieee1394_device_id bebob_id_table[] = { &maudio_special_spec), /* Digidesign Mbox 2 Pro */ SND_BEBOB_DEV_ENTRY(VEN_DIGIDESIGN, 0x0000a9, &spec_normal), + // Toneweal FW66. + SND_BEBOB_DEV_ENTRY(OUI_SHOUYO, 0x020002, &spec_normal), /* IDs are unknown but able to be supported */ /* Apogee, Mini-ME Firewire */ /* Apogee, Mini-DAC Firewire */ diff --git a/sound/firewire/motu/motu-protocol-v2.c b/sound/firewire/motu/motu-protocol-v2.c index e59e69ab1538b17538ed951b561a4226d043702c..f0a0ecad4d74adbd2096a299899327444cbacfeb 100644 --- a/sound/firewire/motu/motu-protocol-v2.c +++ b/sound/firewire/motu/motu-protocol-v2.c @@ -86,24 +86,23 @@ static int detect_clock_source_optical_model(struct snd_motu *motu, u32 data, *src = SND_MOTU_CLOCK_SOURCE_INTERNAL; break; case 1: + *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT; + break; + case 2: { __be32 reg; // To check the configuration of optical interface. - int err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, - ®, sizeof(reg)); + int err = snd_motu_transaction_read(motu, V2_IN_OUT_CONF_OFFSET, ®, sizeof(reg)); if (err < 0) return err; - if (be32_to_cpu(reg) & 0x00000200) + if (((data & V2_OPT_IN_IFACE_MASK) >> V2_OPT_IN_IFACE_SHIFT) == V2_OPT_IFACE_MODE_SPDIF) *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_OPT; else - *src = SND_MOTU_CLOCK_SOURCE_ADAT_ON_OPT; + *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; break; } - case 2: - *src = SND_MOTU_CLOCK_SOURCE_SPDIF_ON_COAX; - break; case 3: *src = SND_MOTU_CLOCK_SOURCE_SPH; break; @@ -353,6 +352,7 @@ const struct snd_motu_spec snd_motu_spec_8pre = { .protocol_version = SND_MOTU_PROTOCOL_V2, .flags = SND_MOTU_SPEC_RX_MIDI_2ND_Q | SND_MOTU_SPEC_TX_MIDI_2ND_Q, - .tx_fixed_pcm_chunks = {10, 6, 0}, - .rx_fixed_pcm_chunks = {10, 6, 0}, + // Two dummy chunks always in the end of data block. + .tx_fixed_pcm_chunks = {10, 10, 0}, + .rx_fixed_pcm_chunks = {6, 6, 0}, }; diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index 9eea25c46dc7e8b43305fb22effa0482a7910707..5490637d278a47fb2cc2fab4945a3b305d603965 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -355,7 +355,7 @@ static const struct ieee1394_device_id oxfw_id_table[] = { * Onyx-i series (former models): 0x081216 * Mackie Onyx Satellite: 0x00200f * Tapco LINK.firewire 4x6: 0x000460 - * d.4 pro: Unknown + * d.2 pro/d.4 pro (built-in card): Unknown * U.420: Unknown * U.420d: Unknown */ diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c index 4669eb0cc8ce2c01124906eec8d29d85040b947b..5434cc90db1dbe2c8ec2b68350a3068e3daaf16e 100644 --- a/sound/isa/cmi8330.c +++ b/sound/isa/cmi8330.c @@ -548,7 +548,7 @@ static int snd_cmi8330_probe(struct snd_card *card, int dev) } if (acard->sb->hardware != SB_HW_16) { snd_printk(KERN_ERR PFX "SB16 not found during probe\n"); - return err; + return -ENODEV; } snd_wss_out(acard->wss, CS4231_MISC_INFO, 0x40); /* switch on MODE2 */ diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c index 1528e04a4d28e3b8b8bebd1abae4337ebb3a7f98..dbcd9ab2c2b76c4e6bff0d55941e071eaec0c96a 100644 --- a/sound/isa/sb/sb16_csp.c +++ b/sound/isa/sb/sb16_csp.c @@ -1072,10 +1072,14 @@ static void snd_sb_qsound_destroy(struct snd_sb_csp * p) card = p->chip->card; down_write(&card->controls_rwsem); - if (p->qsound_switch) + if (p->qsound_switch) { snd_ctl_remove(card, p->qsound_switch); - if (p->qsound_space) + p->qsound_switch = NULL; + } + if (p->qsound_space) { snd_ctl_remove(card, p->qsound_space); + p->qsound_space = NULL; + } up_write(&card->controls_rwsem); /* cancel pending transfer of QSound parameters */ diff --git a/sound/pci/hda/hda_tegra.c b/sound/pci/hda/hda_tegra.c index 361cf2041911ad754970b9ee0f3a48cfedbd97e9..07787698b9738579c49f2acba611cc06064b971c 100644 --- a/sound/pci/hda/hda_tegra.c +++ b/sound/pci/hda/hda_tegra.c @@ -302,6 +302,9 @@ static int hda_tegra_first_init(struct azx *chip, struct platform_device *pdev) const char *sname, *drv_name = "tegra-hda"; struct device_node *np = pdev->dev.of_node; + if (irq_id < 0) + return irq_id; + err = hda_tegra_init_chip(chip, pdev); if (err) return err; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e46e43dac6bfd4e3e87aa4f32a95b4d94866d565..1cc83344c2ecf27e44a94e93a50e888ab0d41782 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -385,6 +385,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec) alc_update_coef_idx(codec, 0x67, 0xf000, 0x3000); fallthrough; case 0x10ec0215: + case 0x10ec0230: case 0x10ec0233: case 0x10ec0235: case 0x10ec0236: @@ -3153,6 +3154,7 @@ static void alc_disable_headset_jack_key(struct hda_codec *codec) alc_update_coef_idx(codec, 0x49, 0x0045, 0x0); alc_update_coef_idx(codec, 0x44, 0x0045 << 8, 0x0); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x48, 0x0); @@ -3180,6 +3182,7 @@ static void alc_enable_headset_jack_key(struct hda_codec *codec) alc_update_coef_idx(codec, 0x49, 0x007f, 0x0045); alc_update_coef_idx(codec, 0x44, 0x007f << 8, 0x0045 << 8); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x48, 0xd011); @@ -4737,6 +4740,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, coef0256); @@ -4851,6 +4855,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin, alc_process_coef_fw(codec, coef0255); snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x45, 0xc489); @@ -5000,6 +5005,7 @@ static void alc_headset_mode_default(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x1b, 0x0e4b); @@ -5098,6 +5104,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, coef0256); @@ -5211,6 +5218,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, coef0255); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, coef0256); @@ -5311,6 +5319,7 @@ static void alc_determine_headset_type(struct hda_codec *codec) val = alc_read_coef_idx(codec, 0x46); is_ctia = (val & 0x0070) == 0x0070; break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_write_coef_idx(codec, 0x1b, 0x0e4b); @@ -5604,6 +5613,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec) case 0x10ec0255: alc_process_coef_fw(codec, alc255fw); break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: alc_process_coef_fw(codec, alc256fw); @@ -6204,6 +6214,7 @@ static void alc_combo_jack_hp_jd_restart(struct hda_codec *codec) alc_update_coef_idx(codec, 0x4a, 0x8000, 1 << 15); /* Reset HP JD */ alc_update_coef_idx(codec, 0x4a, 0x8000, 0 << 15); break; + case 0x10ec0230: case 0x10ec0235: case 0x10ec0236: case 0x10ec0255: @@ -6336,6 +6347,24 @@ static void alc_fixup_no_int_mic(struct hda_codec *codec, } } +static void alc285_fixup_hp_spectre_x360(struct hda_codec *codec, + const struct hda_fixup *fix, int action) +{ + static const hda_nid_t conn[] = { 0x02 }; + static const struct hda_pintbl pincfgs[] = { + { 0x14, 0x90170110 }, /* rear speaker */ + { } + }; + + switch (action) { + case HDA_FIXUP_ACT_PRE_PROBE: + snd_hda_apply_pincfgs(codec, pincfgs); + /* force front speaker to DAC1 */ + snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn); + break; + } +} + /* for hda_fixup_thinkpad_acpi() */ #include "thinkpad_helper.c" @@ -7802,6 +7831,8 @@ static const struct hda_fixup alc269_fixups[] = { { 0x20, AC_VERB_SET_PROC_COEF, 0x4e4b }, { } }, + .chained = true, + .chain_id = ALC289_FIXUP_ASUS_GA401, }, [ALC285_FIXUP_HP_GPIO_LED] = { .type = HDA_FIXUP_FUNC, @@ -8113,13 +8144,8 @@ static const struct hda_fixup alc269_fixups[] = { .chain_id = ALC269_FIXUP_HP_LINE1_MIC1_LED, }, [ALC285_FIXUP_HP_SPECTRE_X360] = { - .type = HDA_FIXUP_PINS, - .v.pins = (const struct hda_pintbl[]) { - { 0x14, 0x90170110 }, /* enable top speaker */ - {} - }, - .chained = true, - .chain_id = ALC285_FIXUP_SPEAKER2_TO_DAC1, + .type = HDA_FIXUP_FUNC, + .v.func = alc285_fixup_hp_spectre_x360, }, [ALC287_FIXUP_IDEAPAD_BASS_SPK_AMP] = { .type = HDA_FIXUP_FUNC, @@ -8305,6 +8331,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN), SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3), SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360), + SND_PCI_QUIRK(0x103c, 0x861f, "HP Elite Dragonfly G1", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x869d, "HP", ALC236_FIXUP_HP_MUTE_LED), SND_PCI_QUIRK(0x103c, 0x86c7, "HP Envy AiO 32", ALC274_FIXUP_HP_ENVY_GPIO), SND_PCI_QUIRK(0x103c, 0x8716, "HP Elite Dragonfly G2 Notebook PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), @@ -8322,13 +8349,19 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f2, "HP ProBook 640 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f4, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f5, "HP", ALC287_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x87f7, "HP Spectre x360 14", ALC245_FIXUP_HP_X360_AMP), + SND_PCI_QUIRK(0x103c, 0x880d, "HP EliteBook 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x8846, "HP EliteBook 850 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8847, "HP EliteBook x360 830 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x884b, "HP EliteBook 840 Aero G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), SND_PCI_QUIRK(0x103c, 0x884c, "HP EliteBook 840 G8 Notebook PC", ALC285_FIXUP_HP_GPIO_LED), + SND_PCI_QUIRK(0x103c, 0x8862, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), + SND_PCI_QUIRK(0x103c, 0x8863, "HP ProBook 445 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF), SND_PCI_QUIRK(0x103c, 0x886d, "HP ZBook Fury 17.3 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x8870, "HP ZBook Fury 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), SND_PCI_QUIRK(0x103c, 0x8873, "HP ZBook Studio 15.6 Inch G8 Mobile Workstation PC", ALC285_FIXUP_HP_GPIO_AMP_INIT), @@ -9326,6 +9359,7 @@ static int patch_alc269(struct hda_codec *codec) spec->shutup = alc256_shutup; spec->init_hook = alc256_init; break; + case 0x10ec0230: case 0x10ec0236: case 0x10ec0256: spec->codec_variant = ALC269_TYPE_ALC256; @@ -10617,6 +10651,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = { HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269), HDA_CODEC_ENTRY(0x10ec0222, "ALC222", patch_alc269), HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269), + HDA_CODEC_ENTRY(0x10ec0230, "ALC236", patch_alc269), HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269), HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269), HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269), diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c index 6fb6f36d0d37711f52f5be6a3c0b61daf6a6d02f..3707dc27324d20ca443900c898455dfd157dff72 100644 --- a/sound/pci/intel8x0.c +++ b/sound/pci/intel8x0.c @@ -715,7 +715,7 @@ static inline void snd_intel8x0_update(struct intel8x0 *chip, struct ichdev *ich int status, civ, i, step; int ack = 0; - if (!ichdev->prepared || ichdev->suspended) + if (!(ichdev->prepared || chip->in_measurement) || ichdev->suspended) return; spin_lock_irqsave(&chip->reg_lock, flags); diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c index 96ef55082bf9a99d714b4156b18488bdfcd756bb..b135d114ce893be82b6d773cdd8160bc8c784adf 100644 --- a/sound/ppc/powermac.c +++ b/sound/ppc/powermac.c @@ -77,7 +77,11 @@ static int snd_pmac_probe(struct platform_device *devptr) sprintf(card->shortname, "PowerMac %s", name_ext); sprintf(card->longname, "%s (Dev %d) Sub-frame %d", card->shortname, chip->device_id, chip->subframe); - if ( snd_pmac_tumbler_init(chip) < 0 || snd_pmac_tumbler_post_init() < 0) + err = snd_pmac_tumbler_init(chip); + if (err < 0) + goto __error; + err = snd_pmac_tumbler_post_init(); + if (err < 0) goto __error; break; case PMAC_AWACS: diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index bbe2b638abb58a83ffc605f504ed25339f151a8a..d870f56c44cfc898774dda93bdebd5199dbe547b 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -200,6 +200,7 @@ struct atmel_i2s_dev { unsigned int fmt; const struct atmel_i2s_gck_param *gck_param; const struct atmel_i2s_caps *caps; + int clk_use_no; }; static irqreturn_t atmel_i2s_interrupt(int irq, void *dev_id) @@ -321,9 +322,16 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream, { struct atmel_i2s_dev *dev = snd_soc_dai_get_drvdata(dai); bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); - unsigned int mr = 0; + unsigned int mr = 0, mr_mask; int ret; + mr_mask = ATMEL_I2SC_MR_FORMAT_MASK | ATMEL_I2SC_MR_MODE_MASK | + ATMEL_I2SC_MR_DATALENGTH_MASK; + if (is_playback) + mr_mask |= ATMEL_I2SC_MR_TXMONO; + else + mr_mask |= ATMEL_I2SC_MR_RXMONO; + switch (dev->fmt & SND_SOC_DAIFMT_FORMAT_MASK) { case SND_SOC_DAIFMT_I2S: mr |= ATMEL_I2SC_MR_FORMAT_I2S; @@ -402,7 +410,7 @@ static int atmel_i2s_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - return regmap_write(dev->regmap, ATMEL_I2SC_MR, mr); + return regmap_update_bits(dev->regmap, ATMEL_I2SC_MR, mr_mask, mr); } static int atmel_i2s_switch_mck_generator(struct atmel_i2s_dev *dev, @@ -495,18 +503,28 @@ static int atmel_i2s_trigger(struct snd_pcm_substream *substream, int cmd, is_master = (mr & ATMEL_I2SC_MR_MODE_MASK) == ATMEL_I2SC_MR_MODE_MASTER; /* If master starts, enable the audio clock. */ - if (is_master && mck_enabled) - err = atmel_i2s_switch_mck_generator(dev, true); - if (err) - return err; + if (is_master && mck_enabled) { + if (!dev->clk_use_no) { + err = atmel_i2s_switch_mck_generator(dev, true); + if (err) + return err; + } + dev->clk_use_no++; + } err = regmap_write(dev->regmap, ATMEL_I2SC_CR, cr); if (err) return err; /* If master stops, disable the audio clock. */ - if (is_master && !mck_enabled) - err = atmel_i2s_switch_mck_generator(dev, false); + if (is_master && !mck_enabled) { + if (dev->clk_use_no == 1) { + err = atmel_i2s_switch_mck_generator(dev, false); + if (err) + return err; + } + dev->clk_use_no--; + } return err; } diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 866d7c873e3c95b0800f2081588cc5c6e3c5994a..ca2019732013ef386a9e4507b90c91eddc39037a 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -77,7 +77,7 @@ #define CS42L42_HP_PDN_SHIFT 3 #define CS42L42_HP_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT) #define CS42L42_ADC_PDN_SHIFT 2 -#define CS42L42_ADC_PDN_MASK (1 << CS42L42_HP_PDN_SHIFT) +#define CS42L42_ADC_PDN_MASK (1 << CS42L42_ADC_PDN_SHIFT) #define CS42L42_PDN_ALL_SHIFT 0 #define CS42L42_PDN_ALL_MASK (1 << CS42L42_PDN_ALL_SHIFT) diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c index 14fd2f9a0bf3ae242b72a7ed67bea41c845ee5d0..39afa011f0e2750dfbd5eaebf2793031bf900830 100644 --- a/sound/soc/codecs/max98373-sdw.c +++ b/sound/soc/codecs/max98373-sdw.c @@ -258,7 +258,7 @@ static __maybe_unused int max98373_resume(struct device *dev) struct max98373_priv *max98373 = dev_get_drvdata(dev); unsigned long time; - if (!max98373->hw_init) + if (!max98373->first_hw_init) return 0; if (!slave->unattach_request) @@ -349,7 +349,7 @@ static int max98373_io_init(struct sdw_slave *slave) struct device *dev = &slave->dev; struct max98373_priv *max98373 = dev_get_drvdata(dev); - if (max98373->pm_init_once) { + if (max98373->first_hw_init) { regcache_cache_only(max98373->regmap, false); regcache_cache_bypass(max98373->regmap, true); } @@ -357,7 +357,7 @@ static int max98373_io_init(struct sdw_slave *slave) /* * PM runtime is only enabled when a Slave reports as Attached */ - if (!max98373->pm_init_once) { + if (!max98373->first_hw_init) { /* set autosuspend parameters */ pm_runtime_set_autosuspend_delay(dev, 3000); pm_runtime_use_autosuspend(dev); @@ -449,12 +449,12 @@ static int max98373_io_init(struct sdw_slave *slave) regmap_write(max98373->regmap, MAX98373_R20B5_BDE_EN, 1); regmap_write(max98373->regmap, MAX98373_R20E2_LIMITER_EN, 1); - if (max98373->pm_init_once) { + if (max98373->first_hw_init) { regcache_cache_bypass(max98373->regmap, false); regcache_mark_dirty(max98373->regmap); } - max98373->pm_init_once = true; + max98373->first_hw_init = true; max98373->hw_init = true; pm_runtime_mark_last_busy(dev); @@ -773,7 +773,7 @@ static int max98373_init(struct sdw_slave *slave, struct regmap *regmap) max98373_slot_config(dev, max98373); max98373->hw_init = false; - max98373->pm_init_once = false; + max98373->first_hw_init = false; /* codec registration */ ret = devm_snd_soc_register_component(dev, &soc_codec_dev_max98373_sdw, diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 4ab29b9d51c74edd602d036e13c110b14ceb56f1..010f6bb21e9a1300a4c69d020946687bfdb85034 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -215,7 +215,7 @@ struct max98373_priv { /* variables to support soundwire */ struct sdw_slave *slave; bool hw_init; - bool pm_init_once; + bool first_hw_init; int slot; unsigned int rx_mask; }; diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c index 940a2fa933edb458dc0588449e83ba49ae068d63..aed18cbb9f68e62e50bcdc25592cad1fe070639c 100644 --- a/sound/soc/codecs/rk3328_codec.c +++ b/sound/soc/codecs/rk3328_codec.c @@ -474,7 +474,8 @@ static int rk3328_platform_probe(struct platform_device *pdev) rk3328->pclk = devm_clk_get(&pdev->dev, "pclk"); if (IS_ERR(rk3328->pclk)) { dev_err(&pdev->dev, "can't get acodec pclk\n"); - return PTR_ERR(rk3328->pclk); + ret = PTR_ERR(rk3328->pclk); + goto err_unprepare_mclk; } ret = clk_prepare_enable(rk3328->pclk); @@ -484,19 +485,34 @@ static int rk3328_platform_probe(struct platform_device *pdev) } base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(base)) - return PTR_ERR(base); + if (IS_ERR(base)) { + ret = PTR_ERR(base); + goto err_unprepare_pclk; + } rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base, &rk3328_codec_regmap_config); - if (IS_ERR(rk3328->regmap)) - return PTR_ERR(rk3328->regmap); + if (IS_ERR(rk3328->regmap)) { + ret = PTR_ERR(rk3328->regmap); + goto err_unprepare_pclk; + } platform_set_drvdata(pdev, rk3328); - return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, + ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328, rk3328_dai, ARRAY_SIZE(rk3328_dai)); + if (ret) + goto err_unprepare_pclk; + + return 0; + +err_unprepare_pclk: + clk_disable_unprepare(rk3328->pclk); + +err_unprepare_mclk: + clk_disable_unprepare(rk3328->mclk); + return ret; } static const struct of_device_id rk3328_codec_of_match[] = { diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index c2621b0afe6c1d4e4934ca8e24a9b0ab5bf1b6fb..31daa749c3db4dae5633d8bfc27680e8f9e96dad 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -709,7 +709,7 @@ static int __maybe_unused rt1308_dev_resume(struct device *dev) struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev); unsigned long time; - if (!rt1308->hw_init) + if (!rt1308->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 7e652843c57d938b3d05fd5d9c88a7b475322f6c..547445d1e3c6947bdffa3aac8df3e6717b7c4a58 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -268,6 +268,7 @@ static void rt5682_i2c_shutdown(struct i2c_client *client) { struct rt5682_priv *rt5682 = i2c_get_clientdata(client); + disable_irq(client->irq); cancel_delayed_work_sync(&rt5682->jack_detect_work); cancel_delayed_work_sync(&rt5682->jd_check_work); diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index aa6c325faeab2a4780d230767eceed695c5d1856..c9868dd096fcde478a18d2c5dd3cdca1da806bfa 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -375,18 +375,12 @@ static int rt5682_sdw_init(struct device *dev, struct regmap *regmap, static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) { struct rt5682_priv *rt5682 = dev_get_drvdata(dev); - int ret = 0; + int ret = 0, loop = 10; unsigned int val; if (rt5682->hw_init) return 0; - regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); - if (val != DEVICE_ID) { - dev_err(dev, "Device with ID register %x is not rt5682\n", val); - return -ENODEV; - } - /* * PM runtime is only enabled when a Slave reports as Attached */ @@ -411,6 +405,19 @@ static int rt5682_io_init(struct device *dev, struct sdw_slave *slave) regcache_cache_bypass(rt5682->regmap, true); } + while (loop > 0) { + regmap_read(rt5682->regmap, RT5682_DEVICE_ID, &val); + if (val == DEVICE_ID) + break; + dev_warn(dev, "Device with ID register %x is not rt5682\n", val); + usleep_range(30000, 30005); + loop--; + } + if (val != DEVICE_ID) { + dev_err(dev, "Device with ID register %x is not rt5682\n", val); + return -ENODEV; + } + rt5682_calibrate(rt5682); if (rt5682->first_hw_init) { @@ -734,7 +741,7 @@ static int __maybe_unused rt5682_dev_resume(struct device *dev) struct rt5682_priv *rt5682 = dev_get_drvdata(dev); unsigned long time; - if (!rt5682->hw_init) + if (!rt5682->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index fb77e77a4ebd5a621be72e1d6a672cf44300db95..3a1db79030d71e0f5850b68e040d4eb774545c75 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -498,7 +498,7 @@ static int __maybe_unused rt700_dev_resume(struct device *dev) struct rt700_priv *rt700 = dev_get_drvdata(dev); unsigned long time; - if (!rt700->hw_init) + if (!rt700->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index f0a0691bd31ccaf03247e954cece6cea686b2dca..eb54e90c1c604a60efa0cb592bb7b9920ca1d3c9 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -500,7 +500,7 @@ static int __maybe_unused rt711_dev_resume(struct device *dev) struct rt711_priv *rt711 = dev_get_drvdata(dev); unsigned long time; - if (!rt711->hw_init) + if (!rt711->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 8f0aa1e8a27371312cdbd7843cd375f3dcaa49f0..361a90ae594cd3f7a6d0f9f0d917baa31aa47c9f 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -541,7 +541,7 @@ static int __maybe_unused rt715_dev_resume(struct device *dev) struct rt715_priv *rt715 = dev_get_drvdata(dev); unsigned long time; - if (!rt715->hw_init) + if (!rt715->first_hw_init) return 0; if (!slave->unattach_request) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 7d8e6d1bf6cfa7668dba7362e395d1eebf5dd689..fa5d0c9f5539a69741e90158e800b5aeb810e608 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1634,7 +1634,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) ret = imx_pcm_dma_init(pdev, IMX_SPDIF_DMABUF_SIZE); if (ret) { - dev_err_probe(&pdev->dev, ret, "imx_pcm_dma_init failed: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "imx_pcm_dma_init failed\n"); goto err_pm_disable; } @@ -1645,6 +1645,13 @@ err_pm_disable: return ret; } +static int fsl_spdif_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + + return 0; +} + #ifdef CONFIG_PM static int fsl_spdif_runtime_suspend(struct device *dev) { @@ -1748,6 +1755,7 @@ static struct platform_driver fsl_spdif_driver = { .pm = &fsl_spdif_pm, }, .probe = fsl_spdif_probe, + .remove = fsl_spdif_remove, }; module_platform_driver(fsl_spdif_driver); diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c index 907f5f1f7b445eb2c7f9363c00e90c5a4cf3a020..ff05b9779e4be85bc6373924addd0ed43c38080a 100644 --- a/sound/soc/hisilicon/hi6210-i2s.c +++ b/sound/soc/hisilicon/hi6210-i2s.c @@ -102,18 +102,15 @@ static int hi6210_i2s_startup(struct snd_pcm_substream *substream, for (n = 0; n < i2s->clocks; n++) { ret = clk_prepare_enable(i2s->clk[n]); - if (ret) { - while (n--) - clk_disable_unprepare(i2s->clk[n]); - return ret; - } + if (ret) + goto err_unprepare_clk; } ret = clk_set_rate(i2s->clk[CLK_I2S_BASE], 49152000); if (ret) { dev_err(i2s->dev, "%s: setting 49.152MHz base rate failed %d\n", __func__, ret); - return ret; + goto err_unprepare_clk; } /* enable clock before frequency division */ @@ -165,6 +162,11 @@ static int hi6210_i2s_startup(struct snd_pcm_substream *substream, hi6210_write_reg(i2s, HII2S_SW_RST_N, val); return 0; + +err_unprepare_clk: + while (n--) + clk_disable_unprepare(i2s->clk[n]); + return ret; } static void hi6210_i2s_shutdown(struct snd_pcm_substream *substream, diff --git a/sound/soc/img/img-i2s-in.c b/sound/soc/img/img-i2s-in.c index 0843235d73c91fbfd3334626ec8bf305e0e9a300..fd3432a1d6ab8aac3e64d2f4daa8e874d581de18 100644 --- a/sound/soc/img/img-i2s-in.c +++ b/sound/soc/img/img-i2s-in.c @@ -464,7 +464,7 @@ static int img_i2s_in_probe(struct platform_device *pdev) if (ret) goto err_pm_disable; } - ret = pm_runtime_get_sync(&pdev->dev); + ret = pm_runtime_resume_and_get(&pdev->dev); if (ret < 0) goto err_suspend; diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index dc3d897ad2802d1ebc579213101b24f459f04a19..36f1f49e0b76beb5954d45d6ba483242bae9b4fe 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -594,7 +594,7 @@ static int kabylake_audio_probe(struct platform_device *pdev) static const struct platform_device_id kbl_board_ids[] = { { - .name = "kbl_da7219_max98357a", + .name = "kbl_da7219_mx98357a", .driver_data = (kernel_ulong_t)&kabylake_audio_card_da7219_m98357a, }, @@ -616,4 +616,4 @@ module_platform_driver(kabylake_audio) MODULE_DESCRIPTION("Audio Machine driver-DA7219 & MAX98357A in I2S mode"); MODULE_AUTHOR("Naveen Manohar <naveen.m@intel.com>"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:kbl_da7219_max98357a"); +MODULE_ALIAS("platform:kbl_da7219_mx98357a"); diff --git a/sound/soc/intel/boards/sof_da7219_max98373.c b/sound/soc/intel/boards/sof_da7219_max98373.c index f3cb0773e70ee8829848c8ba202d8ba82b990aab..8d1ad892e86b6dee8f166b0e0359fd02767992d3 100644 --- a/sound/soc/intel/boards/sof_da7219_max98373.c +++ b/sound/soc/intel/boards/sof_da7219_max98373.c @@ -440,6 +440,7 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids); static struct platform_driver audio = { .probe = audio_probe, diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index ddbb9fe7cc06b083cb2723e3c41cb141ec47ab7f..1f94fa5a15db6b5613e0bd4f45b00d31c6af442e 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -877,6 +877,7 @@ static const struct platform_device_id board_ids[] = { }, { } }; +MODULE_DEVICE_TABLE(platform, board_ids); static struct platform_driver sof_audio = { .probe = sof_audio_probe, diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 9dc982c2c77606145f4c6e2927e04d4ba4471929..2770e8179983a71a9d1c9906f5e41d7964f0764b 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -196,6 +196,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { }, .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | SOF_SDW_TGL_HDMI | + SOF_RT715_DAI_ID_FIX | SOF_SDW_PCH_DMIC), }, {} @@ -353,6 +354,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x714, .version_id = 3, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_sdca_init, }, @@ -360,6 +362,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x715, .version_id = 3, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_sdca_init, }, @@ -367,6 +370,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x714, .version_id = 2, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, @@ -374,6 +378,7 @@ static struct sof_sdw_codec_info codec_info_list[] = { .part_id = 0x715, .version_id = 2, .direction = {false, true}, + .ignore_pch_dmic = true, .dai_name = "rt715-aif2", .init = sof_sdw_rt715_init, }, @@ -730,7 +735,8 @@ static int create_sdw_dailink(struct device *dev, int *be_index, int *cpu_id, bool *group_generated, struct snd_soc_codec_conf *codec_conf, int codec_count, - int *codec_conf_index) + int *codec_conf_index, + bool *ignore_pch_dmic) { const struct snd_soc_acpi_link_adr *link_next; struct snd_soc_dai_link_component *codecs; @@ -783,6 +789,9 @@ static int create_sdw_dailink(struct device *dev, int *be_index, if (codec_index < 0) return codec_index; + if (codec_info_list[codec_index].ignore_pch_dmic) + *ignore_pch_dmic = true; + cpu_dai_index = *cpu_id; for_each_pcm_streams(stream) { char *name, *cpu_name; @@ -914,6 +923,7 @@ static int sof_card_dai_links_create(struct device *dev, const struct snd_soc_acpi_link_adr *adr_link; struct snd_soc_dai_link_component *cpus; struct snd_soc_codec_conf *codec_conf; + bool ignore_pch_dmic = false; int codec_conf_count; int codec_conf_index = 0; bool group_generated[SDW_MAX_GROUPS]; @@ -1020,7 +1030,8 @@ static int sof_card_dai_links_create(struct device *dev, sdw_cpu_dai_num, cpus, adr_link, &cpu_id, group_generated, codec_conf, codec_conf_count, - &codec_conf_index); + &codec_conf_index, + &ignore_pch_dmic); if (ret < 0) { dev_err(dev, "failed to create dai link %d", be_id); return -ENOMEM; @@ -1088,6 +1099,10 @@ SSP: DMIC: /* dmic */ if (dmic_num > 0) { + if (ignore_pch_dmic) { + dev_warn(dev, "Ignoring PCH DMIC\n"); + goto HDMI; + } cpus[cpu_id].dai_name = "DMIC01 Pin"; init_dai_link(links + link_id, be_id, "dmic01", 0, 1, // DMIC only supports capture @@ -1106,6 +1121,7 @@ DMIC: INC_ID(be_id, cpu_id, link_id); } +HDMI: /* HDMI */ if (hdmi_num > 0) { idisp_components = devm_kcalloc(dev, hdmi_num, diff --git a/sound/soc/intel/boards/sof_sdw_common.h b/sound/soc/intel/boards/sof_sdw_common.h index f3cb6796363e7fcb8ce024d437be7018d936e25c..ea60e8ed215c551c0445c66c956dfd68beff01cb 100644 --- a/sound/soc/intel/boards/sof_sdw_common.h +++ b/sound/soc/intel/boards/sof_sdw_common.h @@ -56,6 +56,7 @@ struct sof_sdw_codec_info { int amp_num; const u8 acpi_id[ACPI_ID_LEN]; const bool direction[2]; // playback & capture support + const bool ignore_pch_dmic; const char *dai_name; const struct snd_soc_ops *ops; diff --git a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c index a4fbe6707ca76ce265fe15fc294ded8657e5fa6d..4ed1349affc4d5484cb6ee12e6fd15a38a99007b 100644 --- a/sound/soc/intel/common/soc-acpi-intel-kbl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-kbl-match.c @@ -113,7 +113,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_kbl_machines[] = { }, { .id = "DLGS7219", - .drv_name = "kbl_da7219_max98373", + .drv_name = "kbl_da7219_mx98373", .fw_filename = "intel/dsp_fw_kbl.bin", .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &kbl_7219_98373_codecs, diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index 668fef3e319a073e4dac8d16599e28c492764134..86e982e3209ed43b794d7ea42d638915645d2415 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -1281,7 +1281,7 @@ static const struct snd_soc_component_driver mtk_btcvsd_snd_platform = { static int mtk_btcvsd_snd_probe(struct platform_device *pdev) { - int ret = 0; + int ret; int irq_id; u32 offset[5] = {0, 0, 0, 0, 0}; struct mtk_btcvsd_snd *btcvsd; @@ -1337,7 +1337,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev) btcvsd->bt_sram_bank2_base = of_iomap(dev->of_node, 1); if (!btcvsd->bt_sram_bank2_base) { dev_err(dev, "iomap bt_sram_bank2_base fail\n"); - return -EIO; + ret = -EIO; + goto unmap_pkv_err; } btcvsd->infra = syscon_regmap_lookup_by_phandle(dev->of_node, @@ -1345,7 +1346,8 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev) if (IS_ERR(btcvsd->infra)) { dev_err(dev, "cannot find infra controller: %ld\n", PTR_ERR(btcvsd->infra)); - return PTR_ERR(btcvsd->infra); + ret = PTR_ERR(btcvsd->infra); + goto unmap_bank2_err; } /* get offset */ @@ -1354,7 +1356,7 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev) ARRAY_SIZE(offset)); if (ret) { dev_warn(dev, "%s(), get offset fail, ret %d\n", __func__, ret); - return ret; + goto unmap_bank2_err; } btcvsd->infra_misc_offset = offset[0]; btcvsd->conn_bt_cvsd_mask = offset[1]; @@ -1373,8 +1375,18 @@ static int mtk_btcvsd_snd_probe(struct platform_device *pdev) mtk_btcvsd_snd_set_state(btcvsd, btcvsd->tx, BT_SCO_STATE_IDLE); mtk_btcvsd_snd_set_state(btcvsd, btcvsd->rx, BT_SCO_STATE_IDLE); - return devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform, - NULL, 0); + ret = devm_snd_soc_register_component(dev, &mtk_btcvsd_snd_platform, + NULL, 0); + if (ret) + goto unmap_bank2_err; + + return 0; + +unmap_bank2_err: + iounmap(btcvsd->bt_sram_bank2_base); +unmap_pkv_err: + iounmap(btcvsd->bt_pkv_base); + return ret; } static int mtk_btcvsd_snd_remove(struct platform_device *pdev) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index b9aacf3d3b29c9b0de99830a568371edbffffbe8..7532ab27a48dfe7506833142b2040546b0cc3395 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -289,7 +289,6 @@ static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val) int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); - struct clk *clk; int i; int sel_table[] = { [CLKA] = 0x1, @@ -302,10 +301,9 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) * find suitable clock from * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. */ - for_each_rsnd_clk(clk, adg, i) { + for (i = 0; i < CLKMAX; i++) if (rate == adg->clk_rate[i]) return sel_table[i]; - } /* * find divided clock from BRGA/BRGB diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 9c8fc6ca4ed406a708071ccc40d8e203ea31f9a7..c73768e7f2c1dbbad1f7f086e6b2462ef512762e 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2806,7 +2806,7 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, if (!routes) { dev_err(card->dev, "ASoC: Could not allocate DAPM route table\n"); - return -EINVAL; + return -ENOMEM; } for (i = 0; i < num_routes; i++) { diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 97d8dc2409b7af4736eae2d01d168cbb91764da8..bc580babfceaf60b4db0d337f777dfedc1ddea14 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1737,7 +1737,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, struct snd_soc_dpcm *dpcm; struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(fe_substream); struct snd_soc_dai *fe_cpu_dai; - int err; + int err = 0; int i; /* apply symmetry for FE */ diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c index 8661877bf4c6f7cd2e4a3c9bd96bf30d913cf65a..13a956c6077b88eae6a835dd1a6a4ab1bcedee2c 100644 --- a/sound/soc/tegra/tegra_alc5632.c +++ b/sound/soc/tegra/tegra_alc5632.c @@ -139,6 +139,7 @@ static struct snd_soc_dai_link tegra_alc5632_dai = { static struct snd_soc_card snd_soc_tegra_alc5632 = { .name = "tegra-alc5632", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_alc5632_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_max98090.c b/sound/soc/tegra/tegra_max98090.c index 9d8e16473ab991abcc13563b0c2f7cabad6a3abc..2fdf46bad2bff558e70b7ced2779537a623554a3 100644 --- a/sound/soc/tegra/tegra_max98090.c +++ b/sound/soc/tegra/tegra_max98090.c @@ -182,6 +182,7 @@ static struct snd_soc_dai_link tegra_max98090_dai = { static struct snd_soc_card snd_soc_tegra_max98090 = { .name = "tegra-max98090", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_max98090_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_rt5640.c b/sound/soc/tegra/tegra_rt5640.c index c73bd23b3d679e1a203cb424e4ec1cf7465e25ca..6c2689f5da2240b2f2e0fbfe3a8df6c5047c2752 100644 --- a/sound/soc/tegra/tegra_rt5640.c +++ b/sound/soc/tegra/tegra_rt5640.c @@ -132,6 +132,7 @@ static struct snd_soc_dai_link tegra_rt5640_dai = { static struct snd_soc_card snd_soc_tegra_rt5640 = { .name = "tegra-rt5640", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_rt5640_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_rt5677.c b/sound/soc/tegra/tegra_rt5677.c index 7504507dd8b855772e54beceb8e78fdb5aeb7129..0588889d081a53abb8135ec2db05e3406d5c72d9 100644 --- a/sound/soc/tegra/tegra_rt5677.c +++ b/sound/soc/tegra/tegra_rt5677.c @@ -175,6 +175,7 @@ static struct snd_soc_dai_link tegra_rt5677_dai = { static struct snd_soc_card snd_soc_tegra_rt5677 = { .name = "tegra-rt5677", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_rt5677_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_sgtl5000.c b/sound/soc/tegra/tegra_sgtl5000.c index e1dc8e7d337a2335ec2ffc72c2ee9dc7bf92ee8a..3d35a57d8c0c4065ea49b3b6f9288ac3c384a5b3 100644 --- a/sound/soc/tegra/tegra_sgtl5000.c +++ b/sound/soc/tegra/tegra_sgtl5000.c @@ -97,6 +97,7 @@ static struct snd_soc_dai_link tegra_sgtl5000_dai = { static struct snd_soc_card snd_soc_tegra_sgtl5000 = { .name = "tegra-sgtl5000", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_sgtl5000_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_wm8753.c b/sound/soc/tegra/tegra_wm8753.c index fa41fa366dafaf60338523d8a8532523e42928ab..bdddda4eb91390f3cf2e6cbe11d56cbf84b34316 100644 --- a/sound/soc/tegra/tegra_wm8753.c +++ b/sound/soc/tegra/tegra_wm8753.c @@ -101,6 +101,7 @@ static struct snd_soc_dai_link tegra_wm8753_dai = { static struct snd_soc_card snd_soc_tegra_wm8753 = { .name = "tegra-wm8753", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_wm8753_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c index ef6652aaac9b6ef9d57e75297f4cba4b3c5cde33..98adf93fb898d125160614347326ecf344a18621 100644 --- a/sound/soc/tegra/tegra_wm8903.c +++ b/sound/soc/tegra/tegra_wm8903.c @@ -235,6 +235,7 @@ static struct snd_soc_dai_link tegra_wm8903_dai = { static struct snd_soc_card snd_soc_tegra_wm8903 = { .name = "tegra-wm8903", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_wm8903_dai, .num_links = 1, diff --git a/sound/soc/tegra/tegra_wm9712.c b/sound/soc/tegra/tegra_wm9712.c index 726edfa21a29d07b194a194ad3f805349ba150f1..df7662258bc6dd05cb8aa2114b50c73abea3d1af 100644 --- a/sound/soc/tegra/tegra_wm9712.c +++ b/sound/soc/tegra/tegra_wm9712.c @@ -54,6 +54,7 @@ static struct snd_soc_dai_link tegra_wm9712_dai = { static struct snd_soc_card snd_soc_tegra_wm9712 = { .name = "tegra-wm9712", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &tegra_wm9712_dai, .num_links = 1, diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c index baae4cce7fc66710dd8cda2dc1fcc10199290028..d8fbb22482d5fae0a0ae609dde63d56d5b292d0a 100644 --- a/sound/soc/tegra/trimslice.c +++ b/sound/soc/tegra/trimslice.c @@ -94,6 +94,7 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = { static struct snd_soc_card snd_soc_trimslice = { .name = "tegra-trimslice", + .driver_name = "tegra", .owner = THIS_MODULE, .dai_link = &trimslice_tlv320aic23_dai, .num_links = 1, diff --git a/sound/usb/format.c b/sound/usb/format.c index 91f0ed4a2e7eb16bcaf21cccc841a21dc7947a84..5c5b76c611480fe0343114f81c0229dbb4da936b 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -208,9 +208,11 @@ static int parse_audio_format_rates_v1(struct snd_usb_audio *chip, struct audiof continue; /* C-Media CM6501 mislabels its 96 kHz altsetting */ /* Terratec Aureon 7.1 USB C-Media 6206, too */ + /* Ozone Z90 USB C-Media, too */ if (rate == 48000 && nr_rates == 1 && (chip->usb_id == USB_ID(0x0d8c, 0x0201) || chip->usb_id == USB_ID(0x0d8c, 0x0102) || + chip->usb_id == USB_ID(0x0d8c, 0x0078) || chip->usb_id == USB_ID(0x0ccd, 0x00b1)) && fp->altsetting == 5 && fp->maxpacksize == 392) rate = 96000; diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 375cfb9c9ab7ebbe5d17d0509843e1afcf25aa31..8e11582fbae984f448def61142190d3798a73225 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -3273,8 +3273,9 @@ static void snd_usb_mixer_dump_cval(struct snd_info_buffer *buffer, struct usb_mixer_elem_list *list) { struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); - static const char * const val_types[] = {"BOOLEAN", "INV_BOOLEAN", - "S8", "U8", "S16", "U16"}; + static const char * const val_types[] = { + "BOOLEAN", "INV_BOOLEAN", "S8", "U8", "S16", "U16", "S32", "U32", + }; snd_iprintf(buffer, " Info: id=%i, control=%i, cmask=0x%x, " "channels=%i, type=\"%s\"\n", cval->head.id, cval->control, cval->cmask, cval->channels, @@ -3630,6 +3631,9 @@ static int restore_mixer_value(struct usb_mixer_elem_list *list) struct usb_mixer_elem_info *cval = mixer_elem_list_to_info(list); int c, err, idx; + if (cval->val_type == USB_MIXER_BESPOKEN) + return 0; + if (cval->cmask) { idx = 0; for (c = 0; c < MAX_CHANNELS; c++) { diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index c29e27ac43a7a297d41c3a2a720d8172099a1cd2..6d20ba7ee88fdeabde51a95e069f8ec8169a58c3 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -55,6 +55,7 @@ enum { USB_MIXER_U16, USB_MIXER_S32, USB_MIXER_U32, + USB_MIXER_BESPOKEN, /* non-standard type */ }; typedef void (*usb_mixer_elem_dump_func_t)(struct snd_info_buffer *buffer, diff --git a/sound/usb/mixer_scarlett_gen2.c b/sound/usb/mixer_scarlett_gen2.c index 9a98b0c048e33daf6fc5c6342d7ce58bb40f0373..1b7c7b754c3855b4f87b5106e86c00e3095f2828 100644 --- a/sound/usb/mixer_scarlett_gen2.c +++ b/sound/usb/mixer_scarlett_gen2.c @@ -254,10 +254,10 @@ static const struct scarlett2_device_info s6i6_gen2_info = { .pad_input_count = 2, .line_out_descrs = { - "Monitor L", - "Monitor R", - "Headphones L", - "Headphones R", + "Headphones 1 L", + "Headphones 1 R", + "Headphones 2 L", + "Headphones 2 R", }, .ports = { @@ -356,7 +356,7 @@ static const struct scarlett2_device_info s18i8_gen2_info = { }, [SCARLETT2_PORT_TYPE_PCM] = { .id = 0x600, - .num = { 20, 18, 18, 14, 10 }, + .num = { 8, 18, 18, 14, 10 }, .src_descr = "PCM %d", .src_num_offset = 1, .dst_descr = "PCM %02d Capture" @@ -949,10 +949,15 @@ static int scarlett2_add_new_ctl(struct usb_mixer_interface *mixer, if (!elem) return -ENOMEM; + /* We set USB_MIXER_BESPOKEN type, so that the core USB mixer code + * ignores them for resume and other operations. + * Also, the head.id field is set to 0, as we don't use this field. + */ elem->head.mixer = mixer; elem->control = index; - elem->head.id = index; + elem->head.id = 0; elem->channels = channels; + elem->val_type = USB_MIXER_BESPOKEN; kctl = snd_ctl_new1(ncontrol, elem); if (!kctl) { @@ -1028,11 +1033,10 @@ static int scarlett2_master_volume_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_mixer_data *private = mixer->private_data; - if (private->vol_updated) { - mutex_lock(&private->data_mutex); + mutex_lock(&private->data_mutex); + if (private->vol_updated) scarlett2_update_volumes(mixer); - mutex_unlock(&private->data_mutex); - } + mutex_unlock(&private->data_mutex); ucontrol->value.integer.value[0] = private->master_vol; return 0; @@ -1046,11 +1050,10 @@ static int scarlett2_volume_ctl_get(struct snd_kcontrol *kctl, struct scarlett2_mixer_data *private = mixer->private_data; int index = elem->control; - if (private->vol_updated) { - mutex_lock(&private->data_mutex); + mutex_lock(&private->data_mutex); + if (private->vol_updated) scarlett2_update_volumes(mixer); - mutex_unlock(&private->data_mutex); - } + mutex_unlock(&private->data_mutex); ucontrol->value.integer.value[0] = private->vol[index]; return 0; @@ -1181,6 +1184,8 @@ static int scarlett2_sw_hw_enum_ctl_put(struct snd_kcontrol *kctl, /* Send SW/HW switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_SW_HW_SWITCH, index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); @@ -1241,6 +1246,8 @@ static int scarlett2_level_enum_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_LEVEL_SWITCH, index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); @@ -1291,6 +1298,8 @@ static int scarlett2_pad_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_PAD_SWITCH, index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); @@ -1314,11 +1323,10 @@ static int scarlett2_button_ctl_get(struct snd_kcontrol *kctl, struct usb_mixer_interface *mixer = elem->head.mixer; struct scarlett2_mixer_data *private = mixer->private_data; - if (private->vol_updated) { - mutex_lock(&private->data_mutex); + mutex_lock(&private->data_mutex); + if (private->vol_updated) scarlett2_update_volumes(mixer); - mutex_unlock(&private->data_mutex); - } + mutex_unlock(&private->data_mutex); ucontrol->value.enumerated.item[0] = private->buttons[elem->control]; return 0; @@ -1347,6 +1355,8 @@ static int scarlett2_button_ctl_put(struct snd_kcontrol *kctl, /* Send switch change to the device */ err = scarlett2_usb_set_config(mixer, SCARLETT2_CONFIG_BUTTONS, index, val); + if (err == 0) + err = 1; unlock: mutex_unlock(&private->data_mutex); diff --git a/sound/usb/usx2y/usX2Yhwdep.c b/sound/usb/usx2y/usX2Yhwdep.c index 22412cd69e98588ece0e0cfea4131e5460cb1a19..10868c3fb65611eebf0dc3f1f2950c7e4e1fe6d7 100644 --- a/sound/usb/usx2y/usX2Yhwdep.c +++ b/sound/usb/usx2y/usX2Yhwdep.c @@ -29,7 +29,7 @@ static vm_fault_t snd_us428ctls_vm_fault(struct vm_fault *vmf) vmf->pgoff); offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; + vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->us428ctls_sharedmem + offset; page = virt_to_page(vaddr); get_page(page); vmf->page = page; @@ -47,7 +47,7 @@ static const struct vm_operations_struct us428ctls_vm_ops = { static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; // FIXME this hwdep interface is used twice: fpga download and mmap for controlling Lights etc. Maybe better using 2 hwdep devs? // so as long as the device isn't fully initialised yet we return -EBUSY here. @@ -66,7 +66,7 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v if (!us428->us428ctls_sharedmem) return -ENOMEM; memset(us428->us428ctls_sharedmem, -1, sizeof(struct us428ctls_sharedmem)); - us428->us428ctls_sharedmem->CtlSnapShotLast = -2; + us428->us428ctls_sharedmem->ctl_snapshot_last = -2; } area->vm_ops = &us428ctls_vm_ops; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; @@ -77,21 +77,21 @@ static int snd_us428ctls_mmap(struct snd_hwdep * hw, struct file *filp, struct v static __poll_t snd_us428ctls_poll(struct snd_hwdep *hw, struct file *file, poll_table *wait) { __poll_t mask = 0; - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; struct us428ctls_sharedmem *shm = us428->us428ctls_sharedmem; if (us428->chip_status & USX2Y_STAT_CHIP_HUP) return EPOLLHUP; poll_wait(file, &us428->us428ctls_wait_queue_head, wait); - if (shm != NULL && shm->CtlSnapShotLast != shm->CtlSnapShotRed) + if (shm != NULL && shm->ctl_snapshot_last != shm->ctl_snapshot_red) mask |= EPOLLIN; return mask; } -static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, +static int snd_usx2y_hwdep_dsp_status(struct snd_hwdep *hw, struct snd_hwdep_dsp_status *info) { static const char * const type_ids[USX2Y_TYPE_NUMS] = { @@ -99,7 +99,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, [USX2Y_TYPE_224] = "us224", [USX2Y_TYPE_428] = "us428", }; - struct usX2Ydev *us428 = hw->private_data; + struct usx2ydev *us428 = hw->private_data; int id = -1; switch (le16_to_cpu(us428->dev->descriptor.idProduct)) { @@ -124,7 +124,7 @@ static int snd_usX2Y_hwdep_dsp_status(struct snd_hwdep *hw, } -static int usX2Y_create_usbmidi(struct snd_card *card) +static int usx2y_create_usbmidi(struct snd_card *card) { static const struct snd_usb_midi_endpoint_info quirk_data_1 = { .out_ep = 0x06, @@ -152,28 +152,28 @@ static int usX2Y_create_usbmidi(struct snd_card *card) .type = QUIRK_MIDI_FIXED_ENDPOINT, .data = &quirk_data_2 }; - struct usb_device *dev = usX2Y(card)->dev; + struct usb_device *dev = usx2y(card)->dev; struct usb_interface *iface = usb_ifnum_to_if(dev, 0); const struct snd_usb_audio_quirk *quirk = le16_to_cpu(dev->descriptor.idProduct) == USB_ID_US428 ? &quirk_2 : &quirk_1; - snd_printdd("usX2Y_create_usbmidi \n"); - return snd_usbmidi_create(card, iface, &usX2Y(card)->midi_list, quirk); + snd_printdd("usx2y_create_usbmidi \n"); + return snd_usbmidi_create(card, iface, &usx2y(card)->midi_list, quirk); } -static int usX2Y_create_alsa_devices(struct snd_card *card) +static int usx2y_create_alsa_devices(struct snd_card *card) { int err; do { - if ((err = usX2Y_create_usbmidi(card)) < 0) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices: usX2Y_create_usbmidi error %i \n", err); + if ((err = usx2y_create_usbmidi(card)) < 0) { + snd_printk(KERN_ERR "usx2y_create_alsa_devices: usx2y_create_usbmidi error %i \n", err); break; } - if ((err = usX2Y_audio_create(card)) < 0) + if ((err = usx2y_audio_create(card)) < 0) break; - if ((err = usX2Y_hwdep_pcm_new(card)) < 0) + if ((err = usx2y_hwdep_pcm_new(card)) < 0) break; if ((err = snd_card_register(card)) < 0) break; @@ -182,10 +182,10 @@ static int usX2Y_create_alsa_devices(struct snd_card *card) return err; } -static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, +static int snd_usx2y_hwdep_dsp_load(struct snd_hwdep *hw, struct snd_hwdep_dsp_image *dsp) { - struct usX2Ydev *priv = hw->private_data; + struct usx2ydev *priv = hw->private_data; struct usb_device* dev = priv->dev; int lret, err; char *buf; @@ -206,19 +206,19 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, return err; if (dsp->index == 1) { msleep(250); // give the device some time - err = usX2Y_AsyncSeq04_init(priv); + err = usx2y_async_seq04_init(priv); if (err) { - snd_printk(KERN_ERR "usX2Y_AsyncSeq04_init error \n"); + snd_printk(KERN_ERR "usx2y_async_seq04_init error \n"); return err; } - err = usX2Y_In04_init(priv); + err = usx2y_in04_init(priv); if (err) { - snd_printk(KERN_ERR "usX2Y_In04_init error \n"); + snd_printk(KERN_ERR "usx2y_in04_init error \n"); return err; } - err = usX2Y_create_alsa_devices(hw->card); + err = usx2y_create_alsa_devices(hw->card); if (err) { - snd_printk(KERN_ERR "usX2Y_create_alsa_devices error %i \n", err); + snd_printk(KERN_ERR "usx2y_create_alsa_devices error %i \n", err); snd_card_free(hw->card); return err; } @@ -229,7 +229,7 @@ static int snd_usX2Y_hwdep_dsp_load(struct snd_hwdep *hw, } -int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) +int usx2y_hwdep_new(struct snd_card *card, struct usb_device* device) { int err; struct snd_hwdep *hw; @@ -238,9 +238,9 @@ int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device) return err; hw->iface = SNDRV_HWDEP_IFACE_USX2Y; - hw->private_data = usX2Y(card); - hw->ops.dsp_status = snd_usX2Y_hwdep_dsp_status; - hw->ops.dsp_load = snd_usX2Y_hwdep_dsp_load; + hw->private_data = usx2y(card); + hw->ops.dsp_status = snd_usx2y_hwdep_dsp_status; + hw->ops.dsp_load = snd_usx2y_hwdep_dsp_load; hw->ops.mmap = snd_us428ctls_mmap; hw->ops.poll = snd_us428ctls_poll; hw->exclusive = 1; diff --git a/sound/usb/usx2y/usX2Yhwdep.h b/sound/usb/usx2y/usX2Yhwdep.h index 457199b5ed03b42dbb411bbe4751787fc5882ea8..34cef625712c6fcc05baf0f32b8e0dbb75f26a62 100644 --- a/sound/usb/usx2y/usX2Yhwdep.h +++ b/sound/usb/usx2y/usX2Yhwdep.h @@ -2,6 +2,6 @@ #ifndef USX2YHWDEP_H #define USX2YHWDEP_H -int usX2Y_hwdep_new(struct snd_card *card, struct usb_device* device); +int usx2y_hwdep_new(struct snd_card *card, struct usb_device* device); #endif diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c index 091c071b270af30925223b9ede5813e23fc82099..cff684942c4f0ff22c43cff9cc7b7d346e5c7bc2 100644 --- a/sound/usb/usx2y/usb_stream.c +++ b/sound/usb/usx2y/usb_stream.c @@ -142,8 +142,11 @@ void usb_stream_free(struct usb_stream_kernel *sk) if (!s) return; - free_pages_exact(sk->write_page, s->write_size); - sk->write_page = NULL; + if (sk->write_page) { + free_pages_exact(sk->write_page, s->write_size); + sk->write_page = NULL; + } + free_pages_exact(s, s->read_size); sk->s = NULL; } diff --git a/sound/usb/usx2y/usbus428ctldefs.h b/sound/usb/usx2y/usbus428ctldefs.h index 5a7518ea3aeb4a6532b54224b730c1ffcae51ca9..7366a940ffbbae0e7774c3f4daf85171d11dc0f9 100644 --- a/sound/usb/usx2y/usbus428ctldefs.h +++ b/sound/usb/usx2y/usbus428ctldefs.h @@ -4,28 +4,28 @@ * Copyright (c) 2003 by Karsten Wiese <annabellesgarden@yahoo.de> */ -enum E_In84{ - eFader0 = 0, - eFader1, - eFader2, - eFader3, - eFader4, - eFader5, - eFader6, - eFader7, - eFaderM, - eTransport, - eModifier = 10, - eFilterSelect, - eSelect, - eMute, +enum E_IN84 { + E_FADER_0 = 0, + E_FADER_1, + E_FADER_2, + E_FADER_3, + E_FADER_4, + E_FADER_5, + E_FADER_6, + E_FADER_7, + E_FADER_M, + E_TRANSPORT, + E_MODIFIER = 10, + E_FILTER_SELECT, + E_SELECT, + E_MUTE, - eSwitch = 15, - eWheelGain, - eWheelFreq, - eWheelQ, - eWheelPan, - eWheel = 20 + E_SWITCH = 15, + E_WHEEL_GAIN, + E_WHEEL_FREQ, + E_WHEEL_Q, + E_WHEEL_PAN, + E_WHEEL = 20 }; #define T_RECORD 1 @@ -39,53 +39,53 @@ enum E_In84{ struct us428_ctls { - unsigned char Fader[9]; - unsigned char Transport; - unsigned char Modifier; - unsigned char FilterSelect; - unsigned char Select; - unsigned char Mute; - unsigned char UNKNOWN; - unsigned char Switch; - unsigned char Wheel[5]; + unsigned char fader[9]; + unsigned char transport; + unsigned char modifier; + unsigned char filters_elect; + unsigned char select; + unsigned char mute; + unsigned char unknown; + unsigned char wswitch; + unsigned char wheel[5]; }; -struct us428_setByte { - unsigned char Offset, - Value; +struct us428_set_byte { + unsigned char offset, + value; }; enum { - eLT_Volume = 0, - eLT_Light + ELT_VOLUME = 0, + ELT_LIGHT }; -struct usX2Y_volume { - unsigned char Channel, - LH, - LL, - RH, - RL; +struct usx2y_volume { + unsigned char channel, + lh, + ll, + rh, + rl; }; struct us428_lights { - struct us428_setByte Light[7]; + struct us428_set_byte light[7]; }; struct us428_p4out { char type; union { - struct usX2Y_volume vol; + struct usx2y_volume vol; struct us428_lights lights; } val; }; -#define N_us428_ctl_BUFS 16 -#define N_us428_p4out_BUFS 16 -struct us428ctls_sharedmem{ - struct us428_ctls CtlSnapShot[N_us428_ctl_BUFS]; - int CtlSnapShotDiffersAt[N_us428_ctl_BUFS]; - int CtlSnapShotLast, CtlSnapShotRed; - struct us428_p4out p4out[N_us428_p4out_BUFS]; - int p4outLast, p4outSent; +#define N_US428_CTL_BUFS 16 +#define N_US428_P4OUT_BUFS 16 +struct us428ctls_sharedmem { + struct us428_ctls ctl_snapshot[N_US428_CTL_BUFS]; + int ctl_snapshot_differs_at[N_US428_CTL_BUFS]; + int ctl_snapshot_last, ctl_snapshot_red; + struct us428_p4out p4out[N_US428_P4OUT_BUFS]; + int p4out_last, p4out_sent; }; diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c index c54158146917b42656cf94c1f62f583712a43f12..6d910f23da0d08e02336c401e61f8e1da9d10d86 100644 --- a/sound/usb/usx2y/usbusx2y.c +++ b/sound/usb/usx2y/usbusx2y.c @@ -17,7 +17,7 @@ 2004-10-26 Karsten Wiese Version 0.8.6: - wake_up() process waiting in usX2Y_urbs_start() on error. + wake_up() process waiting in usx2y_urbs_start() on error. 2004-10-21 Karsten Wiese Version 0.8.5: @@ -48,7 +48,7 @@ 2004-06-12 Karsten Wiese Version 0.6.3: Made it thus the following rule is enforced: - "All pcm substreams of one usX2Y have to operate at the same rate & format." + "All pcm substreams of one usx2y have to operate at the same rate & format." 2004-04-06 Karsten Wiese Version 0.6.0: @@ -151,161 +151,161 @@ module_param_array(enable, bool, NULL, 0444); MODULE_PARM_DESC(enable, "Enable "NAME_ALLCAPS"."); -static int snd_usX2Y_card_used[SNDRV_CARDS]; +static int snd_usx2y_card_used[SNDRV_CARDS]; -static void usX2Y_usb_disconnect(struct usb_device* usb_device, void* ptr); -static void snd_usX2Y_card_private_free(struct snd_card *card); +static void usx2y_usb_disconnect(struct usb_device* usb_device, void* ptr); +static void snd_usx2y_card_private_free(struct snd_card *card); /* * pipe 4 is used for switching the lamps, setting samplerate, volumes .... */ -static void i_usX2Y_Out04Int(struct urb *urb) +static void i_usx2y_out04_int(struct urb *urb) { #ifdef CONFIG_SND_DEBUG if (urb->status) { int i; - struct usX2Ydev *usX2Y = urb->context; - for (i = 0; i < 10 && usX2Y->AS04.urb[i] != urb; i++); - snd_printdd("i_usX2Y_Out04Int() urb %i status=%i\n", i, urb->status); + struct usx2ydev *usx2y = urb->context; + for (i = 0; i < 10 && usx2y->as04.urb[i] != urb; i++); + snd_printdd("i_usx2y_out04_int() urb %i status=%i\n", i, urb->status); } #endif } -static void i_usX2Y_In04Int(struct urb *urb) +static void i_usx2y_in04_int(struct urb *urb) { int err = 0; - struct usX2Ydev *usX2Y = urb->context; - struct us428ctls_sharedmem *us428ctls = usX2Y->us428ctls_sharedmem; + struct usx2ydev *usx2y = urb->context; + struct us428ctls_sharedmem *us428ctls = usx2y->us428ctls_sharedmem; - usX2Y->In04IntCalls++; + usx2y->in04_int_calls++; if (urb->status) { snd_printdd("Interrupt Pipe 4 came back with status=%i\n", urb->status); return; } - // printk("%i:0x%02X ", 8, (int)((unsigned char*)usX2Y->In04Buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? + // printk("%i:0x%02X ", 8, (int)((unsigned char*)usx2y->in04_buf)[8]); Master volume shows 0 here if fader is at max during boot ?!? if (us428ctls) { int diff = -1; - if (-2 == us428ctls->CtlSnapShotLast) { + if (-2 == us428ctls->ctl_snapshot_last) { diff = 0; - memcpy(usX2Y->In04Last, usX2Y->In04Buf, sizeof(usX2Y->In04Last)); - us428ctls->CtlSnapShotLast = -1; + memcpy(usx2y->in04_last, usx2y->in04_buf, sizeof(usx2y->in04_last)); + us428ctls->ctl_snapshot_last = -1; } else { int i; for (i = 0; i < 21; i++) { - if (usX2Y->In04Last[i] != ((char*)usX2Y->In04Buf)[i]) { + if (usx2y->in04_last[i] != ((char*)usx2y->in04_buf)[i]) { if (diff < 0) diff = i; - usX2Y->In04Last[i] = ((char*)usX2Y->In04Buf)[i]; + usx2y->in04_last[i] = ((char*)usx2y->in04_buf)[i]; } } } if (0 <= diff) { - int n = us428ctls->CtlSnapShotLast + 1; - if (n >= N_us428_ctl_BUFS || n < 0) + int n = us428ctls->ctl_snapshot_last + 1; + if (n >= N_US428_CTL_BUFS || n < 0) n = 0; - memcpy(us428ctls->CtlSnapShot + n, usX2Y->In04Buf, sizeof(us428ctls->CtlSnapShot[0])); - us428ctls->CtlSnapShotDiffersAt[n] = diff; - us428ctls->CtlSnapShotLast = n; - wake_up(&usX2Y->us428ctls_wait_queue_head); + memcpy(us428ctls->ctl_snapshot + n, usx2y->in04_buf, sizeof(us428ctls->ctl_snapshot[0])); + us428ctls->ctl_snapshot_differs_at[n] = diff; + us428ctls->ctl_snapshot_last = n; + wake_up(&usx2y->us428ctls_wait_queue_head); } } - if (usX2Y->US04) { - if (0 == usX2Y->US04->submitted) + if (usx2y->us04) { + if (0 == usx2y->us04->submitted) do { - err = usb_submit_urb(usX2Y->US04->urb[usX2Y->US04->submitted++], GFP_ATOMIC); - } while (!err && usX2Y->US04->submitted < usX2Y->US04->len); + err = usb_submit_urb(usx2y->us04->urb[usx2y->us04->submitted++], GFP_ATOMIC); + } while (!err && usx2y->us04->submitted < usx2y->us04->len); } else - if (us428ctls && us428ctls->p4outLast >= 0 && us428ctls->p4outLast < N_us428_p4out_BUFS) { - if (us428ctls->p4outLast != us428ctls->p4outSent) { - int j, send = us428ctls->p4outSent + 1; - if (send >= N_us428_p4out_BUFS) + if (us428ctls && us428ctls->p4out_last >= 0 && us428ctls->p4out_last < N_US428_P4OUT_BUFS) { + if (us428ctls->p4out_last != us428ctls->p4out_sent) { + int j, send = us428ctls->p4out_sent + 1; + if (send >= N_US428_P4OUT_BUFS) send = 0; - for (j = 0; j < URBS_AsyncSeq && !err; ++j) - if (0 == usX2Y->AS04.urb[j]->status) { + for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) + if (0 == usx2y->as04.urb[j]->status) { struct us428_p4out *p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost. - usb_fill_bulk_urb(usX2Y->AS04.urb[j], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), &p4out->val.vol, - p4out->type == eLT_Light ? sizeof(struct us428_lights) : 5, - i_usX2Y_Out04Int, usX2Y); - err = usb_submit_urb(usX2Y->AS04.urb[j], GFP_ATOMIC); - us428ctls->p4outSent = send; + usb_fill_bulk_urb(usx2y->as04.urb[j], usx2y->dev, + usb_sndbulkpipe(usx2y->dev, 0x04), &p4out->val.vol, + p4out->type == ELT_LIGHT ? sizeof(struct us428_lights) : 5, + i_usx2y_out04_int, usx2y); + err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC); + us428ctls->p4out_sent = send; break; } } } if (err) - snd_printk(KERN_ERR "In04Int() usb_submit_urb err=%i\n", err); + snd_printk(KERN_ERR "in04_int() usb_submit_urb err=%i\n", err); - urb->dev = usX2Y->dev; + urb->dev = usx2y->dev; usb_submit_urb(urb, GFP_ATOMIC); } /* * Prepare some urbs */ -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y) +int usx2y_async_seq04_init(struct usx2ydev *usx2y) { int err = 0, i; - usX2Y->AS04.buffer = kmalloc_array(URBS_AsyncSeq, - URB_DataLen_AsyncSeq, GFP_KERNEL); - if (NULL == usX2Y->AS04.buffer) { + usx2y->as04.buffer = kmalloc_array(URBS_ASYNC_SEQ, + URB_DATA_LEN_ASYNC_SEQ, GFP_KERNEL); + if (NULL == usx2y->as04.buffer) { err = -ENOMEM; } else - for (i = 0; i < URBS_AsyncSeq; ++i) { - if (NULL == (usX2Y->AS04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { + for (i = 0; i < URBS_ASYNC_SEQ; ++i) { + if (NULL == (usx2y->as04.urb[i] = usb_alloc_urb(0, GFP_KERNEL))) { err = -ENOMEM; break; } - usb_fill_bulk_urb( usX2Y->AS04.urb[i], usX2Y->dev, - usb_sndbulkpipe(usX2Y->dev, 0x04), - usX2Y->AS04.buffer + URB_DataLen_AsyncSeq*i, 0, - i_usX2Y_Out04Int, usX2Y + usb_fill_bulk_urb( usx2y->as04.urb[i], usx2y->dev, + usb_sndbulkpipe(usx2y->dev, 0x04), + usx2y->as04.buffer + URB_DATA_LEN_ASYNC_SEQ*i, 0, + i_usx2y_out04_int, usx2y ); - err = usb_urb_ep_type_check(usX2Y->AS04.urb[i]); + err = usb_urb_ep_type_check(usx2y->as04.urb[i]); if (err < 0) break; } return err; } -int usX2Y_In04_init(struct usX2Ydev *usX2Y) +int usx2y_in04_init(struct usx2ydev *usx2y) { - if (! (usX2Y->In04urb = usb_alloc_urb(0, GFP_KERNEL))) + if (! (usx2y->in04_urb = usb_alloc_urb(0, GFP_KERNEL))) return -ENOMEM; - if (! (usX2Y->In04Buf = kmalloc(21, GFP_KERNEL))) + if (! (usx2y->in04_buf = kmalloc(21, GFP_KERNEL))) return -ENOMEM; - init_waitqueue_head(&usX2Y->In04WaitQueue); - usb_fill_int_urb(usX2Y->In04urb, usX2Y->dev, usb_rcvintpipe(usX2Y->dev, 0x4), - usX2Y->In04Buf, 21, - i_usX2Y_In04Int, usX2Y, + init_waitqueue_head(&usx2y->in04_wait_queue); + usb_fill_int_urb(usx2y->in04_urb, usx2y->dev, usb_rcvintpipe(usx2y->dev, 0x4), + usx2y->in04_buf, 21, + i_usx2y_in04_int, usx2y, 10); - if (usb_urb_ep_type_check(usX2Y->In04urb)) + if (usb_urb_ep_type_check(usx2y->in04_urb)) return -EINVAL; - return usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); + return usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); } -static void usX2Y_unlinkSeq(struct snd_usX2Y_AsyncSeq *S) +static void usx2y_unlinkseq(struct snd_usx2y_async_seq *s) { int i; - for (i = 0; i < URBS_AsyncSeq; ++i) { - usb_kill_urb(S->urb[i]); - usb_free_urb(S->urb[i]); - S->urb[i] = NULL; + for (i = 0; i < URBS_ASYNC_SEQ; ++i) { + usb_kill_urb(s->urb[i]); + usb_free_urb(s->urb[i]); + s->urb[i] = NULL; } - kfree(S->buffer); + kfree(s->buffer); } -static const struct usb_device_id snd_usX2Y_usb_id_table[] = { +static const struct usb_device_id snd_usx2y_usb_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEVICE, .idVendor = 0x1604, @@ -324,7 +324,7 @@ static const struct usb_device_id snd_usX2Y_usb_id_table[] = { { /* terminator */ } }; -static int usX2Y_create_card(struct usb_device *device, +static int usx2y_create_card(struct usb_device *device, struct usb_interface *intf, struct snd_card **cardp) { @@ -333,20 +333,20 @@ static int usX2Y_create_card(struct usb_device *device, int err; for (dev = 0; dev < SNDRV_CARDS; ++dev) - if (enable[dev] && !snd_usX2Y_card_used[dev]) + if (enable[dev] && !snd_usx2y_card_used[dev]) break; if (dev >= SNDRV_CARDS) return -ENODEV; err = snd_card_new(&intf->dev, index[dev], id[dev], THIS_MODULE, - sizeof(struct usX2Ydev), &card); + sizeof(struct usx2ydev), &card); if (err < 0) return err; - snd_usX2Y_card_used[usX2Y(card)->card_index = dev] = 1; - card->private_free = snd_usX2Y_card_private_free; - usX2Y(card)->dev = device; - init_waitqueue_head(&usX2Y(card)->prepare_wait_queue); - mutex_init(&usX2Y(card)->pcm_mutex); - INIT_LIST_HEAD(&usX2Y(card)->midi_list); + snd_usx2y_card_used[usx2y(card)->card_index = dev] = 1; + card->private_free = snd_usx2y_card_private_free; + usx2y(card)->dev = device; + init_waitqueue_head(&usx2y(card)->prepare_wait_queue); + mutex_init(&usx2y(card)->pcm_mutex); + INIT_LIST_HEAD(&usx2y(card)->midi_list); strcpy(card->driver, "USB "NAME_ALLCAPS""); sprintf(card->shortname, "TASCAM "NAME_ALLCAPS""); sprintf(card->longname, "%s (%x:%x if %d at %03d/%03d)", @@ -354,14 +354,14 @@ static int usX2Y_create_card(struct usb_device *device, le16_to_cpu(device->descriptor.idVendor), le16_to_cpu(device->descriptor.idProduct), 0,//us428(card)->usbmidi.ifnum, - usX2Y(card)->dev->bus->busnum, usX2Y(card)->dev->devnum + usx2y(card)->dev->bus->busnum, usx2y(card)->dev->devnum ); *cardp = card; return 0; } -static int usX2Y_usb_probe(struct usb_device *device, +static int usx2y_usb_probe(struct usb_device *device, struct usb_interface *intf, const struct usb_device_id *device_id, struct snd_card **cardp) @@ -376,10 +376,10 @@ static int usX2Y_usb_probe(struct usb_device *device, le16_to_cpu(device->descriptor.idProduct) != USB_ID_US428)) return -EINVAL; - err = usX2Y_create_card(device, intf, &card); + err = usx2y_create_card(device, intf, &card); if (err < 0) return err; - if ((err = usX2Y_hwdep_new(card, device)) < 0 || + if ((err = usx2y_hwdep_new(card, device)) < 0 || (err = snd_card_register(card)) < 0) { snd_card_free(card); return err; @@ -391,64 +391,64 @@ static int usX2Y_usb_probe(struct usb_device *device, /* * new 2.5 USB kernel API */ -static int snd_usX2Y_probe(struct usb_interface *intf, const struct usb_device_id *id) +static int snd_usx2y_probe(struct usb_interface *intf, const struct usb_device_id *id) { struct snd_card *card; int err; - err = usX2Y_usb_probe(interface_to_usbdev(intf), intf, id, &card); + err = usx2y_usb_probe(interface_to_usbdev(intf), intf, id, &card); if (err < 0) return err; dev_set_drvdata(&intf->dev, card); return 0; } -static void snd_usX2Y_disconnect(struct usb_interface *intf) +static void snd_usx2y_disconnect(struct usb_interface *intf) { - usX2Y_usb_disconnect(interface_to_usbdev(intf), + usx2y_usb_disconnect(interface_to_usbdev(intf), usb_get_intfdata(intf)); } -MODULE_DEVICE_TABLE(usb, snd_usX2Y_usb_id_table); -static struct usb_driver snd_usX2Y_usb_driver = { +MODULE_DEVICE_TABLE(usb, snd_usx2y_usb_id_table); +static struct usb_driver snd_usx2y_usb_driver = { .name = "snd-usb-usx2y", - .probe = snd_usX2Y_probe, - .disconnect = snd_usX2Y_disconnect, - .id_table = snd_usX2Y_usb_id_table, + .probe = snd_usx2y_probe, + .disconnect = snd_usx2y_disconnect, + .id_table = snd_usx2y_usb_id_table, }; -static void snd_usX2Y_card_private_free(struct snd_card *card) +static void snd_usx2y_card_private_free(struct snd_card *card) { - kfree(usX2Y(card)->In04Buf); - usb_free_urb(usX2Y(card)->In04urb); - if (usX2Y(card)->us428ctls_sharedmem) - free_pages_exact(usX2Y(card)->us428ctls_sharedmem, - sizeof(*usX2Y(card)->us428ctls_sharedmem)); - if (usX2Y(card)->card_index >= 0 && usX2Y(card)->card_index < SNDRV_CARDS) - snd_usX2Y_card_used[usX2Y(card)->card_index] = 0; + kfree(usx2y(card)->in04_buf); + usb_free_urb(usx2y(card)->in04_urb); + if (usx2y(card)->us428ctls_sharedmem) + free_pages_exact(usx2y(card)->us428ctls_sharedmem, + sizeof(*usx2y(card)->us428ctls_sharedmem)); + if (usx2y(card)->card_index >= 0 && usx2y(card)->card_index < SNDRV_CARDS) + snd_usx2y_card_used[usx2y(card)->card_index] = 0; } /* * Frees the device. */ -static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr) +static void usx2y_usb_disconnect(struct usb_device *device, void* ptr) { if (ptr) { struct snd_card *card = ptr; - struct usX2Ydev *usX2Y = usX2Y(card); + struct usx2ydev *usx2y = usx2y(card); struct list_head *p; - usX2Y->chip_status = USX2Y_STAT_CHIP_HUP; - usX2Y_unlinkSeq(&usX2Y->AS04); - usb_kill_urb(usX2Y->In04urb); + usx2y->chip_status = USX2Y_STAT_CHIP_HUP; + usx2y_unlinkseq(&usx2y->as04); + usb_kill_urb(usx2y->in04_urb); snd_card_disconnect(card); /* release the midi resources */ - list_for_each(p, &usX2Y->midi_list) { + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_disconnect(p); } - if (usX2Y->us428ctls_sharedmem) - wake_up(&usX2Y->us428ctls_wait_queue_head); + if (usx2y->us428ctls_sharedmem) + wake_up(&usx2y->us428ctls_wait_queue_head); snd_card_free(card); } } -module_usb_driver(snd_usX2Y_usb_driver); +module_usb_driver(snd_usx2y_usb_driver); diff --git a/sound/usb/usx2y/usbusx2y.h b/sound/usb/usx2y/usbusx2y.h index 144b85f57bd2a6a45753255da5affe6db2c2f6f2..c330af628bccd8fa21eb8eaed6ffdf18f94c8f50 100644 --- a/sound/usb/usx2y/usbusx2y.h +++ b/sound/usb/usx2y/usbusx2y.h @@ -8,14 +8,14 @@ #define NRURBS 2 -#define URBS_AsyncSeq 10 -#define URB_DataLen_AsyncSeq 32 -struct snd_usX2Y_AsyncSeq { - struct urb *urb[URBS_AsyncSeq]; +#define URBS_ASYNC_SEQ 10 +#define URB_DATA_LEN_ASYNC_SEQ 32 +struct snd_usx2y_async_seq { + struct urb *urb[URBS_ASYNC_SEQ]; char *buffer; }; -struct snd_usX2Y_urbSeq { +struct snd_usx2y_urb_seq { int submitted; int len; struct urb *urb[]; @@ -23,17 +23,17 @@ struct snd_usX2Y_urbSeq { #include "usx2yhwdeppcm.h" -struct usX2Ydev { +struct usx2ydev { struct usb_device *dev; int card_index; int stride; - struct urb *In04urb; - void *In04Buf; - char In04Last[24]; - unsigned In04IntCalls; - struct snd_usX2Y_urbSeq *US04; - wait_queue_head_t In04WaitQueue; - struct snd_usX2Y_AsyncSeq AS04; + struct urb *in04_urb; + void *in04_buf; + char in04_last[24]; + unsigned in04_int_calls; + struct snd_usx2y_urb_seq *us04; + wait_queue_head_t in04_wait_queue; + struct snd_usx2y_async_seq as04; unsigned int rate, format; int chip_status; @@ -41,9 +41,9 @@ struct usX2Ydev { struct us428ctls_sharedmem *us428ctls_sharedmem; int wait_iso_frame; wait_queue_head_t us428ctls_wait_queue_head; - struct snd_usX2Y_hwdep_pcm_shm *hwdep_pcm_shm; - struct snd_usX2Y_substream *subs[4]; - struct snd_usX2Y_substream * volatile prepare_subs; + struct snd_usx2y_hwdep_pcm_shm *hwdep_pcm_shm; + struct snd_usx2y_substream *subs[4]; + struct snd_usx2y_substream * volatile prepare_subs; wait_queue_head_t prepare_wait_queue; struct list_head midi_list; struct list_head pcm_list; @@ -51,21 +51,21 @@ struct usX2Ydev { }; -struct snd_usX2Y_substream { - struct usX2Ydev *usX2Y; +struct snd_usx2y_substream { + struct usx2ydev *usx2y; struct snd_pcm_substream *pcm_substream; int endpoint; unsigned int maxpacksize; /* max packet size in bytes */ atomic_t state; -#define state_STOPPED 0 -#define state_STARTING1 1 -#define state_STARTING2 2 -#define state_STARTING3 3 -#define state_PREPARED 4 -#define state_PRERUNNING 6 -#define state_RUNNING 8 +#define STATE_STOPPED 0 +#define STATE_STARTING1 1 +#define STATE_STARTING2 2 +#define STATE_STARTING3 3 +#define STATE_PREPARED 4 +#define STATE_PRERUNNING 6 +#define STATE_RUNNING 8 int hwptr; /* free frame position in the buffer (only for playback) */ int hwptr_done; /* processed frame position in the buffer */ @@ -77,12 +77,12 @@ struct snd_usX2Y_substream { }; -#define usX2Y(c) ((struct usX2Ydev *)(c)->private_data) +#define usx2y(c) ((struct usx2ydev *)(c)->private_data) -int usX2Y_audio_create(struct snd_card *card); +int usx2y_audio_create(struct snd_card *card); -int usX2Y_AsyncSeq04_init(struct usX2Ydev *usX2Y); -int usX2Y_In04_init(struct usX2Ydev *usX2Y); +int usx2y_async_seq04_init(struct usx2ydev *usx2y); +int usx2y_in04_init(struct usx2ydev *usx2y); #define NAME_ALLCAPS "US-X2Y" diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c index ecaf41265dcd0d61889130558694541288f117ef..8033bb7255d5cd3a7e8802463bb2a9ea40add7a9 100644 --- a/sound/usb/usx2y/usbusx2yaudio.c +++ b/sound/usb/usx2y/usbusx2yaudio.c @@ -54,13 +54,13 @@ #endif -static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) +static int usx2y_urb_capt_retire(struct snd_usx2y_substream *subs) { struct urb *urb = subs->completed_urb; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; unsigned char *cp; int i, len, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; for (i = 0; i < nr_of_packs(); i++) { cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset; @@ -70,7 +70,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } - len = urb->iso_frame_desc[i].actual_length / usX2Y->stride; + len = urb->iso_frame_desc[i].actual_length / usx2y->stride; if (! len) { snd_printd("0 == len ERROR!\n"); continue; @@ -79,12 +79,12 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) /* copy a data chunk */ if ((hwptr_done + len) > runtime->buffer_size) { int cnt = runtime->buffer_size - hwptr_done; - int blen = cnt * usX2Y->stride; - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, blen); - memcpy(runtime->dma_area, cp + blen, len * usX2Y->stride - blen); + int blen = cnt * usx2y->stride; + memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, blen); + memcpy(runtime->dma_area, cp + blen, len * usx2y->stride - blen); } else { - memcpy(runtime->dma_area + hwptr_done * usX2Y->stride, cp, - len * usX2Y->stride); + memcpy(runtime->dma_area + hwptr_done * usx2y->stride, cp, + len * usx2y->stride); } lens += len; if ((hwptr_done += len) >= runtime->buffer_size) @@ -110,18 +110,18 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs) * it directly from the buffer. thus the data is once copied to * a temporary buffer and urb points to that. */ -static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, +static int usx2y_urb_play_prepare(struct snd_usx2y_substream *subs, struct urb *cap_urb, struct urb *urb) { int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; count = 0; for (pack = 0; pack < nr_of_packs(); pack++) { /* calculate the size of a packet */ - counts = cap_urb->iso_frame_desc[pack].actual_length / usX2Y->stride; + counts = cap_urb->iso_frame_desc[pack].actual_length / usx2y->stride; count += counts; if (counts < 43 || counts > 50) { snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); @@ -134,7 +134,7 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, 0; urb->iso_frame_desc[pack].length = cap_urb->iso_frame_desc[pack].actual_length; } - if (atomic_read(&subs->state) >= state_PRERUNNING) + if (atomic_read(&subs->state) >= STATE_PRERUNNING) if (subs->hwptr + count > runtime->buffer_size) { /* err, the transferred area goes over buffer boundary. * copy the data to the temp buffer. @@ -143,20 +143,20 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, len = runtime->buffer_size - subs->hwptr; urb->transfer_buffer = subs->tmpbuf; memcpy(subs->tmpbuf, runtime->dma_area + - subs->hwptr * usX2Y->stride, len * usX2Y->stride); - memcpy(subs->tmpbuf + len * usX2Y->stride, - runtime->dma_area, (count - len) * usX2Y->stride); + subs->hwptr * usx2y->stride, len * usx2y->stride); + memcpy(subs->tmpbuf + len * usx2y->stride, + runtime->dma_area, (count - len) * usx2y->stride); subs->hwptr += count; subs->hwptr -= runtime->buffer_size; } else { /* set the buffer pointer */ - urb->transfer_buffer = runtime->dma_area + subs->hwptr * usX2Y->stride; + urb->transfer_buffer = runtime->dma_area + subs->hwptr * usx2y->stride; if ((subs->hwptr += count) >= runtime->buffer_size) subs->hwptr -= runtime->buffer_size; } else urb->transfer_buffer = subs->tmpbuf; - urb->transfer_buffer_length = count * usX2Y->stride; + urb->transfer_buffer_length = count * usx2y->stride; return 0; } @@ -165,10 +165,10 @@ static int usX2Y_urb_play_prepare(struct snd_usX2Y_substream *subs, * * update the current position and call callback if a period is processed. */ -static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb *urb) +static void usx2y_urb_play_retire(struct snd_usx2y_substream *subs, struct urb *urb) { struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; - int len = urb->actual_length / subs->usX2Y->stride; + int len = urb->actual_length / subs->usx2y->stride; subs->transfer_done += len; subs->hwptr_done += len; @@ -180,14 +180,14 @@ static void usX2Y_urb_play_retire(struct snd_usX2Y_substream *subs, struct urb * } } -static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, int frame) +static int usx2y_urb_submit(struct snd_usx2y_substream *subs, struct urb *urb, int frame) { int err; if (!urb) return -ENODEV; urb->start_frame = (frame + NRURBS * nr_of_packs()); // let hcd do rollover sanity checks urb->hcpriv = NULL; - urb->dev = subs->usX2Y->dev; /* we need to set this at each time */ + urb->dev = subs->usx2y->dev; /* we need to set this at each time */ if ((err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) { snd_printk(KERN_ERR "usb_submit_urb() returned %i\n", err); return err; @@ -195,8 +195,8 @@ static int usX2Y_urb_submit(struct snd_usX2Y_substream *subs, struct urb *urb, i return 0; } -static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *playbacksubs, +static inline int usx2y_usbframe_complete(struct snd_usx2y_substream *capsubs, + struct snd_usx2y_substream *playbacksubs, int frame) { int err, state; @@ -204,25 +204,25 @@ static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, state = atomic_read(&playbacksubs->state); if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) + if (state == STATE_RUNNING) + usx2y_urb_play_retire(playbacksubs, urb); + else if (state >= STATE_PRERUNNING) atomic_inc(&playbacksubs->state); } else { switch (state) { - case state_STARTING1: + case STATE_STARTING1: urb = playbacksubs->urb[0]; atomic_inc(&playbacksubs->state); break; - case state_STARTING2: + case STATE_STARTING2: urb = playbacksubs->urb[1]; atomic_inc(&playbacksubs->state); break; } } if (urb) { - if ((err = usX2Y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { + if ((err = usx2y_urb_play_prepare(playbacksubs, capsubs->completed_urb, urb)) || + (err = usx2y_urb_submit(playbacksubs, urb, frame))) { return err; } } @@ -230,13 +230,13 @@ static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, playbacksubs->completed_urb = NULL; state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_urb_capt_retire(capsubs))) + if (state >= STATE_PREPARED) { + if (state == STATE_RUNNING) { + if ((err = usx2y_urb_capt_retire(capsubs))) return err; - } else if (state >= state_PRERUNNING) + } else if (state >= STATE_PRERUNNING) atomic_inc(&capsubs->state); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) + if ((err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame))) return err; } capsubs->completed_urb = NULL; @@ -244,21 +244,21 @@ static inline int usX2Y_usbframe_complete(struct snd_usX2Y_substream *capsubs, } -static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) +static void usx2y_clients_stop(struct usx2ydev *usx2y) { int s, u; for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + struct snd_usx2y_substream *subs = usx2y->subs[s]; if (subs) { snd_printdd("%i %p state=%i\n", s, subs, atomic_read(&subs->state)); - atomic_set(&subs->state, state_STOPPED); + atomic_set(&subs->state, STATE_STOPPED); } } for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + struct snd_usx2y_substream *subs = usx2y->subs[s]; if (subs) { - if (atomic_read(&subs->state) >= state_PRERUNNING) + if (atomic_read(&subs->state) >= STATE_PRERUNNING) snd_pcm_stop_xrun(subs->pcm_substream); for (u = 0; u < NRURBS; u++) { struct urb *urb = subs->urb[u]; @@ -268,60 +268,60 @@ static void usX2Y_clients_stop(struct usX2Ydev *usX2Y) } } } - usX2Y->prepare_subs = NULL; - wake_up(&usX2Y->prepare_wait_queue); + usx2y->prepare_subs = NULL; + wake_up(&usx2y->prepare_wait_queue); } -static void usX2Y_error_urb_status(struct usX2Ydev *usX2Y, - struct snd_usX2Y_substream *subs, struct urb *urb) +static void usx2y_error_urb_status(struct usx2ydev *usx2y, + struct snd_usx2y_substream *subs, struct urb *urb) { snd_printk(KERN_ERR "ep=%i stalled with status=%i\n", subs->endpoint, urb->status); urb->status = 0; - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } -static void i_usX2Y_urb_complete(struct urb *urb) +static void i_usx2y_urb_complete(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; - if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { + if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), + usb_get_current_frame_number(usx2y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); + usx2y_error_urb_status(usx2y, subs, urb); return; } subs->completed_urb = urb; { - struct snd_usX2Y_substream *capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE], - *playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct snd_usx2y_substream *capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE], + *playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; if (capsubs->completed_urb && - atomic_read(&capsubs->state) >= state_PREPARED && + atomic_read(&capsubs->state) >= STATE_PREPARED && (playbacksubs->completed_urb || - atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); + atomic_read(&playbacksubs->state) < STATE_PREPARED)) { + if (!usx2y_usbframe_complete(capsubs, playbacksubs, urb->start_frame)) + usx2y->wait_iso_frame += nr_of_packs(); else { snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } } } } -static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, +static void usx2y_urbs_set_complete(struct usx2ydev * usx2y, void (*complete)(struct urb *)) { int s, u; for (s = 0; s < 4; s++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[s]; + struct snd_usx2y_substream *subs = usx2y->subs[s]; if (NULL != subs) for (u = 0; u < NRURBS; u++) { struct urb * urb = subs->urb[u]; @@ -331,30 +331,30 @@ static void usX2Y_urbs_set_complete(struct usX2Ydev * usX2Y, } } -static void usX2Y_subs_startup_finish(struct usX2Ydev * usX2Y) +static void usx2y_subs_startup_finish(struct usx2ydev * usx2y) { - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_urb_complete); - usX2Y->prepare_subs = NULL; + usx2y_urbs_set_complete(usx2y, i_usx2y_urb_complete); + usx2y->prepare_subs = NULL; } -static void i_usX2Y_subs_startup(struct urb *urb) +static void i_usx2y_subs_startup(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; if (NULL != prepare_subs) if (urb->start_frame == prepare_subs->urb[0]->start_frame) { - usX2Y_subs_startup_finish(usX2Y); + usx2y_subs_startup_finish(usx2y); atomic_inc(&prepare_subs->state); - wake_up(&usX2Y->prepare_wait_queue); + wake_up(&usx2y->prepare_wait_queue); } - i_usX2Y_urb_complete(urb); + i_usx2y_urb_complete(urb); } -static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) +static void usx2y_subs_prepare(struct snd_usx2y_substream *subs) { - snd_printdd("usX2Y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", + snd_printdd("usx2y_substream_prepare(%p) ep=%i urb0=%p urb1=%p\n", subs, subs->endpoint, subs->urb[0], subs->urb[1]); /* reset the pointer */ subs->hwptr = 0; @@ -363,7 +363,7 @@ static void usX2Y_subs_prepare(struct snd_usX2Y_substream *subs) } -static void usX2Y_urb_release(struct urb **urb, int free_tb) +static void usx2y_urb_release(struct urb **urb, int free_tb) { if (*urb) { usb_kill_urb(*urb); @@ -376,13 +376,13 @@ static void usX2Y_urb_release(struct urb **urb, int free_tb) /* * release a substreams urbs */ -static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs) +static void usx2y_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("usX2Y_urbs_release() %i\n", subs->endpoint); + snd_printdd("usx2y_urbs_release() %i\n", subs->endpoint); for (i = 0; i < NRURBS; i++) - usX2Y_urb_release(subs->urb + i, - subs != subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]); + usx2y_urb_release(subs->urb + i, + subs != subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]); kfree(subs->tmpbuf); subs->tmpbuf = NULL; @@ -390,12 +390,12 @@ static void usX2Y_urbs_release(struct snd_usX2Y_substream *subs) /* * initialize a substream's urbs */ -static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) +static int usx2y_urbs_allocate(struct snd_usx2y_substream *subs) { int i; unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; + int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct usb_device *dev = subs->usx2y->dev; pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); @@ -417,7 +417,7 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) } *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); if (NULL == *purb) { - usX2Y_urbs_release(subs); + usx2y_urbs_release(subs); return -ENOMEM; } if (!is_playback && !(*purb)->transfer_buffer) { @@ -426,7 +426,7 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) kmalloc_array(subs->maxpacksize, nr_of_packs(), GFP_KERNEL); if (NULL == (*purb)->transfer_buffer) { - usX2Y_urbs_release(subs); + usx2y_urbs_release(subs); return -ENOMEM; } } @@ -435,43 +435,43 @@ static int usX2Y_urbs_allocate(struct snd_usX2Y_substream *subs) (*purb)->number_of_packets = nr_of_packs(); (*purb)->context = subs; (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_subs_startup; + (*purb)->complete = i_usx2y_subs_startup; } return 0; } -static void usX2Y_subs_startup(struct snd_usX2Y_substream *subs) +static void usx2y_subs_startup(struct snd_usx2y_substream *subs) { - struct usX2Ydev *usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; + struct usx2ydev *usx2y = subs->usx2y; + usx2y->prepare_subs = subs; subs->urb[0]->start_frame = -1; wmb(); - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_subs_startup); + usx2y_urbs_set_complete(usx2y, i_usx2y_subs_startup); } -static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) +static int usx2y_urbs_start(struct snd_usx2y_substream *subs) { int i, err; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; - if ((err = usX2Y_urbs_allocate(subs)) < 0) + if ((err = usx2y_urbs_allocate(subs)) < 0) return err; subs->completed_urb = NULL; for (i = 0; i < 4; i++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[i]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) + struct snd_usx2y_substream *subs = usx2y->subs[i]; + if (subs != NULL && atomic_read(&subs->state) >= STATE_PREPARED) goto start; } start: - usX2Y_subs_startup(subs); + usx2y_subs_startup(subs); for (i = 0; i < NRURBS; i++) { struct urb *urb = subs->urb[i]; if (usb_pipein(urb->pipe)) { unsigned long pack; if (0 == i) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; + atomic_set(&subs->state, STATE_STARTING3); + urb->dev = usx2y->dev; for (pack = 0; pack < nr_of_packs(); pack++) { urb->iso_frame_desc[pack].offset = subs->maxpacksize * pack; urb->iso_frame_desc[pack].length = subs->maxpacksize; @@ -483,22 +483,22 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) goto cleanup; } else if (i == 0) - usX2Y->wait_iso_frame = urb->start_frame; + usx2y->wait_iso_frame = urb->start_frame; urb->transfer_flags = 0; } else { - atomic_set(&subs->state, state_STARTING1); + atomic_set(&subs->state, STATE_STARTING1); break; } } err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) + wait_event(usx2y->prepare_wait_queue, NULL == usx2y->prepare_subs); + if (atomic_read(&subs->state) != STATE_PREPARED) err = -EPIPE; cleanup: if (err) { - usX2Y_subs_startup_finish(usX2Y); - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything + usx2y_subs_startup_finish(usx2y); + usx2y_clients_stop(usx2y); // something is completely wroong > stop evrything } return err; } @@ -506,33 +506,33 @@ static int usX2Y_urbs_start(struct snd_usX2Y_substream *subs) /* * return the current pcm pointer. just return the hwptr_done value. */ -static snd_pcm_uframes_t snd_usX2Y_pcm_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_usx2y_pcm_pointer(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = substream->runtime->private_data; + struct snd_usx2y_substream *subs = substream->runtime->private_data; return subs->hwptr_done; } /* * start/stop substream */ -static int snd_usX2Y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) +static int snd_usx2y_pcm_trigger(struct snd_pcm_substream *substream, int cmd) { - struct snd_usX2Y_substream *subs = substream->runtime->private_data; + struct snd_usx2y_substream *subs = substream->runtime->private_data; switch (cmd) { case SNDRV_PCM_TRIGGER_START: - snd_printdd("snd_usX2Y_pcm_trigger(START)\n"); - if (atomic_read(&subs->state) == state_PREPARED && - atomic_read(&subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= state_PREPARED) { - atomic_set(&subs->state, state_PRERUNNING); + snd_printdd("snd_usx2y_pcm_trigger(START)\n"); + if (atomic_read(&subs->state) == STATE_PREPARED && + atomic_read(&subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]->state) >= STATE_PREPARED) { + atomic_set(&subs->state, STATE_PRERUNNING); } else { snd_printdd("\n"); return -EPIPE; } break; case SNDRV_PCM_TRIGGER_STOP: - snd_printdd("snd_usX2Y_pcm_trigger(STOP)\n"); - if (atomic_read(&subs->state) >= state_PRERUNNING) - atomic_set(&subs->state, state_PREPARED); + snd_printdd("snd_usx2y_pcm_trigger(STOP)\n"); + if (atomic_read(&subs->state) >= STATE_PRERUNNING) + atomic_set(&subs->state, STATE_PREPARED); break; default: return -EINVAL; @@ -553,7 +553,7 @@ static const struct s_c2 { char c1, c2; } - SetRate44100[] = + setrate_44100[] = { { 0x14, 0x08}, // this line sets 44100, well actually a little less { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... @@ -589,7 +589,7 @@ static const struct s_c2 { 0x18, 0x7C}, { 0x18, 0x7E} }; -static const struct s_c2 SetRate48000[] = +static const struct s_c2 setrate_48000[] = { { 0x14, 0x09}, // this line sets 48000, well actually a little less { 0x18, 0x40}, // only tascam / frontier design knows the further lines ....... @@ -625,26 +625,26 @@ static const struct s_c2 SetRate48000[] = { 0x18, 0x7C}, { 0x18, 0x7E} }; -#define NOOF_SETRATE_URBS ARRAY_SIZE(SetRate48000) +#define NOOF_SETRATE_URBS ARRAY_SIZE(setrate_48000) -static void i_usX2Y_04Int(struct urb *urb) +static void i_usx2y_04int(struct urb *urb) { - struct usX2Ydev *usX2Y = urb->context; + struct usx2ydev *usx2y = urb->context; if (urb->status) - snd_printk(KERN_ERR "snd_usX2Y_04Int() urb->status=%i\n", urb->status); - if (0 == --usX2Y->US04->len) - wake_up(&usX2Y->In04WaitQueue); + snd_printk(KERN_ERR "snd_usx2y_04int() urb->status=%i\n", urb->status); + if (0 == --usx2y->us04->len) + wake_up(&usx2y->in04_wait_queue); } -static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) +static int usx2y_rate_set(struct usx2ydev *usx2y, int rate) { int err = 0, i; - struct snd_usX2Y_urbSeq *us = NULL; + struct snd_usx2y_urb_seq *us = NULL; int *usbdata = NULL; - const struct s_c2 *ra = rate == 48000 ? SetRate48000 : SetRate44100; + const struct s_c2 *ra = rate == 48000 ? setrate_48000 : setrate_44100; - if (usX2Y->rate != rate) { + if (usx2y->rate != rate) { us = kzalloc(sizeof(*us) + sizeof(struct urb*) * NOOF_SETRATE_URBS, GFP_KERNEL); if (NULL == us) { err = -ENOMEM; @@ -663,17 +663,17 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) } ((char*)(usbdata + i))[0] = ra[i].c1; ((char*)(usbdata + i))[1] = ra[i].c2; - usb_fill_bulk_urb(us->urb[i], usX2Y->dev, usb_sndbulkpipe(usX2Y->dev, 4), - usbdata + i, 2, i_usX2Y_04Int, usX2Y); + usb_fill_bulk_urb(us->urb[i], usx2y->dev, usb_sndbulkpipe(usx2y->dev, 4), + usbdata + i, 2, i_usx2y_04int, usx2y); } err = usb_urb_ep_type_check(us->urb[0]); if (err < 0) goto cleanup; us->submitted = 0; us->len = NOOF_SETRATE_URBS; - usX2Y->US04 = us; - wait_event_timeout(usX2Y->In04WaitQueue, 0 == us->len, HZ); - usX2Y->US04 = NULL; + usx2y->us04 = us; + wait_event_timeout(usx2y->in04_wait_queue, 0 == us->len, HZ); + usx2y->us04 = NULL; if (us->len) err = -ENODEV; cleanup: @@ -690,11 +690,11 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) } usb_free_urb(urb); } - usX2Y->US04 = NULL; + usx2y->us04 = NULL; kfree(usbdata); kfree(us); if (!err) - usX2Y->rate = rate; + usx2y->rate = rate; } } @@ -702,53 +702,53 @@ static int usX2Y_rate_set(struct usX2Ydev *usX2Y, int rate) } -static int usX2Y_format_set(struct usX2Ydev *usX2Y, snd_pcm_format_t format) +static int usx2y_format_set(struct usx2ydev *usx2y, snd_pcm_format_t format) { int alternate, err; struct list_head* p; if (format == SNDRV_PCM_FORMAT_S24_3LE) { alternate = 2; - usX2Y->stride = 6; + usx2y->stride = 6; } else { alternate = 1; - usX2Y->stride = 4; + usx2y->stride = 4; } - list_for_each(p, &usX2Y->midi_list) { + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_input_stop(p); } - usb_kill_urb(usX2Y->In04urb); - if ((err = usb_set_interface(usX2Y->dev, 0, alternate))) { + usb_kill_urb(usx2y->in04_urb); + if ((err = usb_set_interface(usx2y->dev, 0, alternate))) { snd_printk(KERN_ERR "usb_set_interface error \n"); return err; } - usX2Y->In04urb->dev = usX2Y->dev; - err = usb_submit_urb(usX2Y->In04urb, GFP_KERNEL); - list_for_each(p, &usX2Y->midi_list) { + usx2y->in04_urb->dev = usx2y->dev; + err = usb_submit_urb(usx2y->in04_urb, GFP_KERNEL); + list_for_each(p, &usx2y->midi_list) { snd_usbmidi_input_start(p); } - usX2Y->format = format; - usX2Y->rate = 0; + usx2y->format = format; + usx2y->rate = 0; return err; } -static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, +static int snd_usx2y_pcm_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *hw_params) { int err = 0; unsigned int rate = params_rate(hw_params); snd_pcm_format_t format = params_format(hw_params); struct snd_card *card = substream->pstr->pcm->card; - struct usX2Ydev *dev = usX2Y(card); + struct usx2ydev *dev = usx2y(card); int i; - mutex_lock(&usX2Y(card)->pcm_mutex); - snd_printdd("snd_usX2Y_hw_params(%p, %p)\n", substream, hw_params); - /* all pcm substreams off one usX2Y have to operate at the same + mutex_lock(&usx2y(card)->pcm_mutex); + snd_printdd("snd_usx2y_hw_params(%p, %p)\n", substream, hw_params); + /* all pcm substreams off one usx2y have to operate at the same * rate & format */ for (i = 0; i < dev->pcm_devs * 2; i++) { - struct snd_usX2Y_substream *subs = dev->subs[i]; + struct snd_usx2y_substream *subs = dev->subs[i]; struct snd_pcm_substream *test_substream; if (!subs) @@ -767,39 +767,39 @@ static int snd_usX2Y_pcm_hw_params(struct snd_pcm_substream *substream, } error: - mutex_unlock(&usX2Y(card)->pcm_mutex); + mutex_unlock(&usx2y(card)->pcm_mutex); return err; } /* * free the buffer */ -static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - mutex_lock(&subs->usX2Y->pcm_mutex); - snd_printdd("snd_usX2Y_hw_free(%p)\n", substream); + struct snd_usx2y_substream *subs = runtime->private_data; + mutex_lock(&subs->usx2y->pcm_mutex); + snd_printdd("snd_usx2y_hw_free(%p)\n", substream); if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); + struct snd_usx2y_substream *cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + atomic_set(&subs->state, STATE_STOPPED); + usx2y_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || !cap_subs->pcm_substream->runtime->status || cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); - usX2Y_urbs_release(cap_subs); + atomic_set(&cap_subs->state, STATE_STOPPED); + usx2y_urbs_release(cap_subs); } } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); - usX2Y_urbs_release(subs); + struct snd_usx2y_substream *playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (atomic_read(&playback_subs->state) < STATE_PREPARED) { + atomic_set(&subs->state, STATE_STOPPED); + usx2y_urbs_release(subs); } } - mutex_unlock(&subs->usX2Y->pcm_mutex); + mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } /* @@ -807,40 +807,40 @@ static int snd_usX2Y_pcm_hw_free(struct snd_pcm_substream *substream) * * set format and initialize urbs */ -static int snd_usX2Y_pcm_prepare(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_usx2y_substream *subs = runtime->private_data; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); + snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream); - mutex_lock(&usX2Y->pcm_mutex); - usX2Y_subs_prepare(subs); + mutex_lock(&usx2y->pcm_mutex); + usx2y_subs_prepare(subs); // Start hardware streams // SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) + if (atomic_read(&capsubs->state) < STATE_PREPARED) { + if (usx2y->format != runtime->format) + if ((err = usx2y_format_set(usx2y, runtime->format)) < 0) goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) + if (usx2y->rate != runtime->rate) + if ((err = usx2y_rate_set(usx2y, runtime->rate)) < 0) goto up_prepare_mutex; snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_urbs_start(capsubs))) + if (0 > (err = usx2y_urbs_start(capsubs))) goto up_prepare_mutex; } - if (subs != capsubs && atomic_read(&subs->state) < state_PREPARED) - err = usX2Y_urbs_start(subs); + if (subs != capsubs && atomic_read(&subs->state) < STATE_PREPARED) + err = usx2y_urbs_start(subs); up_prepare_mutex: - mutex_unlock(&usX2Y->pcm_mutex); + mutex_unlock(&usx2y->pcm_mutex); return err; } -static const struct snd_pcm_hardware snd_usX2Y_2c = +static const struct snd_pcm_hardware snd_usx2y_2c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -862,16 +862,16 @@ static const struct snd_pcm_hardware snd_usX2Y_2c = -static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_open(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) + struct snd_usx2y_substream *subs = ((struct snd_usx2y_substream **) snd_pcm_substream_chip(substream))[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime; - if (subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) + if (subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS) return -EBUSY; - runtime->hw = snd_usX2Y_2c; + runtime->hw = snd_usx2y_2c; runtime->private_data = subs; subs->pcm_substream = substream; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); @@ -880,10 +880,10 @@ static int snd_usX2Y_pcm_open(struct snd_pcm_substream *substream) -static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream) +static int snd_usx2y_pcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *subs = runtime->private_data; subs->pcm_substream = NULL; @@ -891,75 +891,75 @@ static int snd_usX2Y_pcm_close(struct snd_pcm_substream *substream) } -static const struct snd_pcm_ops snd_usX2Y_pcm_ops = +static const struct snd_pcm_ops snd_usx2y_pcm_ops = { - .open = snd_usX2Y_pcm_open, - .close = snd_usX2Y_pcm_close, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_pcm_hw_free, - .prepare = snd_usX2Y_pcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, + .open = snd_usx2y_pcm_open, + .close = snd_usx2y_pcm_close, + .hw_params = snd_usx2y_pcm_hw_params, + .hw_free = snd_usx2y_pcm_hw_free, + .prepare = snd_usx2y_pcm_prepare, + .trigger = snd_usx2y_pcm_trigger, + .pointer = snd_usx2y_pcm_pointer, }; /* * free a usb stream instance */ -static void usX2Y_audio_stream_free(struct snd_usX2Y_substream **usX2Y_substream) +static void usx2y_audio_stream_free(struct snd_usx2y_substream **usx2y_substream) { int stream; for_each_pcm_streams(stream) { - kfree(usX2Y_substream[stream]); - usX2Y_substream[stream] = NULL; + kfree(usx2y_substream[stream]); + usx2y_substream[stream] = NULL; } } -static void snd_usX2Y_pcm_private_free(struct snd_pcm *pcm) +static void snd_usx2y_pcm_private_free(struct snd_pcm *pcm) { - struct snd_usX2Y_substream **usX2Y_stream = pcm->private_data; - if (usX2Y_stream) - usX2Y_audio_stream_free(usX2Y_stream); + struct snd_usx2y_substream **usx2y_stream = pcm->private_data; + if (usx2y_stream) + usx2y_audio_stream_free(usx2y_stream); } -static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) +static int usx2y_audio_stream_new(struct snd_card *card, int playback_endpoint, int capture_endpoint) { struct snd_pcm *pcm; int err, i; - struct snd_usX2Y_substream **usX2Y_substream = - usX2Y(card)->subs + 2 * usX2Y(card)->pcm_devs; + struct snd_usx2y_substream **usx2y_substream = + usx2y(card)->subs + 2 * usx2y(card)->pcm_devs; for (i = playback_endpoint ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE; i <= SNDRV_PCM_STREAM_CAPTURE; ++i) { - usX2Y_substream[i] = kzalloc(sizeof(struct snd_usX2Y_substream), GFP_KERNEL); - if (!usX2Y_substream[i]) + usx2y_substream[i] = kzalloc(sizeof(struct snd_usx2y_substream), GFP_KERNEL); + if (!usx2y_substream[i]) return -ENOMEM; - usX2Y_substream[i]->usX2Y = usX2Y(card); + usx2y_substream[i]->usx2y = usx2y(card); } if (playback_endpoint) - usX2Y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; - usX2Y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; + usx2y_substream[SNDRV_PCM_STREAM_PLAYBACK]->endpoint = playback_endpoint; + usx2y_substream[SNDRV_PCM_STREAM_CAPTURE]->endpoint = capture_endpoint; - err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usX2Y(card)->pcm_devs, + err = snd_pcm_new(card, NAME_ALLCAPS" Audio", usx2y(card)->pcm_devs, playback_endpoint ? 1 : 0, 1, &pcm); if (err < 0) { - usX2Y_audio_stream_free(usX2Y_substream); + usx2y_audio_stream_free(usx2y_substream); return err; } if (playback_endpoint) - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_pcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_pcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_pcm_ops); - pcm->private_data = usX2Y_substream; - pcm->private_free = snd_usX2Y_pcm_private_free; + pcm->private_data = usx2y_substream; + pcm->private_free = snd_usx2y_pcm_private_free; pcm->info_flags = 0; - sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usX2Y(card)->pcm_devs); + sprintf(pcm->name, NAME_ALLCAPS" Audio #%d", usx2y(card)->pcm_devs); if (playback_endpoint) { snd_pcm_set_managed_buffer(pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream, @@ -972,7 +972,7 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, SNDRV_DMA_TYPE_CONTINUOUS, NULL, 64*1024, 128*1024); - usX2Y(card)->pcm_devs++; + usx2y(card)->pcm_devs++; return 0; } @@ -980,18 +980,18 @@ static int usX2Y_audio_stream_new(struct snd_card *card, int playback_endpoint, /* * create a chip instance and set its names. */ -int usX2Y_audio_create(struct snd_card *card) +int usx2y_audio_create(struct snd_card *card) { int err = 0; - INIT_LIST_HEAD(&usX2Y(card)->pcm_list); + INIT_LIST_HEAD(&usx2y(card)->pcm_list); - if (0 > (err = usX2Y_audio_stream_new(card, 0xA, 0x8))) + if (0 > (err = usx2y_audio_stream_new(card, 0xA, 0x8))) return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) == USB_ID_US428) - if (0 > (err = usX2Y_audio_stream_new(card, 0, 0xA))) + if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) == USB_ID_US428) + if (0 > (err = usx2y_audio_stream_new(card, 0, 0xA))) return err; - if (le16_to_cpu(usX2Y(card)->dev->descriptor.idProduct) != USB_ID_US122) - err = usX2Y_rate_set(usX2Y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. + if (le16_to_cpu(usx2y(card)->dev->descriptor.idProduct) != USB_ID_US122) + err = usx2y_rate_set(usx2y(card), 44100); // Lets us428 recognize output-volume settings, disturbs us122. return err; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c index 8253669c6a7d7f759460d1a5b9ebe64183fe8fe0..399470e51c41197291d87420d9d251b19a601868 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.c +++ b/sound/usb/usx2y/usx2yhwdeppcm.c @@ -47,17 +47,17 @@ #include <sound/hwdep.h> -static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urb_capt_retire(struct snd_usx2y_substream *subs) { struct urb *urb = subs->completed_urb; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; int i, lens = 0, hwptr_done = subs->hwptr_done; - struct usX2Ydev *usX2Y = subs->usX2Y; - if (0 > usX2Y->hwdep_pcm_shm->capture_iso_start) { //FIXME - int head = usX2Y->hwdep_pcm_shm->captured_iso_head + 1; - if (head >= ARRAY_SIZE(usX2Y->hwdep_pcm_shm->captured_iso)) + struct usx2ydev *usx2y = subs->usx2y; + if (0 > usx2y->hwdep_pcm_shm->capture_iso_start) { //FIXME + int head = usx2y->hwdep_pcm_shm->captured_iso_head + 1; + if (head >= ARRAY_SIZE(usx2y->hwdep_pcm_shm->captured_iso)) head = 0; - usX2Y->hwdep_pcm_shm->capture_iso_start = head; + usx2y->hwdep_pcm_shm->capture_iso_start = head; snd_printdd("cap start %i\n", head); } for (i = 0; i < nr_of_packs(); i++) { @@ -65,7 +65,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status); return urb->iso_frame_desc[i].status; } - lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride; + lens += urb->iso_frame_desc[i].actual_length / usx2y->stride; } if ((hwptr_done += lens) >= runtime->buffer_size) hwptr_done -= runtime->buffer_size; @@ -79,10 +79,10 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs) return 0; } -static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, - struct usX2Ydev * usX2Y) +static inline int usx2y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, + struct usx2ydev * usx2y) { - return (runtime->buffer_size * 1000) / usX2Y->rate + 1; //FIXME: so far only correct period_size == 2^x ? + return (runtime->buffer_size * 1000) / usx2y->rate + 1; //FIXME: so far only correct period_size == 2^x ? } /* @@ -95,17 +95,17 @@ static inline int usX2Y_iso_frames_per_buffer(struct snd_pcm_runtime *runtime, * it directly from the buffer. thus the data is once copied to * a temporary buffer and urb points to that. */ -static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, +static int usx2y_hwdep_urb_play_prepare(struct snd_usx2y_substream *subs, struct urb *urb) { int count, counts, pack; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_hwdep_pcm_shm *shm = usX2Y->hwdep_pcm_shm; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_hwdep_pcm_shm *shm = usx2y->hwdep_pcm_shm; struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime; if (0 > shm->playback_iso_start) { shm->playback_iso_start = shm->captured_iso_head - - usX2Y_iso_frames_per_buffer(runtime, usX2Y); + usx2y_iso_frames_per_buffer(runtime, usx2y); if (0 > shm->playback_iso_start) shm->playback_iso_start += ARRAY_SIZE(shm->captured_iso); shm->playback_iso_head = shm->playback_iso_start; @@ -114,7 +114,7 @@ static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, count = 0; for (pack = 0; pack < nr_of_packs(); pack++) { /* calculate the size of a packet */ - counts = shm->captured_iso[shm->playback_iso_head].length / usX2Y->stride; + counts = shm->captured_iso[shm->playback_iso_head].length / usx2y->stride; if (counts < 43 || counts > 50) { snd_printk(KERN_ERR "should not be here with counts=%i\n", counts); return -EPIPE; @@ -122,26 +122,26 @@ static int usX2Y_hwdep_urb_play_prepare(struct snd_usX2Y_substream *subs, /* set up descriptor */ urb->iso_frame_desc[pack].offset = shm->captured_iso[shm->playback_iso_head].offset; urb->iso_frame_desc[pack].length = shm->captured_iso[shm->playback_iso_head].length; - if (atomic_read(&subs->state) != state_RUNNING) + if (atomic_read(&subs->state) != STATE_RUNNING) memset((char *)urb->transfer_buffer + urb->iso_frame_desc[pack].offset, 0, urb->iso_frame_desc[pack].length); if (++shm->playback_iso_head >= ARRAY_SIZE(shm->captured_iso)) shm->playback_iso_head = 0; count += counts; } - urb->transfer_buffer_length = count * usX2Y->stride; + urb->transfer_buffer_length = count * usx2y->stride; return 0; } -static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream *subs, +static inline void usx2y_usbpcm_urb_capt_iso_advance(struct snd_usx2y_substream *subs, struct urb *urb) { int pack; for (pack = 0; pack < nr_of_packs(); ++pack) { struct usb_iso_packet_descriptor *desc = urb->iso_frame_desc + pack; if (NULL != subs) { - struct snd_usX2Y_hwdep_pcm_shm *shm = subs->usX2Y->hwdep_pcm_shm; + struct snd_usx2y_hwdep_pcm_shm *shm = subs->usx2y->hwdep_pcm_shm; int head = shm->captured_iso_head + 1; if (head >= ARRAY_SIZE(shm->captured_iso)) head = 0; @@ -157,9 +157,9 @@ static inline void usX2Y_usbpcm_urb_capt_iso_advance(struct snd_usX2Y_substream } } -static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *capsubs, - struct snd_usX2Y_substream *capsubs2, - struct snd_usX2Y_substream *playbacksubs, +static inline int usx2y_usbpcm_usbframe_complete(struct snd_usx2y_substream *capsubs, + struct snd_usx2y_substream *capsubs2, + struct snd_usx2y_substream *playbacksubs, int frame) { int err, state; @@ -167,25 +167,25 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap state = atomic_read(&playbacksubs->state); if (NULL != urb) { - if (state == state_RUNNING) - usX2Y_urb_play_retire(playbacksubs, urb); - else if (state >= state_PRERUNNING) + if (state == STATE_RUNNING) + usx2y_urb_play_retire(playbacksubs, urb); + else if (state >= STATE_PRERUNNING) atomic_inc(&playbacksubs->state); } else { switch (state) { - case state_STARTING1: + case STATE_STARTING1: urb = playbacksubs->urb[0]; atomic_inc(&playbacksubs->state); break; - case state_STARTING2: + case STATE_STARTING2: urb = playbacksubs->urb[1]; atomic_inc(&playbacksubs->state); break; } } if (urb) { - if ((err = usX2Y_hwdep_urb_play_prepare(playbacksubs, urb)) || - (err = usX2Y_urb_submit(playbacksubs, urb, frame))) { + if ((err = usx2y_hwdep_urb_play_prepare(playbacksubs, urb)) || + (err = usx2y_urb_submit(playbacksubs, urb, frame))) { return err; } } @@ -193,19 +193,19 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap playbacksubs->completed_urb = NULL; state = atomic_read(&capsubs->state); - if (state >= state_PREPARED) { - if (state == state_RUNNING) { - if ((err = usX2Y_usbpcm_urb_capt_retire(capsubs))) + if (state >= STATE_PREPARED) { + if (state == STATE_RUNNING) { + if ((err = usx2y_usbpcm_urb_capt_retire(capsubs))) return err; - } else if (state >= state_PRERUNNING) + } else if (state >= STATE_PRERUNNING) atomic_inc(&capsubs->state); - usX2Y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); + usx2y_usbpcm_urb_capt_iso_advance(capsubs, capsubs->completed_urb); if (NULL != capsubs2) - usX2Y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); - if ((err = usX2Y_urb_submit(capsubs, capsubs->completed_urb, frame))) + usx2y_usbpcm_urb_capt_iso_advance(NULL, capsubs2->completed_urb); + if ((err = usx2y_urb_submit(capsubs, capsubs->completed_urb, frame))) return err; if (NULL != capsubs2) - if ((err = usX2Y_urb_submit(capsubs2, capsubs2->completed_urb, frame))) + if ((err = usx2y_urb_submit(capsubs2, capsubs2->completed_urb, frame))) return err; } capsubs->completed_urb = NULL; @@ -215,42 +215,42 @@ static inline int usX2Y_usbpcm_usbframe_complete(struct snd_usX2Y_substream *cap } -static void i_usX2Y_usbpcm_urb_complete(struct urb *urb) +static void i_usx2y_usbpcm_urb_complete(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs, *capsubs2, *playbacksubs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs, *capsubs2, *playbacksubs; - if (unlikely(atomic_read(&subs->state) < state_PREPARED)) { + if (unlikely(atomic_read(&subs->state) < STATE_PREPARED)) { snd_printdd("hcd_frame=%i ep=%i%s status=%i start_frame=%i\n", - usb_get_current_frame_number(usX2Y->dev), + usb_get_current_frame_number(usx2y->dev), subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out", urb->status, urb->start_frame); return; } if (unlikely(urb->status)) { - usX2Y_error_urb_status(usX2Y, subs, urb); + usx2y_error_urb_status(usx2y, subs, urb); return; } subs->completed_urb = urb; - capsubs = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - capsubs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - playbacksubs = usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (capsubs->completed_urb && atomic_read(&capsubs->state) >= state_PREPARED && + capsubs = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + capsubs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + playbacksubs = usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (capsubs->completed_urb && atomic_read(&capsubs->state) >= STATE_PREPARED && (NULL == capsubs2 || capsubs2->completed_urb) && - (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < state_PREPARED)) { - if (!usX2Y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) - usX2Y->wait_iso_frame += nr_of_packs(); + (playbacksubs->completed_urb || atomic_read(&playbacksubs->state) < STATE_PREPARED)) { + if (!usx2y_usbpcm_usbframe_complete(capsubs, capsubs2, playbacksubs, urb->start_frame)) + usx2y->wait_iso_frame += nr_of_packs(); else { snd_printdd("\n"); - usX2Y_clients_stop(usX2Y); + usx2y_clients_stop(usx2y); } } } -static void usX2Y_hwdep_urb_release(struct urb **urb) +static void usx2y_hwdep_urb_release(struct urb **urb) { usb_kill_urb(*urb); usb_free_urb(*urb); @@ -260,49 +260,49 @@ static void usX2Y_hwdep_urb_release(struct urb **urb) /* * release a substream */ -static void usX2Y_usbpcm_urbs_release(struct snd_usX2Y_substream *subs) +static void usx2y_usbpcm_urbs_release(struct snd_usx2y_substream *subs) { int i; - snd_printdd("snd_usX2Y_urbs_release() %i\n", subs->endpoint); + snd_printdd("snd_usx2y_urbs_release() %i\n", subs->endpoint); for (i = 0; i < NRURBS; i++) - usX2Y_hwdep_urb_release(subs->urb + i); + usx2y_hwdep_urb_release(subs->urb + i); } -static void usX2Y_usbpcm_subs_startup_finish(struct usX2Ydev * usX2Y) +static void usx2y_usbpcm_subs_startup_finish(struct usx2ydev * usx2y) { - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_urb_complete); - usX2Y->prepare_subs = NULL; + usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_urb_complete); + usx2y->prepare_subs = NULL; } -static void i_usX2Y_usbpcm_subs_startup(struct urb *urb) +static void i_usx2y_usbpcm_subs_startup(struct urb *urb) { - struct snd_usX2Y_substream *subs = urb->context; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *prepare_subs = usX2Y->prepare_subs; + struct snd_usx2y_substream *subs = urb->context; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *prepare_subs = usx2y->prepare_subs; if (NULL != prepare_subs && urb->start_frame == prepare_subs->urb[0]->start_frame) { atomic_inc(&prepare_subs->state); - if (prepare_subs == usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]) { - struct snd_usX2Y_substream *cap_subs2 = usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + if (prepare_subs == usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]) { + struct snd_usx2y_substream *cap_subs2 = usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; if (cap_subs2 != NULL) atomic_inc(&cap_subs2->state); } - usX2Y_usbpcm_subs_startup_finish(usX2Y); - wake_up(&usX2Y->prepare_wait_queue); + usx2y_usbpcm_subs_startup_finish(usx2y); + wake_up(&usx2y->prepare_wait_queue); } - i_usX2Y_usbpcm_urb_complete(urb); + i_usx2y_usbpcm_urb_complete(urb); } /* * initialize a substream's urbs */ -static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urbs_allocate(struct snd_usx2y_substream *subs) { int i; unsigned int pipe; - int is_playback = subs == subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - struct usb_device *dev = subs->usX2Y->dev; + int is_playback = subs == subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + struct usb_device *dev = subs->usx2y->dev; pipe = is_playback ? usb_sndisocpipe(dev, subs->endpoint) : usb_rcvisocpipe(dev, subs->endpoint); @@ -319,21 +319,21 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) } *purb = usb_alloc_urb(nr_of_packs(), GFP_KERNEL); if (NULL == *purb) { - usX2Y_usbpcm_urbs_release(subs); + usx2y_usbpcm_urbs_release(subs); return -ENOMEM; } (*purb)->transfer_buffer = is_playback ? - subs->usX2Y->hwdep_pcm_shm->playback : ( + subs->usx2y->hwdep_pcm_shm->playback : ( subs->endpoint == 0x8 ? - subs->usX2Y->hwdep_pcm_shm->capture0x8 : - subs->usX2Y->hwdep_pcm_shm->capture0xA); + subs->usx2y->hwdep_pcm_shm->capture0x8 : + subs->usx2y->hwdep_pcm_shm->capture0xA); (*purb)->dev = dev; (*purb)->pipe = pipe; (*purb)->number_of_packets = nr_of_packs(); (*purb)->context = subs; (*purb)->interval = 1; - (*purb)->complete = i_usX2Y_usbpcm_subs_startup; + (*purb)->complete = i_usx2y_usbpcm_subs_startup; } return 0; } @@ -341,91 +341,91 @@ static int usX2Y_usbpcm_urbs_allocate(struct snd_usX2Y_substream *subs) /* * free the buffer */ -static int snd_usX2Y_usbpcm_hw_free(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_hw_free(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data, - *cap_subs2 = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; - mutex_lock(&subs->usX2Y->pcm_mutex); - snd_printdd("snd_usX2Y_usbpcm_hw_free(%p)\n", substream); + struct snd_usx2y_substream *subs = runtime->private_data, + *cap_subs2 = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE + 2]; + mutex_lock(&subs->usx2y->pcm_mutex); + snd_printdd("snd_usx2y_usbpcm_hw_free(%p)\n", substream); if (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) { - struct snd_usX2Y_substream *cap_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; - atomic_set(&subs->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); + struct snd_usx2y_substream *cap_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; + atomic_set(&subs->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(subs); if (!cap_subs->pcm_substream || !cap_subs->pcm_substream->runtime || !cap_subs->pcm_substream->runtime->status || cap_subs->pcm_substream->runtime->status->state < SNDRV_PCM_STATE_PREPARED) { - atomic_set(&cap_subs->state, state_STOPPED); + atomic_set(&cap_subs->state, STATE_STOPPED); if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(cap_subs); + atomic_set(&cap_subs2->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(cap_subs); if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); + usx2y_usbpcm_urbs_release(cap_subs2); } } else { - struct snd_usX2Y_substream *playback_subs = subs->usX2Y->subs[SNDRV_PCM_STREAM_PLAYBACK]; - if (atomic_read(&playback_subs->state) < state_PREPARED) { - atomic_set(&subs->state, state_STOPPED); + struct snd_usx2y_substream *playback_subs = subs->usx2y->subs[SNDRV_PCM_STREAM_PLAYBACK]; + if (atomic_read(&playback_subs->state) < STATE_PREPARED) { + atomic_set(&subs->state, STATE_STOPPED); if (NULL != cap_subs2) - atomic_set(&cap_subs2->state, state_STOPPED); - usX2Y_usbpcm_urbs_release(subs); + atomic_set(&cap_subs2->state, STATE_STOPPED); + usx2y_usbpcm_urbs_release(subs); if (NULL != cap_subs2) - usX2Y_usbpcm_urbs_release(cap_subs2); + usx2y_usbpcm_urbs_release(cap_subs2); } } - mutex_unlock(&subs->usX2Y->pcm_mutex); + mutex_unlock(&subs->usx2y->pcm_mutex); return 0; } -static void usX2Y_usbpcm_subs_startup(struct snd_usX2Y_substream *subs) +static void usx2y_usbpcm_subs_startup(struct snd_usx2y_substream *subs) { - struct usX2Ydev * usX2Y = subs->usX2Y; - usX2Y->prepare_subs = subs; + struct usx2ydev * usx2y = subs->usx2y; + usx2y->prepare_subs = subs; subs->urb[0]->start_frame = -1; - smp_wmb(); // Make sure above modifications are seen by i_usX2Y_subs_startup() - usX2Y_urbs_set_complete(usX2Y, i_usX2Y_usbpcm_subs_startup); + smp_wmb(); // Make sure above modifications are seen by i_usx2y_subs_startup() + usx2y_urbs_set_complete(usx2y, i_usx2y_usbpcm_subs_startup); } -static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) +static int usx2y_usbpcm_urbs_start(struct snd_usx2y_substream *subs) { int p, u, err, stream = subs->pcm_substream->stream; - struct usX2Ydev *usX2Y = subs->usX2Y; + struct usx2ydev *usx2y = subs->usx2y; if (SNDRV_PCM_STREAM_CAPTURE == stream) { - usX2Y->hwdep_pcm_shm->captured_iso_head = -1; - usX2Y->hwdep_pcm_shm->captured_iso_frames = 0; + usx2y->hwdep_pcm_shm->captured_iso_head = -1; + usx2y->hwdep_pcm_shm->captured_iso_frames = 0; } for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; + struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; if (subs != NULL) { - if ((err = usX2Y_usbpcm_urbs_allocate(subs)) < 0) + if ((err = usx2y_usbpcm_urbs_allocate(subs)) < 0) return err; subs->completed_urb = NULL; } } for (p = 0; p < 4; p++) { - struct snd_usX2Y_substream *subs = usX2Y->subs[p]; - if (subs != NULL && atomic_read(&subs->state) >= state_PREPARED) + struct snd_usx2y_substream *subs = usx2y->subs[p]; + if (subs != NULL && atomic_read(&subs->state) >= STATE_PREPARED) goto start; } start: - usX2Y_usbpcm_subs_startup(subs); + usx2y_usbpcm_subs_startup(subs); for (u = 0; u < NRURBS; u++) { for (p = 0; 3 >= (stream + p); p += 2) { - struct snd_usX2Y_substream *subs = usX2Y->subs[stream + p]; + struct snd_usx2y_substream *subs = usx2y->subs[stream + p]; if (subs != NULL) { struct urb *urb = subs->urb[u]; if (usb_pipein(urb->pipe)) { unsigned long pack; if (0 == u) - atomic_set(&subs->state, state_STARTING3); - urb->dev = usX2Y->dev; + atomic_set(&subs->state, STATE_STARTING3); + urb->dev = usx2y->dev; for (pack = 0; pack < nr_of_packs(); pack++) { urb->iso_frame_desc[pack].offset = subs->maxpacksize * (pack + u * nr_of_packs()); urb->iso_frame_desc[pack].length = subs->maxpacksize; @@ -438,25 +438,25 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) } else { snd_printdd("%i\n", urb->start_frame); if (u == 0) - usX2Y->wait_iso_frame = urb->start_frame; + usx2y->wait_iso_frame = urb->start_frame; } urb->transfer_flags = 0; } else { - atomic_set(&subs->state, state_STARTING1); + atomic_set(&subs->state, STATE_STARTING1); break; } } } } err = 0; - wait_event(usX2Y->prepare_wait_queue, NULL == usX2Y->prepare_subs); - if (atomic_read(&subs->state) != state_PREPARED) + wait_event(usx2y->prepare_wait_queue, NULL == usx2y->prepare_subs); + if (atomic_read(&subs->state) != STATE_PREPARED) err = -EPIPE; cleanup: if (err) { - usX2Y_subs_startup_finish(usX2Y); // Call it now - usX2Y_clients_stop(usX2Y); // something is completely wroong > stop evrything + usx2y_subs_startup_finish(usx2y); // Call it now + usx2y_clients_stop(usx2y); // something is completely wroong > stop evrything } return err; } @@ -466,69 +466,69 @@ static int usX2Y_usbpcm_urbs_start(struct snd_usX2Y_substream *subs) * * set format and initialize urbs */ -static int snd_usX2Y_usbpcm_prepare(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_prepare(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; - struct usX2Ydev *usX2Y = subs->usX2Y; - struct snd_usX2Y_substream *capsubs = subs->usX2Y->subs[SNDRV_PCM_STREAM_CAPTURE]; + struct snd_usx2y_substream *subs = runtime->private_data; + struct usx2ydev *usx2y = subs->usx2y; + struct snd_usx2y_substream *capsubs = subs->usx2y->subs[SNDRV_PCM_STREAM_CAPTURE]; int err = 0; - snd_printdd("snd_usX2Y_pcm_prepare(%p)\n", substream); + snd_printdd("snd_usx2y_pcm_prepare(%p)\n", substream); - if (NULL == usX2Y->hwdep_pcm_shm) { - usX2Y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usX2Y_hwdep_pcm_shm), + if (NULL == usx2y->hwdep_pcm_shm) { + usx2y->hwdep_pcm_shm = alloc_pages_exact(sizeof(struct snd_usx2y_hwdep_pcm_shm), GFP_KERNEL); - if (!usX2Y->hwdep_pcm_shm) + if (!usx2y->hwdep_pcm_shm) return -ENOMEM; - memset(usX2Y->hwdep_pcm_shm, 0, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + memset(usx2y->hwdep_pcm_shm, 0, sizeof(struct snd_usx2y_hwdep_pcm_shm)); } - mutex_lock(&usX2Y->pcm_mutex); - usX2Y_subs_prepare(subs); + mutex_lock(&usx2y->pcm_mutex); + usx2y_subs_prepare(subs); // Start hardware streams // SyncStream first.... - if (atomic_read(&capsubs->state) < state_PREPARED) { - if (usX2Y->format != runtime->format) - if ((err = usX2Y_format_set(usX2Y, runtime->format)) < 0) + if (atomic_read(&capsubs->state) < STATE_PREPARED) { + if (usx2y->format != runtime->format) + if ((err = usx2y_format_set(usx2y, runtime->format)) < 0) goto up_prepare_mutex; - if (usX2Y->rate != runtime->rate) - if ((err = usX2Y_rate_set(usX2Y, runtime->rate)) < 0) + if (usx2y->rate != runtime->rate) + if ((err = usx2y_rate_set(usx2y, runtime->rate)) < 0) goto up_prepare_mutex; snd_printdd("starting capture pipe for %s\n", subs == capsubs ? "self" : "playpipe"); - if (0 > (err = usX2Y_usbpcm_urbs_start(capsubs))) + if (0 > (err = usx2y_usbpcm_urbs_start(capsubs))) goto up_prepare_mutex; } if (subs != capsubs) { - usX2Y->hwdep_pcm_shm->playback_iso_start = -1; - if (atomic_read(&subs->state) < state_PREPARED) { - while (usX2Y_iso_frames_per_buffer(runtime, usX2Y) > - usX2Y->hwdep_pcm_shm->captured_iso_frames) { + usx2y->hwdep_pcm_shm->playback_iso_start = -1; + if (atomic_read(&subs->state) < STATE_PREPARED) { + while (usx2y_iso_frames_per_buffer(runtime, usx2y) > + usx2y->hwdep_pcm_shm->captured_iso_frames) { snd_printdd("Wait: iso_frames_per_buffer=%i," "captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); if (msleep_interruptible(10)) { err = -ERESTARTSYS; goto up_prepare_mutex; } } - if (0 > (err = usX2Y_usbpcm_urbs_start(subs))) + if (0 > (err = usx2y_usbpcm_urbs_start(subs))) goto up_prepare_mutex; } snd_printdd("Ready: iso_frames_per_buffer=%i,captured_iso_frames=%i\n", - usX2Y_iso_frames_per_buffer(runtime, usX2Y), - usX2Y->hwdep_pcm_shm->captured_iso_frames); + usx2y_iso_frames_per_buffer(runtime, usx2y), + usx2y->hwdep_pcm_shm->captured_iso_frames); } else - usX2Y->hwdep_pcm_shm->capture_iso_start = -1; + usx2y->hwdep_pcm_shm->capture_iso_start = -1; up_prepare_mutex: - mutex_unlock(&usX2Y->pcm_mutex); + mutex_unlock(&usx2y->pcm_mutex); return err; } -static const struct snd_pcm_hardware snd_usX2Y_4c = +static const struct snd_pcm_hardware snd_usx2y_4c = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | @@ -549,17 +549,17 @@ static const struct snd_pcm_hardware snd_usX2Y_4c = -static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_open(struct snd_pcm_substream *substream) { - struct snd_usX2Y_substream *subs = ((struct snd_usX2Y_substream **) + struct snd_usx2y_substream *subs = ((struct snd_usx2y_substream **) snd_pcm_substream_chip(substream))[substream->stream]; struct snd_pcm_runtime *runtime = substream->runtime; - if (!(subs->usX2Y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) + if (!(subs->usx2y->chip_status & USX2Y_STAT_CHIP_MMAP_PCM_URBS)) return -EBUSY; - runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usX2Y_2c : - (subs->usX2Y->subs[3] ? snd_usX2Y_4c : snd_usX2Y_2c); + runtime->hw = SNDRV_PCM_STREAM_PLAYBACK == substream->stream ? snd_usx2y_2c : + (subs->usx2y->subs[3] ? snd_usx2y_4c : snd_usx2y_2c); runtime->private_data = subs; subs->pcm_substream = substream; snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 1000, 200000); @@ -567,35 +567,35 @@ static int snd_usX2Y_usbpcm_open(struct snd_pcm_substream *substream) } -static int snd_usX2Y_usbpcm_close(struct snd_pcm_substream *substream) +static int snd_usx2y_usbpcm_close(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_usX2Y_substream *subs = runtime->private_data; + struct snd_usx2y_substream *subs = runtime->private_data; subs->pcm_substream = NULL; return 0; } -static const struct snd_pcm_ops snd_usX2Y_usbpcm_ops = +static const struct snd_pcm_ops snd_usx2y_usbpcm_ops = { - .open = snd_usX2Y_usbpcm_open, - .close = snd_usX2Y_usbpcm_close, - .hw_params = snd_usX2Y_pcm_hw_params, - .hw_free = snd_usX2Y_usbpcm_hw_free, - .prepare = snd_usX2Y_usbpcm_prepare, - .trigger = snd_usX2Y_pcm_trigger, - .pointer = snd_usX2Y_pcm_pointer, + .open = snd_usx2y_usbpcm_open, + .close = snd_usx2y_usbpcm_close, + .hw_params = snd_usx2y_pcm_hw_params, + .hw_free = snd_usx2y_usbpcm_hw_free, + .prepare = snd_usx2y_usbpcm_prepare, + .trigger = snd_usx2y_pcm_trigger, + .pointer = snd_usx2y_pcm_pointer, }; -static int usX2Y_pcms_busy_check(struct snd_card *card) +static int usx2y_pcms_busy_check(struct snd_card *card) { - struct usX2Ydev *dev = usX2Y(card); + struct usx2ydev *dev = usx2y(card); int i; for (i = 0; i < dev->pcm_devs * 2; i++) { - struct snd_usX2Y_substream *subs = dev->subs[i]; + struct snd_usx2y_substream *subs = dev->subs[i]; if (subs && subs->pcm_substream && SUBSTREAM_BUSY(subs->pcm_substream)) return -EBUSY; @@ -603,102 +603,102 @@ static int usX2Y_pcms_busy_check(struct snd_card *card) return 0; } -static int snd_usX2Y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) +static int snd_usx2y_hwdep_pcm_open(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; int err; - mutex_lock(&usX2Y(card)->pcm_mutex); - err = usX2Y_pcms_busy_check(card); + mutex_lock(&usx2y(card)->pcm_mutex); + err = usx2y_pcms_busy_check(card); if (!err) - usX2Y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usX2Y(card)->pcm_mutex); + usx2y(card)->chip_status |= USX2Y_STAT_CHIP_MMAP_PCM_URBS; + mutex_unlock(&usx2y(card)->pcm_mutex); return err; } -static int snd_usX2Y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) +static int snd_usx2y_hwdep_pcm_release(struct snd_hwdep *hw, struct file *file) { struct snd_card *card = hw->card; int err; - mutex_lock(&usX2Y(card)->pcm_mutex); - err = usX2Y_pcms_busy_check(card); + mutex_lock(&usx2y(card)->pcm_mutex); + err = usx2y_pcms_busy_check(card); if (!err) - usX2Y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; - mutex_unlock(&usX2Y(card)->pcm_mutex); + usx2y(hw->card)->chip_status &= ~USX2Y_STAT_CHIP_MMAP_PCM_URBS; + mutex_unlock(&usx2y(card)->pcm_mutex); return err; } -static void snd_usX2Y_hwdep_pcm_vm_open(struct vm_area_struct *area) +static void snd_usx2y_hwdep_pcm_vm_open(struct vm_area_struct *area) { } -static void snd_usX2Y_hwdep_pcm_vm_close(struct vm_area_struct *area) +static void snd_usx2y_hwdep_pcm_vm_close(struct vm_area_struct *area) { } -static vm_fault_t snd_usX2Y_hwdep_pcm_vm_fault(struct vm_fault *vmf) +static vm_fault_t snd_usx2y_hwdep_pcm_vm_fault(struct vm_fault *vmf) { unsigned long offset; void *vaddr; offset = vmf->pgoff << PAGE_SHIFT; - vaddr = (char *)((struct usX2Ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; + vaddr = (char *)((struct usx2ydev *)vmf->vma->vm_private_data)->hwdep_pcm_shm + offset; vmf->page = virt_to_page(vaddr); get_page(vmf->page); return 0; } -static const struct vm_operations_struct snd_usX2Y_hwdep_pcm_vm_ops = { - .open = snd_usX2Y_hwdep_pcm_vm_open, - .close = snd_usX2Y_hwdep_pcm_vm_close, - .fault = snd_usX2Y_hwdep_pcm_vm_fault, +static const struct vm_operations_struct snd_usx2y_hwdep_pcm_vm_ops = { + .open = snd_usx2y_hwdep_pcm_vm_open, + .close = snd_usx2y_hwdep_pcm_vm_close, + .fault = snd_usx2y_hwdep_pcm_vm_fault, }; -static int snd_usX2Y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) +static int snd_usx2y_hwdep_pcm_mmap(struct snd_hwdep * hw, struct file *filp, struct vm_area_struct *area) { unsigned long size = (unsigned long)(area->vm_end - area->vm_start); - struct usX2Ydev *usX2Y = hw->private_data; + struct usx2ydev *usx2y = hw->private_data; - if (!(usX2Y->chip_status & USX2Y_STAT_CHIP_INIT)) + if (!(usx2y->chip_status & USX2Y_STAT_CHIP_INIT)) return -EBUSY; /* if userspace tries to mmap beyond end of our buffer, fail */ - if (size > PAGE_ALIGN(sizeof(struct snd_usX2Y_hwdep_pcm_shm))) { - snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + if (size > PAGE_ALIGN(sizeof(struct snd_usx2y_hwdep_pcm_shm))) { + snd_printd("%lu > %lu\n", size, (unsigned long)sizeof(struct snd_usx2y_hwdep_pcm_shm)); return -EINVAL; } - if (!usX2Y->hwdep_pcm_shm) { + if (!usx2y->hwdep_pcm_shm) { return -ENODEV; } - area->vm_ops = &snd_usX2Y_hwdep_pcm_vm_ops; + area->vm_ops = &snd_usx2y_hwdep_pcm_vm_ops; area->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP; area->vm_private_data = hw->private_data; return 0; } -static void snd_usX2Y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) +static void snd_usx2y_hwdep_pcm_private_free(struct snd_hwdep *hwdep) { - struct usX2Ydev *usX2Y = hwdep->private_data; - if (NULL != usX2Y->hwdep_pcm_shm) - free_pages_exact(usX2Y->hwdep_pcm_shm, sizeof(struct snd_usX2Y_hwdep_pcm_shm)); + struct usx2ydev *usx2y = hwdep->private_data; + if (NULL != usx2y->hwdep_pcm_shm) + free_pages_exact(usx2y->hwdep_pcm_shm, sizeof(struct snd_usx2y_hwdep_pcm_shm)); } -int usX2Y_hwdep_pcm_new(struct snd_card *card) +int usx2y_hwdep_pcm_new(struct snd_card *card) { int err; struct snd_hwdep *hw; struct snd_pcm *pcm; - struct usb_device *dev = usX2Y(card)->dev; + struct usb_device *dev = usx2y(card)->dev; if (1 != nr_of_packs()) return 0; @@ -706,11 +706,11 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card) return err; hw->iface = SNDRV_HWDEP_IFACE_USX2Y_PCM; - hw->private_data = usX2Y(card); - hw->private_free = snd_usX2Y_hwdep_pcm_private_free; - hw->ops.open = snd_usX2Y_hwdep_pcm_open; - hw->ops.release = snd_usX2Y_hwdep_pcm_release; - hw->ops.mmap = snd_usX2Y_hwdep_pcm_mmap; + hw->private_data = usx2y(card); + hw->private_free = snd_usx2y_hwdep_pcm_private_free; + hw->ops.open = snd_usx2y_hwdep_pcm_open; + hw->ops.release = snd_usx2y_hwdep_pcm_release; + hw->ops.mmap = snd_usx2y_hwdep_pcm_mmap; hw->exclusive = 1; sprintf(hw->name, "/dev/bus/usb/%03d/%03d/hwdeppcm", dev->bus->busnum, dev->devnum); @@ -718,10 +718,10 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card) if (err < 0) { return err; } - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usX2Y_usbpcm_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usX2Y_usbpcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_usx2y_usbpcm_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_usx2y_usbpcm_ops); - pcm->private_data = usX2Y(card)->subs; + pcm->private_data = usx2y(card)->subs; pcm->info_flags = 0; sprintf(pcm->name, NAME_ALLCAPS" hwdep Audio"); @@ -739,7 +739,7 @@ int usX2Y_hwdep_pcm_new(struct snd_card *card) #else -int usX2Y_hwdep_pcm_new(struct snd_card *card) +int usx2y_hwdep_pcm_new(struct snd_card *card) { return 0; } diff --git a/sound/usb/usx2y/usx2yhwdeppcm.h b/sound/usb/usx2y/usx2yhwdeppcm.h index eb5a46466f0e6a76e9e8bf68330d7f4acc0d5dec..731b1c5a3474152a603dd35587bca73cdb7fb050 100644 --- a/sound/usb/usx2y/usx2yhwdeppcm.h +++ b/sound/usb/usx2y/usx2yhwdeppcm.h @@ -4,7 +4,7 @@ #define MAXSTRIDE 3 #define SSS (((MAXPACK*MAXBUFFERMS*MAXSTRIDE + 4096) / 4096) * 4096) -struct snd_usX2Y_hwdep_pcm_shm { +struct snd_usx2y_hwdep_pcm_shm { char playback[SSS]; char capture0x8[SSS]; char capture0xA[SSS]; @@ -20,4 +20,4 @@ struct snd_usX2Y_hwdep_pcm_shm { int capture_iso_start; }; -int usX2Y_hwdep_pcm_new(struct snd_card *card); +int usx2y_hwdep_pcm_new(struct snd_card *card); diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c index 33068d6ed5d6c395a816991b8dd3b7beb8592dd6..c58a135dc355e68e82de8c00363acf3c95f3757f 100644 --- a/tools/bpf/bpftool/main.c +++ b/tools/bpf/bpftool/main.c @@ -338,8 +338,10 @@ static int do_batch(int argc, char **argv) n_argc = make_args(buf, n_argv, BATCH_ARG_NB_MAX, lines); if (!n_argc) continue; - if (n_argc < 0) + if (n_argc < 0) { + err = n_argc; goto err_close; + } if (json_output) { jsonw_start_object(json_wtr); diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c index d636643ddd35863a19ae122a3dda8854a22a804c..f32c059fbfb4f8b3a50ce86f0e8421e35993aa76 100644 --- a/tools/bpf/resolve_btfids/main.c +++ b/tools/bpf/resolve_btfids/main.c @@ -649,6 +649,9 @@ static int symbols_patch(struct object *obj) if (sets_patch(obj)) return -1; + /* Set type to ensure endian translation occurs. */ + obj->efile.idlist->d_type = ELF_T_WORD; + elf_flagdata(obj->efile.idlist, ELF_C_SET, ELF_F_DIRTY); err = elf_update(obj->efile.elf, ELF_C_WRITE); diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c index dbdffb6673feb63b63fc6b7aa0ec0ed167032881..0bf6b4d4c90a73860571fb89a48c581f0d29495f 100644 --- a/tools/perf/util/llvm-utils.c +++ b/tools/perf/util/llvm-utils.c @@ -504,6 +504,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, goto errout; } + err = -ENOMEM; if (asprintf(&pipe_template, "%s -emit-llvm | %s -march=bpf %s -filetype=obj -o -", template, llc_path, opts) < 0) { pr_err("ERROR:\tnot enough memory to setup command line\n"); @@ -524,6 +525,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf, pr_debug("llvm compiling command template: %s\n", template); + err = -ENOMEM; if (asprintf(&command_echo, "echo -n \"%s\"", template) < 0) goto errout; diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c index c83c2c6564e010895845a243f564750b15789eba..23dc5014e7119193345f62567a5246f21ca59105 100644 --- a/tools/perf/util/scripting-engines/trace-event-python.c +++ b/tools/perf/util/scripting-engines/trace-event-python.c @@ -934,7 +934,7 @@ static PyObject *tuple_new(unsigned int sz) return t; } -static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) +static int tuple_set_s64(PyObject *t, unsigned int pos, s64 val) { #if BITS_PER_LONG == 64 return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); @@ -944,6 +944,22 @@ static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) #endif } +/* + * Databases support only signed 64-bit numbers, so even though we are + * exporting a u64, it must be as s64. + */ +#define tuple_set_d64 tuple_set_s64 + +static int tuple_set_u64(PyObject *t, unsigned int pos, u64 val) +{ +#if BITS_PER_LONG == 64 + return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLong(val)); +#endif +#if BITS_PER_LONG == 32 + return PyTuple_SetItem(t, pos, PyLong_FromUnsignedLongLong(val)); +#endif +} + static int tuple_set_s32(PyObject *t, unsigned int pos, s32 val) { return PyTuple_SetItem(t, pos, _PyLong_FromLong(val)); @@ -967,7 +983,7 @@ static int python_export_evsel(struct db_export *dbe, struct evsel *evsel) t = tuple_new(2); - tuple_set_u64(t, 0, evsel->db_id); + tuple_set_d64(t, 0, evsel->db_id); tuple_set_string(t, 1, evsel__name(evsel)); call_object(tables->evsel_handler, t, "evsel_table"); @@ -985,7 +1001,7 @@ static int python_export_machine(struct db_export *dbe, t = tuple_new(3); - tuple_set_u64(t, 0, machine->db_id); + tuple_set_d64(t, 0, machine->db_id); tuple_set_s32(t, 1, machine->pid); tuple_set_string(t, 2, machine->root_dir ? machine->root_dir : ""); @@ -1004,9 +1020,9 @@ static int python_export_thread(struct db_export *dbe, struct thread *thread, t = tuple_new(5); - tuple_set_u64(t, 0, thread->db_id); - tuple_set_u64(t, 1, machine->db_id); - tuple_set_u64(t, 2, main_thread_db_id); + tuple_set_d64(t, 0, thread->db_id); + tuple_set_d64(t, 1, machine->db_id); + tuple_set_d64(t, 2, main_thread_db_id); tuple_set_s32(t, 3, thread->pid_); tuple_set_s32(t, 4, thread->tid); @@ -1025,10 +1041,10 @@ static int python_export_comm(struct db_export *dbe, struct comm *comm, t = tuple_new(5); - tuple_set_u64(t, 0, comm->db_id); + tuple_set_d64(t, 0, comm->db_id); tuple_set_string(t, 1, comm__str(comm)); - tuple_set_u64(t, 2, thread->db_id); - tuple_set_u64(t, 3, comm->start); + tuple_set_d64(t, 2, thread->db_id); + tuple_set_d64(t, 3, comm->start); tuple_set_s32(t, 4, comm->exec); call_object(tables->comm_handler, t, "comm_table"); @@ -1046,9 +1062,9 @@ static int python_export_comm_thread(struct db_export *dbe, u64 db_id, t = tuple_new(3); - tuple_set_u64(t, 0, db_id); - tuple_set_u64(t, 1, comm->db_id); - tuple_set_u64(t, 2, thread->db_id); + tuple_set_d64(t, 0, db_id); + tuple_set_d64(t, 1, comm->db_id); + tuple_set_d64(t, 2, thread->db_id); call_object(tables->comm_thread_handler, t, "comm_thread_table"); @@ -1068,8 +1084,8 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso, t = tuple_new(5); - tuple_set_u64(t, 0, dso->db_id); - tuple_set_u64(t, 1, machine->db_id); + tuple_set_d64(t, 0, dso->db_id); + tuple_set_d64(t, 1, machine->db_id); tuple_set_string(t, 2, dso->short_name); tuple_set_string(t, 3, dso->long_name); tuple_set_string(t, 4, sbuild_id); @@ -1090,10 +1106,10 @@ static int python_export_symbol(struct db_export *dbe, struct symbol *sym, t = tuple_new(6); - tuple_set_u64(t, 0, *sym_db_id); - tuple_set_u64(t, 1, dso->db_id); - tuple_set_u64(t, 2, sym->start); - tuple_set_u64(t, 3, sym->end); + tuple_set_d64(t, 0, *sym_db_id); + tuple_set_d64(t, 1, dso->db_id); + tuple_set_d64(t, 2, sym->start); + tuple_set_d64(t, 3, sym->end); tuple_set_s32(t, 4, sym->binding); tuple_set_string(t, 5, sym->name); @@ -1130,30 +1146,30 @@ static void python_export_sample_table(struct db_export *dbe, t = tuple_new(24); - tuple_set_u64(t, 0, es->db_id); - tuple_set_u64(t, 1, es->evsel->db_id); - tuple_set_u64(t, 2, es->al->maps->machine->db_id); - tuple_set_u64(t, 3, es->al->thread->db_id); - tuple_set_u64(t, 4, es->comm_db_id); - tuple_set_u64(t, 5, es->dso_db_id); - tuple_set_u64(t, 6, es->sym_db_id); - tuple_set_u64(t, 7, es->offset); - tuple_set_u64(t, 8, es->sample->ip); - tuple_set_u64(t, 9, es->sample->time); + tuple_set_d64(t, 0, es->db_id); + tuple_set_d64(t, 1, es->evsel->db_id); + tuple_set_d64(t, 2, es->al->maps->machine->db_id); + tuple_set_d64(t, 3, es->al->thread->db_id); + tuple_set_d64(t, 4, es->comm_db_id); + tuple_set_d64(t, 5, es->dso_db_id); + tuple_set_d64(t, 6, es->sym_db_id); + tuple_set_d64(t, 7, es->offset); + tuple_set_d64(t, 8, es->sample->ip); + tuple_set_d64(t, 9, es->sample->time); tuple_set_s32(t, 10, es->sample->cpu); - tuple_set_u64(t, 11, es->addr_dso_db_id); - tuple_set_u64(t, 12, es->addr_sym_db_id); - tuple_set_u64(t, 13, es->addr_offset); - tuple_set_u64(t, 14, es->sample->addr); - tuple_set_u64(t, 15, es->sample->period); - tuple_set_u64(t, 16, es->sample->weight); - tuple_set_u64(t, 17, es->sample->transaction); - tuple_set_u64(t, 18, es->sample->data_src); + tuple_set_d64(t, 11, es->addr_dso_db_id); + tuple_set_d64(t, 12, es->addr_sym_db_id); + tuple_set_d64(t, 13, es->addr_offset); + tuple_set_d64(t, 14, es->sample->addr); + tuple_set_d64(t, 15, es->sample->period); + tuple_set_d64(t, 16, es->sample->weight); + tuple_set_d64(t, 17, es->sample->transaction); + tuple_set_d64(t, 18, es->sample->data_src); tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); - tuple_set_u64(t, 21, es->call_path_id); - tuple_set_u64(t, 22, es->sample->insn_cnt); - tuple_set_u64(t, 23, es->sample->cyc_cnt); + tuple_set_d64(t, 21, es->call_path_id); + tuple_set_d64(t, 22, es->sample->insn_cnt); + tuple_set_d64(t, 23, es->sample->cyc_cnt); call_object(tables->sample_handler, t, "sample_table"); @@ -1167,8 +1183,8 @@ static void python_export_synth(struct db_export *dbe, struct export_sample *es) t = tuple_new(3); - tuple_set_u64(t, 0, es->db_id); - tuple_set_u64(t, 1, es->evsel->core.attr.config); + tuple_set_d64(t, 0, es->db_id); + tuple_set_d64(t, 1, es->evsel->core.attr.config); tuple_set_bytes(t, 2, es->sample->raw_data, es->sample->raw_size); call_object(tables->synth_handler, t, "synth_data"); @@ -1200,10 +1216,10 @@ static int python_export_call_path(struct db_export *dbe, struct call_path *cp) t = tuple_new(4); - tuple_set_u64(t, 0, cp->db_id); - tuple_set_u64(t, 1, parent_db_id); - tuple_set_u64(t, 2, sym_db_id); - tuple_set_u64(t, 3, cp->ip); + tuple_set_d64(t, 0, cp->db_id); + tuple_set_d64(t, 1, parent_db_id); + tuple_set_d64(t, 2, sym_db_id); + tuple_set_d64(t, 3, cp->ip); call_object(tables->call_path_handler, t, "call_path_table"); @@ -1221,20 +1237,20 @@ static int python_export_call_return(struct db_export *dbe, t = tuple_new(14); - tuple_set_u64(t, 0, cr->db_id); - tuple_set_u64(t, 1, cr->thread->db_id); - tuple_set_u64(t, 2, comm_db_id); - tuple_set_u64(t, 3, cr->cp->db_id); - tuple_set_u64(t, 4, cr->call_time); - tuple_set_u64(t, 5, cr->return_time); - tuple_set_u64(t, 6, cr->branch_count); - tuple_set_u64(t, 7, cr->call_ref); - tuple_set_u64(t, 8, cr->return_ref); - tuple_set_u64(t, 9, cr->cp->parent->db_id); + tuple_set_d64(t, 0, cr->db_id); + tuple_set_d64(t, 1, cr->thread->db_id); + tuple_set_d64(t, 2, comm_db_id); + tuple_set_d64(t, 3, cr->cp->db_id); + tuple_set_d64(t, 4, cr->call_time); + tuple_set_d64(t, 5, cr->return_time); + tuple_set_d64(t, 6, cr->branch_count); + tuple_set_d64(t, 7, cr->call_ref); + tuple_set_d64(t, 8, cr->return_ref); + tuple_set_d64(t, 9, cr->cp->parent->db_id); tuple_set_s32(t, 10, cr->flags); - tuple_set_u64(t, 11, cr->parent_db_id); - tuple_set_u64(t, 12, cr->insn_count); - tuple_set_u64(t, 13, cr->cyc_count); + tuple_set_d64(t, 11, cr->parent_db_id); + tuple_set_d64(t, 12, cr->insn_count); + tuple_set_d64(t, 13, cr->cyc_count); call_object(tables->call_return_handler, t, "call_return_table"); @@ -1254,14 +1270,14 @@ static int python_export_context_switch(struct db_export *dbe, u64 db_id, t = tuple_new(9); - tuple_set_u64(t, 0, db_id); - tuple_set_u64(t, 1, machine->db_id); - tuple_set_u64(t, 2, sample->time); + tuple_set_d64(t, 0, db_id); + tuple_set_d64(t, 1, machine->db_id); + tuple_set_d64(t, 2, sample->time); tuple_set_s32(t, 3, sample->cpu); - tuple_set_u64(t, 4, th_out_id); - tuple_set_u64(t, 5, comm_out_id); - tuple_set_u64(t, 6, th_in_id); - tuple_set_u64(t, 7, comm_in_id); + tuple_set_d64(t, 4, th_out_id); + tuple_set_d64(t, 5, comm_out_id); + tuple_set_d64(t, 6, th_in_id); + tuple_set_d64(t, 7, comm_in_id); tuple_set_s32(t, 8, flags); call_object(tables->context_switch_handler, t, "context_switch"); diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore index 3ab1200e172fa803731f8703aa28a599cab7d66e..b1b37dcade9f2e3a6afcce58a24adcd5679fbfd9 100644 --- a/tools/testing/selftests/bpf/.gitignore +++ b/tools/testing/selftests/bpf/.gitignore @@ -9,6 +9,7 @@ fixdep test_dev_cgroup /test_progs* test_tcpbpf_user +!test_progs.h test_verifier_log feature test_sock diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh index f5abb1ebd3923be8cfbe0f689cbe83862d28848c..269b2680611b4e052d6150fb360df1e1c1ae461b 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_drops.sh @@ -108,6 +108,9 @@ router_destroy() __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64 tc qdisc del dev $rp2 clsact + + ip link set dev $rp2 down + ip link set dev $rp1 down } setup_prepare() diff --git a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh index 1fedfc9da434fc0052f4beb69412a903d98bf898..1d157b1bd838a1dadd654b33391fb148e08eceab 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/devlink_trap_l3_exceptions.sh @@ -111,6 +111,9 @@ router_destroy() __addr_add_del $rp1 del 192.0.2.2/24 2001:db8:1::2/64 tc qdisc del dev $rp2 clsact + + ip link set dev $rp2 down + ip link set dev $rp1 down } setup_prepare() diff --git a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh index 5cbff8038f84cb8e4d4ab3290ac90ebdc762c64b..28a570006d4d9b4c844d1767e7d6b68b9f4328c4 100755 --- a/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh +++ b/tools/testing/selftests/drivers/net/mlxsw/qos_dscp_bridge.sh @@ -93,7 +93,9 @@ switch_destroy() lldptool -T -i $swp1 -V APP -d $(dscp_map 10) >/dev/null lldpad_app_wait_del + ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc b/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc index e6eb78f0b95459956c97117b12974d6cab0663b8..9933ed24f9012441b7bd28ed35ffca4e40514fc8 100644 --- a/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc +++ b/tools/testing/selftests/ftrace/test.d/event/event-no-pid.tc @@ -57,6 +57,10 @@ enable_events() { echo 1 > tracing_on } +other_task() { + sleep .001 || usleep 1 || sleep 1 +} + echo 0 > options/event-fork do_reset @@ -94,6 +98,9 @@ child=$! echo "child = $child" wait $child +# Be sure some other events will happen for small systems (e.g. 1 core) +other_task + echo 0 > tracing_on cnt=`count_pid $mypid` diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c index 126c6727a6b096c48e768150b72dbe1e7c4df110..49805fd16fdf53c48c7499df6b4b8c169778e21c 100644 --- a/tools/testing/selftests/kvm/lib/kvm_util.c +++ b/tools/testing/selftests/kvm/lib/kvm_util.c @@ -55,7 +55,7 @@ int kvm_check_cap(long cap) exit(KSFT_SKIP); ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, cap); - TEST_ASSERT(ret != -1, "KVM_CHECK_EXTENSION IOCTL failed,\n" + TEST_ASSERT(ret >= 0, "KVM_CHECK_EXTENSION IOCTL failed,\n" " rc: %i errno: %i", ret, errno); close(kvm_fd); diff --git a/tools/testing/selftests/lkdtm/run.sh b/tools/testing/selftests/lkdtm/run.sh index bb7a1775307b809a2e18254a1b4de01f1c294678..e95e79bd3126893bd7750524958395024215aba9 100755 --- a/tools/testing/selftests/lkdtm/run.sh +++ b/tools/testing/selftests/lkdtm/run.sh @@ -76,10 +76,14 @@ fi # Save existing dmesg so we can detect new content below dmesg > "$DMESG" -# Most shells yell about signals and we're expecting the "cat" process -# to usually be killed by the kernel. So we have to run it in a sub-shell -# and silence errors. -($SHELL -c 'cat <(echo '"$test"') >'"$TRIGGER" 2>/dev/null) || true +# Since the kernel is likely killing the process writing to the trigger +# file, it must not be the script's shell itself. i.e. we cannot do: +# echo "$test" >"$TRIGGER" +# Instead, use "cat" to take the signal. Since the shell will yell about +# the signal that killed the subprocess, we must ignore the failure and +# continue. However we don't silence stderr since there might be other +# useful details reported there in the case of other unexpected conditions. +echo "$test" | cat >"$TRIGGER" || true # Record and dump the results dmesg | comm --nocheck-order -13 "$DMESG" - > "$LOG" || true diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt index 74a8d329a72c80cd4ab1590d3a95377ed30438f1..9b84cba9e9114d859c17f01b3f3436c3dcea2103 100644 --- a/tools/testing/selftests/lkdtm/tests.txt +++ b/tools/testing/selftests/lkdtm/tests.txt @@ -11,7 +11,7 @@ CORRUPT_LIST_ADD list_add corruption CORRUPT_LIST_DEL list_del corruption STACK_GUARD_PAGE_LEADING STACK_GUARD_PAGE_TRAILING -UNSET_SMEP CR4 bits went missing +UNSET_SMEP pinned CR4 bits changed: DOUBLE_FAULT CORRUPT_PAC UNALIGNED_LOAD_STORE_WRITE diff --git a/tools/testing/selftests/net/forwarding/pedit_dsfield.sh b/tools/testing/selftests/net/forwarding/pedit_dsfield.sh index 55eeacf592411bd905411efab7934f3a88b6b4aa..64fbd211d907b071c7e5d1566e51d94ca89f8c99 100755 --- a/tools/testing/selftests/net/forwarding/pedit_dsfield.sh +++ b/tools/testing/selftests/net/forwarding/pedit_dsfield.sh @@ -75,7 +75,9 @@ switch_destroy() tc qdisc del dev $swp2 clsact tc qdisc del dev $swp1 clsact + ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/net/forwarding/pedit_l4port.sh b/tools/testing/selftests/net/forwarding/pedit_l4port.sh index 5f20d289ee43cf2622defaf744243f4920d9c87e..10e594c551175b5b7ade331b9d5f345bb1b25d08 100755 --- a/tools/testing/selftests/net/forwarding/pedit_l4port.sh +++ b/tools/testing/selftests/net/forwarding/pedit_l4port.sh @@ -71,7 +71,9 @@ switch_destroy() tc qdisc del dev $swp2 clsact tc qdisc del dev $swp1 clsact + ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/net/forwarding/skbedit_priority.sh b/tools/testing/selftests/net/forwarding/skbedit_priority.sh index e3bd8a6bb8b40a1cdad6e4dd3ee588ffe75e3bd9..bde11dc27873c9a0bace7ed6ebb0c8e38b49bf32 100755 --- a/tools/testing/selftests/net/forwarding/skbedit_priority.sh +++ b/tools/testing/selftests/net/forwarding/skbedit_priority.sh @@ -72,7 +72,9 @@ switch_destroy() tc qdisc del dev $swp2 clsact tc qdisc del dev $swp1 clsact + ip link set dev $swp2 down ip link set dev $swp2 nomaster + ip link set dev $swp1 down ip link set dev $swp1 nomaster ip link del dev br1 } diff --git a/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c b/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c index fc5bf4870d8e65f4cf582fbcd69cf42eae3a5571..01e827c31169dbea8f892aa807df882862008389 100644 --- a/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c +++ b/tools/testing/selftests/powerpc/pmu/ebb/no_handler_test.c @@ -50,8 +50,6 @@ static int no_handler_test(void) event_close(&event); - dump_ebb_state(); - /* The real test is that we never took an EBB at 0x0 */ return 0; diff --git a/tools/testing/selftests/resctrl/README b/tools/testing/selftests/resctrl/README index 6e5a0ffa18e8b88e64fef38e57ba273b83624368..20502cb4791fc6f70c0aea34778ab7de9a6e3458 100644 --- a/tools/testing/selftests/resctrl/README +++ b/tools/testing/selftests/resctrl/README @@ -47,7 +47,7 @@ Parameter '-h' shows usage information. usage: resctrl_tests [-h] [-b "benchmark_cmd [options]"] [-t test list] [-n no_of_bits] -b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CQM default benchmark is builtin fill_buf - -t test list: run tests specified in the test list, e.g. -t mbm, mba, cqm, cat + -t test list: run tests specified in the test list, e.g. -t mbm,mba,cqm,cat -n no_of_bits: run cache tests using specified no of bits in cache bit mask -p cpu_no: specify CPU number to run the test. 1 is default -h: help diff --git a/tools/testing/selftests/resctrl/resctrl_tests.c b/tools/testing/selftests/resctrl/resctrl_tests.c index ac2269610aa9d7fdbd82b7b14b49545b1c996556..bd98746c6f8580561d88bbc9da1954166b2186e3 100644 --- a/tools/testing/selftests/resctrl/resctrl_tests.c +++ b/tools/testing/selftests/resctrl/resctrl_tests.c @@ -40,7 +40,7 @@ static void cmd_help(void) printf("\t-b benchmark_cmd [options]: run specified benchmark for MBM, MBA and CQM"); printf("\t default benchmark is builtin fill_buf\n"); printf("\t-t test list: run tests specified in the test list, "); - printf("e.g. -t mbm, mba, cqm, cat\n"); + printf("e.g. -t mbm,mba,cqm,cat\n"); printf("\t-n no_of_bits: run cache tests using specified no of bits in cache bit mask\n"); printf("\t-p cpu_no: specify CPU number to run the test. 1 is default\n"); printf("\t-h: help\n"); @@ -98,7 +98,7 @@ int main(int argc, char **argv) return -1; } - token = strtok(NULL, ":\t"); + token = strtok(NULL, ","); } break; case 'p': diff --git a/tools/testing/selftests/splice/short_splice_read.sh b/tools/testing/selftests/splice/short_splice_read.sh index 7810d3589d9ab0ef5a491cca24d0f09c4177b369..22b6c8910b182fd987402189add117ebc967b5e9 100755 --- a/tools/testing/selftests/splice/short_splice_read.sh +++ b/tools/testing/selftests/splice/short_splice_read.sh @@ -1,21 +1,87 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 +# +# Test for mishandling of splice() on pseudofilesystems, which should catch +# bugs like 11990a5bd7e5 ("module: Correctly truncate sysfs sections output") +# +# Since splice fallback was removed as part of the set_fs() rework, many of these +# tests expect to fail now. See https://lore.kernel.org/lkml/202009181443.C2179FB@keescook/ set -e +DIR=$(dirname "$0") + ret=0 +expect_success() +{ + title="$1" + shift + + echo "" >&2 + echo "$title ..." >&2 + + set +e + "$@" + rc=$? + set -e + + case "$rc" in + 0) + echo "ok: $title succeeded" >&2 + ;; + 1) + echo "FAIL: $title should work" >&2 + ret=$(( ret + 1 )) + ;; + *) + echo "FAIL: something else went wrong" >&2 + ret=$(( ret + 1 )) + ;; + esac +} + +expect_failure() +{ + title="$1" + shift + + echo "" >&2 + echo "$title ..." >&2 + + set +e + "$@" + rc=$? + set -e + + case "$rc" in + 0) + echo "FAIL: $title unexpectedly worked" >&2 + ret=$(( ret + 1 )) + ;; + 1) + echo "ok: $title correctly failed" >&2 + ;; + *) + echo "FAIL: something else went wrong" >&2 + ret=$(( ret + 1 )) + ;; + esac +} + do_splice() { filename="$1" bytes="$2" expected="$3" + report="$4" - out=$(./splice_read "$filename" "$bytes" | cat) + out=$("$DIR"/splice_read "$filename" "$bytes" | cat) if [ "$out" = "$expected" ] ; then - echo "ok: $filename $bytes" + echo " matched $report" >&2 + return 0 else - echo "FAIL: $filename $bytes" - ret=1 + echo " no match: '$out' vs $report" >&2 + return 1 fi } @@ -23,34 +89,45 @@ test_splice() { filename="$1" + echo " checking $filename ..." >&2 + full=$(cat "$filename") + rc=$? + if [ $rc -ne 0 ] ; then + return 2 + fi + two=$(echo "$full" | grep -m1 . | cut -c-2) # Make sure full splice has the same contents as a standard read. - do_splice "$filename" 4096 "$full" + echo " splicing 4096 bytes ..." >&2 + if ! do_splice "$filename" 4096 "$full" "full read" ; then + return 1 + fi # Make sure a partial splice see the first two characters. - do_splice "$filename" 2 "$two" + echo " splicing 2 bytes ..." >&2 + if ! do_splice "$filename" 2 "$two" "'$two'" ; then + return 1 + fi + + return 0 } -# proc_single_open(), seq_read() -test_splice /proc/$$/limits -# special open, seq_read() -test_splice /proc/$$/comm +### /proc/$pid/ has no splice interface; these should all fail. +expect_failure "proc_single_open(), seq_read() splice" test_splice /proc/$$/limits +expect_failure "special open(), seq_read() splice" test_splice /proc/$$/comm -# proc_handler, proc_dointvec_minmax -test_splice /proc/sys/fs/nr_open -# proc_handler, proc_dostring -test_splice /proc/sys/kernel/modprobe -# proc_handler, special read -test_splice /proc/sys/kernel/version +### /proc/sys/ has a splice interface; these should all succeed. +expect_success "proc_handler: proc_dointvec_minmax() splice" test_splice /proc/sys/fs/nr_open +expect_success "proc_handler: proc_dostring() splice" test_splice /proc/sys/kernel/modprobe +expect_success "proc_handler: special read splice" test_splice /proc/sys/kernel/version +### /sys/ has no splice interface; these should all fail. if ! [ -d /sys/module/test_module/sections ] ; then - modprobe test_module + expect_success "test_module kernel module load" modprobe test_module fi -# kernfs, attr -test_splice /sys/module/test_module/coresize -# kernfs, binattr -test_splice /sys/module/test_module/sections/.init.text +expect_failure "kernfs attr splice" test_splice /sys/module/test_module/coresize +expect_failure "kernfs binattr splice" test_splice /sys/module/test_module/sections/.init.text exit $ret diff --git a/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py b/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py index 229ee185b27e198dd1a1ec7a4408751e54428d60..a7b21658af9b463cef8c9b3d4023f222426f239b 100644 --- a/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py +++ b/tools/testing/selftests/tc-testing/plugin-lib/scapyPlugin.py @@ -36,7 +36,7 @@ class SubPlugin(TdcPlugin): for k in scapy_keys: if k not in scapyinfo: keyfail = True - missing_keys.add(k) + missing_keys.append(k) if keyfail: print('{}: Scapy block present in the test, but is missing info:' .format(self.sub_class)) diff --git a/tools/testing/selftests/timers/rtcpie.c b/tools/testing/selftests/timers/rtcpie.c index 47b5bad1b3933343548579fce9e06650c09186ce..4ef2184f1558809c4328becc4b1d4771cbd6d339 100644 --- a/tools/testing/selftests/timers/rtcpie.c +++ b/tools/testing/selftests/timers/rtcpie.c @@ -18,6 +18,8 @@ #include <stdlib.h> #include <errno.h> +#include "../kselftest.h" + /* * This expects the new RTC class driver framework, working with * clocks that will often not be clones of what the PC-AT had. @@ -35,8 +37,14 @@ int main(int argc, char **argv) switch (argc) { case 2: rtc = argv[1]; - /* FALLTHROUGH */ + break; case 1: + fd = open(default_rtc, O_RDONLY); + if (fd == -1) { + printf("Default RTC %s does not exist. Test Skipped!\n", default_rtc); + exit(KSFT_SKIP); + } + close(fd); break; default: fprintf(stderr, "usage: rtctest [rtcdev] [d]\n"); diff --git a/tools/testing/selftests/vm/protection_keys.c b/tools/testing/selftests/vm/protection_keys.c index fdbb602ecf325457c135dc6f0c18da877d9712fc..87eecd5ba577b380dd628e8ea5bb13622ff9ea80 100644 --- a/tools/testing/selftests/vm/protection_keys.c +++ b/tools/testing/selftests/vm/protection_keys.c @@ -510,7 +510,7 @@ int alloc_pkey(void) " shadow: 0x%016llx\n", __func__, __LINE__, ret, __read_pkey_reg(), shadow_pkey_reg); - if (ret) { + if (ret > 0) { /* clear both the bits: */ shadow_pkey_reg = set_pkey_bits(shadow_pkey_reg, ret, ~PKEY_MASK); @@ -561,7 +561,6 @@ int alloc_random_pkey(void) int nr_alloced = 0; int random_index; memset(alloced_pkeys, 0, sizeof(alloced_pkeys)); - srand((unsigned int)time(NULL)); /* allocate every possible key and make a note of which ones we got */ max_nr_pkey_allocs = NR_PKEYS; @@ -1449,6 +1448,13 @@ void test_implicit_mprotect_exec_only_memory(int *ptr, u16 pkey) ret = mprotect(p1, PAGE_SIZE, PROT_EXEC); pkey_assert(!ret); + /* + * Reset the shadow, assuming that the above mprotect() + * correctly changed PKRU, but to an unknown value since + * the actual alllocated pkey is unknown. + */ + shadow_pkey_reg = __read_pkey_reg(); + dprintf2("pkey_reg: %016llx\n", read_pkey_reg()); /* Make sure this is an *instruction* fault */ @@ -1552,6 +1558,8 @@ int main(void) int nr_iterations = 22; int pkeys_supported = is_pkeys_supported(); + srand((unsigned int)time(NULL)); + setup_handlers(); printf("has pkeys: %d\n", pkeys_supported); diff --git a/virt/kvm/coalesced_mmio.c b/virt/kvm/coalesced_mmio.c index 6edfcf1f3bd6651c92592ff62bc84f526aaf743f..d5bebb37238c0bc9908d0d1f82f954310fa696ea 100644 --- a/virt/kvm/coalesced_mmio.c +++ b/virt/kvm/coalesced_mmio.c @@ -186,7 +186,6 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, coalesced_mmio_in_range(dev, zone->addr, zone->size)) { r = kvm_io_bus_unregister_dev(kvm, zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev); - kvm_iodevice_destructor(&dev->dev); /* * On failure, unregister destroys all devices on the @@ -196,6 +195,7 @@ int kvm_vm_ioctl_unregister_coalesced_mmio(struct kvm *kvm, */ if (r) break; + kvm_iodevice_destructor(&dev->dev); } } diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index f446c36f58003e6db97dbd66e34e61e2d9129931..1353439691cf78c5e110c53e7f640da17882e9fb 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -1883,6 +1883,13 @@ static bool vma_is_valid(struct vm_area_struct *vma, bool write_fault) return true; } +static int kvm_try_get_pfn(kvm_pfn_t pfn) +{ + if (kvm_is_reserved_pfn(pfn)) + return 1; + return get_page_unless_zero(pfn_to_page(pfn)); +} + static int hva_to_pfn_remapped(struct vm_area_struct *vma, unsigned long addr, bool *async, bool write_fault, bool *writable, @@ -1932,13 +1939,21 @@ static int hva_to_pfn_remapped(struct vm_area_struct *vma, * Whoever called remap_pfn_range is also going to call e.g. * unmap_mapping_range before the underlying pages are freed, * causing a call to our MMU notifier. + * + * Certain IO or PFNMAP mappings can be backed with valid + * struct pages, but be allocated without refcounting e.g., + * tail pages of non-compound higher order allocations, which + * would then underflow the refcount when the caller does the + * required put_page. Don't allow those pages here. */ - kvm_get_pfn(pfn); + if (!kvm_try_get_pfn(pfn)) + r = -EFAULT; out: pte_unmap_unlock(ptep, ptl); *p_pfn = pfn; - return 0; + + return r; } /*