diff --git a/AndroidKernel.mk b/AndroidKernel.mk index f7e26617f635..73a2232be4a2 100644 --- a/AndroidKernel.mk +++ b/AndroidKernel.mk @@ -10,6 +10,8 @@ ifneq ($(TARGET_KERNEL_APPEND_DTB), true) $(info Using DTB Image) INSTALLED_DTBIMAGE_TARGET := $(PRODUCT_OUT)/dtb.img endif +MAKE_ARGS := $(strip $(TARGET_KERNEL_MAKE_ARGS)) +KERNEL_DISABLE_DEBUGFS := $(TARGET_KERNEL_DISABLE_DEBUGFS) TARGET_KERNEL_MAKE_ENV := $(strip $(TARGET_KERNEL_MAKE_ENV)) ifeq ($(TARGET_KERNEL_MAKE_ENV),) @@ -138,6 +140,7 @@ $(info Using appended DTB) TARGET_PREBUILT_INT_KERNEL := $(TARGET_PREBUILT_INT_KERNEL)-dtb endif +KERNEL_DEBUGFS := $(KERNEL_OUT)/tmp KERNEL_HEADERS_INSTALL := $(KERNEL_OUT)/usr KERNEL_MODULES_INSTALL ?= system KERNEL_MODULES_OUT ?= $(PRODUCT_OUT)/$(KERNEL_MODULES_INSTALL)/lib/modules @@ -162,6 +165,9 @@ mpath=`dirname $$mdpath`; rm -rf $$mpath;\ fi endef +$(KERNEL_OUT): $(KERNEL_DEBUGFS) + mkdir -p $(KERNEL_OUT) + ifneq ($(KERNEL_LEGACY_DIR),true) $(KERNEL_USR): $(KERNEL_HEADERS_INSTALL) rm -rf $(KERNEL_SYMLINK) @@ -170,9 +176,6 @@ $(KERNEL_USR): $(KERNEL_HEADERS_INSTALL) $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_USR) endif -$(KERNEL_OUT): - mkdir -p $(KERNEL_OUT) - $(KERNEL_CONFIG): $(KERNEL_OUT) $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) $(KERNEL_DEFCONFIG) $(hide) if [ ! -z "$(KERNEL_CONFIG_OVERRIDE)" ]; then \ @@ -206,6 +209,17 @@ $(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL) $(clean-module-folder) endif +$(KERNEL_DEBUGFS): + KERNEL_DIR=$(TARGET_KERNEL_SOURCE) \ + DEFCONFIG=$(KERNEL_DEFCONFIG) \ + OUT_DIR=$(KERNEL_OUT) \ + ARCH=$(KERNEL_ARCH) \ + CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) \ + DISABLE_DEBUGFS=$(KERNEL_DISABLE_DEBUGFS) \ + $(TARGET_KERNEL_SOURCE)/disable_dbgfs.sh \ + $(real_cc) \ + $(TARGET_KERNEL_MAKE_ARGS) + $(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT) $(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \ rm -f $(BUILD_ROOT_LOC)$(KERNEL_CONFIG) && \ diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio index 64e65450f483..e21e2ca3e4f9 100644 --- a/Documentation/ABI/testing/sysfs-bus-iio +++ b/Documentation/ABI/testing/sysfs-bus-iio @@ -1524,7 +1524,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_concentrationX_voc_raw KernelVersion: 4.3 Contact: linux-iio@vger.kernel.org Description: - Raw (unscaled no offset etc.) percentage reading of a substance. + Raw (unscaled no offset etc.) reading of a substance. Units + after application of scale and offset are percents. What: /sys/bus/iio/devices/iio:deviceX/in_resistance_raw What: /sys/bus/iio/devices/iio:deviceX/in_resistanceX_raw diff --git a/Documentation/devicetree/bindings/iio/adc/qcom-rradc.txt b/Documentation/devicetree/bindings/iio/adc/qcom-rradc.txt index 1ab49edfe30c..240c6d82deb0 100644 --- a/Documentation/devicetree/bindings/iio/adc/qcom-rradc.txt +++ b/Documentation/devicetree/bindings/iio/adc/qcom-rradc.txt @@ -45,6 +45,10 @@ Optional property: - qcom,pmic-revid : Phandle pointing to the revision peripheral node. Use it to query the PMIC fabrication ID for applying the appropriate temperature compensation parameters. +- qcom,batt-id-delay-ms : + Value type: + Definition: Used to specify HW settling time in MS for measuring BATT_ID. + Possible values are: 0, 1, 4, 12, 20, 40, 60, 80. Example: /* RRADC node */ diff --git a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt index c82794002595..89647d714387 100644 --- a/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt +++ b/Documentation/devicetree/bindings/iio/multiplexer/io-channel-mux.txt @@ -21,7 +21,7 @@ controller state. The mux controller state is described in Example: mux: mux-controller { - compatible = "mux-gpio"; + compatible = "gpio-mux"; #mux-control-cells = <0>; mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>, diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt b/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt index 4b1f08612865..b22615bdafef 100644 --- a/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt +++ b/Documentation/devicetree/bindings/media/video/msm-cam-smmu.txt @@ -67,6 +67,11 @@ Second Level Node - CAM SMMU context bank device or firmware device Value type: boolean Definition: Specifies if the context bank is a secure context bank. +- qcom,secure-pixel-cb + Usage: optional + Value type: boolean + Definition: Specifies if the context bank is a secure pixel context bank. + ============================================= Third Level Node - CAM SMMU memory map device ============================================= diff --git a/Documentation/devicetree/bindings/net/qrtr-ethernet-dev.txt b/Documentation/devicetree/bindings/net/qrtr-ethernet-dev.txt new file mode 100644 index 000000000000..94b9f9fd3374 --- /dev/null +++ b/Documentation/devicetree/bindings/net/qrtr-ethernet-dev.txt @@ -0,0 +1,30 @@ +QTI QRTR Ethernet Device transport binding + +- compatible: + Usage: required + Value type: + Definition: must be "qcom,qrtr-ethernet-dev" + +- qcom,net-id: + Usage: optional + Value type: + Definition: indicates what subnet this transport belongs to. Should be + passed into the qrtr core logic to determine if forwarding + is needed on this endpoint. + +- qcom,low-latency: + Usage: optional + Value type: + Definition: indicates whether this transport receiving thread needs to + be set to realtime priority for enhanced performance. + += EXAMPLE +The following example represents the qrtr ethernet dev transport node on a +device configured as an ethernet endpoint and needs to forward data from the +host to a modem co-processor. + + qcom,eth_dev_qrtr { + compatible = "qcom,qrtr-ethernet-dev"; + qcom,net-id = <4>; + qcom,low-latency; + }; diff --git a/Documentation/devicetree/bindings/soc/qcom/blocknames.txt b/Documentation/devicetree/bindings/soc/qcom/blocknames.txt new file mode 100644 index 000000000000..a0f4b39b8eda --- /dev/null +++ b/Documentation/devicetree/bindings/soc/qcom/blocknames.txt @@ -0,0 +1,18 @@ +* rename block devices + +Required properties: + +- compatible: "qcom,blkdev-rename" compatibility string +- actual-dev: Name of the disk assigned by generic driver +- rename-dev: Re-name of the disk to set for disks + +Example: + +rename_blk: rename_blk { + compatible = "qcom,blkdev-rename"; + actual-dev = "vda", "vdb", "vdc", + "vdd", "vde", "vdf", + "vdg", "vdh"; + rename-dev = "la_system", "la_userdata", "la_vendor", + "la_persist", "modem", "bluetooth", + "la_misc", "vbmeta"; diff --git a/Makefile b/Makefile index 18bb45ffb8b8..aa1fb6f89f02 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 VERSION = 4 PATCHLEVEL = 14 -SUBLEVEL = 193 +SUBLEVEL = 194 EXTRAVERSION = NAME = Petit Gorille diff --git a/arch/arm/configs/vendor/sa515m-perf_defconfig b/arch/arm/configs/vendor/sa515m-perf_defconfig index 8b002ff2c108..ba1f7b8d3bca 100644 --- a/arch/arm/configs/vendor/sa515m-perf_defconfig +++ b/arch/arm/configs/vendor/sa515m-perf_defconfig @@ -166,6 +166,7 @@ CONFIG_BRIDGE=y CONFIG_VLAN_8021Q=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SWITCHDEV=y CONFIG_QRTR=y CONFIG_QRTR_NODE_ID=2 CONFIG_QRTR_SMD=y @@ -322,7 +323,6 @@ CONFIG_USB_CONFIGFS_RNDIS=y CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_UEVENT=y -CONFIG_USB_CONFIGFS_F_UAC1=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_GSI=y diff --git a/arch/arm/configs/vendor/sa515m_defconfig b/arch/arm/configs/vendor/sa515m_defconfig index 98c80cfb7720..90b571160d95 100644 --- a/arch/arm/configs/vendor/sa515m_defconfig +++ b/arch/arm/configs/vendor/sa515m_defconfig @@ -166,6 +166,7 @@ CONFIG_BRIDGE=y CONFIG_VLAN_8021Q=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_PRIO=y +CONFIG_NET_SWITCHDEV=y CONFIG_QRTR=y CONFIG_QRTR_NODE_ID=2 CONFIG_QRTR_SMD=y @@ -324,7 +325,6 @@ CONFIG_USB_CONFIGFS_RNDIS=y CONFIG_USB_CONFIGFS_MASS_STORAGE=y CONFIG_USB_CONFIGFS_F_FS=y CONFIG_USB_CONFIGFS_UEVENT=y -CONFIG_USB_CONFIGFS_F_UAC1=y CONFIG_USB_CONFIGFS_F_DIAG=y CONFIG_USB_CONFIGFS_F_CDEV=y CONFIG_USB_CONFIGFS_F_GSI=y diff --git a/arch/arm/configs/vendor/sdm429-bg-perf_defconfig b/arch/arm/configs/vendor/sdm429-bg-perf_defconfig index a78dc6c5c287..d1fdcb58461c 100644 --- a/arch/arm/configs/vendor/sdm429-bg-perf_defconfig +++ b/arch/arm/configs/vendor/sdm429-bg-perf_defconfig @@ -41,7 +41,6 @@ CONFIG_EMBEDDED=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_PROFILING=y -CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -298,7 +297,6 @@ CONFIG_USB_USBNET=y CONFIG_WIL6210=m CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CLD_LL_CORE=y -CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set diff --git a/arch/arm/configs/vendor/sdm429-bg_defconfig b/arch/arm/configs/vendor/sdm429-bg_defconfig index 725b4396e640..23b7a19357f8 100644 --- a/arch/arm/configs/vendor/sdm429-bg_defconfig +++ b/arch/arm/configs/vendor/sdm429-bg_defconfig @@ -42,7 +42,6 @@ CONFIG_EMBEDDED=y CONFIG_SLAB_FREELIST_RANDOM=y CONFIG_SLAB_FREELIST_HARDENED=y CONFIG_PROFILING=y -CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y @@ -304,7 +303,6 @@ CONFIG_USB_RTL8152=y CONFIG_USB_USBNET=y CONFIG_WCNSS_MEM_PRE_ALLOC=y CONFIG_CLD_LL_CORE=y -CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c index 65228bf4c6df..ba9b9a77bcd2 100644 --- a/arch/arm/kernel/stacktrace.c +++ b/arch/arm/kernel/stacktrace.c @@ -20,6 +20,19 @@ * A simple function epilogue looks like this: * ldm sp, {fp, sp, pc} * + * When compiled with clang, pc and sp are not pushed. A simple function + * prologue looks like this when built with clang: + * + * stmdb {..., fp, lr} + * add fp, sp, #x + * sub sp, sp, #y + * + * A simple function epilogue looks like this when built with clang: + * + * sub sp, fp, #x + * ldm {..., fp, pc} + * + * * Note that with framepointer enabled, even the leaf functions have the same * prologue and epilogue, therefore we can ignore the LR value in this case. */ @@ -32,6 +45,16 @@ int notrace unwind_frame(struct stackframe *frame) low = frame->sp; high = ALIGN(low, THREAD_SIZE); +#ifdef CONFIG_CC_IS_CLANG + /* check current frame pointer is within bounds */ + if (fp < low + 4 || fp > high - 4) + return -EINVAL; + + frame->sp = frame->fp; + frame->fp = *(unsigned long *)(fp); + frame->pc = frame->lr; + frame->lr = *(unsigned long *)(fp + 4); +#else /* check current frame pointer is within bounds */ if (fp < low + 12 || fp > high - 4) return -EINVAL; @@ -40,6 +63,7 @@ int notrace unwind_frame(struct stackframe *frame) frame->fp = *(unsigned long *)(fp - 12); frame->sp = *(unsigned long *)(fp - 8); frame->pc = *(unsigned long *)(fp - 4); +#endif return 0; } diff --git a/arch/arm/mach-at91/pm.c b/arch/arm/mach-at91/pm.c index 849014c01cf4..bebaa0b0aef4 100644 --- a/arch/arm/mach-at91/pm.c +++ b/arch/arm/mach-at91/pm.c @@ -456,13 +456,13 @@ static void __init at91_pm_sram_init(void) sram_pool = gen_pool_get(&pdev->dev, NULL); if (!sram_pool) { pr_warn("%s: sram pool unavailable!\n", __func__); - return; + goto out_put_device; } sram_base = gen_pool_alloc(sram_pool, at91_pm_suspend_in_sram_sz); if (!sram_base) { pr_warn("%s: unable to alloc sram!\n", __func__); - return; + goto out_put_device; } sram_pbase = gen_pool_virt_to_phys(sram_pool, sram_base); @@ -470,12 +470,17 @@ static void __init at91_pm_sram_init(void) at91_pm_suspend_in_sram_sz, false); if (!at91_suspend_sram_fn) { pr_warn("SRAM: Could not map\n"); - return; + goto out_put_device; } /* Copy the pm suspend handler to SRAM */ at91_suspend_sram_fn = fncpy(at91_suspend_sram_fn, &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz); + return; + +out_put_device: + put_device(&pdev->dev); + return; } static void __init at91_pm_backup_init(void) diff --git a/arch/arm/mach-socfpga/pm.c b/arch/arm/mach-socfpga/pm.c index c378ab0c2431..93f2245c9775 100644 --- a/arch/arm/mach-socfpga/pm.c +++ b/arch/arm/mach-socfpga/pm.c @@ -60,14 +60,14 @@ static int socfpga_setup_ocram_self_refresh(void) if (!ocram_pool) { pr_warn("%s: ocram pool unavailable!\n", __func__); ret = -ENODEV; - goto put_node; + goto put_device; } ocram_base = gen_pool_alloc(ocram_pool, socfpga_sdram_self_refresh_sz); if (!ocram_base) { pr_warn("%s: unable to alloc ocram!\n", __func__); ret = -ENOMEM; - goto put_node; + goto put_device; } ocram_pbase = gen_pool_virt_to_phys(ocram_pool, ocram_base); @@ -78,7 +78,7 @@ static int socfpga_setup_ocram_self_refresh(void) if (!suspend_ocram_base) { pr_warn("%s: __arm_ioremap_exec failed!\n", __func__); ret = -ENOMEM; - goto put_node; + goto put_device; } /* Copy the code that puts DDR in self refresh to ocram */ @@ -92,6 +92,8 @@ static int socfpga_setup_ocram_self_refresh(void) if (!socfpga_sdram_self_refresh_in_ocram) ret = -EFAULT; +put_device: + put_device(&pdev->dev); put_node: of_node_put(np); diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index d8d90cf65b39..b397cf1e486d 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -18,6 +18,7 @@ #include #include #include +#include #include "proc-macros.S" @@ -547,10 +548,10 @@ __v7_setup_stack_ptr: ENDPROC(__v7_setup) .bss - .align 2 + .align L1_CACHE_SHIFT __v7_setup_stack: .space 4 * 7 @ 7 registers - + .align L1_CACHE_SHIFT __INITDATA .weak cpu_v7_bugs_init diff --git a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts index 4a8b1fb51243..c8824b918693 100644 --- a/arch/arm64/boot/dts/exynos/exynos7-espresso.dts +++ b/arch/arm64/boot/dts/exynos/exynos7-espresso.dts @@ -155,6 +155,7 @@ regulator-min-microvolt = <700000>; regulator-max-microvolt = <1150000>; regulator-enable-ramp-delay = <125>; + regulator-always-on; }; ldo8_reg: LDO8 { diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts index e9f87cb61ade..8587912e1eb0 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts +++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts @@ -210,6 +210,17 @@ status = "ok"; compatible = "adi,adv7533"; reg = <0x39>; + adi,dsi-lanes = <4>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + }; + port@1 { + reg = <1>; + }; + }; }; }; diff --git a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts index 6887cc1a743d..f78e6468b02f 100644 --- a/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts +++ b/arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts @@ -513,7 +513,7 @@ reg = <0x39>; interrupt-parent = <&gpio1>; interrupts = <1 2>; - pd-gpio = <&gpio0 4 0>; + pd-gpios = <&gpio0 4 0>; adi,dsi-lanes = <4>; #sound-dai-cells = <0>; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index a73ab1a92bb4..af5d397e4e9c 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -223,6 +223,7 @@ dtb-$(CONFIG_QTI_GVM) += sa8155-vm-la.dtb \ sa8195-vm-la.dtb \ sa8195-vm-la-mt.dtb \ sa8195-vm-lv.dtb \ + sa8195-vm-lv-lxc.dtb \ sa8195-vm-lv-mt.dtb ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y) diff --git a/arch/arm64/boot/dts/qcom/mdm9607-ion.dtsi b/arch/arm64/boot/dts/qcom/mdm9607-ion.dtsi index b828b3ccf78b..5b8d3bcc2ea1 100644 --- a/arch/arm64/boot/dts/qcom/mdm9607-ion.dtsi +++ b/arch/arm64/boot/dts/qcom/mdm9607-ion.dtsi @@ -32,7 +32,7 @@ reg = <27>; memory-region = <&qseecom_mem>; qcom,ion-heap-type = "DMA"; - status = "disabled"; + status = "ok"; }; }; }; diff --git a/arch/arm64/boot/dts/qcom/mdm9607.dtsi b/arch/arm64/boot/dts/qcom/mdm9607.dtsi index a21deb71ecec..285495da97d7 100644 --- a/arch/arm64/boot/dts/qcom/mdm9607.dtsi +++ b/arch/arm64/boot/dts/qcom/mdm9607.dtsi @@ -1679,7 +1679,7 @@ qcom,ce-opp-freq = <100000000>; }; - qcom_seecom: qseecom@87a80000 { + qcom_seecom: qseecom@88000000 { compatible = "qcom,qseecom"; reg = <0x88000000 0x500000>; reg-names = "secapp-region"; @@ -1687,6 +1687,7 @@ qcom,hlos-num-ce-hw-instances = <1>; qcom,hlos-ce-hw-instance = <0>; qcom,qsee-ce-hw-instance = <0>; + qcom,support-bus-scaling; qcom,msm-bus,name = "qseecom-noc"; qcom,msm-bus,num-cases = <4>; qcom,msm-bus,num-paths = <1>; diff --git a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi index 4cb0b5834143..69ba1d79bcd5 100644 --- a/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi +++ b/arch/arm64/boot/dts/qcom/msm8916-pins.dtsi @@ -542,7 +542,7 @@ pins = "gpio63", "gpio64", "gpio65", "gpio66", "gpio67", "gpio68"; drive-strength = <8>; - bias-pull-none; + bias-disable; }; }; cdc_pdm_lines_sus: pdm_lines_off { @@ -571,7 +571,7 @@ pins = "gpio113", "gpio114", "gpio115", "gpio116"; drive-strength = <8>; - bias-pull-none; + bias-disable; }; }; @@ -599,7 +599,7 @@ pinconf { pins = "gpio110"; drive-strength = <8>; - bias-pull-none; + bias-disable; }; }; @@ -625,7 +625,7 @@ pinconf { pins = "gpio116"; drive-strength = <8>; - bias-pull-none; + bias-disable; }; }; ext_mclk_tlmm_lines_sus: mclk_lines_off { @@ -653,7 +653,7 @@ pins = "gpio112", "gpio117", "gpio118", "gpio119"; drive-strength = <8>; - bias-pull-none; + bias-disable; }; }; ext_sec_tlmm_lines_sus: tlmm_lines_off { diff --git a/arch/arm64/boot/dts/qcom/qcs405.dtsi b/arch/arm64/boot/dts/qcom/qcs405.dtsi index dfbb2146b1c9..45574c4891c6 100644 --- a/arch/arm64/boot/dts/qcom/qcs405.dtsi +++ b/arch/arm64/boot/dts/qcom/qcs405.dtsi @@ -962,6 +962,11 @@ qcom,proc-img-to-load = "cdsp"; }; + qcom,eth_dev_qrtr { + compatible = "qcom,qrtr-ethernet-dev"; + qcom,low-latency; + }; + qcom,glink { compatible = "qcom,glink"; #address-cells = <1>; @@ -1718,9 +1723,9 @@ qcom,msm-bus,num-paths = <2>; qcom,msm-bus,vectors-KBps = <98 512 0 0>, <1 781 0 0>, /* No vote */ - <98 512 1250 0>, <1 781 0 40000>, /* 10Mbps vote */ - <98 512 12500 0>, <1 781 0 40000>, /* 100Mbps vote */ - <98 512 125000 0>, <1 781 0 40000>; /* 1000Mbps vote */ + <98 512 2500 0>, <1 781 0 40000>, /* 10Mbps vote */ + <98 512 25000 0>, <1 781 0 40000>, /* 100Mbps vote */ + <98 512 250000 0>, <1 781 0 40000>; /* 1000Mbps vote */ qcom,bus-vector-names = "0", "10", "100", "1000"; clocks = <&clock_gcc GCC_ETH_AXI_CLK>, <&clock_gcc GCC_ETH_PTP_CLK>, diff --git a/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi b/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi index 90aa33ba6541..5c5abef195ae 100644 --- a/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi +++ b/arch/arm64/boot/dts/qcom/quin-vm-common.dtsi @@ -79,6 +79,16 @@ }; }; }; + + rename_blk: rename_blk { + compatible = "qcom,blkdev-rename"; + actual-dev = "vda", "vdb", "vdc", + "vdd", "vde", "vdf", + "vdg", "vdh"; + rename-dev = "la_system", "la_userdata", "la_vendor", + "la_persist", "modem", "bluetooth", + "la_misc", "vbmeta"; + }; }; &soc { diff --git a/arch/arm64/boot/dts/qcom/raphael-sm8150.dtsi b/arch/arm64/boot/dts/qcom/raphael-sm8150.dtsi index 1b63c10408f4..cd0a11582675 100644 --- a/arch/arm64/boot/dts/qcom/raphael-sm8150.dtsi +++ b/arch/arm64/boot/dts/qcom/raphael-sm8150.dtsi @@ -23,10 +23,11 @@ And public attribution of xiaomi platforms(like F1 and so and) &pm8150b_fg { qcom,battery-data = <&mtp_batterydata>; qcom,rapid-soc-dec-en; + qcom,soc-scale-mode-en; qcom,fg-sys-term-current = <(-300)>; qcom,fg-cutoff-voltage = <3400>; qcom,fg-cutoff-current = <200>; - qcom,fg-empty-voltage = <3100>; + qcom,fg-empty-voltage = <3000>; qcom,fg-batt-temp-delta = <6>; qcom,fg-force-load-profile; qcom,five-pin-battery; diff --git a/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts b/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts index 3a5c5aef5c77..19b33f9f06ba 100644 --- a/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts +++ b/arch/arm64/boot/dts/qcom/sa2145p-ccard-nand-dc.dts @@ -54,3 +54,30 @@ /delete-node/ wlan_msa_region@88E0000; /delete-node/ wlan_fw_mem@86400000; }; + +&tlmm { + wakeup_gpio_default: wakeup_gpio_default { + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + drive-strength = <2>; + bias-pull-down; + }; + }; +}; + +&sdx_ext_ipc { + qcom,wakeup-gpio-out = <&tlmm 77 0x00>; +}; + +ðqos_hw { + rxc-skew-ps = <720>; + io-macro-info { + rx-prog-swap; + rx-dll-bypass; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts b/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts index fb3ae4f7843d..418d9bb685a5 100644 --- a/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts +++ b/arch/arm64/boot/dts/qcom/sa2150p-ccard-nand-dc.dts @@ -128,3 +128,30 @@ /delete-node/ wlan_msa_region@88E0000; /delete-node/ wlan_fw_mem@86400000; }; + +&tlmm { + wakeup_gpio_default: wakeup_gpio_default { + mux { + pins = "gpio77"; + function = "gpio"; + }; + + config { + pins = "gpio77"; + drive-strength = <2>; + bias-pull-down; + }; + }; +}; + +&sdx_ext_ipc { + qcom,wakeup-gpio-out = <&tlmm 77 0x00>; +}; + +ðqos_hw { + rxc-skew-ps = <720>; + io-macro-info { + rx-prog-swap; + rx-dll-bypass; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa6155p-camera.dtsi b/arch/arm64/boot/dts/qcom/sa6155p-camera.dtsi index 3eb01a1b915b..d9b3dd8a4490 100644 --- a/arch/arm64/boot/dts/qcom/sa6155p-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155p-camera.dtsi @@ -46,6 +46,26 @@ status = "disabled"; }; +&cam_smmu { + msm_cam_smmu_ife_cp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x821 0x1C0>, + <&apps_smmu 0x841 0x0>, + <&apps_smmu 0x861 0x1C0>; + label = "ife-cp"; + qcom,secure-pixel-cb; + ife_cp_iova_mem_map: iova-mem-map { + /* IO region is approximately 2.5 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0x98C00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; +}; &soc { /delete-node/ cam_isp_mgr; diff --git a/arch/arm64/boot/dts/qcom/sa6155p-vm-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sa6155p-vm-qupv3.dtsi index a3b8ff0bb9ef..5b77a4412e49 100644 --- a/arch/arm64/boot/dts/qcom/sa6155p-vm-qupv3.dtsi +++ b/arch/arm64/boot/dts/qcom/sa6155p-vm-qupv3.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -426,6 +426,7 @@ pinctrl-1 = <&qupv3_se9_spi_sleep>; spi-max-frequency = <50000000>; qcom,wrapper-core = <&qupv3_2>; + qcom,disable-dma; status = "disabled"; }; @@ -445,6 +446,7 @@ pinctrl-1 = <&qupv3_se10_spi_sleep>; spi-max-frequency = <50000000>; qcom,wrapper-core = <&qupv3_2>; + qcom,disable-dma; status = "disabled"; }; }; diff --git a/arch/arm64/boot/dts/qcom/sa8155-camera.dtsi b/arch/arm64/boot/dts/qcom/sa8155-camera.dtsi index 2ded8cd4df2f..708cc284af93 100644 --- a/arch/arm64/boot/dts/qcom/sa8155-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8155-camera.dtsi @@ -62,6 +62,31 @@ status = "disabled"; }; +&cam_smmu { + msm_cam_smmu_ife_cp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0x841 0x620>, + <&apps_smmu 0x861 0x620>, + <&apps_smmu 0xA41 0x620>, + <&apps_smmu 0xA61 0x620>, + <&apps_smmu 0xC41 0x620>, + <&apps_smmu 0xC61 0x620>, + <&apps_smmu 0xE41 0x620>, + <&apps_smmu 0xE61 0x620>; + label = "ife-cp"; + qcom,secure-pixel-cb; + ife_cp_iova_mem_map: iova-mem-map { + /* IO region is approximately 2.5 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0x98C00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; +}; &soc { /delete-node/ cam_isp_mgr; diff --git a/arch/arm64/boot/dts/qcom/sa8195-vm-lv-lxc.dts b/arch/arm64/boot/dts/qcom/sa8195-vm-lv-lxc.dts new file mode 100644 index 000000000000..fc7e93ba2874 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8195-vm-lv-lxc.dts @@ -0,0 +1,40 @@ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include "sa8195-vm.dtsi" +#include "sa8195-vm-lv-lxc.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA8195 Single LV Virtual Machine"; + compatible = "qcom,sa8195p"; + qcom,pmic-name = "PM8195"; + qcom,board-id = <0x1000002 0>; +}; + +&soc { + sde_kms_hyp1: qcom,sde_kms_hyp@ae10000 { + compatible = "qcom,sde-kms-hyp"; + qcom,client-id = "7815"; + }; + + sde_kms_hyp2: qcom,sde_kms_hyp@ae20000 { + compatible = "qcom,sde-kms-hyp"; + qcom,client-id = "7818"; + }; + + sde_kms_hyp3: qcom,sde_kms_hyp@ae30000 { + compatible = "qcom,sde-kms-hyp"; + qcom,client-id = "7819"; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8195-vm-lv-lxc.dtsi b/arch/arm64/boot/dts/qcom/sa8195-vm-lv-lxc.dtsi new file mode 100644 index 000000000000..98522181a703 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/sa8195-vm-lv-lxc.dtsi @@ -0,0 +1,60 @@ +/* Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/ { + reserved_memory: reserved-memory { + + pmem_shared: pmem_shared_region@a0000000 { + reg = <0x0 0xa0000000 0x0 0x20000000>; + label = "pmem_shared_mem"; + }; + }; + + /delete-node/ rename_blk; +}; + +&hab { + vmid = <3>; +}; + +&slpi_tlmm { + status = "ok"; +}; + +&apps_smmu { + status = "ok"; +}; + +&qupv3_se13_4uart { + status = "ok"; +}; + +&usb0 { + status = "ok"; +}; + +&usb2_phy0 { + status = "ok"; +}; + +&pcie0_msi { + status = "ok"; +}; + +&pcie0 { + status = "ok"; +}; + +&sde_kms_hyp { + /delete-property/ qcom,client-id; + qcom,client-id = "7816"; +}; diff --git a/arch/arm64/boot/dts/qcom/sa8195p-camera.dtsi b/arch/arm64/boot/dts/qcom/sa8195p-camera.dtsi index 7a3bd743658a..b869b06b6f97 100644 --- a/arch/arm64/boot/dts/qcom/sa8195p-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sa8195p-camera.dtsi @@ -532,14 +532,22 @@ msm_cam_smmu_ife { compatible = "qcom,msm-cam-smmu-cb"; - iommus = <&apps_smmu 0xAA0 0x4E0>, - <&apps_smmu 0xA20 0x4E0>, - <&apps_smmu 0xA00 0x4E0>, + iommus = <&apps_smmu 0xA00 0x4E0>, + <&apps_smmu 0xAA0 0x4E0>, + <&apps_smmu 0xA40 0x4E0>, + <&apps_smmu 0xA60 0x4E0>, <&apps_smmu 0xA80 0x4E0>, - <&apps_smmu 0xEA0 0x4E0>, - <&apps_smmu 0xE20 0x4E0>, + <&apps_smmu 0xA20 0x4E0>, + <&apps_smmu 0xAC0 0x4E0>, + <&apps_smmu 0xAE0 0x4E0>, <&apps_smmu 0xE00 0x4E0>, - <&apps_smmu 0xE80 0x4E0>; + <&apps_smmu 0xEA0 0x4E0>, + <&apps_smmu 0xE40 0x4E0>, + <&apps_smmu 0xE60 0x4E0>, + <&apps_smmu 0xE80 0x4E0>, + <&apps_smmu 0xE20 0x4E0>, + <&apps_smmu 0xEC0 0x4E0>, + <&apps_smmu 0xEE0 0x4E0>; label = "ife"; ife_iova_mem_map: iova-mem-map { /* IO region is approximately 3.4 GB */ @@ -553,6 +561,38 @@ }; }; + msm_cam_smmu_ife_cp { + compatible = "qcom,msm-cam-smmu-cb"; + iommus = <&apps_smmu 0xA01 0x5E0>, + <&apps_smmu 0xAA1 0x5E0>, + <&apps_smmu 0xA41 0x5E0>, + <&apps_smmu 0xA61 0x5E0>, + <&apps_smmu 0xA81 0x5E0>, + <&apps_smmu 0xA21 0x5E0>, + <&apps_smmu 0xAC1 0x5E0>, + <&apps_smmu 0xAE1 0x5E0>, + <&apps_smmu 0xE01 0x5E0>, + <&apps_smmu 0xEA1 0x5E0>, + <&apps_smmu 0xE41 0x5E0>, + <&apps_smmu 0xE61 0x5E0>, + <&apps_smmu 0xE81 0x5E0>, + <&apps_smmu 0xE21 0x5E0>, + <&apps_smmu 0xEC1 0x5E0>, + <&apps_smmu 0xEE1 0x5E0>; + label = "ife-cp"; + qcom,secure-pixel-cb; + ife_cp_iova_mem_map: iova-mem-map { + /* IO region is approximately 2.5 GB */ + iova-mem-region-io { + iova-region-name = "io"; + iova-region-start = <0x7400000>; + iova-region-len = <0x98C00000>; + iova-region-id = <0x3>; + status = "ok"; + }; + }; + }; + msm_cam_smmu_jpeg { compatible = "qcom,msm-cam-smmu-cb"; iommus = <&apps_smmu 0x2100 0x20>, diff --git a/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts b/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts index 04d3b38f2d42..449691b4c68d 100644 --- a/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sda429-bg-dvt2-wtp-overlay.dts @@ -17,6 +17,7 @@ #include #include "sda429-bg-dvt2-wtp.dtsi" #include "sdm429-mdss-panels.dtsi" +#include "sdm429-spyro-qrd-evt-audio.dtsi" / { model = "Qualcomm Technologies, Inc. SDA429 QRD BG WTP Overlay"; diff --git a/arch/arm64/boot/dts/qcom/sdm429-blsp.dtsi b/arch/arm64/boot/dts/qcom/sdm429-blsp.dtsi index e661a4f1db0b..06f9e76d7983 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-blsp.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-blsp.dtsi @@ -198,6 +198,7 @@ interrupts = <0 97 IRQ_TYPE_LEVEL_HIGH>, <0 238 IRQ_TYPE_LEVEL_HIGH>; spi-max-frequency = <50000000>; + qcom,use-bam; qcom,ver-reg-exists; qcom,bam-consumer-pipe-index = <8>; qcom,bam-producer-pipe-index = <9>; diff --git a/arch/arm64/boot/dts/qcom/sdm429w-bg-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-bg-pm660.dtsi index 5ceebb2c9b30..21004c2dbc1d 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-bg-pm660.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-bg-pm660.dtsi @@ -29,7 +29,3 @@ &pm660_fg { qcom,fg-disable-in-twm; }; - -&pm660_haptics { - qcom,haptics-ext-pin-twm; -}; diff --git a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi index c670547294ba..eb338f2af52f 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi @@ -131,7 +131,6 @@ /delete-property/ qcom,lra-allow-variable-play; /delete-property/ qcom,lra-allow-variable-play-rate; qcom,actuator-type = "erm"; - qcom,ilim-ma = <400>; qcom,play-rate-us = <10000>; wf_0 { diff --git a/arch/arm64/boot/dts/qcom/sdm660-usbc-audio-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm660-usbc-audio-mtp-overlay.dts index 661437a49e92..20ec19a543e7 100644 --- a/arch/arm64/boot/dts/qcom/sdm660-usbc-audio-mtp-overlay.dts +++ b/arch/arm64/boot/dts/qcom/sdm660-usbc-audio-mtp-overlay.dts @@ -13,6 +13,7 @@ /dts-v1/; /plugin/; #include +#include #include "sdm660-mtp.dtsi" #include "sdm660-external-codec.dtsi" diff --git a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi index 86098aa8ccba..2e2abfe4b014 100644 --- a/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmmagpie.dtsi @@ -2633,6 +2633,13 @@ qcom,minidump-id = <3>; qcom,complete-ramdump; + qcom,msm-bus,name = "pil-modem"; + qcom,msm-bus,num-cases = <2>; + qcom,msm-bus,num-paths = <1>; + qcom,msm-bus,vectors-KBps = + <129 512 0 0>, + <129 512 0 7000000>; + /* Inputs from mss */ interrupts-extended = <&pdc GIC_SPI 266 IRQ_TYPE_EDGE_RISING>, <&modem_smp2p_in 0 IRQ_TYPE_NONE>, diff --git a/arch/arm64/boot/dts/qcom/sdmshrike.dtsi b/arch/arm64/boot/dts/qcom/sdmshrike.dtsi index a737a5321d4a..12825eaef049 100644 --- a/arch/arm64/boot/dts/qcom/sdmshrike.dtsi +++ b/arch/arm64/boot/dts/qcom/sdmshrike.dtsi @@ -719,7 +719,7 @@ alloc-ranges = <0x0 0x00000000 0x0 0xffffffff>; reusable; alignment = <0x0 0x400000>; - size = <0x0 0x2800000>; + size = <0x0 0x3c00000>; linux,cma-default; }; }; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie-audio.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie-audio.dtsi index 26204b4f6814..589e790f9e78 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie-audio.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie-audio.dtsi @@ -38,7 +38,9 @@ <&afe_proxy_tx>, <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, <&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>, + <&dai_pri_tdm_rx_1>, <&dai_pri_tdm_tx_1>, <&dai_sec_tdm_rx_0>, <&dai_sec_tdm_tx_0>, + <&dai_sec_tdm_rx_1>, <&dai_sec_tdm_tx_1>, <&dai_sec_auxpcm>, <&incall2_record_rx>, <&incall_music_2_rx>, <&incall_music_dl_rx>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", @@ -50,7 +52,9 @@ "msm-dai-q6-dev.240", "msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", "msm-dai-q6-tdm.36864", "msm-dai-q6-tdm.36865", + "msm-dai-q6-tdm.36866", "msm-dai-q6-tdm.36867", "msm-dai-q6-tdm.36880", "msm-dai-q6-tdm.36881", + "msm-dai-q6-tdm.36882", "msm-dai-q6-tdm.36883", "msm-dai-q6-auxpcm.2", "msm-dai-q6-dev.32769", "msm-dai-q6-dev.32770", "msm-dai-q6-dev.32774"; }; diff --git a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi index ae83aacc0450..3206654f92a7 100644 --- a/arch/arm64/boot/dts/qcom/sdxprairie.dtsi +++ b/arch/arm64/boot/dts/qcom/sdxprairie.dtsi @@ -704,6 +704,12 @@ qcom,net-id = <3>; }; + eth_dev_qrtr: qcom,eth_dev_qrtr { + compatible = "qcom,qrtr-ethernet-dev"; + qcom,net-id = <4>; + qcom,low-latency; + }; + qcom,glinkpkt { compatible = "qcom,glinkpkt"; diff --git a/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi b/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi index f0acba499904..7ce2aec6b3a8 100644 --- a/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sm6150-camera.dtsi @@ -227,7 +227,7 @@ }; }; - qcom,cam_smmu { + cam_smmu: qcom,cam_smmu { compatible = "qcom,msm-cam-smmu"; status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi b/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi index 07aea5e101b8..2c08330b15bc 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-camera.dtsi @@ -316,7 +316,7 @@ }; }; - msm_cam_smmu: qcom,cam_smmu { + cam_smmu: qcom,cam_smmu { compatible = "qcom,msm-cam-smmu"; status = "ok"; diff --git a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi index 2b0974243132..aee5d7896abe 100644 --- a/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi +++ b/arch/arm64/boot/dts/qcom/sm8150-sde.dtsi @@ -200,9 +200,6 @@ qcom,sde-cdp-setting = <1 1>, <1 0>; - qcom,sde-qos-cpu-mask = <0x3>; - qcom,sde-qos-cpu-dma-latency = <44>; - /* offsets are relative to "mdp_phys + qcom,sde-off */ qcom,sde-reg-dma-off = <0>; diff --git a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi index 1fc5060d7027..0d5679380b2a 100644 --- a/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi +++ b/arch/arm64/boot/dts/rockchip/rk3399-puma.dtsi @@ -138,7 +138,7 @@ vcc5v0_host: vcc5v0-host-regulator { compatible = "regulator-fixed"; - gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_HIGH>; + gpio = <&gpio4 RK_PA3 GPIO_ACTIVE_LOW>; enable-active-low; pinctrl-names = "default"; pinctrl-0 = <&vcc5v0_host_en>; @@ -193,7 +193,7 @@ phy-mode = "rgmii"; pinctrl-names = "default"; pinctrl-0 = <&rgmii_pins>; - snps,reset-gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_HIGH>; + snps,reset-gpio = <&gpio3 RK_PC0 GPIO_ACTIVE_LOW>; snps,reset-active-low; snps,reset-delays-us = <0 10000 50000>; tx_delay = <0x10>; diff --git a/arch/arm64/configs/raphael_defconfig b/arch/arm64/configs/raphael_defconfig index d304c046bf27..655bd109d451 100644 --- a/arch/arm64/configs/raphael_defconfig +++ b/arch/arm64/configs/raphael_defconfig @@ -239,7 +239,7 @@ CONFIG_SLAB_MERGE_DEFAULT=y # CONFIG_SLAB_FREELIST_HARDENED is not set CONFIG_SLUB_CPU_PARTIAL=y # CONFIG_SYSTEM_DATA_VERIFICATION is not set -# CONFIG_PROFILING is not set +CONFIG_PROFILING=y CONFIG_JUMP_LABEL=y # CONFIG_STATIC_KEYS_SELFTEST is not set # CONFIG_UPROBES is not set @@ -1581,7 +1581,7 @@ CONFIG_DM_BUFIO=y # CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING is not set CONFIG_DM_CRYPT=y CONFIG_DM_DEFAULT_KEY=y -# CONFIG_DM_SNAPSHOT is not set +CONFIG_DM_SNAPSHOT=y # CONFIG_DM_THIN_PROVISIONING is not set # CONFIG_DM_CACHE is not set # CONFIG_DM_ERA is not set @@ -1620,7 +1620,7 @@ CONFIG_DUMMY=y # CONFIG_RMNET_IPLO is not set CONFIG_TUN=y # CONFIG_TUN_VNET_CROSS_LE is not set -# CONFIG_VETH is not set +CONFIG_VETH=y # CONFIG_NLMON is not set # @@ -5094,7 +5094,8 @@ CONFIG_HAVE_HARDENED_USERCOPY_ALLOCATOR=y CONFIG_HARDENED_USERCOPY=y # CONFIG_HARDENED_USERCOPY_PAGESPAN is not set CONFIG_FORTIFY_SOURCE=y -# CONFIG_STATIC_USERMODEHELPER is not set +CONFIG_STATIC_USERMODEHELPER=y +CONFIG_STATIC_USERMODEHELPER_PATH="/sbin/usermode-helper" CONFIG_SECURITY_SELINUX=y # CONFIG_SECURITY_SELINUX_BOOTPARAM is not set # CONFIG_SECURITY_SELINUX_DISABLE is not set diff --git a/arch/arm64/configs/vendor/atoll-perf_defconfig b/arch/arm64/configs/vendor/atoll-perf_defconfig index 7268935d0211..2b5babeda540 100644 --- a/arch/arm64/configs/vendor/atoll-perf_defconfig +++ b/arch/arm64/configs/vendor/atoll-perf_defconfig @@ -17,18 +17,17 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -39,6 +38,7 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set @@ -48,7 +48,6 @@ CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -78,6 +77,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y # CONFIG_EFI is not set @@ -245,6 +245,7 @@ CONFIG_NET_ACT_MIRRED=y CONFIG_NET_ACT_SKBEDIT=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -320,6 +321,8 @@ CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_ST=y @@ -457,7 +460,6 @@ CONFIG_HID_NINTENDO=y CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y CONFIG_HID_QVR=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -660,6 +662,7 @@ CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_QCOM_QFPROM=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y @@ -702,6 +705,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_LIST=y CONFIG_IPC_LOGGING=y CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_CORESIGHT=y @@ -721,6 +725,7 @@ CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/atoll_defconfig b/arch/arm64/configs/vendor/atoll_defconfig index 571da08e467a..38e428ac723f 100644 --- a/arch/arm64/configs/vendor/atoll_defconfig +++ b/arch/arm64/configs/vendor/atoll_defconfig @@ -16,12 +16,12 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y CONFIG_DEBUG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y @@ -29,7 +29,6 @@ CONFIG_CGROUP_BPF=y CONFIG_CGROUP_DEBUG=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -41,6 +40,7 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB_FREELIST_RANDOM=y @@ -50,7 +50,6 @@ CONFIG_KPROBES=y CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -84,6 +83,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y CONFIG_KRYO_PMU_WORKAROUND=y @@ -253,6 +253,7 @@ CONFIG_NET_ACT_SKBEDIT=y CONFIG_DNS_RESOLVER=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -330,6 +331,7 @@ CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ATMEL_MXT=y CONFIG_TOUCHSCREEN_ST=y @@ -472,7 +474,6 @@ CONFIG_HID_NINTENDO=y CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y CONFIG_HID_QVR=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -690,6 +691,7 @@ CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_QCOM_QFPROM=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y @@ -809,6 +811,7 @@ CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig b/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig index 394690495768..1aeade82c3bc 100644 --- a/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig +++ b/arch/arm64/configs/vendor/qti-quin-gvm-perf_defconfig @@ -457,12 +457,12 @@ CONFIG_MSM_PIL=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_BOOT_TIME_MARKER=y -CONFIG_QCOM_SECURE_BUFFER=y CONFIG_QCOM_GLINK=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_HAB=y CONFIG_QCOM_HGSL_TCSR_SIGNAL=y CONFIG_QCOM_HGSL=y +CONFIG_RENAME_BLOCK_DEVICE=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y CONFIG_EXTCON_USB_GPIO=y diff --git a/arch/arm64/configs/vendor/qti-quin-gvm_defconfig b/arch/arm64/configs/vendor/qti-quin-gvm_defconfig index aec2c05011ab..050f57e87abc 100644 --- a/arch/arm64/configs/vendor/qti-quin-gvm_defconfig +++ b/arch/arm64/configs/vendor/qti-quin-gvm_defconfig @@ -468,12 +468,12 @@ CONFIG_MSM_PIL=y CONFIG_MSM_PIL_SSR_GENERIC=y CONFIG_MSM_BOOT_STATS=y CONFIG_MSM_BOOT_TIME_MARKER=y -CONFIG_QCOM_SECURE_BUFFER=y CONFIG_QCOM_GLINK=y CONFIG_MEM_SHARE_QMI_SERVICE=y CONFIG_MSM_HAB=y CONFIG_QCOM_HGSL_TCSR_SIGNAL=y CONFIG_QCOM_HGSL=y +CONFIG_RENAME_BLOCK_DEVICE=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y CONFIG_EXTCON_USB_GPIO=y diff --git a/arch/arm64/configs/vendor/sa2150p-nand-perf_defconfig b/arch/arm64/configs/vendor/sa2150p-nand-perf_defconfig index 8949cf9519a0..cd9423f0a52a 100644 --- a/arch/arm64/configs/vendor/sa2150p-nand-perf_defconfig +++ b/arch/arm64/configs/vendor/sa2150p-nand-perf_defconfig @@ -238,6 +238,9 @@ CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_STMMAC_ETH=y +# CONFIG_DWMAC_GENERIC is not set +# CONFIG_DWMAC_IPQ806X is not set CONFIG_AT803X_PHY=y CONFIG_MICREL_PHY=y CONFIG_PPP=y @@ -276,11 +279,11 @@ CONFIG_I2C_MUX=y CONFIG_I2C_MSM_V2=y CONFIG_SPI=y CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y CONFIG_SPMI=y CONFIG_SLIMBUS=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_PPS_CLIENT_GPIO=y -CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_QCS405=y CONFIG_FRAGMENTED_GPIO_ADDRESS_SPACE=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y diff --git a/arch/arm64/configs/vendor/sa2150p-nand_defconfig b/arch/arm64/configs/vendor/sa2150p-nand_defconfig index e35d9fe9cf9c..77c30567355a 100644 --- a/arch/arm64/configs/vendor/sa2150p-nand_defconfig +++ b/arch/arm64/configs/vendor/sa2150p-nand_defconfig @@ -238,6 +238,9 @@ CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y CONFIG_DUMMY=y CONFIG_TUN=y +CONFIG_STMMAC_ETH=y +# CONFIG_DWMAC_GENERIC is not set +# CONFIG_DWMAC_IPQ806X is not set CONFIG_AT803X_PHY=y CONFIG_MICREL_PHY=y CONFIG_PPP=y @@ -282,7 +285,6 @@ CONFIG_SPMI=y CONFIG_SLIMBUS=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_PPS_CLIENT_GPIO=y -CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_QCS405=y CONFIG_FRAGMENTED_GPIO_ADDRESS_SPACE=y CONFIG_PINCTRL_QCOM_SPMI_PMIC=y diff --git a/arch/arm64/configs/vendor/sa2150p-perf_defconfig b/arch/arm64/configs/vendor/sa2150p-perf_defconfig index c0a089b14414..e1e518583dcf 100644 --- a/arch/arm64/configs/vendor/sa2150p-perf_defconfig +++ b/arch/arm64/configs/vendor/sa2150p-perf_defconfig @@ -290,6 +290,7 @@ CONFIG_I2C_MUX=y CONFIG_I2C_MSM_V2=y CONFIG_SPI=y CONFIG_SPI_QUP=y +CONFIG_SPI_SPIDEV=y CONFIG_SPMI=y CONFIG_SLIMBUS_MSM_NGD=y CONFIG_PPS_CLIENT_GPIO=y diff --git a/arch/arm64/configs/vendor/sa8155-perf_defconfig b/arch/arm64/configs/vendor/sa8155-perf_defconfig index e15c2f8b3418..5032fae84d52 100644 --- a/arch/arm64/configs/vendor/sa8155-perf_defconfig +++ b/arch/arm64/configs/vendor/sa8155-perf_defconfig @@ -318,6 +318,7 @@ CONFIG_CNSS2=y CONFIG_CNSS2_DEBUG=y CONFIG_CNSS2_QMI=y CONFIG_CNSS_ASYNC=y +CONFIG_CNSS_UTILS=y CONFIG_CNSS_GENL=y CONFIG_NVM=y CONFIG_NVM_RRPC=y diff --git a/arch/arm64/configs/vendor/sa8155_defconfig b/arch/arm64/configs/vendor/sa8155_defconfig index 189f980e5bd8..359ae8a3e879 100644 --- a/arch/arm64/configs/vendor/sa8155_defconfig +++ b/arch/arm64/configs/vendor/sa8155_defconfig @@ -329,6 +329,7 @@ CONFIG_CNSS2=y CONFIG_CNSS2_DEBUG=y CONFIG_CNSS2_QMI=y CONFIG_CNSS_ASYNC=y +CONFIG_CNSS_UTILS=y CONFIG_CNSS_GENL=y CONFIG_NVM=y CONFIG_NVM_RRPC=y diff --git a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig index 6069cb150ce2..cf2d2fe4c5bc 100644 --- a/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe-perf_defconfig @@ -16,18 +16,17 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -38,6 +37,7 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set @@ -47,7 +47,6 @@ CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -73,6 +72,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y # CONFIG_EFI is not set @@ -241,6 +241,7 @@ CONFIG_NET_ACT_MIRRED=y CONFIG_NET_ACT_SKBEDIT=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -316,6 +317,8 @@ CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ST=y CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y @@ -442,7 +445,6 @@ CONFIG_HID_NINTENDO=y CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y CONFIG_HID_QVR=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -640,6 +642,7 @@ CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y CONFIG_ESOC=y @@ -681,6 +684,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_LIST=y CONFIG_IPC_LOGGING=y CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_CORESIGHT=y @@ -700,6 +704,7 @@ CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/sdmsteppe_defconfig b/arch/arm64/configs/vendor/sdmsteppe_defconfig index 2d93f5047063..3c788d2bca17 100644 --- a/arch/arm64/configs/vendor/sdmsteppe_defconfig +++ b/arch/arm64/configs/vendor/sdmsteppe_defconfig @@ -15,12 +15,12 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y CONFIG_DEBUG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y @@ -28,7 +28,6 @@ CONFIG_CGROUP_BPF=y CONFIG_CGROUP_DEBUG=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -40,6 +39,7 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB_FREELIST_RANDOM=y @@ -48,7 +48,6 @@ CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -79,6 +78,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y CONFIG_KRYO_PMU_WORKAROUND=y @@ -249,6 +249,7 @@ CONFIG_NET_ACT_SKBEDIT=y CONFIG_DNS_RESOLVER=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -326,6 +327,7 @@ CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ST=y CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y @@ -466,7 +468,6 @@ CONFIG_HID_NINTENDO=y CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y CONFIG_HID_QVR=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -677,6 +678,7 @@ CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y CONFIG_ESOC=y @@ -795,6 +797,7 @@ CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/sm8150-perf_defconfig b/arch/arm64/configs/vendor/sm8150-perf_defconfig index 084e44000588..6b8a37fc3af9 100644 --- a/arch/arm64/configs/vendor/sm8150-perf_defconfig +++ b/arch/arm64/configs/vendor/sm8150-perf_defconfig @@ -17,18 +17,17 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -39,6 +38,7 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_SLUB_DEBUG is not set # CONFIG_COMPAT_BRK is not set @@ -49,7 +49,6 @@ CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_REFCOUNT_FULL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -78,6 +77,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y # CONFIG_EFI is not set @@ -249,6 +249,7 @@ CONFIG_QRTR=y CONFIG_QRTR_SMD=y CONFIG_QRTR_MHI=y CONFIG_QRTR_FIFO=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -325,6 +326,8 @@ CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ST=y CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y @@ -451,7 +454,6 @@ CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y CONFIG_HID_QVR=y CONFIG_USB_HIDDEV=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -647,6 +649,7 @@ CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y CONFIG_ESOC=y @@ -688,6 +691,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=-1 CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_LIST=y CONFIG_IPC_LOGGING=y CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_CORESIGHT=y @@ -709,6 +713,7 @@ CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/sm8150_defconfig b/arch/arm64/configs/vendor/sm8150_defconfig index e21d100fa8ad..1f1866b3ebec 100644 --- a/arch/arm64/configs/vendor/sm8150_defconfig +++ b/arch/arm64/configs/vendor/sm8150_defconfig @@ -16,12 +16,12 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y CONFIG_DEBUG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y @@ -29,7 +29,6 @@ CONFIG_CGROUP_BPF=y CONFIG_CGROUP_DEBUG=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -41,6 +40,7 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB_FREELIST_RANDOM=y @@ -51,7 +51,6 @@ CONFIG_REFCOUNT_FULL=y CONFIG_PANIC_ON_REFCOUNT_ERROR=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -85,6 +84,7 @@ CONFIG_ARMV8_DEPRECATED=y CONFIG_SWP_EMULATION=y CONFIG_CP15_BARRIER_EMULATION=y CONFIG_SETEND_EMULATION=y +CONFIG_ARM64_SW_TTBR0_PAN=y # CONFIG_ARM64_VHE is not set CONFIG_RANDOMIZE_BASE=y CONFIG_BUILD_ARM64_UNCOMPRESSED_KERNEL=y @@ -258,6 +258,7 @@ CONFIG_QRTR=y CONFIG_QRTR_SMD=y CONFIG_QRTR_MHI=y CONFIG_QRTR_FIFO=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -337,6 +338,7 @@ CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_ST=y CONFIG_TOUCHSCREEN_SYNAPTICS_TCM=y @@ -467,7 +469,6 @@ CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y CONFIG_HID_QVR=y CONFIG_USB_HIDDEV=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -677,6 +678,7 @@ CONFIG_QCOM_LLCC_PMU=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y CONFIG_ESOC=y @@ -796,6 +798,7 @@ CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/trinket-perf_defconfig b/arch/arm64/configs/vendor/trinket-perf_defconfig index d6b5f618497e..9248468b02eb 100644 --- a/arch/arm64/configs/vendor/trinket-perf_defconfig +++ b/arch/arm64/configs/vendor/trinket-perf_defconfig @@ -17,18 +17,17 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y CONFIG_CGROUP_BPF=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -39,6 +38,7 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_RD_LZ4 is not set CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB_FREELIST_RANDOM=y @@ -47,7 +47,6 @@ CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -244,6 +243,7 @@ CONFIG_NET_ACT_MIRRED=y CONFIG_NET_ACT_SKBEDIT=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -316,6 +316,8 @@ CONFIG_CNSS_GENL=y CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y CONFIG_TOUCHSCREEN_HIMAX_I2C=y @@ -458,7 +460,6 @@ CONFIG_HID_MULTITOUCH=y CONFIG_HID_NINTENDO=y CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -631,6 +632,7 @@ CONFIG_QTI_MPM=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_QCOM_QFPROM=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y @@ -648,6 +650,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y @@ -665,6 +668,7 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_PANIC_TIMEOUT=5 CONFIG_SCHEDSTATS=y # CONFIG_DEBUG_PREEMPT is not set +CONFIG_DEBUG_LIST=y CONFIG_IPC_LOGGING=y CONFIG_DEBUG_ALIGN_RODATA=y CONFIG_CORESIGHT=y @@ -684,6 +688,7 @@ CONFIG_SECURITY_PERF_EVENTS_RESTRICT=y CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/arm64/configs/vendor/trinket_defconfig b/arch/arm64/configs/vendor/trinket_defconfig index 5132a6da3b89..cf1f806d7c9b 100644 --- a/arch/arm64/configs/vendor/trinket_defconfig +++ b/arch/arm64/configs/vendor/trinket_defconfig @@ -16,12 +16,12 @@ CONFIG_RCU_FAST_NO_HZ=y CONFIG_RCU_NOCB_CPU=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=y CONFIG_LOG_CPU_MAX_BUF_SHIFT=17 CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_BLK_CGROUP=y CONFIG_DEBUG_BLK_CGROUP=y -CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_FREEZER=y CONFIG_CPUSETS=y CONFIG_CGROUP_CPUACCT=y @@ -29,7 +29,6 @@ CONFIG_CGROUP_BPF=y CONFIG_CGROUP_DEBUG=y CONFIG_SCHED_CORE_CTL=y CONFIG_NAMESPACES=y -# CONFIG_UTS_NS is not set # CONFIG_PID_NS is not set CONFIG_SCHED_AUTOGROUP=y CONFIG_SCHED_TUNE=y @@ -41,6 +40,7 @@ CONFIG_BLK_DEV_INITRD=y CONFIG_CC_OPTIMIZE_FOR_SIZE=y CONFIG_KALLSYMS_ALL=y CONFIG_BPF_SYSCALL=y +CONFIG_BPF_JIT_ALWAYS_ON=y CONFIG_EMBEDDED=y # CONFIG_COMPAT_BRK is not set CONFIG_SLAB_FREELIST_RANDOM=y @@ -49,7 +49,6 @@ CONFIG_PROFILING=y CONFIG_CC_STACKPROTECTOR_STRONG=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y -CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SIG=y CONFIG_MODULE_SIG_FORCE=y @@ -253,6 +252,7 @@ CONFIG_NET_ACT_SKBEDIT=y CONFIG_DNS_RESOLVER=y CONFIG_QRTR=y CONFIG_QRTR_SMD=y +CONFIG_BPF_JIT=y CONFIG_SOCKEV_NLMCAST=y CONFIG_BT=y CONFIG_MSM_BT_POWER=y @@ -328,6 +328,7 @@ CONFIG_INPUT_EVDEV=y CONFIG_KEYBOARD_GPIO=y # CONFIG_INPUT_MOUSE is not set CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_XPAD=y CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCREEN_HIMAX_CHIPSET=y CONFIG_TOUCHSCREEN_HIMAX_I2C=y @@ -474,7 +475,6 @@ CONFIG_HID_MULTITOUCH=y CONFIG_HID_NINTENDO=y CONFIG_HID_PLANTRONICS=y CONFIG_HID_SONY=y -CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y CONFIG_USB_EHCI_HCD=y @@ -663,6 +663,7 @@ CONFIG_PHY_XGENE=y CONFIG_RAS=y CONFIG_ANDROID=y CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDERFS=y CONFIG_QCOM_QFPROM=y CONFIG_NVMEM_SPMI_SDAM=y CONFIG_SENSORS_SSC=y @@ -680,6 +681,7 @@ CONFIG_QUOTA_NETLINK_INTERFACE=y CONFIG_QFMT_V2=y CONFIG_FUSE_FS=y CONFIG_OVERLAY_FS=y +CONFIG_INCREMENTAL_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_TMPFS_POSIX_ACL=y @@ -772,6 +774,7 @@ CONFIG_SECURITY=y CONFIG_HARDENED_USERCOPY=y CONFIG_HARDENED_USERCOPY_PAGESPAN=y CONFIG_FORTIFY_SOURCE=y +CONFIG_STATIC_USERMODEHELPER=y CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SMACK=y CONFIG_CRYPTO_GCM=y diff --git a/arch/m68k/mac/iop.c b/arch/m68k/mac/iop.c index 4c1e606e7d03..0b94f6672c5f 100644 --- a/arch/m68k/mac/iop.c +++ b/arch/m68k/mac/iop.c @@ -183,7 +183,7 @@ static __inline__ void iop_writeb(volatile struct mac_iop *iop, __u16 addr, __u8 static __inline__ void iop_stop(volatile struct mac_iop *iop) { - iop->status_ctrl &= ~IOP_RUN; + iop->status_ctrl = IOP_AUTOINC; } static __inline__ void iop_start(volatile struct mac_iop *iop) @@ -191,14 +191,9 @@ static __inline__ void iop_start(volatile struct mac_iop *iop) iop->status_ctrl = IOP_RUN | IOP_AUTOINC; } -static __inline__ void iop_bypass(volatile struct mac_iop *iop) -{ - iop->status_ctrl |= IOP_BYPASS; -} - static __inline__ void iop_interrupt(volatile struct mac_iop *iop) { - iop->status_ctrl |= IOP_IRQ; + iop->status_ctrl = IOP_IRQ | IOP_RUN | IOP_AUTOINC; } static int iop_alive(volatile struct mac_iop *iop) @@ -244,7 +239,6 @@ void __init iop_preinit(void) } else { iop_base[IOP_NUM_SCC] = (struct mac_iop *) SCC_IOP_BASE_QUADRA; } - iop_base[IOP_NUM_SCC]->status_ctrl = 0x87; iop_scc_present = 1; } else { iop_base[IOP_NUM_SCC] = NULL; @@ -256,7 +250,7 @@ void __init iop_preinit(void) } else { iop_base[IOP_NUM_ISM] = (struct mac_iop *) ISM_IOP_BASE_QUADRA; } - iop_base[IOP_NUM_ISM]->status_ctrl = 0; + iop_stop(iop_base[IOP_NUM_ISM]); iop_ism_present = 1; } else { iop_base[IOP_NUM_ISM] = NULL; @@ -416,7 +410,8 @@ static void iop_handle_send(uint iop_num, uint chan) msg->status = IOP_MSGSTATUS_UNUSED; msg = msg->next; iop_send_queue[iop_num][chan] = msg; - if (msg) iop_do_send(msg); + if (msg && iop_readb(iop, IOP_ADDR_SEND_STATE + chan) == IOP_MSG_IDLE) + iop_do_send(msg); } /* @@ -490,16 +485,12 @@ int iop_send_message(uint iop_num, uint chan, void *privdata, if (!(q = iop_send_queue[iop_num][chan])) { iop_send_queue[iop_num][chan] = msg; + iop_do_send(msg); } else { while (q->next) q = q->next; q->next = msg; } - if (iop_readb(iop_base[iop_num], - IOP_ADDR_SEND_STATE + chan) == IOP_MSG_IDLE) { - iop_do_send(msg); - } - return 0; } diff --git a/arch/mips/cavium-octeon/octeon-usb.c b/arch/mips/cavium-octeon/octeon-usb.c index bfdfaf32d2c4..75189ff2f3c7 100644 --- a/arch/mips/cavium-octeon/octeon-usb.c +++ b/arch/mips/cavium-octeon/octeon-usb.c @@ -517,6 +517,7 @@ static int __init dwc3_octeon_device_init(void) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (res == NULL) { + put_device(&pdev->dev); dev_err(&pdev->dev, "No memory resources\n"); return -ENXIO; } @@ -528,8 +529,10 @@ static int __init dwc3_octeon_device_init(void) * know the difference. */ base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) + if (IS_ERR(base)) { + put_device(&pdev->dev); return PTR_ERR(base); + } mutex_lock(&dwc3_octeon_clocks_mutex); dwc3_octeon_clocks_start(&pdev->dev, (u64)base); diff --git a/arch/mips/kernel/topology.c b/arch/mips/kernel/topology.c index cd3e1f82e1a5..08ad6371fbe0 100644 --- a/arch/mips/kernel/topology.c +++ b/arch/mips/kernel/topology.c @@ -20,7 +20,7 @@ static int __init topology_init(void) for_each_present_cpu(i) { struct cpu *c = &per_cpu(cpu_devices, i); - c->hotpluggable = 1; + c->hotpluggable = !!i; ret = register_cpu(c, i); if (ret) printk(KERN_WARNING "topology_init: register_cpu %d " diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h index dbaaca84f27f..640d46edf32e 100644 --- a/arch/parisc/include/asm/barrier.h +++ b/arch/parisc/include/asm/barrier.h @@ -26,6 +26,67 @@ #define __smp_rmb() mb() #define __smp_wmb() mb() +#define __smp_store_release(p, v) \ +do { \ + typeof(p) __p = (p); \ + union { typeof(*p) __val; char __c[1]; } __u = \ + { .__val = (__force typeof(*p)) (v) }; \ + compiletime_assert_atomic_type(*p); \ + switch (sizeof(*p)) { \ + case 1: \ + asm volatile("stb,ma %0,0(%1)" \ + : : "r"(*(__u8 *)__u.__c), "r"(__p) \ + : "memory"); \ + break; \ + case 2: \ + asm volatile("sth,ma %0,0(%1)" \ + : : "r"(*(__u16 *)__u.__c), "r"(__p) \ + : "memory"); \ + break; \ + case 4: \ + asm volatile("stw,ma %0,0(%1)" \ + : : "r"(*(__u32 *)__u.__c), "r"(__p) \ + : "memory"); \ + break; \ + case 8: \ + if (IS_ENABLED(CONFIG_64BIT)) \ + asm volatile("std,ma %0,0(%1)" \ + : : "r"(*(__u64 *)__u.__c), "r"(__p) \ + : "memory"); \ + break; \ + } \ +} while (0) + +#define __smp_load_acquire(p) \ +({ \ + union { typeof(*p) __val; char __c[1]; } __u; \ + typeof(p) __p = (p); \ + compiletime_assert_atomic_type(*p); \ + switch (sizeof(*p)) { \ + case 1: \ + asm volatile("ldb,ma 0(%1),%0" \ + : "=r"(*(__u8 *)__u.__c) : "r"(__p) \ + : "memory"); \ + break; \ + case 2: \ + asm volatile("ldh,ma 0(%1),%0" \ + : "=r"(*(__u16 *)__u.__c) : "r"(__p) \ + : "memory"); \ + break; \ + case 4: \ + asm volatile("ldw,ma 0(%1),%0" \ + : "=r"(*(__u32 *)__u.__c) : "r"(__p) \ + : "memory"); \ + break; \ + case 8: \ + if (IS_ENABLED(CONFIG_64BIT)) \ + asm volatile("ldd,ma 0(%1),%0" \ + : "=r"(*(__u64 *)__u.__c) : "r"(__p) \ + : "memory"); \ + break; \ + } \ + __u.__val; \ +}) #include #endif /* !__ASSEMBLY__ */ diff --git a/arch/powerpc/include/asm/percpu.h b/arch/powerpc/include/asm/percpu.h index dce863a7635c..8e5b7d0b851c 100644 --- a/arch/powerpc/include/asm/percpu.h +++ b/arch/powerpc/include/asm/percpu.h @@ -10,8 +10,6 @@ #ifdef CONFIG_SMP -#include - #define __my_cpu_offset local_paca->data_offset #endif /* CONFIG_SMP */ @@ -19,4 +17,6 @@ #include +#include + #endif /* _ASM_POWERPC_PERCPU_H_ */ diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index c4f59971e515..f6ddea9122c0 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c @@ -704,7 +704,7 @@ int vdso_getcpu_init(void) node = cpu_to_node(cpu); WARN_ON_ONCE(node > 0xffff); - val = (cpu & 0xfff) | ((node & 0xffff) << 16); + val = (cpu & 0xffff) | ((node & 0xffff) << 16); mtspr(SPRN_SPRG_VDSO_WRITE, val); get_paca()->sprg_vdso = val; diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index a0847be0b035..1a3cffdaa1e8 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c @@ -30,7 +30,7 @@ static bool rtas_hp_event; unsigned long pseries_memory_block_size(void) { struct device_node *np; - unsigned int memblock_size = MIN_MEMORY_BLOCK_SIZE; + u64 memblock_size = MIN_MEMORY_BLOCK_SIZE; struct resource r; np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); diff --git a/arch/sh/boards/mach-landisk/setup.c b/arch/sh/boards/mach-landisk/setup.c index f1147caebacf..af69fb7fef7c 100644 --- a/arch/sh/boards/mach-landisk/setup.c +++ b/arch/sh/boards/mach-landisk/setup.c @@ -85,6 +85,9 @@ device_initcall(landisk_devices_setup); static void __init landisk_setup(char **cmdline_p) { + /* I/O port identity mapping */ + __set_io_port_base(0); + /* LED ON */ __raw_writeb(__raw_readb(PA_LED) | 0x03, PA_LED); diff --git a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S index 5f6a5af9c489..77043a82da51 100644 --- a/arch/x86/crypto/aes_ctrby8_avx-x86_64.S +++ b/arch/x86/crypto/aes_ctrby8_avx-x86_64.S @@ -127,10 +127,6 @@ ddq_add_8: /* generate a unique variable for ddq_add_x */ -.macro setddq n - var_ddq_add = ddq_add_\n -.endm - /* generate a unique variable for xmm register */ .macro setxdata n var_xdata = %xmm\n @@ -140,9 +136,7 @@ ddq_add_8: .macro club name, id .altmacro - .if \name == DDQ_DATA - setddq %\id - .elseif \name == XDATA + .if \name == XDATA setxdata %\id .endif .noaltmacro @@ -165,9 +159,8 @@ ddq_add_8: .set i, 1 .rept (by - 1) - club DDQ_DATA, i club XDATA, i - vpaddq var_ddq_add(%rip), xcounter, var_xdata + vpaddq (ddq_add_1 + 16 * (i - 1))(%rip), xcounter, var_xdata vptest ddq_low_msk(%rip), var_xdata jnz 1f vpaddq ddq_high_add_1(%rip), var_xdata, var_xdata @@ -180,8 +173,7 @@ ddq_add_8: vmovdqa 1*16(p_keys), xkeyA vpxor xkey0, xdata0, xdata0 - club DDQ_DATA, by - vpaddq var_ddq_add(%rip), xcounter, xcounter + vpaddq (ddq_add_1 + 16 * (by - 1))(%rip), xcounter, xcounter vptest ddq_low_msk(%rip), xcounter jnz 1f vpaddq ddq_high_add_1(%rip), xcounter, xcounter diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index b5652233e674..a1c4a13782da 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -2252,8 +2252,13 @@ static int mp_irqdomain_create(int ioapic) static void ioapic_destroy_irqdomain(int idx) { + struct ioapic_domain_cfg *cfg = &ioapics[idx].irqdomain_cfg; + struct fwnode_handle *fn = ioapics[idx].irqdomain->fwnode; + if (ioapics[idx].irqdomain) { irq_domain_remove(ioapics[idx].irqdomain); + if (!cfg->dev) + irq_domain_free_fwnode(fn); ioapics[idx].irqdomain = NULL; } } diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index 36cd34524ac1..637cf4dfccc9 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c @@ -368,6 +368,10 @@ static int x86_vector_alloc_irqs(struct irq_domain *domain, unsigned int virq, irq_data->chip = &lapic_controller; irq_data->chip_data = data; irq_data->hwirq = virq + i; + + /* Don't invoke affinity setter on deactivated interrupts */ + irqd_set_affinity_on_activate(irq_data); + err = assign_irq_vector_policy(virq + i, node, data, info, irq_data); if (err) { diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c index e57b59762f9f..94aa91b09c28 100644 --- a/arch/x86/kernel/cpu/mcheck/mce-inject.c +++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c @@ -518,7 +518,7 @@ static void do_inject(void) */ if (inj_type == DFR_INT_INJ) { i_mce.status |= MCI_STATUS_DEFERRED; - i_mce.status |= (i_mce.status & ~MCI_STATUS_UC); + i_mce.status &= ~MCI_STATUS_UC; } /* diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index 734549492a18..dc4d27000aa3 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -374,7 +374,7 @@ static unsigned long task_seg_base(struct task_struct *task, */ mutex_lock(&task->mm->context.lock); ldt = task->mm->context.ldt; - if (unlikely(idx >= ldt->nr_entries)) + if (unlikely(!ldt || idx >= ldt->nr_entries)) base = 0; else base = get_desc_base(ldt->entries + idx); diff --git a/arch/xtensa/kernel/perf_event.c b/arch/xtensa/kernel/perf_event.c index ff1d81385ed7..768e1f7ab871 100644 --- a/arch/xtensa/kernel/perf_event.c +++ b/arch/xtensa/kernel/perf_event.c @@ -404,7 +404,7 @@ static struct pmu xtensa_pmu = { .read = xtensa_pmu_read, }; -static int xtensa_pmu_setup(int cpu) +static int xtensa_pmu_setup(unsigned int cpu) { unsigned i; diff --git a/disable_dbgfs.sh b/disable_dbgfs.sh new file mode 100755 index 000000000000..fe23680972a5 --- /dev/null +++ b/disable_dbgfs.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# disable debugfs for user builds +export MAKE_ARGS=$@ + +if [ ${DISABLE_DEBUGFS} == "true" ]; then + echo "build variant ${TARGET_BUILD_VARIANT}" + if [ ${TARGET_BUILD_VARIANT} == "user" ] && \ + [ ${ARCH} == "arm64" ]; then + echo "combining fragments for user build" + (cd $KERNEL_DIR && \ + ARCH=${ARCH} CROSS_COMPILE=${CROSS_COMPILE}\ + ./scripts/kconfig/merge_config.sh \ + ./arch/${ARCH}/configs/$DEFCONFIG \ + ./arch/${ARCH}/configs/vendor/debugfs.config + make ${MAKE_ARGS} ARCH=${ARCH} \ + CROSS_COMPILE=${CROSS_COMPILE} savedefconfig + mv defconfig ./arch/${ARCH}/configs/$DEFCONFIG + rm .config) + else + if [[ ${DEFCONFIG} == *"perf_defconfig" ]] && \ + [ ${ARCH} == "arm64" ]; then + echo "resetting perf defconfig" + (cd ${KERNEL_DIR} && \ + git checkout arch/$ARCH/configs/$DEFCONFIG) + fi + fi +fi diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 8de060664204..e23f3d54bb31 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -507,10 +507,6 @@ acpi_status acpi_ex_prep_field_value(struct acpi_create_field_info *info) (u8)access_byte_width; } } - /* An additional reference for the container */ - - acpi_ut_add_reference(obj_desc->field.region_obj); - ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, "RegionField: BitOff %X, Off %X, Gran %X, Region %p\n", obj_desc->field.start_field_bit_offset, diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index c6eb9fae70f9..61a979d0fbc5 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -593,11 +593,6 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) next_object = object->buffer_field.buffer_obj; break; - case ACPI_TYPE_LOCAL_REGION_FIELD: - - next_object = object->field.region_obj; - break; - case ACPI_TYPE_LOCAL_BANK_FIELD: next_object = object->bank_field.bank_obj; @@ -638,6 +633,7 @@ acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) } break; + case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_REGION: default: diff --git a/drivers/android/binder.c b/drivers/android/binder.c index e88f4a52c34e..bea21644113e 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3088,6 +3088,12 @@ static void binder_transaction(struct binder_proc *proc, goto err_dead_binder; } e->to_node = target_node->debug_id; + if (WARN_ON(proc == target_proc)) { + return_error = BR_FAILED_REPLY; + return_error_param = -EINVAL; + return_error_line = __LINE__; + goto err_invalid_target_handle; + } if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { return_error = BR_FAILED_REPLY; @@ -3690,10 +3696,17 @@ static int binder_thread_write(struct binder_proc *proc, struct binder_node *ctx_mgr_node; mutex_lock(&context->context_mgr_node_lock); ctx_mgr_node = context->binder_context_mgr_node; - if (ctx_mgr_node) + if (ctx_mgr_node) { + if (ctx_mgr_node->proc == proc) { + binder_user_error("%d:%d context manager tried to acquire desc 0\n", + proc->pid, thread->pid); + mutex_unlock(&context->context_mgr_node_lock); + return -EINVAL; + } ret = binder_inc_ref_for_node( proc, ctx_mgr_node, strong, NULL, &rdata); + } mutex_unlock(&context->context_mgr_node_lock); } if (ret) diff --git a/drivers/android/binderfs.c b/drivers/android/binderfs.c index 14a4bef358cd..3fd7cf48c39e 100644 --- a/drivers/android/binderfs.c +++ b/drivers/android/binderfs.c @@ -448,6 +448,7 @@ static int binderfs_binder_ctl_create(struct super_block *sb) inode->i_uid = info->root_uid; inode->i_gid = info->root_gid; + refcount_set(&device->ref, 1); device->binderfs_inode = inode; device->miscdev.minor = minor; diff --git a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c index afebeb1c3e1e..723bad1201cc 100644 --- a/drivers/atm/atmtcp.c +++ b/drivers/atm/atmtcp.c @@ -432,9 +432,15 @@ static int atmtcp_remove_persistent(int itf) return -EMEDIUMTYPE; } dev_data = PRIV(dev); - if (!dev_data->persist) return 0; + if (!dev_data->persist) { + atm_dev_put(dev); + return 0; + } dev_data->persist = 0; - if (PRIV(dev)->vcc) return 0; + if (PRIV(dev)->vcc) { + atm_dev_put(dev); + return 0; + } kfree(dev_data); atm_dev_put(dev); atm_dev_deregister(dev); diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c index 69c00a3db538..72cf2d97b682 100644 --- a/drivers/bluetooth/hci_serdev.c +++ b/drivers/bluetooth/hci_serdev.c @@ -361,7 +361,8 @@ void hci_uart_unregister_device(struct hci_uart *hu) struct hci_dev *hdev = hu->hdev; clear_bit(HCI_UART_PROTO_READY, &hu->flags); - hci_unregister_dev(hdev); + if (test_bit(HCI_UART_REGISTERED, &hu->flags)) + hci_unregister_dev(hdev); hci_free_dev(hdev); cancel_work_sync(&hu->write_work); diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 2fc9f6ade535..7f06ab26a3b8 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -738,9 +738,11 @@ static void fastrpc_mmap_free(struct fastrpc_mmap *map, uint32_t flags) } if (map->flags == ADSP_MMAP_HEAP_ADDR || map->flags == ADSP_MMAP_REMOTE_HEAP_ADDR) { + spin_lock(&me->hlock); map->refs--; if (!map->refs) hlist_del_init(&map->hn); + spin_unlock(&me->hlock); if (map->refs > 0) return; } else { diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index 7516ba981b63..34cc853772bc 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c @@ -304,8 +304,10 @@ static int intel_gtt_setup_scratch_page(void) if (intel_private.needs_dmar) { dma_addr = pci_map_page(intel_private.pcidev, page, 0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) + if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) { + __free_page(page); return -EINVAL; + } intel_private.scratch_page_dma = dma_addr; } else diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c index 740c62150cbc..be8e57e5c7ed 100644 --- a/drivers/char/diag/diagfwd_cntl.c +++ b/drivers/char/diag/diagfwd_cntl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -886,6 +886,9 @@ void diag_cntl_process_read_data(struct diagfwd_info *p_info, void *buf, while (read_len + header_len < len) { ctrl_pkt = (struct diag_ctrl_pkt_header_t *)ptr; + if (((size_t)read_len + (size_t)ctrl_pkt->len + + header_len) > len) + return; switch (ctrl_pkt->pkt_id) { case DIAG_CTRL_MSG_REG: process_command_registration(ptr, ctrl_pkt->len, diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c index 665fa681b2e1..1e6bdf22c3b6 100644 --- a/drivers/clk/sirf/clk-atlas6.c +++ b/drivers/clk/sirf/clk-atlas6.c @@ -136,7 +136,7 @@ static void __init atlas6_clk_init(struct device_node *np) for (i = pll1; i < maxclk; i++) { atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]); - BUG_ON(!atlas6_clks[i]); + BUG_ON(IS_ERR(atlas6_clks[i])); } clk_register_clkdev(atlas6_clks[cpu], NULL, "cpu"); clk_register_clkdev(atlas6_clks[io], NULL, "io"); diff --git a/drivers/crypto/cavium/cpt/cptvf_algs.c b/drivers/crypto/cavium/cpt/cptvf_algs.c index df21d996db7e..2d1b28c29a8e 100644 --- a/drivers/crypto/cavium/cpt/cptvf_algs.c +++ b/drivers/crypto/cavium/cpt/cptvf_algs.c @@ -205,6 +205,7 @@ static inline int cvm_enc_dec(struct ablkcipher_request *req, u32 enc) int status; memset(req_info, 0, sizeof(struct cpt_request_info)); + req_info->may_sleep = (req->base.flags & CRYPTO_TFM_REQ_MAY_SLEEP) != 0; memset(fctx, 0, sizeof(struct fc_context)); create_input_list(req, enc, enc_iv_len); create_output_list(req, enc_iv_len); diff --git a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c index b0ba4331944b..43fe69d0981a 100644 --- a/drivers/crypto/cavium/cpt/cptvf_reqmanager.c +++ b/drivers/crypto/cavium/cpt/cptvf_reqmanager.c @@ -136,7 +136,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, /* Setup gather (input) components */ g_sz_bytes = ((req->incnt + 3) / 4) * sizeof(struct sglist_component); - info->gather_components = kzalloc(g_sz_bytes, GFP_KERNEL); + info->gather_components = kzalloc(g_sz_bytes, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); if (!info->gather_components) { ret = -ENOMEM; goto scatter_gather_clean; @@ -153,7 +153,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, /* Setup scatter (output) components */ s_sz_bytes = ((req->outcnt + 3) / 4) * sizeof(struct sglist_component); - info->scatter_components = kzalloc(s_sz_bytes, GFP_KERNEL); + info->scatter_components = kzalloc(s_sz_bytes, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); if (!info->scatter_components) { ret = -ENOMEM; goto scatter_gather_clean; @@ -170,7 +170,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, /* Create and initialize DPTR */ info->dlen = g_sz_bytes + s_sz_bytes + SG_LIST_HDR_SIZE; - info->in_buffer = kzalloc(info->dlen, GFP_KERNEL); + info->in_buffer = kzalloc(info->dlen, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); if (!info->in_buffer) { ret = -ENOMEM; goto scatter_gather_clean; @@ -198,7 +198,7 @@ static inline int setup_sgio_list(struct cpt_vf *cptvf, } /* Create and initialize RPTR */ - info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, GFP_KERNEL); + info->out_buffer = kzalloc(COMPLETION_CODE_SIZE, req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); if (!info->out_buffer) { ret = -ENOMEM; goto scatter_gather_clean; @@ -434,7 +434,7 @@ int process_request(struct cpt_vf *cptvf, struct cpt_request_info *req) struct cpt_vq_command vq_cmd; union cpt_inst_s cptinst; - info = kzalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); if (unlikely(!info)) { dev_err(&pdev->dev, "Unable to allocate memory for info_buffer\n"); return -ENOMEM; @@ -456,7 +456,7 @@ int process_request(struct cpt_vf *cptvf, struct cpt_request_info *req) * Get buffer for union cpt_res_s response * structure and its physical address */ - info->completion_addr = kzalloc(sizeof(union cpt_res_s), GFP_KERNEL); + info->completion_addr = kzalloc(sizeof(union cpt_res_s), req->may_sleep ? GFP_KERNEL : GFP_ATOMIC); if (unlikely(!info->completion_addr)) { dev_err(&pdev->dev, "Unable to allocate memory for completion_addr\n"); ret = -ENOMEM; diff --git a/drivers/crypto/cavium/cpt/request_manager.h b/drivers/crypto/cavium/cpt/request_manager.h index 80ee074c6e0c..09930d95ad24 100644 --- a/drivers/crypto/cavium/cpt/request_manager.h +++ b/drivers/crypto/cavium/cpt/request_manager.h @@ -65,6 +65,8 @@ struct cpt_request_info { union ctrl_info ctrl; /* User control information */ struct cptvf_request req; /* Request Information (Core specific) */ + bool may_sleep; + struct buf_ptr in[MAX_BUF_CNT]; struct buf_ptr out[MAX_BUF_CNT]; diff --git a/drivers/crypto/ccp/ccp-dev.h b/drivers/crypto/ccp/ccp-dev.h index 7442b0422f8a..bd43b5c1450c 100644 --- a/drivers/crypto/ccp/ccp-dev.h +++ b/drivers/crypto/ccp/ccp-dev.h @@ -471,6 +471,7 @@ struct ccp_sg_workarea { unsigned int sg_used; struct scatterlist *dma_sg; + struct scatterlist *dma_sg_head; struct device *dma_dev; unsigned int dma_count; enum dma_data_direction dma_dir; diff --git a/drivers/crypto/ccp/ccp-ops.c b/drivers/crypto/ccp/ccp-ops.c index 43b74cf0787e..626b643d610e 100644 --- a/drivers/crypto/ccp/ccp-ops.c +++ b/drivers/crypto/ccp/ccp-ops.c @@ -67,7 +67,7 @@ static u32 ccp_gen_jobid(struct ccp_device *ccp) static void ccp_sg_free(struct ccp_sg_workarea *wa) { if (wa->dma_count) - dma_unmap_sg(wa->dma_dev, wa->dma_sg, wa->nents, wa->dma_dir); + dma_unmap_sg(wa->dma_dev, wa->dma_sg_head, wa->nents, wa->dma_dir); wa->dma_count = 0; } @@ -96,6 +96,7 @@ static int ccp_init_sg_workarea(struct ccp_sg_workarea *wa, struct device *dev, return 0; wa->dma_sg = sg; + wa->dma_sg_head = sg; wa->dma_dev = dev; wa->dma_dir = dma_dir; wa->dma_count = dma_map_sg(dev, sg, wa->nents, dma_dir); @@ -108,14 +109,28 @@ static int ccp_init_sg_workarea(struct ccp_sg_workarea *wa, struct device *dev, static void ccp_update_sg_workarea(struct ccp_sg_workarea *wa, unsigned int len) { unsigned int nbytes = min_t(u64, len, wa->bytes_left); + unsigned int sg_combined_len = 0; if (!wa->sg) return; wa->sg_used += nbytes; wa->bytes_left -= nbytes; - if (wa->sg_used == wa->sg->length) { - wa->sg = sg_next(wa->sg); + if (wa->sg_used == sg_dma_len(wa->dma_sg)) { + /* Advance to the next DMA scatterlist entry */ + wa->dma_sg = sg_next(wa->dma_sg); + + /* In the case that the DMA mapped scatterlist has entries + * that have been merged, the non-DMA mapped scatterlist + * must be advanced multiple times for each merged entry. + * This ensures that the current non-DMA mapped entry + * corresponds to the current DMA mapped entry. + */ + do { + sg_combined_len += wa->sg->length; + wa->sg = sg_next(wa->sg); + } while (wa->sg_used > sg_combined_len); + wa->sg_used = 0; } } @@ -304,7 +319,7 @@ static unsigned int ccp_queue_buf(struct ccp_data *data, unsigned int from) /* Update the structures and generate the count */ buf_count = 0; while (sg_wa->bytes_left && (buf_count < dm_wa->length)) { - nbytes = min(sg_wa->sg->length - sg_wa->sg_used, + nbytes = min(sg_dma_len(sg_wa->dma_sg) - sg_wa->sg_used, dm_wa->length - buf_count); nbytes = min_t(u64, sg_wa->bytes_left, nbytes); @@ -336,11 +351,11 @@ static void ccp_prepare_data(struct ccp_data *src, struct ccp_data *dst, * and destination. The resulting len values will always be <= UINT_MAX * because the dma length is an unsigned int. */ - sg_src_len = sg_dma_len(src->sg_wa.sg) - src->sg_wa.sg_used; + sg_src_len = sg_dma_len(src->sg_wa.dma_sg) - src->sg_wa.sg_used; sg_src_len = min_t(u64, src->sg_wa.bytes_left, sg_src_len); if (dst) { - sg_dst_len = sg_dma_len(dst->sg_wa.sg) - dst->sg_wa.sg_used; + sg_dst_len = sg_dma_len(dst->sg_wa.dma_sg) - dst->sg_wa.sg_used; sg_dst_len = min_t(u64, src->sg_wa.bytes_left, sg_dst_len); op_len = min(sg_src_len, sg_dst_len); } else { @@ -370,7 +385,7 @@ static void ccp_prepare_data(struct ccp_data *src, struct ccp_data *dst, /* Enough data in the sg element, but we need to * adjust for any previously copied data */ - op->src.u.dma.address = sg_dma_address(src->sg_wa.sg); + op->src.u.dma.address = sg_dma_address(src->sg_wa.dma_sg); op->src.u.dma.offset = src->sg_wa.sg_used; op->src.u.dma.length = op_len & ~(block_size - 1); @@ -391,7 +406,7 @@ static void ccp_prepare_data(struct ccp_data *src, struct ccp_data *dst, /* Enough room in the sg element, but we need to * adjust for any previously used area */ - op->dst.u.dma.address = sg_dma_address(dst->sg_wa.sg); + op->dst.u.dma.address = sg_dma_address(dst->sg_wa.dma_sg); op->dst.u.dma.offset = dst->sg_wa.sg_used; op->dst.u.dma.length = op->src.u.dma.length; } @@ -2034,7 +2049,7 @@ ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) dst.sg_wa.sg_used = 0; for (i = 1; i <= src.sg_wa.dma_count; i++) { if (!dst.sg_wa.sg || - (dst.sg_wa.sg->length < src.sg_wa.sg->length)) { + (sg_dma_len(dst.sg_wa.sg) < sg_dma_len(src.sg_wa.sg))) { ret = -EINVAL; goto e_dst; } @@ -2060,8 +2075,8 @@ ccp_run_passthru_cmd(struct ccp_cmd_queue *cmd_q, struct ccp_cmd *cmd) goto e_dst; } - dst.sg_wa.sg_used += src.sg_wa.sg->length; - if (dst.sg_wa.sg_used == dst.sg_wa.sg->length) { + dst.sg_wa.sg_used += sg_dma_len(src.sg_wa.sg); + if (dst.sg_wa.sg_used == sg_dma_len(dst.sg_wa.sg)) { dst.sg_wa.sg = sg_next(dst.sg_wa.sg); dst.sg_wa.sg_used = 0; } diff --git a/drivers/crypto/qat/qat_common/qat_uclo.c b/drivers/crypto/qat/qat_common/qat_uclo.c index 506e9a7d9acb..ad0b3b4add21 100644 --- a/drivers/crypto/qat/qat_common/qat_uclo.c +++ b/drivers/crypto/qat/qat_common/qat_uclo.c @@ -332,13 +332,18 @@ static int qat_uclo_create_batch_init_list(struct icp_qat_fw_loader_handle } return 0; out_err: + /* Do not free the list head unless we allocated it. */ + tail_old = tail_old->next; + if (flag) { + kfree(*init_tab_base); + *init_tab_base = NULL; + } + while (tail_old) { mem_init = tail_old->next; kfree(tail_old); tail_old = mem_init; } - if (flag) - kfree(*init_tab_base); return -ENOMEM; } diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index b59c3477ded7..6bc708acf0ee 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -104,10 +104,10 @@ static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen) goto out; } spin_unlock(&dentry->d_lock); - mutex_lock(&dmabuf->lock); + spin_lock(&dmabuf->name_lock); if (dmabuf->name) ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN); - mutex_unlock(&dmabuf->lock); + spin_unlock(&dmabuf->name_lock); dmabuf_dent_put(dmabuf); out: return dynamic_dname(dentry, buffer, buflen, "/%s:%s", diff --git a/drivers/edac/edac_device_sysfs.c b/drivers/edac/edac_device_sysfs.c index eb53260813c2..e869be0c79a2 100644 --- a/drivers/edac/edac_device_sysfs.c +++ b/drivers/edac/edac_device_sysfs.c @@ -301,6 +301,7 @@ int edac_device_register_sysfs_main_kobj(struct edac_device_ctl_info *edac_dev) /* Error exit stack */ err_kobj_reg: + kobject_put(&edac_dev->kobj); module_put(edac_dev->owner); err_out: diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index 72c9eb9fdffb..53042af7262e 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c @@ -386,7 +386,7 @@ static int edac_pci_main_kobj_setup(void) /* Error unwind statck */ kobject_init_and_add_fail: - kfree(edac_pci_top_main_kobj); + kobject_put(edac_pci_top_main_kobj); kzalloc_fail: module_put(THIS_MODULE); diff --git a/drivers/gpu/drm/arm/malidp_planes.c b/drivers/gpu/drm/arm/malidp_planes.c index 16b8b310ae5c..7072d738b072 100644 --- a/drivers/gpu/drm/arm/malidp_planes.c +++ b/drivers/gpu/drm/arm/malidp_planes.c @@ -369,7 +369,7 @@ int malidp_de_planes_init(struct drm_device *drm) const struct malidp_hw_regmap *map = &malidp->dev->map; struct malidp_plane *plane = NULL; enum drm_plane_type plane_type; - unsigned long crtcs = 1 << drm->mode_config.num_crtc; + unsigned long crtcs = BIT(drm->mode_config.num_crtc); unsigned long flags = DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y; u32 *formats; diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c index 0cb69ee94ac1..b93486892f4a 100644 --- a/drivers/gpu/drm/bridge/sil-sii8620.c +++ b/drivers/gpu/drm/bridge/sil-sii8620.c @@ -167,7 +167,7 @@ static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len) static u8 sii8620_readb(struct sii8620 *ctx, u16 addr) { - u8 ret; + u8 ret = 0; sii8620_read_buf(ctx, addr, &ret, 1); return ret; diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index c1807d5754b2..454deba13ee5 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -250,13 +250,13 @@ static ssize_t connector_write(struct file *file, const char __user *ubuf, buf[len] = '\0'; - if (!strcmp(buf, "on")) + if (sysfs_streq(buf, "on")) connector->force = DRM_FORCE_ON; - else if (!strcmp(buf, "digital")) + else if (sysfs_streq(buf, "digital")) connector->force = DRM_FORCE_ON_DIGITAL; - else if (!strcmp(buf, "off")) + else if (sysfs_streq(buf, "off")) connector->force = DRM_FORCE_OFF; - else if (!strcmp(buf, "unspecified")) + else if (sysfs_streq(buf, "unspecified")) connector->force = DRM_FORCE_UNSPECIFIED; else return -EINVAL; diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c index d72ba5dd71b0..709491f9e5e2 100644 --- a/drivers/gpu/drm/drm_mipi_dsi.c +++ b/drivers/gpu/drm/drm_mipi_dsi.c @@ -1032,11 +1032,11 @@ EXPORT_SYMBOL(mipi_dsi_dcs_set_pixel_format); */ int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline) { - u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8, - scanline & 0xff }; + u8 payload[2] = { scanline >> 8, scanline & 0xff }; ssize_t err; - err = mipi_dsi_generic_write(dsi, payload, sizeof(payload)); + err = mipi_dsi_dcs_write(dsi, MIPI_DCS_SET_TEAR_SCANLINE, payload, + sizeof(payload)); if (err < 0) return err; diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 4f2e6c7e04c1..d38648a7ef2d 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -311,18 +311,19 @@ static void imx_ldb_encoder_disable(struct drm_encoder *encoder) { struct imx_ldb_channel *imx_ldb_ch = enc_to_imx_ldb_ch(encoder); struct imx_ldb *ldb = imx_ldb_ch->ldb; + int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; int mux, ret; drm_panel_disable(imx_ldb_ch->panel); - if (imx_ldb_ch == &ldb->channel[0]) + if (imx_ldb_ch == &ldb->channel[0] || dual) ldb->ldb_ctrl &= ~LDB_CH0_MODE_EN_MASK; - else if (imx_ldb_ch == &ldb->channel[1]) + if (imx_ldb_ch == &ldb->channel[1] || dual) ldb->ldb_ctrl &= ~LDB_CH1_MODE_EN_MASK; regmap_write(ldb->regmap, IOMUXC_GPR2, ldb->ldb_ctrl); - if (ldb->ldb_ctrl & LDB_SPLIT_MODE_EN) { + if (dual) { clk_disable_unprepare(ldb->clk[0]); clk_disable_unprepare(ldb->clk[1]); } diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index bc27c2699464..c22c3e6e9b7a 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -498,6 +498,13 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve) return 0; } +static void imx_tve_disable_regulator(void *data) +{ + struct imx_tve *tve = data; + + regulator_disable(tve->dac_reg); +} + static bool imx_tve_readable_reg(struct device *dev, unsigned int reg) { return (reg % 4 == 0) && (reg <= 0xdc); @@ -622,6 +629,9 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data) ret = regulator_enable(tve->dac_reg); if (ret) return ret; + ret = devm_add_action_or_reset(dev, imx_tve_disable_regulator, tve); + if (ret) + return ret; } tve->clk = devm_clk_get(dev, "tve"); @@ -668,18 +678,8 @@ static int imx_tve_bind(struct device *dev, struct device *master, void *data) return 0; } -static void imx_tve_unbind(struct device *dev, struct device *master, - void *data) -{ - struct imx_tve *tve = dev_get_drvdata(dev); - - if (!IS_ERR(tve->dac_reg)) - regulator_disable(tve->dac_reg); -} - static const struct component_ops imx_tve_ops = { .bind = imx_tve_bind, - .unbind = imx_tve_unbind, }; static int imx_tve_probe(struct platform_device *pdev) diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c index 2fe931e12c32..b082778a4590 100644 --- a/drivers/gpu/drm/msm/sde/sde_core_irq.c +++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c @@ -44,6 +44,8 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx) &sde_kms->irq_obj.enable_counts[irq_idx]); } + atomic_inc(&irq_obj->irq_counts[irq_idx]); + /* * Perform registered function callback */ @@ -70,6 +72,15 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx) SDE_EVT32_IRQ(irq_idx, enable_counts, SDE_EVTLOG_ERROR); } } + + /* + * Clear pending interrupt status in HW. + * NOTE: sde_core_irq_callback_handler is protected by top-level + * spinlock, so it is safe to clear any interrupt status here. + */ + sde_kms->hw_intr->ops.clear_intr_status_nolock( + sde_kms->hw_intr, + irq_idx); } int sde_core_irq_idx_lookup(struct sde_kms *sde_kms, @@ -94,7 +105,8 @@ static int _sde_core_irq_enable(struct sde_kms *sde_kms, int irq_idx) int ret = 0; if (!sde_kms || !sde_kms->hw_intr || - !sde_kms->irq_obj.enable_counts) { + !sde_kms->irq_obj.enable_counts || + !sde_kms->irq_obj.irq_counts) { SDE_ERROR("invalid params\n"); return -EINVAL; } @@ -400,14 +412,15 @@ static int sde_debugfs_core_irq_show(struct seq_file *s, void *v) for (i = 0; i < irq_obj->total_irqs; i++) { spin_lock_irqsave(&irq_obj->cb_lock, irq_flags); cb_count = 0; + irq_count = atomic_read(&irq_obj->irq_counts[i]); enable_count = atomic_read(&irq_obj->enable_counts[i]); list_for_each_entry(cb, &irq_obj->irq_cb_tbl[i], list) cb_count++; spin_unlock_irqrestore(&irq_obj->cb_lock, irq_flags); if (irq_count || enable_count || cb_count) - seq_printf(s, "idx:%d enable:%d cb:%d\n", - i, enable_count, cb_count); + seq_printf(s, "idx:%d irq:%d enable:%d cb:%d\n", + i, irq_count, enable_count, cb_count); } return 0; @@ -481,7 +494,10 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms) sizeof(struct list_head), GFP_KERNEL); sde_kms->irq_obj.enable_counts = kcalloc(sde_kms->irq_obj.total_irqs, sizeof(atomic_t), GFP_KERNEL); - if (!sde_kms->irq_obj.irq_cb_tbl || !sde_kms->irq_obj.enable_counts) + sde_kms->irq_obj.irq_counts = kcalloc(sde_kms->irq_obj.total_irqs, + sizeof(atomic_t), GFP_KERNEL); + if (!sde_kms->irq_obj.irq_cb_tbl || !sde_kms->irq_obj.enable_counts + || !sde_kms->irq_obj.irq_counts) return; for (i = 0; i < sde_kms->irq_obj.total_irqs; i++) { @@ -489,6 +505,8 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms) INIT_LIST_HEAD(&sde_kms->irq_obj.irq_cb_tbl[i]); if (sde_kms->irq_obj.enable_counts) atomic_set(&sde_kms->irq_obj.enable_counts[i], 0); + if (sde_kms->irq_obj.irq_counts) + atomic_set(&sde_kms->irq_obj.irq_counts[i], 0); } } @@ -536,8 +554,10 @@ void sde_core_irq_uninstall(struct sde_kms *sde_kms) spin_lock_irqsave(&sde_kms->irq_obj.cb_lock, irq_flags); kfree(sde_kms->irq_obj.irq_cb_tbl); kfree(sde_kms->irq_obj.enable_counts); + kfree(sde_kms->irq_obj.irq_counts); sde_kms->irq_obj.irq_cb_tbl = NULL; sde_kms->irq_obj.enable_counts = NULL; + sde_kms->irq_obj.irq_counts = NULL; sde_kms->irq_obj.total_irqs = 0; spin_unlock_irqrestore(&sde_kms->irq_obj.cb_lock, irq_flags); } @@ -641,6 +661,15 @@ int sde_core_irq_domain_fini(struct sde_kms *sde_kms) irqreturn_t sde_core_irq(struct sde_kms *sde_kms) { + /* + * Read interrupt status from all sources. Interrupt status are + * stored within hw_intr. + * Function will also clear the interrupt status after reading. + * Individual interrupt status bit will only get stored if it + * is enabled. + */ + sde_kms->hw_intr->ops.get_interrupt_statuses(sde_kms->hw_intr); + /* * Dispatch to HW driver to handle interrupt lookup that is being * fired. When matching interrupt is located, HW driver will call to diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c index 210cbeb42ac4..2eaac555d3b6 100644 --- a/drivers/gpu/drm/msm/sde/sde_encoder.c +++ b/drivers/gpu/drm/msm/sde/sde_encoder.c @@ -227,7 +227,6 @@ enum sde_enc_rc_states { * @recovery_events_enabled: status of hw recovery feature enable by client * @elevated_ahb_vote: increase AHB bus speed for the first frame * after power collapse - * @pm_qos_cpu_req: pm_qos request for cpu frequency */ struct sde_encoder_virt { struct drm_encoder base; @@ -288,44 +287,10 @@ struct sde_encoder_virt { bool recovery_events_enabled; bool elevated_ahb_vote; - struct pm_qos_request pm_qos_cpu_req; }; #define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base) -static void _sde_encoder_pm_qos_add_request(struct drm_encoder *drm_enc, - struct sde_kms *sde_kms) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - struct pm_qos_request *req; - u32 cpu_mask; - u32 cpu_dma_latency; - - if (!sde_kms->catalog || !sde_kms->catalog->perf.cpu_mask) - return; - - cpu_mask = sde_kms->catalog->perf.cpu_mask; - cpu_dma_latency = sde_kms->catalog->perf.cpu_dma_latency; - - req = &sde_enc->pm_qos_cpu_req; - req->type = PM_QOS_REQ_AFFINE_CORES; - atomic_set(&req->cpus_affine, cpu_mask); - pm_qos_add_request(req, PM_QOS_CPU_DMA_LATENCY, cpu_dma_latency); - - SDE_EVT32_VERBOSE(DRMID(drm_enc), cpu_mask, cpu_dma_latency); -} - -static void _sde_encoder_pm_qos_remove_request(struct drm_encoder *drm_enc, - struct sde_kms *sde_kms) -{ - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - - if (!sde_kms->catalog || !sde_kms->catalog->perf.cpu_mask) - return; - - pm_qos_remove_request(&sde_enc->pm_qos_cpu_req); -} - static struct drm_connector_state *_sde_encoder_get_conn_state( struct drm_encoder *drm_enc) { @@ -2199,14 +2164,12 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, struct sde_kms *sde_kms; struct sde_encoder_virt *sde_enc; int rc; - bool is_cmd_mode, is_primary; + bool is_primary; sde_enc = to_sde_encoder_virt(drm_enc); priv = drm_enc->dev->dev_private; sde_kms = to_sde_kms(priv->kms); - is_cmd_mode = sde_enc->disp_info.capabilities & - MSM_DISPLAY_CAP_CMD_MODE; is_primary = sde_enc->disp_info.is_primary; SDE_DEBUG_ENC(sde_enc, "enable:%d\n", enable); @@ -2240,14 +2203,7 @@ static int _sde_encoder_resource_control_helper(struct drm_encoder *drm_enc, /* enable all the irq */ _sde_encoder_irq_control(drm_enc, true); - - if (is_cmd_mode) - _sde_encoder_pm_qos_add_request(drm_enc, sde_kms); - } else { - if (is_cmd_mode) - _sde_encoder_pm_qos_remove_request(drm_enc, sde_kms); - /* disable all the irq */ _sde_encoder_irq_control(drm_enc, false); diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c index d6b4f8a462fc..c34aed434dca 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.c @@ -880,17 +880,13 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, return; /* + * The dispatcher will save the IRQ status before calling here. * Now need to go through each IRQ status and find matching * irq lookup index. */ spin_lock_irqsave(&intr->irq_lock, irq_flags); for (reg_idx = 0; reg_idx < intr->sde_irq_size; reg_idx++) { - /* Read interrupt status */ - irq_status = SDE_REG_READ(&intr->hw, - intr->sde_irq_tbl[reg_idx].status_off); - - if (!irq_status) - continue; + irq_status = intr->save_irq_status[reg_idx]; /* get the global offset in 'sde_irq_map' */ sde_irq_idx = intr->sde_irq_tbl[reg_idx].sde_irq_idx; @@ -916,13 +912,20 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, for (irq_idx = start_idx; (irq_idx < end_idx) && irq_status; irq_idx++) - if (irq_status & sde_irq_map[irq_idx].irq_mask) { + if ((irq_status & sde_irq_map[irq_idx].irq_mask) && + (sde_irq_map[irq_idx].reg_idx == reg_idx)) { /* * Once a match on irq mask, perform a callback - * to the given cbfunc. + * to the given cbfunc. cbfunc will take care + * the interrupt status clearing. If cbfunc is + * not provided, then the interrupt clearing + * is here. */ if (cbfunc) cbfunc(arg, irq_idx); + else + intr->ops.clear_intr_status_nolock( + intr, irq_idx); /* * When callback finish, clear the irq_status @@ -931,15 +934,7 @@ static void sde_hw_intr_dispatch_irq(struct sde_hw_intr *intr, */ irq_status &= ~sde_irq_map[irq_idx].irq_mask; } - - /* Clear the interrupt */ - SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[reg_idx].clr_off, - 0xffffffff); } - - /* ensure register writes go through */ - wmb(); - spin_unlock_irqrestore(&intr->irq_lock, irq_flags); } @@ -1120,6 +1115,40 @@ static int sde_hw_intr_get_interrupt_sources(struct sde_hw_intr *intr, return 0; } +static void sde_hw_intr_get_interrupt_statuses(struct sde_hw_intr *intr) +{ + int i; + u32 enable_mask; + unsigned long irq_flags; + + if (!intr) + return; + + spin_lock_irqsave(&intr->irq_lock, irq_flags); + for (i = 0; i < intr->sde_irq_size; i++) { + /* Read interrupt status */ + intr->save_irq_status[i] = SDE_REG_READ(&intr->hw, + intr->sde_irq_tbl[i].status_off); + + /* Read enable mask */ + enable_mask = SDE_REG_READ(&intr->hw, + intr->sde_irq_tbl[i].en_off); + + /* and clear the interrupt */ + if (intr->save_irq_status[i]) + SDE_REG_WRITE(&intr->hw, intr->sde_irq_tbl[i].clr_off, + intr->save_irq_status[i]); + + /* Finally update IRQ status based on enable mask */ + intr->save_irq_status[i] &= enable_mask; + } + + /* ensure register writes go through */ + wmb(); + + spin_unlock_irqrestore(&intr->irq_lock, irq_flags); +} + static void sde_hw_intr_clear_intr_status_force_mask(struct sde_hw_intr *intr, int irq_idx, u32 irq_mask) { @@ -1292,6 +1321,7 @@ static void __setup_intr_ops(struct sde_hw_intr_ops *ops) ops->disable_all_irqs = sde_hw_intr_disable_irqs; ops->get_valid_interrupts = sde_hw_intr_get_valid_interrupts; ops->get_interrupt_sources = sde_hw_intr_get_interrupt_sources; + ops->get_interrupt_statuses = sde_hw_intr_get_interrupt_statuses; ops->clear_interrupt_status = sde_hw_intr_clear_interrupt_status; ops->clear_intr_status_nolock = sde_hw_intr_clear_intr_status_nolock; ops->clear_intr_status_force_mask = @@ -1439,6 +1469,7 @@ void sde_hw_intr_destroy(struct sde_hw_intr *intr) if (intr) { kfree(intr->sde_irq_tbl); kfree(intr->cache_irq_mask); + kfree(intr->save_irq_status); kfree(intr); } } @@ -1547,6 +1578,13 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, goto exit; } + intr->save_irq_status = kcalloc(intr->sde_irq_size, sizeof(u32), + GFP_KERNEL); + if (intr->save_irq_status == NULL) { + ret = -ENOMEM; + goto exit; + } + spin_lock_init(&intr->irq_lock); return intr; @@ -1554,6 +1592,7 @@ struct sde_hw_intr *sde_hw_intr_init(void __iomem *addr, exit: kfree(intr->sde_irq_tbl); kfree(intr->cache_irq_mask); + kfree(intr->save_irq_status); kfree(intr); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h index e2de0e33bd59..1d5a8427d0aa 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h +++ b/drivers/gpu/drm/msm/sde/sde_hw_interrupts.h @@ -188,6 +188,14 @@ struct sde_hw_intr_ops { void (*cbfunc)(void *arg, int irq_idx), void *arg); + /** + * get_interrupt_statuses - Gets and store value from all interrupt + * status registers that are currently fired. + * @intr: HW interrupt handle + */ + void (*get_interrupt_statuses)( + struct sde_hw_intr *intr); + /** * clear_interrupt_status - Clears HW interrupt status based on given * lookup IRQ index. @@ -284,6 +292,7 @@ struct sde_hw_intr_ops { * @hw: virtual address mapping * @ops: function pointer mapping for IRQ handling * @cache_irq_mask: array of IRQ enable masks reg storage created during init + * @save_irq_status: array of IRQ status reg storage created during init * @irq_idx_tbl_size: total number of irq_idx mapped in the hw_interrupts * @irq_lock: spinlock for accessing IRQ resources * @sde_irq_size: total number of elements of the sde_irq_tbl @@ -294,6 +303,7 @@ struct sde_hw_intr { struct sde_hw_blk_reg_map hw; struct sde_hw_intr_ops ops; u32 *cache_irq_mask; + u32 *save_irq_status; u32 irq_idx_tbl_size; u32 sde_irq_size; struct sde_intr_reg *sde_irq_tbl; diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h index 38d3e1d45052..cc9748346b17 100644 --- a/drivers/gpu/drm/msm/sde/sde_kms.h +++ b/drivers/gpu/drm/msm/sde/sde_kms.h @@ -202,6 +202,7 @@ struct sde_irq { u32 total_irqs; struct list_head *irq_cb_tbl; atomic_t *enable_counts; + atomic_t *irq_counts; spinlock_t cb_lock; struct dentry *debugfs_file; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index d00524a5d7f0..fb6b1d0f7fef 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -840,8 +840,10 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) /* need to bring up power immediately if opening device */ ret = pm_runtime_get_sync(dev->dev); - if (ret < 0 && ret != -EACCES) + if (ret < 0 && ret != -EACCES) { + pm_runtime_put_autosuspend(dev->dev); return ret; + } get_task_comm(tmpname, current); snprintf(name, sizeof(name), "%s[%d]", tmpname, pid_nr(fpriv->pid)); @@ -930,8 +932,10 @@ nouveau_drm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) long ret; ret = pm_runtime_get_sync(dev->dev); - if (ret < 0 && ret != -EACCES) + if (ret < 0 && ret != -EACCES) { + pm_runtime_put_autosuspend(dev->dev); return ret; + } switch (_IOC_NR(cmd) - DRM_COMMAND_BASE) { case DRM_NOUVEAU_NVIF: diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 2b12d82aac15..9ffb09679cc4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -310,7 +310,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, struct nouveau_framebuffer *fb; struct nouveau_channel *chan; struct nouveau_bo *nvbo; - struct drm_mode_fb_cmd2 mode_cmd; + struct drm_mode_fb_cmd2 mode_cmd = {}; int ret; mode_cmd.width = sizes->surface_width; @@ -543,6 +543,7 @@ fini: drm_fb_helper_fini(&fbcon->helper); free: kfree(fbcon); + drm->fbcon = NULL; return ret; } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 60ffb70bb908..c6149b5be073 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -42,8 +42,10 @@ nouveau_gem_object_del(struct drm_gem_object *gem) int ret; ret = pm_runtime_get_sync(dev); - if (WARN_ON(ret < 0 && ret != -EACCES)) + if (WARN_ON(ret < 0 && ret != -EACCES)) { + pm_runtime_put_autosuspend(dev); return; + } if (gem->import_attach) drm_prime_gem_destroy(gem, nvbo->bo.sg); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index c1daed3fe842..6df312ba1826 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1253,7 +1253,7 @@ static const struct drm_display_mode lg_lb070wv8_mode = { static const struct panel_desc lg_lb070wv8 = { .modes = &lg_lb070wv8_mode, .num_modes = 1, - .bpc = 16, + .bpc = 8, .size = { .width = 151, .height = 91, diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index cfbf0fa36a21..bf6bfc455fb9 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -4342,7 +4342,7 @@ static int ci_set_mc_special_registers(struct radeon_device *rdev, table->mc_reg_table_entry[k].mc_data[j] |= 0x100; } j++; - if (j > SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) + if (j >= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) return -EINVAL; if (!pi->mem_gddr5) { diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d86110cdf085..b2334349799d 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -627,8 +627,10 @@ radeon_crtc_set_config(struct drm_mode_set *set, dev = set->crtc->dev; ret = pm_runtime_get_sync(dev->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_autosuspend(dev->dev); return ret; + } ret = drm_crtc_helper_set_config(set, ctx); diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index f6908e2f9e55..41e8abd09978 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -496,8 +496,10 @@ long radeon_drm_ioctl(struct file *filp, long ret; dev = file_priv->minor->dev; ret = pm_runtime_get_sync(dev->dev); - if (ret < 0) + if (ret < 0) { + pm_runtime_put_autosuspend(dev->dev); return ret; + } ret = drm_ioctl(filp, cmd, arg); diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index dfee8f7d94ae..2e28cf811840 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -659,8 +659,10 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) file_priv->driver_priv = NULL; r = pm_runtime_get_sync(dev->dev); - if (r < 0) + if (r < 0) { + pm_runtime_put_autosuspend(dev->dev); return r; + } /* new gpu have virtual address space support */ if (rdev->family >= CHIP_CAYMAN) { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 1813a3623ce6..0484b2cf0e2b 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -152,12 +152,16 @@ static int panel_connector_get_modes(struct drm_connector *connector) int i; for (i = 0; i < timings->num_timings; i++) { - struct drm_display_mode *mode = drm_mode_create(dev); + struct drm_display_mode *mode; struct videomode vm; if (videomode_from_timings(timings, &vm, i)) break; + mode = drm_mode_create(dev); + if (!mode) + break; + drm_display_mode_from_videomode(&vm, mode); mode->type = DRM_MODE_TYPE_DRIVER; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 2cb39189139f..9d507bfab6fa 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2707,7 +2707,7 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, ++i; } - if (i != unit) { + if (&con->head == &dev_priv->dev->mode_config.connector_list) { DRM_ERROR("Could not find initial display unit.\n"); return -EINVAL; } @@ -2729,13 +2729,13 @@ int vmw_kms_fbdev_init_data(struct vmw_private *dev_priv, break; } - if (mode->type & DRM_MODE_TYPE_PREFERRED) - *p_mode = mode; - else { + if (&mode->head == &con->modes) { WARN_ONCE(true, "Could not find initial preferred mode.\n"); *p_mode = list_first_entry(&con->modes, struct drm_display_mode, head); + } else { + *p_mode = mode; } return 0; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 3824595fece1..39f4ad0dab8d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -79,7 +79,7 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) struct vmw_legacy_display_unit *entry; struct drm_framebuffer *fb = NULL; struct drm_crtc *crtc = NULL; - int i = 0; + int i; /* If there is no display topology the host just assumes * that the guest will set the same layout as the host. @@ -90,12 +90,11 @@ static int vmw_ldu_commit_list(struct vmw_private *dev_priv) crtc = &entry->base.crtc; w = max(w, crtc->x + crtc->mode.hdisplay); h = max(h, crtc->y + crtc->mode.vdisplay); - i++; } if (crtc == NULL) return 0; - fb = entry->base.crtc.primary->state->fb; + fb = crtc->primary->state->fb; return vmw_kms_write_svga(dev_priv, w, h, fb->pitches[0], fb->format->cpp[0] * 8, diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c index 2aae0e63214c..0b8c23c399c2 100644 --- a/drivers/gpu/host1x/debug.c +++ b/drivers/gpu/host1x/debug.c @@ -25,6 +25,8 @@ #include "debug.h" #include "channel.h" +static DEFINE_MUTEX(debug_lock); + unsigned int host1x_debug_trace_cmdbuf; static pid_t host1x_debug_force_timeout_pid; @@ -49,12 +51,14 @@ static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo) struct output *o = data; mutex_lock(&ch->cdma.lock); + mutex_lock(&debug_lock); if (show_fifo) host1x_hw_show_channel_fifo(m, ch, o); host1x_hw_show_channel_cdma(m, ch, o); + mutex_unlock(&debug_lock); mutex_unlock(&ch->cdma.lock); return 0; diff --git a/drivers/gpu/ipu-v3/ipu-image-convert.c b/drivers/gpu/ipu-v3/ipu-image-convert.c index a5e33d58e02f..d2f9e6552267 100644 --- a/drivers/gpu/ipu-v3/ipu-image-convert.c +++ b/drivers/gpu/ipu-v3/ipu-image-convert.c @@ -992,38 +992,7 @@ done: return IRQ_WAKE_THREAD; } -static irqreturn_t norotate_irq(int irq, void *data) -{ - struct ipu_image_convert_chan *chan = data; - struct ipu_image_convert_ctx *ctx; - struct ipu_image_convert_run *run; - unsigned long flags; - irqreturn_t ret; - - spin_lock_irqsave(&chan->irqlock, flags); - - /* get current run and its context */ - run = chan->current_run; - if (!run) { - ret = IRQ_NONE; - goto out; - } - - ctx = run->ctx; - - if (ipu_rot_mode_is_irt(ctx->rot_mode)) { - /* this is a rotation operation, just ignore */ - spin_unlock_irqrestore(&chan->irqlock, flags); - return IRQ_HANDLED; - } - - ret = do_irq(run); -out: - spin_unlock_irqrestore(&chan->irqlock, flags); - return ret; -} - -static irqreturn_t rotate_irq(int irq, void *data) +static irqreturn_t eof_irq(int irq, void *data) { struct ipu_image_convert_chan *chan = data; struct ipu_image_convert_priv *priv = chan->priv; @@ -1043,11 +1012,24 @@ static irqreturn_t rotate_irq(int irq, void *data) ctx = run->ctx; - if (!ipu_rot_mode_is_irt(ctx->rot_mode)) { - /* this was NOT a rotation operation, shouldn't happen */ - dev_err(priv->ipu->dev, "Unexpected rotation interrupt\n"); - spin_unlock_irqrestore(&chan->irqlock, flags); - return IRQ_HANDLED; + if (irq == chan->out_eof_irq) { + if (ipu_rot_mode_is_irt(ctx->rot_mode)) { + /* this is a rotation op, just ignore */ + ret = IRQ_HANDLED; + goto out; + } + } else if (irq == chan->rot_out_eof_irq) { + if (!ipu_rot_mode_is_irt(ctx->rot_mode)) { + /* this was NOT a rotation op, shouldn't happen */ + dev_err(priv->ipu->dev, + "Unexpected rotation interrupt\n"); + ret = IRQ_HANDLED; + goto out; + } + } else { + dev_err(priv->ipu->dev, "Received unknown irq %d\n", irq); + ret = IRQ_NONE; + goto out; } ret = do_irq(run); @@ -1142,7 +1124,7 @@ static int get_ipu_resources(struct ipu_image_convert_chan *chan) chan->out_chan, IPU_IRQ_EOF); - ret = request_threaded_irq(chan->out_eof_irq, norotate_irq, do_bh, + ret = request_threaded_irq(chan->out_eof_irq, eof_irq, do_bh, 0, "ipu-ic", chan); if (ret < 0) { dev_err(priv->ipu->dev, "could not acquire irq %d\n", @@ -1155,7 +1137,7 @@ static int get_ipu_resources(struct ipu_image_convert_chan *chan) chan->rotation_out_chan, IPU_IRQ_EOF); - ret = request_threaded_irq(chan->rot_out_eof_irq, rotate_irq, do_bh, + ret = request_threaded_irq(chan->rot_out_eof_irq, eof_irq, do_bh, 0, "ipu-ic", chan); if (ret < 0) { dev_err(priv->ipu->dev, "could not acquire irq %d\n", diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index df8039e42441..57fbf3c2db61 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2008-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 14e4003fde4d..204ccf674533 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -362,13 +362,13 @@ static int hidinput_query_battery_capacity(struct hid_device *dev) u8 *buf; int ret; - buf = kmalloc(2, GFP_KERNEL); + buf = kmalloc(4, GFP_KERNEL); if (!buf) return -ENOMEM; - ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 2, + ret = hid_hw_raw_request(dev, dev->battery_report_id, buf, 4, dev->battery_report_type, HID_REQ_GET_REPORT); - if (ret != 2) { + if (ret < 2) { kfree(buf); return -ENODATA; } diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 43eaf54736f4..462f7f363faa 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -1228,6 +1228,8 @@ channel_message_table[CHANNELMSG_COUNT] = { { CHANNELMSG_19, 0, NULL }, { CHANNELMSG_20, 0, NULL }, { CHANNELMSG_TL_CONNECT_REQUEST, 0, NULL }, + { CHANNELMSG_22, 0, NULL }, + { CHANNELMSG_TL_CONNECT_RESULT, 0, NULL }, }; /* @@ -1239,23 +1241,14 @@ void vmbus_onmessage(void *context) { struct hv_message *msg = context; struct vmbus_channel_message_header *hdr; - int size; hdr = (struct vmbus_channel_message_header *)msg->u.payload; - size = msg->header.payload_size; - if (hdr->msgtype >= CHANNELMSG_COUNT) { - pr_err("Received invalid channel message type %d size %d\n", - hdr->msgtype, size); - print_hex_dump_bytes("", DUMP_PREFIX_NONE, - (unsigned char *)msg->u.payload, size); - return; - } - - if (channel_message_table[hdr->msgtype].message_handler) - channel_message_table[hdr->msgtype].message_handler(hdr); - else - pr_err("Unhandled channel message type %d\n", hdr->msgtype); + /* + * vmbus_on_msg_dpc() makes sure the hdr->msgtype here can not go + * out of bound and the message_handler pointer can not be NULL. + */ + channel_message_table[hdr->msgtype].message_handler(hdr); } /* diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index 1fd812ed679b..45b8ccdfb085 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -890,6 +890,10 @@ void vmbus_on_msg_dpc(unsigned long data) } entry = &channel_message_table[hdr->msgtype]; + + if (!entry->message_handler) + goto msg_handled; + if (entry->handler_type == VMHT_BLOCKING) { ctx = kmalloc(sizeof(*ctx), GFP_ATOMIC); if (ctx == NULL) diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c index 6d0cb43361bc..1ee12fc0d698 100644 --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c @@ -673,6 +673,12 @@ int tmc_read_unprepare_etb(struct tmc_drvdata *drvdata) /* Re-enable the TMC if need be */ if (drvdata->mode == CS_MODE_SYSFS) { + /* There is no point in reading a TMC in HW FIFO mode */ + mode = readl_relaxed(drvdata->base + TMC_MODE); + if (mode != TMC_MODE_CIRCULAR_BUFFER) { + spin_unlock_irqrestore(&drvdata->spinlock, flags); + return -EINVAL; + } /* * The trace run will continue with the same allocated trace * buffer. As such zero-out the buffer so that we don't end diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index db9ca8e926ca..ed0f06810978 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -538,13 +538,14 @@ static bool rcar_i2c_slave_irq(struct rcar_i2c_priv *priv) rcar_i2c_write(priv, ICSIER, SDR | SSR | SAR); } - rcar_i2c_write(priv, ICSSR, ~SAR & 0xff); + /* Clear SSR, too, because of old STOPs to other clients than us */ + rcar_i2c_write(priv, ICSSR, ~(SAR | SSR) & 0xff); } /* master sent stop */ if (ssr_filtered & SSR) { i2c_slave_event(priv->slave, I2C_SLAVE_STOP, &value); - rcar_i2c_write(priv, ICSIER, SAR | SSR); + rcar_i2c_write(priv, ICSIER, SAR); rcar_i2c_write(priv, ICSSR, ~SSR & 0xff); } @@ -802,7 +803,7 @@ static int rcar_reg_slave(struct i2c_client *slave) priv->slave = slave; rcar_i2c_write(priv, ICSAR, slave->addr); rcar_i2c_write(priv, ICSSR, 0); - rcar_i2c_write(priv, ICSIER, SAR | SSR); + rcar_i2c_write(priv, ICSIER, SAR); rcar_i2c_write(priv, ICSCR, SIE | SDBS); return 0; @@ -814,12 +815,14 @@ static int rcar_unreg_slave(struct i2c_client *slave) WARN_ON(!priv->slave); - /* disable irqs and ensure none is running before clearing ptr */ + /* ensure no irq is running before clearing ptr */ + disable_irq(priv->irq); rcar_i2c_write(priv, ICSIER, 0); - rcar_i2c_write(priv, ICSCR, 0); + rcar_i2c_write(priv, ICSSR, 0); + enable_irq(priv->irq); + rcar_i2c_write(priv, ICSCR, SDBS); rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ - synchronize_irq(priv->irq); priv->slave = NULL; pm_runtime_put(rcar_i2c_priv_to_dev(priv)); diff --git a/drivers/i2c/i2c-core-slave.c b/drivers/i2c/i2c-core-slave.c index 4a78c65e9971..d89bc31e0622 100644 --- a/drivers/i2c/i2c-core-slave.c +++ b/drivers/i2c/i2c-core-slave.c @@ -22,10 +22,8 @@ int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb) { int ret; - if (!client || !slave_cb) { - WARN(1, "insufficient data\n"); + if (WARN(IS_ERR_OR_NULL(client) || !slave_cb, "insufficient data\n")) return -EINVAL; - } if (!(client->flags & I2C_CLIENT_SLAVE)) dev_warn(&client->dev, "%s: client slave flag not set. You might see address collisions\n", @@ -64,6 +62,9 @@ int i2c_slave_unregister(struct i2c_client *client) { int ret; + if (IS_ERR_OR_NULL(client)) + return -EINVAL; + if (!client->adapter->algo->unreg_slave) { dev_err(&client->dev, "%s: not supported by adapter\n", __func__); return -EOPNOTSUPP; diff --git a/drivers/iio/adc/qcom-rradc.c b/drivers/iio/adc/qcom-rradc.c index 02dfbf86d6c2..20136383c66b 100644 --- a/drivers/iio/adc/qcom-rradc.c +++ b/drivers/iio/adc/qcom-rradc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2017, 2019-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -199,6 +199,9 @@ #define FG_RR_TP_REV_VERSION2 29 #define FG_RR_TP_REV_VERSION3 32 +#define BATT_ID_SETTLE_SHIFT 5 +#define RRADC_BATT_ID_DELAY_MAX 8 + /* * The channel number is not a physical index in hardware, * rather it's a list of supported channels and an index to @@ -229,6 +232,7 @@ struct rradc_chip { struct mutex lock; struct regmap *regmap; u16 base; + int batt_id_delay; struct iio_chan_spec *iio_chans; unsigned int nchannels; struct rradc_chan_prop *chan_props; @@ -256,6 +260,8 @@ struct rradc_chan_prop { u16 adc_code, int *result); }; +static const int batt_id_delays[] = {0, 1, 4, 12, 20, 40, 60, 80}; + static int rradc_masked_write(struct rradc_chip *rr_adc, u16 offset, u8 mask, u8 val) { @@ -767,8 +773,7 @@ static int rradc_check_status_ready_with_retry(struct rradc_chip *chip, if (((prop->channel == RR_ADC_CHG_TEMP) || (prop->channel == RR_ADC_SKIN_TEMP) || - (prop->channel == RR_ADC_USBIN_I) || - (prop->channel == RR_ADC_DIE_TEMP)) && + (prop->channel == RR_ADC_USBIN_I)) && ((!rradc_is_usb_present(chip)))) { pr_debug("USB not present for %d\n", prop->channel); rc = -ENODATA; @@ -854,7 +859,7 @@ static int rradc_enable_batt_id_channel(struct rradc_chip *chip, bool enable) static int rradc_do_batt_id_conversion(struct rradc_chip *chip, struct rradc_chan_prop *prop, u16 *data, u8 *buf) { - int rc = 0, ret = 0; + int rc = 0, ret = 0, batt_id_delay; rc = rradc_enable_batt_id_channel(chip, true); if (rc < 0) { @@ -862,6 +867,14 @@ static int rradc_do_batt_id_conversion(struct rradc_chip *chip, return rc; } + if (chip->batt_id_delay != -EINVAL) { + batt_id_delay = chip->batt_id_delay << BATT_ID_SETTLE_SHIFT; + rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_CFG, + batt_id_delay, batt_id_delay); + if (rc < 0) + pr_err("BATT_ID settling time config failed:%d\n", rc); + } + rc = rradc_masked_write(chip, FG_ADC_RR_BATT_ID_TRIGGER, FG_ADC_RR_BATT_ID_TRIGGER_CTL, FG_ADC_RR_BATT_ID_TRIGGER_CTL); @@ -938,6 +951,30 @@ static int rradc_do_conversion(struct rradc_chip *chip, goto fail; } break; + case RR_ADC_DIE_TEMP: + /* Force conversion every cycle */ + rc = rradc_masked_write(chip, FG_ADC_RR_PMI_DIE_TEMP_TRIGGER, + FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, + FG_ADC_RR_USB_IN_V_EVERY_CYCLE); + if (rc < 0) { + pr_err("Force every cycle update failed:%d\n", rc); + goto fail; + } + + rc = rradc_read_channel_with_continuous_mode(chip, prop, buf); + if (rc < 0) { + pr_err("Error reading in continuous mode:%d\n", rc); + goto fail; + } + + /* Restore aux_therm trigger */ + rc = rradc_masked_write(chip, FG_ADC_RR_PMI_DIE_TEMP_TRIGGER, + FG_ADC_RR_USB_IN_V_EVERY_CYCLE_MASK, 0); + if (rc < 0) { + pr_err("Restore every cycle update failed:%d\n", rc); + goto fail; + } + break; case RR_ADC_CHG_HOT_TEMP: case RR_ADC_CHG_TOO_HOT_TEMP: case RR_ADC_SKIN_HOT_TEMP: @@ -1106,6 +1143,21 @@ static int rradc_get_dt_data(struct rradc_chip *chip, struct device_node *node) return rc; } + chip->batt_id_delay = -EINVAL; + + rc = of_property_read_u32(node, "qcom,batt-id-delay-ms", + &chip->batt_id_delay); + if (!rc) { + for (i = 0; i < RRADC_BATT_ID_DELAY_MAX; i++) { + if (chip->batt_id_delay == batt_id_delays[i]) + break; + } + if (i == RRADC_BATT_ID_DELAY_MAX) + pr_err("Invalid batt_id_delay, rc=%d\n", rc); + else + chip->batt_id_delay = i; + } + chip->base = base; chip->revid_dev_node = of_parse_phandle(node, "qcom,pmic-revid", 0); if (chip->revid_dev_node) { diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c index 93c9b461c955..39b3b2144e5b 100644 --- a/drivers/iio/dac/ad5592r-base.c +++ b/drivers/iio/dac/ad5592r-base.c @@ -417,7 +417,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, s64 tmp = *val * (3767897513LL / 25LL); *val = div_s64_rem(tmp, 1000000000LL, val2); - ret = IIO_VAL_INT_PLUS_MICRO; + return IIO_VAL_INT_PLUS_MICRO; } else { int mult; @@ -448,7 +448,7 @@ static int ad5592r_read_raw(struct iio_dev *iio_dev, ret = IIO_VAL_INT; break; default: - ret = -EINVAL; + return -EINVAL; } unlock: diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 4a5c7a07a631..268e23ba4a63 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -509,7 +509,7 @@ void ipoib_ib_dev_cleanup(struct net_device *dev); int ipoib_ib_dev_open_default(struct net_device *dev); int ipoib_ib_dev_open(struct net_device *dev); -int ipoib_ib_dev_stop(struct net_device *dev); +void ipoib_ib_dev_stop(struct net_device *dev); void ipoib_ib_dev_up(struct net_device *dev); void ipoib_ib_dev_down(struct net_device *dev); int ipoib_ib_dev_stop_default(struct net_device *dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index d77e8e2ae05f..8e1f48fe6f2e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -809,7 +809,7 @@ timeout: return 0; } -int ipoib_ib_dev_stop(struct net_device *dev) +void ipoib_ib_dev_stop(struct net_device *dev) { struct ipoib_dev_priv *priv = ipoib_priv(dev); @@ -817,8 +817,6 @@ int ipoib_ib_dev_stop(struct net_device *dev) clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); ipoib_flush_ah(dev); - - return 0; } void ipoib_ib_tx_timer_func(unsigned long ctx) diff --git a/drivers/input/misc/qti-haptics.c b/drivers/input/misc/qti-haptics.c index d17aebaee166..48797423d658 100644 --- a/drivers/input/misc/qti-haptics.c +++ b/drivers/input/misc/qti-haptics.c @@ -250,6 +250,13 @@ static struct hap_addr_val twm_ext_cfg[] = { {REG_HAP_EN_CTL1, 0x80}, /* Enable haptics driver */ }; +static struct hap_addr_val twm_cfg[] = { + {REG_HAP_PLAY, 0x00}, /* Stop playing haptics waveform */ + {REG_HAP_SEL, 0x00}, /* Configure for cmd mode */ + {REG_HAP_EN_CTL1, 0x00}, /* Enable haptics driver */ + {REG_HAP_PERPH_RESET_CTL3, 0x0D}, /* Disable SHUTDOWN1_RB reset */ +}; + static int wf_repeat[8] = {1, 2, 4, 8, 16, 32, 64, 128}; static int wf_s_repeat[4] = {1, 2, 4, 8}; @@ -1060,20 +1067,30 @@ static void qti_haptics_set_gain(struct input_dev *dev, u16 gain) qti_haptics_config_vmax(chip, play->vmax_mv); } -static int qti_haptics_twm_config(struct qti_hap_chip *chip) +static int qti_haptics_twm_config(struct qti_hap_chip *chip, bool ext_pin) { - int rc, i; + int rc = 0, i; - for (i = 0; i < ARRAY_SIZE(twm_ext_cfg); i++) { - rc = qti_haptics_write(chip, twm_ext_cfg[i].addr, - &twm_ext_cfg[i].value, 1); - if (rc < 0) { - dev_err(chip->dev, "Haptics TWM config failed, rc=%d\n", - rc); - return rc; + if (ext_pin) { + for (i = 0; i < ARRAY_SIZE(twm_ext_cfg); i++) { + rc = qti_haptics_write(chip, twm_ext_cfg[i].addr, + &twm_ext_cfg[i].value, 1); + if (rc < 0) + break; + } + } else { + for (i = 0; i < ARRAY_SIZE(twm_cfg); i++) { + rc = qti_haptics_write(chip, twm_cfg[i].addr, + &twm_cfg[i].value, 1); + if (rc < 0) + break; } } - pr_debug("Enabled haptics for TWM mode\n"); + + if (rc < 0) + pr_err("Failed to write twm_config rc=%d\n", rc); + else + pr_debug("Enabled haptics for TWM mode\n"); return 0; } @@ -2032,7 +2049,6 @@ static void qti_haptics_shutdown(struct platform_device *pdev) { struct qti_hap_chip *chip = dev_get_drvdata(&pdev->dev); int rc; - bool enable_haptics_twm; dev_dbg(chip->dev, "Shutdown!\n"); @@ -2048,10 +2064,8 @@ static void qti_haptics_shutdown(struct platform_device *pdev) chip->vdd_enabled = false; } - enable_haptics_twm = chip->haptics_ext_pin_twm && twm_sys_enable; - - if (chip->twm_state == PMIC_TWM_ENABLE && enable_haptics_twm) { - rc = qti_haptics_twm_config(chip); + if (chip->twm_state == PMIC_TWM_ENABLE && twm_sys_enable) { + rc = qti_haptics_twm_config(chip, chip->haptics_ext_pin_twm); if (rc < 0) pr_err("Haptics TWM config failed rc=%d\n", rc); } diff --git a/drivers/input/mouse/sentelic.c b/drivers/input/mouse/sentelic.c index 11c32ac8234b..779d0b9341c0 100644 --- a/drivers/input/mouse/sentelic.c +++ b/drivers/input/mouse/sentelic.c @@ -454,7 +454,7 @@ static ssize_t fsp_attr_set_setreg(struct psmouse *psmouse, void *data, fsp_reg_write_enable(psmouse, false); - return count; + return retval; } PSMOUSE_DEFINE_WO_ATTR(setreg, S_IWUSR, NULL, fsp_attr_set_setreg); diff --git a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c index 7696437425f4..b838f45ada05 100644 --- a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c +++ b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_core.c @@ -1131,13 +1131,6 @@ static int goodix_ts_gpio_setup(struct goodix_ts_core *core_data) return 0; } -static ssize_t gtp_touch_suspend_notify_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%d\n", !!atomic_read(&goodix_core_data->suspend_stat)); -} - static ssize_t gtp_fod_test_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -1202,9 +1195,6 @@ static DEVICE_ATTR(fod_status, (S_IRUGO | S_IWUSR | S_IWGRP), static DEVICE_ATTR(fod_test, (S_IRUGO | S_IWUSR | S_IWGRP), NULL, gtp_fod_test_store); -static DEVICE_ATTR(touch_suspend_notify, (S_IRUGO | S_IRGRP), - gtp_touch_suspend_notify_show, NULL); - static void goodix_switch_mode_work(struct work_struct *work) { struct goodix_mode_switch *ms = @@ -1618,9 +1608,6 @@ out: release_all_touches(core_data); core_data->ts_event.event_data.touch_data.touch_num = 0; - sysfs_notify(&core_data->gtp_touch_dev->kobj, NULL, - "touch_suspend_notify"); - mutex_unlock(&core_data->work_stat); ts_info("Suspend end"); @@ -1708,9 +1695,6 @@ out: } core_data->sleep_finger = 0; - sysfs_notify(&core_data->gtp_touch_dev->kobj, NULL, - "touch_suspend_notify"); - mutex_unlock(&core_data->work_stat); ts_info("Resume end"); @@ -2243,12 +2227,6 @@ static int goodix_ts_probe(struct platform_device *pdev) } dev_set_drvdata(core_data->gtp_touch_dev, core_data); - if (sysfs_create_file(&core_data->gtp_touch_dev->kobj, - &dev_attr_touch_suspend_notify.attr)) { - ts_err("Failed to create sysfs group!\n"); - goto out; - } - if (sysfs_create_file(&core_data->gtp_touch_dev->kobj, &dev_attr_fod_status.attr)) { ts_err("Failed to create fod_status sysfs group!\n"); diff --git a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_gesture.c b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_gesture.c index c4dd45d76775..266d6c07f72d 100644 --- a/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_gesture.c +++ b/drivers/input/touchscreen/goodix_driver_gt9886/goodix_ts_gesture.c @@ -479,16 +479,16 @@ static int gsx_gesture_ist(struct goodix_ts_core *core_data, if ((FP_Event_Gesture == 1) && (temp_data[2] == 0xff)) { if (core_data->fod_pressed) { ts_debug("Gesture report up"); - input_mt_slot(core_data->input_dev, 0); - input_mt_report_slot_state(core_data->input_dev, MT_TOOL_FINGER, false); - input_report_abs(core_data->input_dev, ABS_MT_WIDTH_MINOR, 0); - input_report_key(core_data->input_dev, BTN_INFO, 0); - /*input_report_key(core_data->input_dev, KEY_INFO, 0);*/ - input_report_key(core_data->input_dev, BTN_TOUCH, 0); - input_report_key(core_data->input_dev, BTN_TOOL_FINGER, 0); - input_sync(core_data->input_dev); - __clear_bit(0, &core_data->touch_id); - core_data->fod_pressed = false; + input_mt_slot(core_data->input_dev, 0); + input_mt_report_slot_state(core_data->input_dev, MT_TOOL_FINGER, false); + input_report_abs(core_data->input_dev, ABS_MT_WIDTH_MINOR, 0); + input_report_key(core_data->input_dev, BTN_INFO, 0); + /*input_report_key(core_data->input_dev, KEY_INFO, 0);*/ + input_report_key(core_data->input_dev, BTN_TOUCH, 0); + input_report_key(core_data->input_dev, BTN_TOOL_FINGER, 0); + input_sync(core_data->input_dev); + __clear_bit(0, &core_data->touch_id); + core_data->fod_pressed = false; } core_data->sleep_finger = 0; } @@ -619,11 +619,11 @@ static int goodix_wakeup_and_set_suspend_func(struct goodix_ts_core *core_data) } } while (r < 0 && ++retry < 3); - if (core_data->double_wakeup && core_data->fod_status) { + if (core_data->double_wakeup && (core_data->fod_status || core_data->aod_status)) { atomic_set(&core_data->suspend_stat, TP_GESTURE_DBCLK_FOD); } else if (core_data->double_wakeup) { atomic_set(&core_data->suspend_stat, TP_GESTURE_DBCLK); - } else if (core_data->fod_status) { + } else if (core_data->fod_status || core_data->aod_status) { atomic_set(&core_data->suspend_stat, TP_GESTURE_FOD); } ts_info("suspend_stat[%d]", atomic_read(&core_data->suspend_stat)); diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 154949a499c2..7cc5b04e30b7 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -601,13 +601,21 @@ out_free_table: static void intel_teardown_irq_remapping(struct intel_iommu *iommu) { + struct fwnode_handle *fn; + if (iommu && iommu->ir_table) { if (iommu->ir_msi_domain) { + fn = iommu->ir_msi_domain->fwnode; + irq_domain_remove(iommu->ir_msi_domain); + irq_domain_free_fwnode(fn); iommu->ir_msi_domain = NULL; } if (iommu->ir_domain) { + fn = iommu->ir_domain->fwnode; + irq_domain_remove(iommu->ir_domain); + irq_domain_free_fwnode(fn); iommu->ir_domain = NULL; } free_pages((unsigned long)iommu->ir_table->base, diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 505548aafeff..cec33e90e399 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -101,8 +101,11 @@ static ssize_t debug_read_regs(struct file *file, char __user *userbuf, mutex_lock(&iommu_debug_lock); bytes = omap_iommu_dump_ctx(obj, p, count); + if (bytes < 0) + goto err; bytes = simple_read_from_buffer(userbuf, count, ppos, buf, bytes); +err: mutex_unlock(&iommu_debug_lock); kfree(buf); diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index a2d5c4744c0b..2a6d9f7933f2 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -2200,6 +2200,7 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, { msi_alloc_info_t *info = args; struct its_device *its_dev = info->scratchpad[0].ptr; + struct irq_data *irqd; irq_hw_number_t hwirq; int err; int i; @@ -2215,7 +2216,9 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq, irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i, &its_irq_chip, its_dev); - irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i))); + irqd = irq_get_irq_data(virq + i); + irqd_set_single_target(irqd); + irqd_set_affinity_on_activate(irqd); pr_debug("ID:%d pID:%d vID:%d\n", (int)(hwirq + i - its_dev->event_map.lpi_base), (int)(hwirq + i), virq + i); diff --git a/drivers/irqchip/irq-mtk-sysirq.c b/drivers/irqchip/irq-mtk-sysirq.c index 90aaf190157f..42455f31b061 100644 --- a/drivers/irqchip/irq-mtk-sysirq.c +++ b/drivers/irqchip/irq-mtk-sysirq.c @@ -23,7 +23,7 @@ #include struct mtk_sysirq_chip_data { - spinlock_t lock; + raw_spinlock_t lock; u32 nr_intpol_bases; void __iomem **intpol_bases; u32 *intpol_words; @@ -45,7 +45,7 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) reg_index = chip_data->which_word[hwirq]; offset = hwirq & 0x1f; - spin_lock_irqsave(&chip_data->lock, flags); + raw_spin_lock_irqsave(&chip_data->lock, flags); value = readl_relaxed(base + reg_index * 4); if (type == IRQ_TYPE_LEVEL_LOW || type == IRQ_TYPE_EDGE_FALLING) { if (type == IRQ_TYPE_LEVEL_LOW) @@ -61,7 +61,7 @@ static int mtk_sysirq_set_type(struct irq_data *data, unsigned int type) data = data->parent_data; ret = data->chip->irq_set_type(data, type); - spin_unlock_irqrestore(&chip_data->lock, flags); + raw_spin_unlock_irqrestore(&chip_data->lock, flags); return ret; } @@ -220,7 +220,7 @@ static int __init mtk_sysirq_of_init(struct device_node *node, ret = -ENOMEM; goto out_free_which_word; } - spin_lock_init(&chip_data->lock); + raw_spin_lock_init(&chip_data->lock); return 0; diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 16ce3539bc70..715b38775589 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -194,6 +194,7 @@ void led_classdev_suspend(struct led_classdev *led_cdev) { led_cdev->flags |= LED_SUSPENDED; led_set_brightness_nopm(led_cdev, 0); + flush_work(&led_cdev->set_brightness_work); } EXPORT_SYMBOL_GPL(led_classdev_suspend); diff --git a/drivers/leds/leds-88pm860x.c b/drivers/leds/leds-88pm860x.c index 77a104d2b124..13f414ff6fd0 100644 --- a/drivers/leds/leds-88pm860x.c +++ b/drivers/leds/leds-88pm860x.c @@ -207,21 +207,33 @@ static int pm860x_led_probe(struct platform_device *pdev) data->cdev.brightness_set_blocking = pm860x_led_set; mutex_init(&data->lock); - ret = devm_led_classdev_register(chip->dev, &data->cdev); + ret = led_classdev_register(chip->dev, &data->cdev); if (ret < 0) { dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); return ret; } pm860x_led_set(&data->cdev, 0); + + platform_set_drvdata(pdev, data); + return 0; } +static int pm860x_led_remove(struct platform_device *pdev) +{ + struct pm860x_led *data = platform_get_drvdata(pdev); + + led_classdev_unregister(&data->cdev); + + return 0; +} static struct platform_driver pm860x_led_driver = { .driver = { .name = "88pm860x-led", }, .probe = pm860x_led_probe, + .remove = pm860x_led_remove, }; module_platform_driver(pm860x_led_driver); diff --git a/drivers/leds/leds-da903x.c b/drivers/leds/leds-da903x.c index 5ff7d72f73aa..ecc265bb69a0 100644 --- a/drivers/leds/leds-da903x.c +++ b/drivers/leds/leds-da903x.c @@ -113,12 +113,23 @@ static int da903x_led_probe(struct platform_device *pdev) led->flags = pdata->flags; led->master = pdev->dev.parent; - ret = devm_led_classdev_register(led->master, &led->cdev); + ret = led_classdev_register(led->master, &led->cdev); if (ret) { dev_err(&pdev->dev, "failed to register LED %d\n", id); return ret; } + platform_set_drvdata(pdev, led); + + return 0; +} + +static int da903x_led_remove(struct platform_device *pdev) +{ + struct da903x_led *led = platform_get_drvdata(pdev); + + led_classdev_unregister(&led->cdev); + return 0; } @@ -127,6 +138,7 @@ static struct platform_driver da903x_led_driver = { .name = "da903x-led", }, .probe = da903x_led_probe, + .remove = da903x_led_remove, }; module_platform_driver(da903x_led_driver); diff --git a/drivers/leds/leds-lm3533.c b/drivers/leds/leds-lm3533.c index 72224b599ffc..c1e562a4d6ad 100644 --- a/drivers/leds/leds-lm3533.c +++ b/drivers/leds/leds-lm3533.c @@ -698,7 +698,7 @@ static int lm3533_led_probe(struct platform_device *pdev) platform_set_drvdata(pdev, led); - ret = devm_led_classdev_register(pdev->dev.parent, &led->cdev); + ret = led_classdev_register(pdev->dev.parent, &led->cdev); if (ret) { dev_err(&pdev->dev, "failed to register LED %d\n", pdev->id); return ret; @@ -708,13 +708,18 @@ static int lm3533_led_probe(struct platform_device *pdev) ret = lm3533_led_setup(led, pdata); if (ret) - return ret; + goto err_deregister; ret = lm3533_ctrlbank_enable(&led->cb); if (ret) - return ret; + goto err_deregister; return 0; + +err_deregister: + led_classdev_unregister(&led->cdev); + + return ret; } static int lm3533_led_remove(struct platform_device *pdev) @@ -724,6 +729,7 @@ static int lm3533_led_remove(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s\n", __func__); lm3533_ctrlbank_disable(&led->cb); + led_classdev_unregister(&led->cdev); return 0; } diff --git a/drivers/leds/leds-lm355x.c b/drivers/leds/leds-lm355x.c index 6cb94f9a2f3f..b9c60dd2b132 100644 --- a/drivers/leds/leds-lm355x.c +++ b/drivers/leds/leds-lm355x.c @@ -168,18 +168,19 @@ static int lm355x_chip_init(struct lm355x_chip_data *chip) /* input and output pins configuration */ switch (chip->type) { case CHIP_LM3554: - reg_val = pdata->pin_tx2 | pdata->ntc_pin; + reg_val = (u32)pdata->pin_tx2 | (u32)pdata->ntc_pin; ret = regmap_update_bits(chip->regmap, 0xE0, 0x28, reg_val); if (ret < 0) goto out; - reg_val = pdata->pass_mode; + reg_val = (u32)pdata->pass_mode; ret = regmap_update_bits(chip->regmap, 0xA0, 0x04, reg_val); if (ret < 0) goto out; break; case CHIP_LM3556: - reg_val = pdata->pin_tx2 | pdata->ntc_pin | pdata->pass_mode; + reg_val = (u32)pdata->pin_tx2 | (u32)pdata->ntc_pin | + (u32)pdata->pass_mode; ret = regmap_update_bits(chip->regmap, 0x0A, 0xC4, reg_val); if (ret < 0) goto out; diff --git a/drivers/leds/leds-wm831x-status.c b/drivers/leds/leds-wm831x-status.c index be93b20e792a..4f0ba19c3577 100644 --- a/drivers/leds/leds-wm831x-status.c +++ b/drivers/leds/leds-wm831x-status.c @@ -283,12 +283,23 @@ static int wm831x_status_probe(struct platform_device *pdev) drvdata->cdev.blink_set = wm831x_status_blink_set; drvdata->cdev.groups = wm831x_status_groups; - ret = devm_led_classdev_register(wm831x->dev, &drvdata->cdev); + ret = led_classdev_register(wm831x->dev, &drvdata->cdev); if (ret < 0) { dev_err(&pdev->dev, "Failed to register LED: %d\n", ret); return ret; } + platform_set_drvdata(pdev, drvdata); + + return 0; +} + +static int wm831x_status_remove(struct platform_device *pdev) +{ + struct wm831x_status *drvdata = platform_get_drvdata(pdev); + + led_classdev_unregister(&drvdata->cdev); + return 0; } @@ -297,6 +308,7 @@ static struct platform_driver wm831x_status_driver = { .name = "wm831x-status", }, .probe = wm831x_status_probe, + .remove = wm831x_status_remove, }; module_platform_driver(wm831x_status_driver); diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c index 1edf9515345e..03fb06c61e1c 100644 --- a/drivers/md/bcache/bset.c +++ b/drivers/md/bcache/bset.c @@ -319,7 +319,7 @@ int bch_btree_keys_alloc(struct btree_keys *b, unsigned page_order, gfp_t gfp) b->page_order = page_order; - t->data = (void *) __get_free_pages(gfp, b->page_order); + t->data = (void *) __get_free_pages(__GFP_COMP|gfp, b->page_order); if (!t->data) goto err; diff --git a/drivers/md/bcache/btree.c b/drivers/md/bcache/btree.c index 66c764491a83..9fca837d0b41 100644 --- a/drivers/md/bcache/btree.c +++ b/drivers/md/bcache/btree.c @@ -794,7 +794,7 @@ int bch_btree_cache_alloc(struct cache_set *c) mutex_init(&c->verify_lock); c->verify_ondisk = (void *) - __get_free_pages(GFP_KERNEL, ilog2(bucket_pages(c))); + __get_free_pages(GFP_KERNEL|__GFP_COMP, ilog2(bucket_pages(c))); c->verify_data = mca_bucket_alloc(c, &ZERO_KEY, GFP_KERNEL); diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index 6394be5ee9a8..6aafda26903c 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -838,8 +838,8 @@ int bch_journal_alloc(struct cache_set *c) j->w[1].c = c; if (!(init_fifo(&j->pin, JOURNAL_PIN, GFP_KERNEL)) || - !(j->w[0].data = (void *) __get_free_pages(GFP_KERNEL, JSET_BITS)) || - !(j->w[1].data = (void *) __get_free_pages(GFP_KERNEL, JSET_BITS))) + !(j->w[0].data = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP, JSET_BITS)) || + !(j->w[1].data = (void *) __get_free_pages(GFP_KERNEL|__GFP_COMP, JSET_BITS))) return -ENOMEM; return 0; diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index f4d20deaec1b..cbeedf11fa4e 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1468,7 +1468,7 @@ void bch_cache_set_unregister(struct cache_set *c) } #define alloc_bucket_pages(gfp, c) \ - ((void *) __get_free_pages(__GFP_ZERO|gfp, ilog2(bucket_pages(c)))) + ((void *) __get_free_pages(__GFP_ZERO|__GFP_COMP|gfp, ilog2(bucket_pages(c)))) struct cache_set *bch_cache_set_alloc(struct cache_sb *sb) { @@ -1780,7 +1780,14 @@ found: sysfs_create_link(&c->kobj, &ca->kobj, buf)) goto err; - if (ca->sb.seq > c->sb.seq) { + /* + * A special case is both ca->sb.seq and c->sb.seq are 0, + * such condition happens on a new created cache device whose + * super block is never flushed yet. In this case c->sb.version + * and other members should be updated too, otherwise we will + * have a mistaken super block version in cache set. + */ + if (ca->sb.seq > c->sb.seq || c->sb.seq == 0) { c->sb.version = ca->sb.version; memcpy(c->sb.set_uuid, ca->sb.set_uuid, 16); c->sb.flags = ca->sb.flags; diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 69cdb29ef6be..280873b13e74 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c @@ -410,7 +410,6 @@ struct cache { spinlock_t lock; struct list_head deferred_cells; struct bio_list deferred_bios; - struct bio_list deferred_writethrough_bios; sector_t migration_threshold; wait_queue_head_t migration_wait; atomic_t nr_allocated_migrations; @@ -446,10 +445,10 @@ struct cache { struct dm_kcopyd_client *copier; struct workqueue_struct *wq; struct work_struct deferred_bio_worker; - struct work_struct deferred_writethrough_worker; struct work_struct migration_worker; struct delayed_work waker; struct dm_bio_prison_v2 *prison; + struct bio_set *bs; mempool_t *migration_pool; @@ -490,15 +489,6 @@ struct per_bio_data { struct dm_bio_prison_cell_v2 *cell; struct dm_hook_info hook_info; sector_t len; - - /* - * writethrough fields. These MUST remain at the end of this - * structure and the 'cache' member must be the first as it - * is used to determine the offset of the writethrough fields. - */ - struct cache *cache; - dm_cblock_t cblock; - struct dm_bio_details bio_details; }; struct dm_cache_migration { @@ -515,19 +505,19 @@ struct dm_cache_migration { /*----------------------------------------------------------------*/ -static bool writethrough_mode(struct cache_features *f) +static bool writethrough_mode(struct cache *cache) { - return f->io_mode == CM_IO_WRITETHROUGH; + return cache->features.io_mode == CM_IO_WRITETHROUGH; } -static bool writeback_mode(struct cache_features *f) +static bool writeback_mode(struct cache *cache) { - return f->io_mode == CM_IO_WRITEBACK; + return cache->features.io_mode == CM_IO_WRITEBACK; } -static inline bool passthrough_mode(struct cache_features *f) +static inline bool passthrough_mode(struct cache *cache) { - return unlikely(f->io_mode == CM_IO_PASSTHROUGH); + return unlikely(cache->features.io_mode == CM_IO_PASSTHROUGH); } /*----------------------------------------------------------------*/ @@ -537,14 +527,9 @@ static void wake_deferred_bio_worker(struct cache *cache) queue_work(cache->wq, &cache->deferred_bio_worker); } -static void wake_deferred_writethrough_worker(struct cache *cache) -{ - queue_work(cache->wq, &cache->deferred_writethrough_worker); -} - static void wake_migration_worker(struct cache *cache) { - if (passthrough_mode(&cache->features)) + if (passthrough_mode(cache)) return; queue_work(cache->wq, &cache->migration_worker); @@ -618,15 +603,9 @@ static unsigned lock_level(struct bio *bio) * Per bio data *--------------------------------------------------------------*/ -/* - * If using writeback, leave out struct per_bio_data's writethrough fields. - */ -#define PB_DATA_SIZE_WB (offsetof(struct per_bio_data, cache)) -#define PB_DATA_SIZE_WT (sizeof(struct per_bio_data)) - static size_t get_per_bio_data_size(struct cache *cache) { - return writethrough_mode(&cache->features) ? PB_DATA_SIZE_WT : PB_DATA_SIZE_WB; + return sizeof(struct per_bio_data); } static struct per_bio_data *get_per_bio_data(struct bio *bio, size_t data_size) @@ -868,16 +847,23 @@ static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio) spin_unlock_irqrestore(&cache->lock, flags); } -static void remap_to_origin_clear_discard(struct cache *cache, struct bio *bio, - dm_oblock_t oblock) +static void __remap_to_origin_clear_discard(struct cache *cache, struct bio *bio, + dm_oblock_t oblock, bool bio_has_pbd) { - // FIXME: this is called way too much. - check_if_tick_bio_needed(cache, bio); + if (bio_has_pbd) + check_if_tick_bio_needed(cache, bio); remap_to_origin(cache, bio); if (bio_data_dir(bio) == WRITE) clear_discard(cache, oblock_to_dblock(cache, oblock)); } +static void remap_to_origin_clear_discard(struct cache *cache, struct bio *bio, + dm_oblock_t oblock) +{ + // FIXME: check_if_tick_bio_needed() is called way too much through this interface + __remap_to_origin_clear_discard(cache, bio, oblock, true); +} + static void remap_to_cache_dirty(struct cache *cache, struct bio *bio, dm_oblock_t oblock, dm_cblock_t cblock) { @@ -937,57 +923,26 @@ static void issue_op(struct bio *bio, void *context) accounted_request(cache, bio); } -static void defer_writethrough_bio(struct cache *cache, struct bio *bio) -{ - unsigned long flags; - - spin_lock_irqsave(&cache->lock, flags); - bio_list_add(&cache->deferred_writethrough_bios, bio); - spin_unlock_irqrestore(&cache->lock, flags); - - wake_deferred_writethrough_worker(cache); -} - -static void writethrough_endio(struct bio *bio) -{ - struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT); - - dm_unhook_bio(&pb->hook_info, bio); - - if (bio->bi_status) { - bio_endio(bio); - return; - } - - dm_bio_restore(&pb->bio_details, bio); - remap_to_cache(pb->cache, bio, pb->cblock); - - /* - * We can't issue this bio directly, since we're in interrupt - * context. So it gets put on a bio list for processing by the - * worker thread. - */ - defer_writethrough_bio(pb->cache, bio); -} - /* - * FIXME: send in parallel, huge latency as is. * When running in writethrough mode we need to send writes to clean blocks - * to both the cache and origin devices. In future we'd like to clone the - * bio and send them in parallel, but for now we're doing them in - * series as this is easier. + * to both the cache and origin devices. Clone the bio and send them in parallel. */ -static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio, - dm_oblock_t oblock, dm_cblock_t cblock) +static void remap_to_origin_and_cache(struct cache *cache, struct bio *bio, + dm_oblock_t oblock, dm_cblock_t cblock) { - struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT); + struct bio *origin_bio = bio_clone_fast(bio, GFP_NOIO, cache->bs); - pb->cache = cache; - pb->cblock = cblock; - dm_hook_bio(&pb->hook_info, bio, writethrough_endio, NULL); - dm_bio_record(&pb->bio_details, bio); + BUG_ON(!origin_bio); - remap_to_origin_clear_discard(pb->cache, bio, oblock); + bio_chain(origin_bio, bio); + /* + * Passing false to __remap_to_origin_clear_discard() skips + * all code that might use per_bio_data (since clone doesn't have it) + */ + __remap_to_origin_clear_discard(cache, origin_bio, oblock, false); + submit_bio(origin_bio); + + remap_to_cache(cache, bio, cblock); } /*---------------------------------------------------------------- @@ -1209,7 +1164,7 @@ static bool bio_writes_complete_block(struct cache *cache, struct bio *bio) static bool optimisable_bio(struct cache *cache, struct bio *bio, dm_oblock_t block) { - return writeback_mode(&cache->features) && + return writeback_mode(cache) && (is_discarded_oblock(cache, block) || bio_writes_complete_block(cache, bio)); } @@ -1862,7 +1817,7 @@ static int map_bio(struct cache *cache, struct bio *bio, dm_oblock_t block, * Passthrough always maps to the origin, invalidating any * cache blocks that are written to. */ - if (passthrough_mode(&cache->features)) { + if (passthrough_mode(cache)) { if (bio_data_dir(bio) == WRITE) { bio_drop_shared_lock(cache, bio); atomic_inc(&cache->stats.demotion); @@ -1871,9 +1826,9 @@ static int map_bio(struct cache *cache, struct bio *bio, dm_oblock_t block, remap_to_origin_clear_discard(cache, bio, block); } else { - if (bio_data_dir(bio) == WRITE && writethrough_mode(&cache->features) && + if (bio_data_dir(bio) == WRITE && writethrough_mode(cache) && !is_dirty(cache, cblock)) { - remap_to_origin_then_cache(cache, bio, block, cblock); + remap_to_origin_and_cache(cache, bio, block, cblock); accounted_begin(cache, bio); } else remap_to_cache_dirty(cache, bio, block, cblock); @@ -2003,28 +1958,6 @@ static void process_deferred_bios(struct work_struct *ws) schedule_commit(&cache->committer); } -static void process_deferred_writethrough_bios(struct work_struct *ws) -{ - struct cache *cache = container_of(ws, struct cache, deferred_writethrough_worker); - - unsigned long flags; - struct bio_list bios; - struct bio *bio; - - bio_list_init(&bios); - - spin_lock_irqsave(&cache->lock, flags); - bio_list_merge(&bios, &cache->deferred_writethrough_bios); - bio_list_init(&cache->deferred_writethrough_bios); - spin_unlock_irqrestore(&cache->lock, flags); - - /* - * These bios have already been through accounted_begin() - */ - while ((bio = bio_list_pop(&bios))) - generic_make_request(bio); -} - /*---------------------------------------------------------------- * Main worker loop *--------------------------------------------------------------*/ @@ -2132,6 +2065,9 @@ static void destroy(struct cache *cache) kfree(cache->ctr_args[i]); kfree(cache->ctr_args); + if (cache->bs) + bioset_free(cache->bs); + kfree(cache); } @@ -2589,6 +2525,13 @@ static int cache_create(struct cache_args *ca, struct cache **result) cache->features = ca->features; ti->per_io_data_size = get_per_bio_data_size(cache); + if (writethrough_mode(cache)) { + /* Create bioset for writethrough bios issued to origin */ + cache->bs = bioset_create(BIO_POOL_SIZE, 0, 0); + if (!cache->bs) + goto bad; + } + cache->callbacks.congested_fn = cache_is_congested; dm_table_add_target_callbacks(ti->table, &cache->callbacks); @@ -2649,7 +2592,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) goto bad; } - if (passthrough_mode(&cache->features)) { + if (passthrough_mode(cache)) { bool all_clean; r = dm_cache_metadata_all_clean(cache->cmd, &all_clean); @@ -2670,7 +2613,6 @@ static int cache_create(struct cache_args *ca, struct cache **result) spin_lock_init(&cache->lock); INIT_LIST_HEAD(&cache->deferred_cells); bio_list_init(&cache->deferred_bios); - bio_list_init(&cache->deferred_writethrough_bios); atomic_set(&cache->nr_allocated_migrations, 0); atomic_set(&cache->nr_io_migrations, 0); init_waitqueue_head(&cache->migration_wait); @@ -2709,8 +2651,6 @@ static int cache_create(struct cache_args *ca, struct cache **result) goto bad; } INIT_WORK(&cache->deferred_bio_worker, process_deferred_bios); - INIT_WORK(&cache->deferred_writethrough_worker, - process_deferred_writethrough_bios); INIT_WORK(&cache->migration_worker, check_migrations); INIT_DELAYED_WORK(&cache->waker, do_waker); @@ -3279,13 +3219,13 @@ static void cache_status(struct dm_target *ti, status_type_t type, else DMEMIT("1 "); - if (writethrough_mode(&cache->features)) + if (writethrough_mode(cache)) DMEMIT("writethrough "); - else if (passthrough_mode(&cache->features)) + else if (passthrough_mode(cache)) DMEMIT("passthrough "); - else if (writeback_mode(&cache->features)) + else if (writeback_mode(cache)) DMEMIT("writeback "); else { @@ -3451,7 +3391,7 @@ static int process_invalidate_cblocks_message(struct cache *cache, unsigned coun unsigned i; struct cblock_range range; - if (!passthrough_mode(&cache->features)) { + if (!passthrough_mode(cache)) { DMERR("%s: cache has to be in passthrough mode for invalidation", cache_device_name(cache)); return -EPERM; diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c index eadfcfd106ff..cac8ec16e603 100644 --- a/drivers/md/dm-rq.c +++ b/drivers/md/dm-rq.c @@ -95,9 +95,6 @@ static void dm_old_stop_queue(struct request_queue *q) static void dm_mq_stop_queue(struct request_queue *q) { - if (blk_mq_queue_stopped(q)) - return; - blk_mq_quiesce_queue(q); } diff --git a/drivers/md/md-cluster.c b/drivers/md/md-cluster.c index a9e7f23a739a..09b2aeabf6ce 100644 --- a/drivers/md/md-cluster.c +++ b/drivers/md/md-cluster.c @@ -1423,6 +1423,7 @@ static void unlock_all_bitmaps(struct mddev *mddev) } } kfree(cinfo->other_bitmap_lockres); + cinfo->other_bitmap_lockres = NULL; } } diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5791066dd511..7b1fff568676 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -3593,6 +3593,7 @@ static int need_this_block(struct stripe_head *sh, struct stripe_head_state *s, * is missing/faulty, then we need to read everything we can. */ if (sh->raid_conf->level != 6 && + sh->raid_conf->rmw_level != PARITY_DISABLE_RMW && sh->sector < sh->raid_conf->mddev->recovery_cp) /* reconstruct-write isn't being forced */ return 0; @@ -4829,7 +4830,7 @@ static void handle_stripe(struct stripe_head *sh) * or to load a block that is being partially written. */ if (s.to_read || s.non_overwrite - || (conf->level == 6 && s.to_write && s.failed) + || (s.to_write && s.failed) || (s.syncing && (s.uptodate + s.compute < disks)) || s.replacing || s.expanding) diff --git a/drivers/media/firewire/firedtv-fw.c b/drivers/media/firewire/firedtv-fw.c index 247f0e7cb5f7..5d634706a7ea 100644 --- a/drivers/media/firewire/firedtv-fw.c +++ b/drivers/media/firewire/firedtv-fw.c @@ -271,6 +271,8 @@ static int node_probe(struct fw_unit *unit, const struct ieee1394_device_id *id) name_len = fw_csr_string(unit->directory, CSR_MODEL, name, sizeof(name)); + if (name_len < 0) + return name_len; for (i = ARRAY_SIZE(model_names); --i; ) if (strlen(model_names[i]) <= name_len && strncmp(name, model_names[i], name_len) == 0) diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index b2eb830c0360..f772c9b92d9b 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c @@ -1258,6 +1258,9 @@ static int fimc_md_get_pinctrl(struct fimc_md *fmd) pctl->state_idle = pinctrl_lookup_state(pctl->pinctrl, PINCTRL_STATE_IDLE); + if (IS_ERR(pctl->state_idle)) + return PTR_ERR(pctl->state_idle); + return 0; } diff --git a/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.c b/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.c index 5ff489592c9e..89e378afcebe 100644 --- a/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.c +++ b/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.c @@ -498,7 +498,8 @@ static void ais_ife_dev_iommu_fault_handler( p_ife_dev = (struct ais_ife_dev *)token; - CAM_ERR(CAM_ISP, "IFE%d Pagefault at %lu", p_ife_dev->hw_idx, iova); + CAM_ERR(CAM_ISP, "IFE%d Pagefault at iova 0x%x %s", + p_ife_dev->hw_idx, iova, domain->name); } static int ais_ife_dev_remove(struct platform_device *pdev) @@ -549,7 +550,6 @@ static int ais_ife_dev_probe(struct platform_device *pdev) } mutex_init(&p_ife_dev->mutex); - spin_lock_init(&p_ife_dev->eventq_lock); /* * for now, we only support one iommu handle. later @@ -571,13 +571,19 @@ static int ais_ife_dev_probe(struct platform_device *pdev) goto attach_fail; } - rc = cam_smmu_get_handle("cam-secure", + rc = cam_smmu_get_handle("ife-cp", &p_ife_dev->iommu_hdl_secure); if (rc) { CAM_ERR(CAM_ISP, "Failed to get secure iommu handle %d", rc); goto secure_fail; } + rc = cam_smmu_ops(p_ife_dev->iommu_hdl_secure, CAM_SMMU_ATTACH); + if (rc && rc != -EALREADY) { + CAM_ERR(CAM_ISP, "Attach secure iommu handle failed %d", rc); + goto secure_fail; + } + CAM_DBG(CAM_ISP, "iommu_handles: non-secure[0x%x], secure[0x%x]", p_ife_dev->iommu_hdl, p_ife_dev->iommu_hdl_secure); @@ -585,6 +591,9 @@ static int ais_ife_dev_probe(struct platform_device *pdev) cam_smmu_set_client_page_fault_handler(p_ife_dev->iommu_hdl, ais_ife_dev_iommu_fault_handler, p_ife_dev); + cam_smmu_set_client_page_fault_handler(p_ife_dev->iommu_hdl_secure, + ais_ife_dev_iommu_fault_handler, p_ife_dev); + hw_init.hw_idx = p_ife_dev->hw_idx; hw_init.iommu_hdl = p_ife_dev->iommu_hdl; hw_init.iommu_hdl_secure = p_ife_dev->iommu_hdl_secure; @@ -594,14 +603,14 @@ static int ais_ife_dev_probe(struct platform_device *pdev) rc = ais_ife_csid_hw_init(&p_ife_dev->p_csid_drv, &hw_init); if (rc) { CAM_ERR(CAM_ISP, "IFE%d no CSID dev", p_ife_dev->hw_idx, rc); - goto secure_fail; + goto secure_attach_fail; } rc = ais_vfe_hw_init(&p_ife_dev->p_vfe_drv, &hw_init, p_ife_dev->p_csid_drv); if (rc) { CAM_ERR(CAM_ISP, "IFE%d no VFE dev", p_ife_dev->hw_idx, rc); - goto secure_fail; + goto secure_attach_fail; } CAM_INFO(CAM_ISP, "IFE%d probe complete", p_ife_dev->hw_idx); @@ -610,6 +619,9 @@ static int ais_ife_dev_probe(struct platform_device *pdev) return 0; +secure_attach_fail: + cam_smmu_ops(p_ife_dev->iommu_hdl_secure, + CAM_SMMU_DETACH); secure_fail: cam_smmu_ops(p_ife_dev->iommu_hdl, CAM_SMMU_DETACH); diff --git a/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.h b/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.h index 340b6ee91b43..4273c4c1f7ab 100644 --- a/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.h +++ b/drivers/media/platform/msm/ais/ais_isp/ais_ife_dev.h @@ -40,7 +40,6 @@ struct ais_ife_dev { int iommu_hdl; int iommu_hdl_secure; - spinlock_t eventq_lock; struct mutex mutex; int32_t open_cnt; }; diff --git a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c index 00219b70667a..305120afbf3e 100644 --- a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c +++ b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.c @@ -438,6 +438,8 @@ int ais_vfe_reserve(void *hw_priv, void *reserve_args, uint32_t arg_size) goto EXIT; } + rdi_path->secure_mode = rdi_cfg->out_cfg.secure_mode; + cam_io_w(0xf, core_info->mem_base + client_regs->burst_limit); /*disable pack as it is done in CSID*/ cam_io_w(0x0, core_info->mem_base + client_regs->packer_cfg); @@ -766,8 +768,11 @@ static int ais_vfe_cmd_enq_buf(struct ais_vfe_hw_core_info *core_info, vfe_buf->bufIdx = enq_buf->buffer.idx; vfe_buf->mem_handle = enq_buf->buffer.mem_handle; - mmu_hdl = cam_mem_is_secure_buf(vfe_buf->mem_handle) ? - core_info->iommu_hdl_secure : core_info->iommu_hdl; + mmu_hdl = core_info->iommu_hdl; + + if (cam_mem_is_secure_buf(vfe_buf->mem_handle) || rdi_path->secure_mode) + mmu_hdl = core_info->iommu_hdl_secure; + rc = cam_mem_get_io_buf(vfe_buf->mem_handle, mmu_hdl, &vfe_buf->iova_addr, &src_buf_size); if (rc < 0) { @@ -985,7 +990,7 @@ static void ais_vfe_handle_sof_rdi(struct ais_vfe_hw_core_info *core_info, //enq curr sof.sof_ts = work_data->ts; - sof.cur_sof_hw_ts = prev_sof_hw_ts; + sof.cur_sof_hw_ts = cur_sof_hw_ts; sof.frame_cnt = p_rdi->frame_cnt; ais_vfe_q_sof(core_info, path, &sof); @@ -1098,25 +1103,31 @@ static int ais_vfe_handle_error( continue; p_rdi = &core_info->rdi_out[path]; + if (p_rdi->state != AIS_ISP_RESOURCE_STATE_STREAMING) continue; + CAM_ERR(CAM_ISP, "IFE%d Turn off RDI %d", + core_info->vfe_idx, path); + p_rdi->state = AIS_ISP_RESOURCE_STATE_ERROR; client_regs = &bus_hw_info->bus_client_reg[path]; - /* Disable WM and reg-update */ - cam_io_w_mb(0x0, core_info->mem_base + client_regs->cfg); - cam_io_w_mb(AIS_VFE_REGUP_RDI_ALL, core_info->mem_base + - top_hw_info->common_reg->reg_update_cmd); - cam_io_w_mb((1 << path), core_info->mem_base + - bus_hw_info->common_reg.sw_reset); - core_info->bus_wr_mask1 &= ~(1 << path); cam_io_w_mb(core_info->bus_wr_mask1, core_info->mem_base + bus_hw_irq_regs[1].mask_reg_offset); + /* Disable WM and reg-update */ + cam_io_w_mb(0x0, core_info->mem_base + client_regs->cfg); + cam_io_w_mb(AIS_VFE_REGUP_RDI_ALL, core_info->mem_base + + top_hw_info->common_reg->reg_update_cmd); + + cam_io_w_mb((1 << path), core_info->mem_base + + bus_hw_info->common_reg.sw_reset); + + core_info->event.type = AIS_IFE_MSG_OUTPUT_ERROR; core_info->event.path = path; @@ -1551,9 +1562,10 @@ irqreturn_t ais_vfe_irq(int irq_num, void *data) AIS_VFE_STATUS1_RDI_OVERFLOW_IRQ_SHFT) & AIS_VFE_STATUS1_RDI_OVERFLOW_IRQ_MSK; - CAM_ERR(CAM_ISP, "IFE%d Overflow 0x%x", - core_info->vfe_idx, - work_data.path); + CAM_ERR_RATE_LIMIT(CAM_ISP, + "IFE%d Overflow 0x%x", + core_info->vfe_idx, + work_data.path); work_data.evt_type = AIS_VFE_HW_IRQ_EVENT_ERROR; ais_vfe_dispatch_irq(vfe_hw, &work_data); } diff --git a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.h b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.h index 3b5ee36182bc..c4bd0648dd27 100644 --- a/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.h +++ b/drivers/media/platform/msm/ais/ais_isp/vfe_hw/ais_vfe_core.h @@ -96,6 +96,7 @@ struct ais_vfe_rdi_output { enum ais_isp_resource_state state; uint32_t en_cfg; + uint32_t secure_mode; spinlock_t buffer_lock; struct ais_vfe_buffer_t buffers[AIS_VFE_MAX_BUF]; diff --git a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 7c349f66c3de..78e8332729ea 100644 --- a/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/ais/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -6337,9 +6337,10 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) return -EINVAL; } - if (cam_smmu_ops(g_ife_hw_mgr.mgr_common.img_iommu_hdl, - CAM_SMMU_ATTACH)) { - CAM_ERR(CAM_ISP, "Attach iommu handle failed."); + rc = cam_smmu_ops(g_ife_hw_mgr.mgr_common.img_iommu_hdl, + CAM_SMMU_ATTACH); + if (rc && rc != -EALREADY) { + CAM_ERR(CAM_ISP, "Attach iommu handle failed %d", rc); goto attach_fail; } diff --git a/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c b/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c index 33094cd010a1..33949b9161fb 100644 --- a/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c +++ b/drivers/media/platform/msm/ais/cam_req_mgr/cam_mem_mgr.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -217,6 +217,7 @@ int cam_mem_get_io_buf(int32_t buf_handle, int32_t mmu_handle, tbl.bufq[idx].fd, iova_ptr, len_ptr); + if (rc) { CAM_ERR(CAM_MEM, "fail to map buf_hdl:0x%x, mmu_hdl: 0x%x for fd:%d", @@ -511,6 +512,9 @@ static int cam_mem_util_ion_alloc(struct cam_mem_mgr_alloc_cmd *cmd, } else if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) { heap_id = ION_HEAP(ION_SECURE_DISPLAY_HEAP_ID); ion_flag |= ION_FLAG_SECURE | ION_FLAG_CP_CAMERA; + } else if (cmd->flags & CAM_MEM_FLAG_CP_PIXEL) { + heap_id = ION_HEAP(ION_SECURE_HEAP_ID); + ion_flag |= ION_FLAG_SECURE | ION_FLAG_CP_PIXEL; } else { heap_id = ION_HEAP(ION_SYSTEM_HEAP_ID) | ION_HEAP(ION_CAMERA_HEAP_ID); @@ -540,8 +544,9 @@ static int cam_mem_util_check_alloc_flags(struct cam_mem_mgr_alloc_cmd *cmd) return -EINVAL; } - if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE && - cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) { + if (((cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) || + (cmd->flags & CAM_MEM_FLAG_CP_PIXEL)) && + (cmd->flags & CAM_MEM_FLAG_KMD_ACCESS)) { CAM_ERR(CAM_MEM, "Kernel mapping in secure mode not allowed"); return -EINVAL; } @@ -562,8 +567,9 @@ static int cam_mem_util_check_map_flags(struct cam_mem_mgr_map_cmd *cmd) return -EINVAL; } - if (cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE && - cmd->flags & CAM_MEM_FLAG_KMD_ACCESS) { + if (((cmd->flags & CAM_MEM_FLAG_PROTECTED_MODE) || + (cmd->flags & CAM_MEM_FLAG_CP_PIXEL)) && + (cmd->flags & CAM_MEM_FLAG_KMD_ACCESS)) { CAM_ERR(CAM_MEM, "Kernel mapping in secure mode not allowed, flags=0x%x", cmd->flags); diff --git a/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c index 1bc5a8ec640e..70a8ecc8d5a5 100644 --- a/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c +++ b/drivers/media/platform/msm/ais/cam_smmu/cam_smmu_api.c @@ -36,7 +36,7 @@ #define COOKIE_SIZE (BYTE_SIZE*COOKIE_NUM_BYTE) #define COOKIE_MASK ((1<> COOKIE_SIZE) & COOKIE_MASK) @@ -105,7 +105,10 @@ struct cam_context_bank_info { dma_addr_t va_start; size_t va_len; const char *name; + /* stage 2 only */ bool is_secure; + /* stage 1 */ + bool is_secure_pixel; uint8_t scratch_buf_support; uint8_t firmware_support; uint8_t shared_support; @@ -3269,6 +3272,20 @@ static int cam_smmu_setup_cb(struct cam_context_bank_info *cb, goto end; } + if (cb->is_secure_pixel) { + int secure_vmid = VMID_CP_PIXEL; + + rc = iommu_domain_set_attr(cb->mapping->domain, + DOMAIN_ATTR_SECURE_VMID, &secure_vmid); + if (rc) { + CAM_ERR(CAM_SMMU, + "programming secure vmid failed: %s %d", + dev_name(dev), rc); + rc = -ENODEV; + goto end; + } + } + return rc; end: if (cb->shared_support) { @@ -3345,6 +3362,10 @@ static int cam_smmu_get_memory_regions_info(struct device_node *of_node, mem_map_node = of_get_child_by_name(of_node, "iova-mem-map"); cb->is_secure = of_property_read_bool(of_node, "qcom,secure-cb"); + if (!cb->is_secure) + cb->is_secure_pixel = of_property_read_bool(of_node, + "qcom,secure-pixel-cb"); + /* * We always expect a memory map node, except when it is a secure * context bank. diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c index 6bc114c5949b..8d705b0a76d6 100644 --- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c @@ -228,7 +228,7 @@ static void __cam_isp_ctx_dump_state_monitor_array( ctx_monitor = ctx_isp->cam_isp_ctx_state_monitor; if (log_rate_limit) - CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20, + CAM_DBG(CAM_ISP, "Dumping state information for preceding requests"); else CAM_INFO(CAM_ISP, @@ -241,8 +241,8 @@ static void __cam_isp_ctx_dump_state_monitor_array( CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES); if (log_rate_limit) { - CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20, - "time[%lld] last reported req_id[%llu] frame id[%lld] applied id[%lld] current state[%s] next state[%s] hw_event[%s]", + CAM_DBG(CAM_ISP, + "time[%lld] last reported req_id[%u] frame id[%lld] applied id[%lld] current state[%s] next state[%s] hw_event[%s]", ctx_monitor[index].evt_time_stamp, ctx_monitor[index].last_reported_id, ctx_monitor[index].frame_id, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c index 8ca1edfdc27b..3de0232873a1 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c @@ -813,9 +813,6 @@ int read_platform_resources_from_drv_data( res->debug_timeout = find_key_value(platform_data, "qcom,debug-timeout"); - res->pm_qos_latency_us = find_key_value(platform_data, - "qcom,pm-qos-latency-us"); - res->max_secure_inst_count = find_key_value(platform_data, "qcom,max-secure-instances"); diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h index 53d62fb91c45..a5ebba093383 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h +++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h @@ -193,7 +193,6 @@ struct msm_vidc_platform_resources { const char *hfi_version; bool never_unload_fw; bool debug_timeout; - uint32_t pm_qos_latency_us; uint32_t max_inst_count; uint32_t max_secure_inst_count; int msm_vidc_hw_rsp_timeout; diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 4deed7f6b8ed..ad6197425045 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -2224,14 +2223,6 @@ static int venus_hfi_core_init(void *device) __set_subcaches(device); __dsp_send_hfi_queue(device); - if (dev->res->pm_qos_latency_us) { -#ifdef CONFIG_SMP - dev->qos.type = PM_QOS_REQ_AFFINE_IRQ; - dev->qos.irq = dev->hal_data->irq; -#endif - pm_qos_add_request(&dev->qos, PM_QOS_CPU_DMA_LATENCY, - dev->res->pm_qos_latency_us); - } dprintk(VIDC_DBG, "Core inited successfully\n"); mutex_unlock(&dev->lock); return rc; @@ -2258,10 +2249,6 @@ static int venus_hfi_core_release(void *dev) mutex_lock(&device->lock); dprintk(VIDC_DBG, "Core releasing\n"); - if (device->res->pm_qos_latency_us && - pm_qos_request_active(&device->qos)) - pm_qos_remove_request(&device->qos); - __resume(device); __set_state(device, VENUS_STATE_DEINIT); __dsp_shutdown(device, 0); @@ -4801,10 +4788,6 @@ static inline int __suspend(struct venus_hfi_device *device) dprintk(VIDC_PROF, "Entering suspend\n"); - if (device->res->pm_qos_latency_us && - pm_qos_request_active(&device->qos)) - pm_qos_remove_request(&device->qos); - rc = __tzbsp_set_video_state(TZBSP_VIDEO_STATE_SUSPEND); if (rc) { dprintk(VIDC_WARN, "Failed to suspend video core %d\n", rc); @@ -4864,15 +4847,6 @@ static inline int __resume(struct venus_hfi_device *device) */ __set_threshold_registers(device); - if (device->res->pm_qos_latency_us) { -#ifdef CONFIG_SMP - device->qos.type = PM_QOS_REQ_AFFINE_IRQ; - device->qos.irq = device->hal_data->irq; -#endif - pm_qos_add_request(&device->qos, PM_QOS_CPU_DMA_LATENCY, - device->res->pm_qos_latency_us); - } - __sys_set_debug(device, msm_vidc_fw_debug); __enable_subcaches(device); diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c index e981eb2330f1..ac005ae4d21b 100644 --- a/drivers/media/platform/omap3isp/isppreview.c +++ b/drivers/media/platform/omap3isp/isppreview.c @@ -2290,7 +2290,7 @@ static int preview_init_entities(struct isp_prev_device *prev) me->ops = &preview_media_ops; ret = media_entity_pads_init(me, PREV_PADS_NUM, pads); if (ret < 0) - return ret; + goto error_handler_free; preview_init_formats(sd, NULL); @@ -2323,6 +2323,8 @@ error_video_out: omap3isp_video_cleanup(&prev->video_in); error_video_in: media_entity_cleanup(&prev->subdev.entity); +error_handler_free: + v4l2_ctrl_handler_free(&prev->ctrls); return ret; } diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index ad8a5296c50b..9aa33141e7f1 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -1528,6 +1528,15 @@ err_irq: arizona_irq_exit(arizona); err_pm: pm_runtime_disable(arizona->dev); + + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + arizona_clk32k_disable(arizona); + break; + default: + break; + } err_reset: arizona_enable_reset(arizona); regulator_disable(arizona->dcvdd); @@ -1550,6 +1559,15 @@ int arizona_dev_exit(struct arizona *arizona) regulator_disable(arizona->dcvdd); regulator_put(arizona->dcvdd); + switch (arizona->pdata.clk32k_src) { + case ARIZONA_32KZ_MCLK1: + case ARIZONA_32KZ_MCLK2: + arizona_clk32k_disable(arizona); + break; + default: + break; + } + mfd_remove_devices(arizona->dev); arizona_free_irq(arizona, ARIZONA_IRQ_UNDERCLOCKED, arizona); arizona_free_irq(arizona, ARIZONA_IRQ_OVERCLOCKED, arizona); diff --git a/drivers/mfd/dln2.c b/drivers/mfd/dln2.c index 672831d5ee32..97a69cd6f127 100644 --- a/drivers/mfd/dln2.c +++ b/drivers/mfd/dln2.c @@ -294,7 +294,11 @@ static void dln2_rx(struct urb *urb) len = urb->actual_length - sizeof(struct dln2_header); if (handle == DLN2_HANDLE_EVENT) { + unsigned long flags; + + spin_lock_irqsave(&dln2->event_cb_lock, flags); dln2_run_event_callbacks(dln2, id, echo, data, len); + spin_unlock_irqrestore(&dln2->event_cb_lock, flags); } else { /* URB will be re-submitted in _dln2_transfer (free_rx_slot) */ if (dln2_transfer_complete(dln2, urb, handle, echo)) diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 393a80bdb846..b0285c5d8d38 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c @@ -606,7 +606,7 @@ static struct afu_config_record *cxl_sysfs_afu_new_cr(struct cxl_afu *afu, int c rc = kobject_init_and_add(&cr->kobj, &afu_config_record_type, &afu->dev.kobj, "cr%i", cr->cr); if (rc) - goto err; + goto err1; rc = sysfs_create_bin_file(&cr->kobj, &cr->config_attr); if (rc) diff --git a/drivers/mtd/devices/msm_qpic_nand.c b/drivers/mtd/devices/msm_qpic_nand.c index 8cb1feb3dcd1..6e84a4b2c54b 100644 --- a/drivers/mtd/devices/msm_qpic_nand.c +++ b/drivers/mtd/devices/msm_qpic_nand.c @@ -26,6 +26,8 @@ #define MAX_DESC 16 #define SMEM_AARM_PARTITION_TABLE 9 #define SMEM_APPS 0 +#define ONE_CODEWORD_SIZE 516 + static bool enable_euclean; static bool enable_perfstats; @@ -1183,10 +1185,16 @@ static int msm_nand_validate_mtd_params(struct mtd_info *mtd, bool read, err = -EINVAL; goto out; } - args->page_count = ops->len / (mtd->writesize + mtd->oobsize); + if (ops->len <= ONE_CODEWORD_SIZE) + args->page_count = 1; + else + args->page_count = ops->len / + (mtd->writesize + mtd->oobsize); } else if (ops->mode == MTD_OPS_AUTO_OOB) { - if (ops->datbuf && (ops->len % mtd->writesize) != 0) { + if (ops->datbuf && (ops->len % + ((ops->len <= ONE_CODEWORD_SIZE) ? + ONE_CODEWORD_SIZE : mtd->writesize)) != 0) { /* when ops->datbuf is NULL, ops->len can be ooblen */ pr_err("unsupported data len %d for AUTO mode\n", ops->len); @@ -1199,7 +1207,10 @@ static int msm_nand_validate_mtd_params(struct mtd_info *mtd, bool read, if ((args->page_count == 0) && (ops->ooblen)) args->page_count = 1; } else if (ops->datbuf) { - args->page_count = ops->len / mtd->writesize; + if (ops->len <= ONE_CODEWORD_SIZE) + args->page_count = 1; + else + args->page_count = ops->len / mtd->writesize; } } @@ -1245,12 +1256,20 @@ static void msm_nand_update_rw_reg_data(struct msm_nand_chip *chip, struct msm_nand_rw_params *args, struct msm_nand_rw_reg_data *data) { + /* + * While reading one codeword, CW_PER_PAGE bits of QPIC_NAND_DEV0_CFG0 + * should be set to 0, which implies 1 codeword per page. 'n' below, + * is used to configure cfg0 for reading one full page or one single + * codeword. + */ + int n = (ops->len <= ONE_CODEWORD_SIZE) ? args->cwperpage : 1; + if (args->read) { if (ops->mode != MTD_OPS_RAW) { data->cmd = MSM_NAND_CMD_PAGE_READ_ECC; data->cfg0 = (chip->cfg0 & ~(7U << CW_PER_PAGE)) | - (((args->cwperpage-1) - args->start_sector) + (((args->cwperpage-n) - args->start_sector) << CW_PER_PAGE); data->cfg1 = chip->cfg1; data->ecc_bch_cfg = chip->ecc_bch_cfg; @@ -1258,7 +1277,7 @@ static void msm_nand_update_rw_reg_data(struct msm_nand_chip *chip, data->cmd = MSM_NAND_CMD_PAGE_READ_ALL; data->cfg0 = (chip->cfg0_raw & ~(7U << CW_PER_PAGE)) | - (((args->cwperpage-1) - args->start_sector) + (((args->cwperpage-n) - args->start_sector) << CW_PER_PAGE); data->cfg1 = chip->cfg1_raw; data->ecc_bch_cfg = chip->ecc_cfg_raw; @@ -1302,6 +1321,11 @@ static void msm_nand_prep_rw_cmd_desc(struct mtd_oob_ops *ops, uint32_t offset, size, last_read; struct sps_command_element *curr_ce, *start_ce; uint32_t *flags_ptr, *num_ce_ptr; + /* + * Variable to configure read_location register parameters + * while reading one codeword or one full page + */ + int n = (ops->len <= ONE_CODEWORD_SIZE) ? args->cwperpage : 1; if (curr_cw == args->start_sector) { curr_ce = start_ce = &cmd_list->setup_desc.ce[0]; @@ -1394,10 +1418,15 @@ static void msm_nand_prep_rw_cmd_desc(struct mtd_oob_ops *ops, if (ops->mode == MTD_OPS_AUTO_OOB) { if (ops->datbuf) { offset = 0; - size = (curr_cw < (args->cwperpage - 1)) ? 516 : - (512 - ((args->cwperpage - 1) << 2)); - last_read = (curr_cw < (args->cwperpage - 1)) ? 1 : - (ops->oobbuf ? 0 : 1); + if (ops->len <= ONE_CODEWORD_SIZE) { + size = ONE_CODEWORD_SIZE; + last_read = 1; + } else { + size = (curr_cw < (args->cwperpage - 1)) ? 516 : + (512 - ((args->cwperpage - 1) << 2)); + last_read = (curr_cw < (args->cwperpage - 1)) ? + 1 : (ops->oobbuf ? 0 : 1); + } rdata = (offset << 0) | (size << 16) | (last_read << 31); @@ -1413,7 +1442,7 @@ static void msm_nand_prep_rw_cmd_desc(struct mtd_oob_ops *ops, curr_ce++; } } - if (curr_cw == (args->cwperpage - 1) && ops->oobbuf) { + if (curr_cw == (args->cwperpage - n) && ops->oobbuf) { offset = 512 - ((args->cwperpage - 1) << 2); size = (args->cwperpage) << 2; if (size > args->oob_len_cmd) @@ -1471,6 +1500,11 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops, uint32_t sectordatasize, sectoroobsize; uint32_t sps_flags = 0; int err = 0; + /* + * Variable to configure sectordatasize and sectoroobsize + * while reading one codeword or one full page. + */ + int n = (ops->len <= ONE_CODEWORD_SIZE) ? args->cwperpage : 1; if (args->read) data_pipe_handle = info->sps.data_prod.handle; @@ -1479,7 +1513,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops, if (ops->mode == MTD_OPS_RAW) { if (ecc_parity_bytes && args->read) { - if (curr_cw == (args->cwperpage - 1)) + if (curr_cw == (args->cwperpage - n)) sps_flags |= SPS_IOVEC_FLAG_INT; /* read only ecc bytes */ @@ -1494,7 +1528,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops, sectordatasize = chip->cw_size; if (!args->read) sps_flags = SPS_IOVEC_FLAG_EOT; - if (curr_cw == (args->cwperpage - 1)) + if (curr_cw == (args->cwperpage - n)) sps_flags |= SPS_IOVEC_FLAG_INT; err = sps_transfer_one(data_pipe_handle, @@ -1507,8 +1541,13 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops, } } else if (ops->mode == MTD_OPS_AUTO_OOB) { if (ops->datbuf) { - sectordatasize = (curr_cw < (args->cwperpage - 1)) - ? 516 : (512 - ((args->cwperpage - 1) << 2)); + if (ops->len <= ONE_CODEWORD_SIZE) + sectordatasize = ONE_CODEWORD_SIZE; + else + sectordatasize = + (curr_cw < (args->cwperpage - 1)) + ? 516 : + (512 - ((args->cwperpage - 1) << 2)); if (!args->read) { sps_flags = SPS_IOVEC_FLAG_EOT; @@ -1516,7 +1555,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops, ops->oobbuf) sps_flags = 0; } - if ((curr_cw == (args->cwperpage - 1)) && !ops->oobbuf) + if ((curr_cw == (args->cwperpage - n)) && !ops->oobbuf) sps_flags |= SPS_IOVEC_FLAG_INT; err = sps_transfer_one(data_pipe_handle, @@ -1528,7 +1567,7 @@ static int msm_nand_submit_rw_data_desc(struct mtd_oob_ops *ops, args->data_dma_addr_curr += sectordatasize; } - if (ops->oobbuf && (curr_cw == (args->cwperpage - 1))) { + if (ops->oobbuf && (curr_cw == (args->cwperpage - n))) { sectoroobsize = args->cwperpage << 2; if (sectoroobsize > args->oob_len_data) sectoroobsize = args->oob_len_data; @@ -1984,7 +2023,7 @@ free_dma: total_ecc_byte_cnt, DMA_FROM_DEVICE); /* check for bit flips in ecc data */ ecc_temp = ecc; - for (n = rw_params->start_sector; n < cwperpage; n++) { + for (n = rw_params->start_sector; !err && n < cwperpage; n++) { int last_pos = 0, next_pos = 0; int ecc_bytes_percw_in_bits = (chip->ecc_parity_bytes * 8); @@ -1995,7 +2034,7 @@ free_dma: if (last_pos < ecc_bytes_percw_in_bits) num_zero_bits++; - if (num_zero_bits > MAX_ECC_BIT_FLIPS) { + if (num_zero_bits > info->flash_dev.ecc_capability) { *erased_page = false; goto free_mem; } @@ -2007,7 +2046,8 @@ free_dma: ecc_temp += chip->ecc_parity_bytes; } - if ((n == cwperpage) && (num_zero_bits <= MAX_ECC_BIT_FLIPS)) + if ((n == cwperpage) && + (num_zero_bits <= info->flash_dev.ecc_capability)) *erased_page = true; free_mem: kfree(ecc); @@ -2651,7 +2691,7 @@ free_dma: total_ecc_byte_cnt, DMA_FROM_DEVICE); /* check for bit flips in ecc data */ ecc_temp = ecc; - for (n = rw_params->start_sector; n < cwperpage; n++) { + for (n = rw_params->start_sector; !err && n < cwperpage; n++) { int last_pos = 0, next_pos = 0; int ecc_bytes_percw_in_bits = (chip->ecc_parity_bytes * 8); @@ -2662,7 +2702,7 @@ free_dma: if (last_pos < ecc_bytes_percw_in_bits) num_zero_bits++; - if (num_zero_bits > MAX_ECC_BIT_FLIPS) { + if (num_zero_bits > info->flash_dev.ecc_capability) { *erased_page = false; goto free_mem; } @@ -2674,7 +2714,8 @@ free_dma: ecc_temp += chip->ecc_parity_bytes; } - if ((n == cwperpage) && (num_zero_bits <= MAX_ECC_BIT_FLIPS)) + if ((n == cwperpage) && + (num_zero_bits <= info->flash_dev.ecc_capability)) *erased_page = true; free_mem: kfree(ecc); @@ -2755,6 +2796,9 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, data.addr0 = (rw_params.page << 16) | rw_params.oob_col; data.addr1 = (rw_params.page >> 16) & 0xff; + if (ops->len <= ONE_CODEWORD_SIZE) + cwperpage = 1; + for (n = rw_params.start_sector; n < cwperpage; n++) { struct sps_command_element *curr_ce, *start_ce; @@ -2832,7 +2876,7 @@ static int msm_nand_read_oob(struct mtd_info *mtd, loff_t from, } else if (ops->mode == MTD_OPS_AUTO_OOB) { if (ops->datbuf) submitted_num_desc = cwperpage - - rw_params.start_sector; + rw_params.start_sector; if (ops->oobbuf) submitted_num_desc++; } @@ -3052,7 +3096,10 @@ free_dma: } validate_mtd_params_failed: if (ops->mode != MTD_OPS_RAW) - ops->retlen = mtd->writesize * pages_read; + if (ops->len <= ONE_CODEWORD_SIZE) + ops->retlen = ONE_CODEWORD_SIZE; + else + ops->retlen = mtd->writesize * pages_read; else ops->retlen = (mtd->writesize + mtd->oobsize) * pages_read; ops->oobretlen = ops->ooblen - rw_params.oob_len_data; @@ -3125,8 +3172,11 @@ static int msm_nand_read_partial_page(struct mtd_info *mtd, ops->datbuf = no_copy ? actual_buf : bounce_buf; if (info->nand_chip.caps & MSM_NAND_CAP_PAGE_SCOPE_READ) err = msm_nand_read_pagescope(mtd, aligned_from, ops); - else + else { + if ((len <= ONE_CODEWORD_SIZE) && (offset == 0)) + ops->len = ONE_CODEWORD_SIZE; err = msm_nand_read_oob(mtd, aligned_from, ops); + } if (err == -EUCLEAN) { is_euclean = 1; err = 0; diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 2eb704242b89..c07b0a946d6f 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -373,9 +373,6 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd, uint32_t retlen; int ret = 0; - if (!(file->f_mode & FMODE_WRITE)) - return -EPERM; - if (length > 4096) return -EINVAL; @@ -682,6 +679,48 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) return -EFAULT; } + /* + * Check the file mode to require "dangerous" commands to have write + * permissions. + */ + switch (cmd) { + /* "safe" commands */ + case MEMGETREGIONCOUNT: + case MEMGETREGIONINFO: + case MEMGETINFO: + case MEMREADOOB: + case MEMREADOOB64: + case MEMLOCK: + case MEMUNLOCK: + case MEMISLOCKED: + case MEMGETOOBSEL: + case MEMGETBADBLOCK: + case MEMSETBADBLOCK: + case OTPSELECT: + case OTPGETREGIONCOUNT: + case OTPGETREGIONINFO: + case OTPLOCK: + case ECCGETLAYOUT: + case ECCGETSTATS: + case MTDFILEMODE: + case BLKPG: + case BLKRRPART: + break; + + /* "dangerous" commands */ + case MEMERASE: + case MEMERASE64: + case MEMWRITEOOB: + case MEMWRITEOOB64: + case MEMWRITE: + if (!(file->f_mode & FMODE_WRITE)) + return -EPERM; + break; + + default: + return -ENOTTY; + } + switch (cmd) { case MEMGETREGIONCOUNT: if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) @@ -729,9 +768,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) { struct erase_info *erase; - if(!(file->f_mode & FMODE_WRITE)) - return -EPERM; - erase=kzalloc(sizeof(struct erase_info),GFP_KERNEL); if (!erase) ret = -ENOMEM; @@ -1055,9 +1091,6 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) ret = 0; break; } - - default: - ret = -ENOTTY; } return ret; @@ -1101,6 +1134,11 @@ static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd, struct mtd_oob_buf32 buf; struct mtd_oob_buf32 __user *buf_user = argp; + if (!(file->f_mode & FMODE_WRITE)) { + ret = -EPERM; + break; + } + if (copy_from_user(&buf, argp, sizeof(buf))) ret = -EFAULT; else diff --git a/drivers/mtd/nand/qcom_nandc.c b/drivers/mtd/nand/qcom_nandc.c index 20ad11626f86..9db1023f8059 100644 --- a/drivers/mtd/nand/qcom_nandc.c +++ b/drivers/mtd/nand/qcom_nandc.c @@ -435,11 +435,13 @@ struct qcom_nand_host { * among different NAND controllers. * @ecc_modes - ecc mode for NAND * @is_bam - whether NAND controller is using BAM + * @is_qpic - whether NAND CTRL is part of qpic IP * @dev_cmd_reg_start - NAND_DEV_CMD_* registers starting offset */ struct qcom_nandc_props { u32 ecc_modes; bool is_bam; + bool is_qpic; u32 dev_cmd_reg_start; }; @@ -2508,7 +2510,8 @@ static int qcom_nandc_setup(struct qcom_nand_controller *nandc) u32 nand_ctrl; /* kill onenand */ - nandc_write(nandc, SFLASHC_BURST_CFG, 0); + if (!nandc->props->is_qpic) + nandc_write(nandc, SFLASHC_BURST_CFG, 0); nandc_write(nandc, dev_cmd_reg_addr(nandc, NAND_DEV_CMD_VLD), NAND_DEV_CMD_VLD_VAL); @@ -2779,12 +2782,14 @@ static const struct qcom_nandc_props ipq806x_nandc_props = { static const struct qcom_nandc_props ipq4019_nandc_props = { .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), .is_bam = true, + .is_qpic = true, .dev_cmd_reg_start = 0x0, }; static const struct qcom_nandc_props ipq8074_nandc_props = { .ecc_modes = (ECC_BCH_4BIT | ECC_BCH_8BIT), .is_bam = true, + .is_qpic = true, .dev_cmd_reg_start = 0x7000, }; diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 10ea01459a36..f4268f032266 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2450,7 +2450,6 @@ static const struct mv88e6xxx_ops mv88e6097_ops = { .port_set_frame_mode = mv88e6351_port_set_frame_mode, .port_set_egress_floods = mv88e6352_port_set_egress_floods, .port_set_ether_type = mv88e6351_port_set_ether_type, - .port_set_jumbo_size = mv88e6165_port_set_jumbo_size, .port_egress_rate_limiting = mv88e6095_port_egress_rate_limiting, .port_pause_limit = mv88e6097_port_pause_limit, .port_disable_learn_limit = mv88e6xxx_port_disable_learn_limit, diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index b83ee74d2839..77e5c6926814 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -746,7 +746,7 @@ static int hw_atl_a0_hw_multicast_list_set(struct aq_hw_s *self, int err = 0; if (count > (HW_ATL_A0_MAC_MAX - HW_ATL_A0_MAC_MIN)) { - err = EBADRQC; + err = -EBADRQC; goto err_exit; } for (self->aq_nic_cfg->mc_list_count = 0U; diff --git a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c index 2e089b5ff8f3..30f0e54f658e 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +++ b/drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c @@ -1167,7 +1167,7 @@ static int cn23xx_get_pf_num(struct octeon_device *oct) oct->pf_num = ((fdl_bit >> CN23XX_PCIE_SRIOV_FDL_BIT_POS) & CN23XX_PCIE_SRIOV_FDL_MASK); } else { - ret = EINVAL; + ret = -EINVAL; /* Under some virtual environments, extended PCI regs are * inaccessible, in which case the above read will have failed. diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c index 9080d2332d03..cdd48b1cc84a 100644 --- a/drivers/net/ethernet/freescale/fman/fman.c +++ b/drivers/net/ethernet/freescale/fman/fman.c @@ -1396,8 +1396,7 @@ static void enable_time_stamp(struct fman *fman) { struct fman_fpm_regs __iomem *fpm_rg = fman->fpm_regs; u16 fm_clk_freq = fman->state->fm_clk_freq; - u32 tmp, intgr, ts_freq; - u64 frac; + u32 tmp, intgr, ts_freq, frac; ts_freq = (u32)(1 << fman->state->count1_micro_bit); /* configure timestamp so that bit 8 will count 1 microsecond diff --git a/drivers/net/ethernet/freescale/fman/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/fman_dtsec.c index 7af31ddd093f..61238b3af204 100644 --- a/drivers/net/ethernet/freescale/fman/fman_dtsec.c +++ b/drivers/net/ethernet/freescale/fman/fman_dtsec.c @@ -1159,7 +1159,7 @@ int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr) list_for_each(pos, &dtsec->multicast_addr_hash->lsts[bucket]) { hash_entry = ETH_HASH_ENTRY_OBJ(pos); - if (hash_entry->addr == addr) { + if (hash_entry && hash_entry->addr == addr) { list_del_init(&hash_entry->node); kfree(hash_entry); break; @@ -1172,7 +1172,7 @@ int dtsec_del_hash_mac_address(struct fman_mac *dtsec, enet_addr_t *eth_addr) list_for_each(pos, &dtsec->unicast_addr_hash->lsts[bucket]) { hash_entry = ETH_HASH_ENTRY_OBJ(pos); - if (hash_entry->addr == addr) { + if (hash_entry && hash_entry->addr == addr) { list_del_init(&hash_entry->node); kfree(hash_entry); break; diff --git a/drivers/net/ethernet/freescale/fman/fman_mac.h b/drivers/net/ethernet/freescale/fman/fman_mac.h index dd6d0526f6c1..19f327efdaff 100644 --- a/drivers/net/ethernet/freescale/fman/fman_mac.h +++ b/drivers/net/ethernet/freescale/fman/fman_mac.h @@ -252,7 +252,7 @@ static inline struct eth_hash_t *alloc_hash_table(u16 size) struct eth_hash_t *hash; /* Allocate address hash table */ - hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL); + hash = kmalloc(sizeof(*hash), GFP_KERNEL); if (!hash) return NULL; diff --git a/drivers/net/ethernet/freescale/fman/fman_memac.c b/drivers/net/ethernet/freescale/fman/fman_memac.c index b33650a897f1..460f9e58e987 100644 --- a/drivers/net/ethernet/freescale/fman/fman_memac.c +++ b/drivers/net/ethernet/freescale/fman/fman_memac.c @@ -855,7 +855,6 @@ int memac_set_tx_pause_frames(struct fman_mac *memac, u8 priority, tmp = ioread32be(®s->command_config); tmp &= ~CMD_CFG_PFC_MODE; - priority = 0; iowrite32be(tmp, ®s->command_config); @@ -957,7 +956,7 @@ int memac_del_hash_mac_address(struct fman_mac *memac, enet_addr_t *eth_addr) list_for_each(pos, &memac->multicast_addr_hash->lsts[hash]) { hash_entry = ETH_HASH_ENTRY_OBJ(pos); - if (hash_entry->addr == addr) { + if (hash_entry && hash_entry->addr == addr) { list_del_init(&hash_entry->node); kfree(hash_entry); break; diff --git a/drivers/net/ethernet/freescale/fman/fman_port.c b/drivers/net/ethernet/freescale/fman/fman_port.c index 495190764155..ac3d791f5282 100644 --- a/drivers/net/ethernet/freescale/fman/fman_port.c +++ b/drivers/net/ethernet/freescale/fman/fman_port.c @@ -1744,6 +1744,7 @@ static int fman_port_probe(struct platform_device *of_dev) struct fman_port *port; struct fman *fman; struct device_node *fm_node, *port_node; + struct platform_device *fm_pdev; struct resource res; struct resource *dev_res; u32 val; @@ -1768,8 +1769,14 @@ static int fman_port_probe(struct platform_device *of_dev) goto return_err; } - fman = dev_get_drvdata(&of_find_device_by_node(fm_node)->dev); + fm_pdev = of_find_device_by_node(fm_node); of_node_put(fm_node); + if (!fm_pdev) { + err = -EINVAL; + goto return_err; + } + + fman = dev_get_drvdata(&fm_pdev->dev); if (!fman) { err = -EINVAL; goto return_err; diff --git a/drivers/net/ethernet/freescale/fman/fman_tgec.c b/drivers/net/ethernet/freescale/fman/fman_tgec.c index e575259d20f4..c8ad9b8a75f8 100644 --- a/drivers/net/ethernet/freescale/fman/fman_tgec.c +++ b/drivers/net/ethernet/freescale/fman/fman_tgec.c @@ -585,7 +585,7 @@ int tgec_del_hash_mac_address(struct fman_mac *tgec, enet_addr_t *eth_addr) list_for_each(pos, &tgec->multicast_addr_hash->lsts[hash]) { hash_entry = ETH_HASH_ENTRY_OBJ(pos); - if (hash_entry->addr == addr) { + if (hash_entry && hash_entry->addr == addr) { list_del_init(&hash_entry->node); kfree(hash_entry); break; diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index 78fa1ebb3987..bc7d96a64017 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5488,9 +5488,18 @@ static void igb_reset_task(struct work_struct *work) struct igb_adapter *adapter; adapter = container_of(work, struct igb_adapter, reset_task); + rtnl_lock(); + /* If we're already down or resetting, just bail */ + if (test_bit(__IGB_DOWN, &adapter->state) || + test_bit(__IGB_RESETTING, &adapter->state)) { + rtnl_unlock(); + return; + } + igb_dump(adapter); netdev_err(adapter->netdev, "Reset adapter\n"); igb_reinit_locked(adapter); + rtnl_unlock(); } /** diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 9ba699cbdbc5..a52909db67f6 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -2452,6 +2452,8 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) eth->netdev[id]->irq = eth->irq[0]; eth->netdev[id]->dev.of_node = np; + eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH - MTK_RX_ETH_HLEN; + return 0; free_netdev: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index e69674d38f16..a3107d133b40 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -180,7 +180,7 @@ int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr) struct mlx5_eswitch_rep *rep = rpriv->rep; struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; - if (esw->mode == SRIOV_NONE) + if (esw->mode != SRIOV_OFFLOADS) return -EOPNOTSUPP; switch (attr->id) { diff --git a/drivers/net/ethernet/qualcomm/emac/emac.c b/drivers/net/ethernet/qualcomm/emac/emac.c index 759543512117..5ab83751a471 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac.c @@ -493,13 +493,24 @@ static int emac_clks_phase1_init(struct platform_device *pdev, ret = clk_prepare_enable(adpt->clk[EMAC_CLK_CFG_AHB]); if (ret) - return ret; + goto disable_clk_axi; ret = clk_set_rate(adpt->clk[EMAC_CLK_HIGH_SPEED], 19200000); if (ret) - return ret; + goto disable_clk_cfg_ahb; - return clk_prepare_enable(adpt->clk[EMAC_CLK_HIGH_SPEED]); + ret = clk_prepare_enable(adpt->clk[EMAC_CLK_HIGH_SPEED]); + if (ret) + goto disable_clk_cfg_ahb; + + return 0; + +disable_clk_cfg_ahb: + clk_disable_unprepare(adpt->clk[EMAC_CLK_CFG_AHB]); +disable_clk_axi: + clk_disable_unprepare(adpt->clk[EMAC_CLK_AXI]); + + return ret; } /* Enable clocks; needs emac_clks_phase1_init to be called before */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c index 63de429ca11e..77803e8d34b5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c @@ -362,6 +362,7 @@ static int ipq806x_gmac_probe(struct platform_device *pdev) plat_dat->has_gmac = true; plat_dat->bsp_priv = gmac; plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed; + plat_dat->multicast_filter_bins = 0; err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); if (err) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index 651fd5500151..b6c8996c99b5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -23,15 +23,28 @@ #include #include #include - +#include +#include +#include +#include #include "stmmac.h" #include "stmmac_platform.h" #include "dwmac-qcom-ethqos.h" #include "stmmac_ptp.h" #include "dwmac-qcom-ipa-offload.h" +#define PHY_LOOPBACK_1000 0x4140 +#define PHY_LOOPBACK_100 0x6100 +#define PHY_LOOPBACK_10 0x4100 + static void __iomem *tlmm_central_base_addr; +static void ethqos_rgmii_io_macro_loopback(struct qcom_ethqos *ethqos, + int mode); +static int phy_digital_loopback_config( + struct qcom_ethqos *ethqos, int speed, int config); + bool phy_intr_en; +static char buf[2000]; static struct ethqos_emac_por emac_por[] = { { .offset = RGMII_IO_MACRO_CONFIG, .value = 0x0 }, @@ -77,7 +90,7 @@ static void qcom_ethqos_read_iomacro_por_values(struct qcom_ethqos *ethqos) ethqos->por[i].offset); } -static inline unsigned int dwmac_qcom_get_eth_type(unsigned char *buf) +unsigned int dwmac_qcom_get_eth_type(unsigned char *buf) { return ((((u16)buf[QTAG_ETH_TYPE_OFFSET] << 8) | @@ -926,6 +939,12 @@ static int ethqos_mdio_read(struct stmmac_priv *priv, int phyaddr, int phyreg) u32 v; int data; u32 value = MII_BUSY; + struct qcom_ethqos *ethqos = priv->plat->bsp_priv; + + if (ethqos->phy_state == PHY_IS_OFF) { + ETHQOSINFO("Phy is in off state reading is not possible\n"); + return -EOPNOTSUPP; + } value |= (phyaddr << priv->hw->mii.addr_shift) & priv->hw->mii.addr_mask; @@ -951,6 +970,44 @@ static int ethqos_mdio_read(struct stmmac_priv *priv, int phyaddr, int phyreg) return data; } +static int ethqos_mdio_write(struct stmmac_priv *priv, int phyaddr, int phyreg, + u16 phydata) +{ + unsigned int mii_address = priv->hw->mii.addr; + unsigned int mii_data = priv->hw->mii.data; + u32 v; + u32 value = MII_BUSY; + struct qcom_ethqos *ethqos = priv->plat->bsp_priv; + + if (ethqos->phy_state == PHY_IS_OFF) { + ETHQOSINFO("Phy is in off state writing is not possible\n"); + return -EOPNOTSUPP; + } + value |= (phyaddr << priv->hw->mii.addr_shift) + & priv->hw->mii.addr_mask; + value |= (phyreg << priv->hw->mii.reg_shift) & priv->hw->mii.reg_mask; + + value |= (priv->clk_csr << priv->hw->mii.clk_csr_shift) + & priv->hw->mii.clk_csr_mask; + if (priv->plat->has_gmac4) + value |= MII_GMAC4_WRITE; + else + value |= MII_WRITE; + + /* Wait until any existing MII operation is complete */ + if (readl_poll_timeout(priv->ioaddr + mii_address, v, !(v & MII_BUSY), + 100, 10000)) + return -EBUSY; + + /* Set the MII address register to write */ + writel_relaxed(phydata, priv->ioaddr + mii_data); + writel_relaxed(value, priv->ioaddr + mii_address); + + /* Wait until any existing MII operation is complete */ + return readl_poll_timeout(priv->ioaddr + mii_address, v, + !(v & MII_BUSY), 100, 10000); +} + static int ethqos_phy_intr_config(struct qcom_ethqos *ethqos) { int ret = 0; @@ -1107,6 +1164,10 @@ static ssize_t read_phy_reg_dump(struct file *file, char __user *user_buf, ETHQOSERR("NULL Pointer\n"); return -EINVAL; } + if (ethqos->phy_state == PHY_IS_OFF) { + ETHQOSINFO("Phy is in off state phy dump is not possible\n"); + return -EOPNOTSUPP; + } buf = kzalloc(buf_len, GFP_KERNEL); if (!buf) @@ -1203,6 +1264,458 @@ static ssize_t read_rgmii_reg_dump(struct file *file, return ret_cnt; } +static ssize_t read_phy_off(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + unsigned int len = 0, buf_len = 2000; + struct qcom_ethqos *ethqos = file->private_data; + + if (ethqos->current_phy_mode == DISABLE_PHY_IMMEDIATELY) + len += scnprintf(buf + len, buf_len - len, + "Disable phy immediately enabled\n"); + else if (ethqos->current_phy_mode == ENABLE_PHY_IMMEDIATELY) + len += scnprintf(buf + len, buf_len - len, + "Enable phy immediately enabled\n"); + else if (ethqos->current_phy_mode == DISABLE_PHY_AT_SUSPEND_ONLY) { + len += scnprintf(buf + len, buf_len - len, + "Disable Phy at suspend\n"); + len += scnprintf(buf + len, buf_len - len, + " & do not enable at resume enabled\n"); + } else if (ethqos->current_phy_mode == + DISABLE_PHY_SUSPEND_ENABLE_RESUME) { + len += scnprintf(buf + len, buf_len - len, + "Disable Phy at suspend\n"); + len += scnprintf(buf + len, buf_len - len, + " & enable at resume enabled\n"); + } else if (ethqos->current_phy_mode == DISABLE_PHY_ON_OFF) + len += scnprintf(buf + len, buf_len - len, + "Disable phy on/off disabled\n"); + else + len += scnprintf(buf + len, buf_len - len, + "Invalid Phy State\n"); + + if (len > buf_len) + len = buf_len; + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t phy_off_config( + struct file *file, const char __user *user_buffer, + size_t count, loff_t *position) +{ + char *in_buf; + int buf_len = 2000; + unsigned long ret; + int config = 0; + struct qcom_ethqos *ethqos = file->private_data; + + in_buf = kzalloc(buf_len, GFP_KERNEL); + if (!in_buf) + return -ENOMEM; + + ret = copy_from_user(in_buf, user_buffer, buf_len); + if (ret) { + ETHQOSERR("unable to copy from user\n"); + return -EFAULT; + } + + ret = sscanf(in_buf, "%d", &config); + if (ret != 1) { + ETHQOSERR("Error in reading option from user"); + return -EINVAL; + } + if (config > DISABLE_PHY_ON_OFF || config < DISABLE_PHY_IMMEDIATELY) { + ETHQOSERR("Invalid option =%d", config); + return -EINVAL; + } + if (config == ethqos->current_phy_mode) { + ETHQOSERR("No effect as duplicate config"); + return -EPERM; + } + if (config == DISABLE_PHY_IMMEDIATELY) { + ethqos->current_phy_mode = DISABLE_PHY_IMMEDIATELY; + //make phy off + if (ethqos->current_loopback == ENABLE_PHY_LOOPBACK) { + /* If Phy loopback is enabled + * Disabled It before phy off + */ + phy_digital_loopback_config(ethqos, + ethqos->loopback_speed, 0); + ETHQOSDBG("Disable phy Loopback"); + ethqos->current_loopback = ENABLE_PHY_LOOPBACK; + } + ethqos_phy_power_off(ethqos); + } else if (config == ENABLE_PHY_IMMEDIATELY) { + ethqos->current_phy_mode = ENABLE_PHY_IMMEDIATELY; + //make phy on + ethqos_phy_power_on(ethqos); + ethqos_reset_phy_enable_interrupt(ethqos); + if (ethqos->current_loopback == ENABLE_PHY_LOOPBACK) { + /*If Phy loopback is enabled , enabled It again*/ + phy_digital_loopback_config(ethqos, + ethqos->loopback_speed, 1); + ETHQOSDBG("Enabling Phy loopback again"); + } + } else if (config == DISABLE_PHY_AT_SUSPEND_ONLY) { + ethqos->current_phy_mode = DISABLE_PHY_AT_SUSPEND_ONLY; + } else if (config == DISABLE_PHY_SUSPEND_ENABLE_RESUME) { + ethqos->current_phy_mode = DISABLE_PHY_SUSPEND_ENABLE_RESUME; + } else if (config == DISABLE_PHY_ON_OFF) { + ethqos->current_phy_mode = DISABLE_PHY_ON_OFF; + } else { + ETHQOSERR("Invalid option\n"); + return -EINVAL; + } + kfree(in_buf); + return count; +} + +static void ethqos_rgmii_io_macro_loopback(struct qcom_ethqos *ethqos, int mode) +{ + /* Set loopback mode */ + if (mode == 1) { + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG2); + } else { + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + } +} + +static void ethqos_mac_loopback(struct qcom_ethqos *ethqos, int mode) +{ + u32 read_value = (u32)readl_relaxed(ethqos->ioaddr + MAC_CONFIGURATION); + /* Set loopback mode */ + if (mode == 1) + read_value |= MAC_LM; + else + read_value &= ~MAC_LM; + writel_relaxed(read_value, ethqos->ioaddr + MAC_CONFIGURATION); +} + +static int phy_digital_loopback_config( + struct qcom_ethqos *ethqos, int speed, int config) +{ + struct platform_device *pdev = ethqos->pdev; + struct net_device *dev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(dev); + int phydata = 0; + + if (config == 1) { + ETHQOSINFO("Request for phy digital loopback enable\n"); + switch (speed) { + case SPEED_1000: + phydata = PHY_LOOPBACK_1000; + break; + case SPEED_100: + phydata = PHY_LOOPBACK_100; + break; + case SPEED_10: + phydata = PHY_LOOPBACK_10; + break; + default: + ETHQOSERR("Invalid link speed\n"); + break; + } + } else if (config == 0) { + ETHQOSINFO("Request for phy digital loopback disable\n"); + if (ethqos->bmcr_backup) + phydata = ethqos->bmcr_backup; + else + phydata = 0x1140; + } else { + ETHQOSERR("Invalid option\n"); + return -EINVAL; + } + if (phydata != 0) { + ethqos_mdio_write( + priv, priv->plat->phy_addr, MII_BMCR, phydata); + ETHQOSINFO("write done for phy loopback\n"); + } + return 0; +} + +static void print_loopback_detail(enum loopback_mode loopback) +{ + switch (loopback) { + case DISABLE_LOOPBACK: + ETHQOSINFO("Loopback is disabled\n"); + break; + case ENABLE_IO_MACRO_LOOPBACK: + ETHQOSINFO("Loopback is Enabled as IO MACRO LOOPBACK\n"); + break; + case ENABLE_MAC_LOOPBACK: + ETHQOSINFO("Loopback is Enabled as MAC LOOPBACK\n"); + break; + case ENABLE_PHY_LOOPBACK: + ETHQOSINFO("Loopback is Enabled as PHY LOOPBACK\n"); + break; + default: + ETHQOSINFO("Invalid Loopback=%d\n", loopback); + break; + } +} + +static void setup_config_registers(struct qcom_ethqos *ethqos, + int speed, int duplex, int mode) +{ + struct platform_device *pdev = ethqos->pdev; + struct net_device *dev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(dev); + u32 ctrl = 0; + + ETHQOSDBG("Speed=%d,dupex=%d,mode=%d\n", speed, duplex, mode); + + if (mode > DISABLE_LOOPBACK && !qcom_ethqos_is_phy_link_up(ethqos)) { + /*If Link is Down & need to enable Loopback*/ + ETHQOSDBG("Enable Lower Up Flag & disable phy dev\n"); + ETHQOSDBG("IRQ so that Rx/Tx can happen beforeee Link down\n"); + netif_carrier_on(dev); + /*Disable phy interrupt by Link/Down by cable plug in/out*/ + disable_irq(ethqos->phy_intr); + } else if (mode > DISABLE_LOOPBACK && + qcom_ethqos_is_phy_link_up(ethqos)) { + ETHQOSDBG("Only disable phy irqqq Lin is UP\n"); + /*Since link is up no need to set Lower UP flag*/ + /*Disable phy interrupt by Link/Down by cable plug in/out*/ + disable_irq(ethqos->phy_intr); + } else if (mode == DISABLE_LOOPBACK && + !qcom_ethqos_is_phy_link_up(ethqos)) { + ETHQOSDBG("Disable Lower Up as Link is down\n"); + netif_carrier_off(dev); + enable_irq(ethqos->phy_intr); + } + ETHQOSDBG("Old ctrl=%d dupex full\n", ctrl); + ctrl = readl_relaxed(priv->ioaddr + MAC_CTRL_REG); + ETHQOSDBG("Old ctrl=0x%x with mask with flow control\n", ctrl); + + ctrl |= priv->hw->link.duplex; + priv->dev->phydev->duplex = duplex; + ctrl &= ~priv->hw->link.speed_mask; + switch (speed) { + case SPEED_1000: + ctrl |= priv->hw->link.speed1000; + break; + case SPEED_100: + ctrl |= priv->hw->link.speed100; + break; + case SPEED_10: + ctrl |= priv->hw->link.speed10; + break; + default: + speed = SPEED_UNKNOWN; + ETHQOSDBG("unkwon speed\n"); + break; + } + writel_relaxed(ctrl, priv->ioaddr + MAC_CTRL_REG); + ETHQOSDBG("New ctrl=%x priv hw speeed =%d\n", ctrl, + priv->hw->link.speed1000); + priv->dev->phydev->speed = speed; + priv->speed = speed; + + if (mode > DISABLE_LOOPBACK && !qcom_ethqos_is_phy_link_up(ethqos)) { + /*If Link is Down & need to enable Loopback*/ + ETHQOSDBG("Link is down . manual ipa setting up\n"); + if (priv->tx_queue[IPA_DMA_TX_CH].skip_sw) + ethqos_ipa_offload_event_handler(priv, + EV_PHY_LINK_UP); + } else if (mode == DISABLE_LOOPBACK && + !qcom_ethqos_is_phy_link_up(ethqos)) { + ETHQOSDBG("Disable request since link was down disable ipa\n"); + if (priv->tx_queue[IPA_DMA_TX_CH].skip_sw) + ethqos_ipa_offload_event_handler(priv, + EV_PHY_LINK_DOWN); + } + + if (priv->dev->phydev->speed != SPEED_UNKNOWN) + ethqos_fix_mac_speed(ethqos, speed); + + if (mode > DISABLE_LOOPBACK) { + if (mode == ENABLE_MAC_LOOPBACK || + mode == ENABLE_IO_MACRO_LOOPBACK) + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + RGMII_CONFIG_LOOPBACK_EN, + RGMII_IO_MACRO_CONFIG); + } else if (mode == DISABLE_LOOPBACK) { + if (ethqos->emac_ver == EMAC_HW_v2_3_2 || + ethqos->emac_ver == EMAC_HW_v2_1_2) + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG); + } + ETHQOSERR("End\n"); +} + +static ssize_t loopback_handling_config( + struct file *file, const char __user *user_buffer, + size_t count, loff_t *position) +{ + char *in_buf; + int buf_len = 2000; + unsigned long ret; + int config = 0; + struct qcom_ethqos *ethqos = file->private_data; + struct platform_device *pdev = ethqos->pdev; + struct net_device *dev = platform_get_drvdata(pdev); + struct stmmac_priv *priv = netdev_priv(dev); + int speed = 0; + + in_buf = kzalloc(buf_len, GFP_KERNEL); + if (!in_buf) + return -ENOMEM; + + ret = copy_from_user(in_buf, user_buffer, buf_len); + if (ret) { + ETHQOSERR("unable to copy from user\n"); + return -EFAULT; + } + + ret = sscanf(in_buf, "%d %d", &config, &speed); + if (config > DISABLE_LOOPBACK && ret != 2) { + ETHQOSERR("Speed is also needed while enabling loopback\n"); + return -EINVAL; + } + if (config < DISABLE_LOOPBACK || config > ENABLE_PHY_LOOPBACK) { + ETHQOSERR("Invalid config =%d\n", config); + return -EINVAL; + } + if ((config == ENABLE_PHY_LOOPBACK || ethqos->current_loopback == + ENABLE_PHY_LOOPBACK) && + ethqos->current_phy_mode == DISABLE_PHY_IMMEDIATELY) { + ETHQOSERR("Can't enabled/disable "); + ETHQOSERR("phy loopback when phy is off\n"); + return -EPERM; + } + + /*Argument validation*/ + if (config == DISABLE_LOOPBACK || config == ENABLE_IO_MACRO_LOOPBACK || + config == ENABLE_MAC_LOOPBACK || config == ENABLE_PHY_LOOPBACK) { + if (speed != SPEED_1000 && speed != SPEED_100 && + speed != SPEED_10) + return -EINVAL; + } else { + return -EINVAL; + } + + if (config == ethqos->current_loopback) { + switch (config) { + case DISABLE_LOOPBACK: + ETHQOSINFO("Loopback is already disabled\n"); + break; + case ENABLE_IO_MACRO_LOOPBACK: + ETHQOSINFO("Loopback is already Enabled as "); + ETHQOSINFO("IO MACRO LOOPBACK\n"); + break; + case ENABLE_MAC_LOOPBACK: + ETHQOSINFO("Loopback is already Enabled as "); + ETHQOSINFO("MAC LOOPBACK\n"); + break; + case ENABLE_PHY_LOOPBACK: + ETHQOSINFO("Loopback is already Enabled as "); + ETHQOSINFO("PHY LOOPBACK\n"); + break; + } + return -EINVAL; + } + /*If request to enable loopback & some other loopback already enabled*/ + if (config != DISABLE_LOOPBACK && + ethqos->current_loopback > DISABLE_LOOPBACK) { + ETHQOSINFO("Loopback is already enabled\n"); + print_loopback_detail(ethqos->current_loopback); + return -EINVAL; + } + ETHQOSINFO("enable loopback = %d with link speed = %d backup now\n", + config, speed); + + /*Backup speed & duplex before Enabling Loopback */ + if (ethqos->current_loopback == DISABLE_LOOPBACK && + config > DISABLE_LOOPBACK) { + /*Backup old speed & duplex*/ + ethqos->backup_speed = priv->speed; + ethqos->backup_duplex = priv->dev->phydev->duplex; + } + /*Backup BMCR before Enabling Phy LoopbackLoopback */ + if (ethqos->current_loopback == DISABLE_LOOPBACK && + config == ENABLE_PHY_LOOPBACK) + ethqos->bmcr_backup = ethqos_mdio_read(priv, + priv->plat->phy_addr, + MII_BMCR); + + if (config == DISABLE_LOOPBACK) + setup_config_registers(ethqos, ethqos->backup_speed, + ethqos->backup_duplex, 0); + else + setup_config_registers(ethqos, speed, DUPLEX_FULL, config); + + switch (config) { + case DISABLE_LOOPBACK: + ETHQOSINFO("Request to Disable Loopback\n"); + if (ethqos->current_loopback == ENABLE_IO_MACRO_LOOPBACK) + ethqos_rgmii_io_macro_loopback(ethqos, 0); + else if (ethqos->current_loopback == ENABLE_MAC_LOOPBACK) + ethqos_mac_loopback(ethqos, 0); + else if (ethqos->current_loopback == ENABLE_PHY_LOOPBACK) + phy_digital_loopback_config(ethqos, + ethqos->backup_speed, 0); + break; + case ENABLE_IO_MACRO_LOOPBACK: + ETHQOSINFO("Request to Enable IO MACRO LOOPBACK\n"); + ethqos_rgmii_io_macro_loopback(ethqos, 1); + break; + case ENABLE_MAC_LOOPBACK: + ETHQOSINFO("Request to Enable MAC LOOPBACK\n"); + ethqos_mac_loopback(ethqos, 1); + break; + case ENABLE_PHY_LOOPBACK: + ETHQOSINFO("Request to Enable PHY LOOPBACK\n"); + ethqos->loopback_speed = speed; + phy_digital_loopback_config(ethqos, speed, 1); + break; + default: + ETHQOSINFO("Invalid Loopback=%d\n", config); + break; + } + + ethqos->current_loopback = config; + kfree(in_buf); + return count; +} + +static ssize_t read_loopback_config(struct file *file, + char __user *user_buf, + size_t count, loff_t *ppos) +{ + unsigned int len = 0, buf_len = 2000; + struct qcom_ethqos *ethqos = file->private_data; + + if (ethqos->current_loopback == DISABLE_LOOPBACK) + len += scnprintf(buf + len, buf_len - len, + "Loopback is Disabled\n"); + else if (ethqos->current_loopback == ENABLE_IO_MACRO_LOOPBACK) + len += scnprintf(buf + len, buf_len - len, + "Current Loopback is IO MACRO LOOPBACK\n"); + else if (ethqos->current_loopback == ENABLE_MAC_LOOPBACK) + len += scnprintf(buf + len, buf_len - len, + "Current Loopback is MAC LOOPBACK\n"); + else if (ethqos->current_loopback == ENABLE_PHY_LOOPBACK) + len += scnprintf(buf + len, buf_len - len, + "Current Loopback is PHY LOOPBACK\n"); + else + len += scnprintf(buf + len, buf_len - len, + "Invalid LOOPBACK Config\n"); + if (len > buf_len) + len = buf_len; + + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + static const struct file_operations fops_phy_reg_dump = { .read = read_phy_reg_dump, .open = simple_open, @@ -1254,6 +1767,22 @@ static ssize_t write_ipc_stmmac_log_ctxt_low(struct file *file, return count; } +static const struct file_operations fops_phy_off = { + .read = read_phy_off, + .write = phy_off_config, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + +static const struct file_operations fops_loopback_config = { + .read = read_loopback_config, + .write = loopback_handling_config, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static const struct file_operations fops_ipc_stmmac_log_low = { .write = write_ipc_stmmac_log_ctxt_low, .open = simple_open, @@ -1266,6 +1795,8 @@ static int ethqos_create_debugfs(struct qcom_ethqos *ethqos) static struct dentry *phy_reg_dump; static struct dentry *rgmii_reg_dump; static struct dentry *ipc_stmmac_log_low; + static struct dentry *phy_off; + static struct dentry *loopback_enable_mode; if (!ethqos) { ETHQOSERR("Null Param %s\n", __func__); @@ -1299,11 +1830,26 @@ static int ethqos_create_debugfs(struct qcom_ethqos *ethqos) ethqos->debugfs_dir, ethqos, &fops_ipc_stmmac_log_low); if (!ipc_stmmac_log_low || IS_ERR(ipc_stmmac_log_low)) { - ETHQOSERR("Cannot create debugfs ipc_stmmac_log_low %d\n", - (int)ipc_stmmac_log_low); + ETHQOSERR("Cannot create debugfs ipc_stmmac_log_low %x\n", + ipc_stmmac_log_low); + goto fail; + } + phy_off = debugfs_create_file("phy_off", 0400, + ethqos->debugfs_dir, ethqos, + &fops_phy_off); + if (!phy_off || IS_ERR(phy_off)) { + ETHQOSERR("Can't create phy_off %x\n", phy_off); goto fail; } + loopback_enable_mode = debugfs_create_file("loopback_enable_mode", 0400, + ethqos->debugfs_dir, ethqos, + &fops_loopback_config); + if (!loopback_enable_mode || IS_ERR(loopback_enable_mode)) { + ETHQOSERR("Can't create loopback_enable_mode %d\n", + (int)loopback_enable_mode); + goto fail; + } return 0; fail: @@ -1914,6 +2460,21 @@ static int qcom_ethqos_probe(struct platform_device *pdev) } ETHQOSDBG(": emac_core_version = %d\n", ethqos->emac_ver); + if (of_property_read_bool(pdev->dev.of_node, + "emac-phy-off-suspend")) { + /* Read emac core version value from dtsi */ + ret = of_property_read_u32(pdev->dev.of_node, + "emac-phy-off-suspend", + ðqos->current_phy_mode); + if (ret) { + ETHQOSDBG(":resource emac-phy-off-suspend! "); + ETHQOSDBG("not in dtsi\n"); + ethqos->current_phy_mode = 0; + } + } + ETHQOSINFO("emac-phy-off-suspend = %d\n", + ethqos->current_phy_mode); + ethqos->ioaddr = (&stmmac_res)->addr; ethqos_update_rgmii_tx_drv_strength(ethqos); @@ -2011,6 +2572,8 @@ static int qcom_ethqos_suspend(struct device *dev) struct net_device *ndev = NULL; int ret; int allow_suspend = 0; + struct stmmac_priv *priv; + struct plat_stmmacenet_data *plat; ETHQOSDBG("Suspend Enter\n"); if (of_device_is_compatible(dev->of_node, "qcom,emac-smmu-embedded")) { @@ -2023,6 +2586,8 @@ static int qcom_ethqos_suspend(struct device *dev) return -ENODEV; ndev = dev_get_drvdata(dev); + priv = netdev_priv(ndev); + plat = priv->plat; ethqos_ipa_offload_event_handler(&allow_suspend, EV_DPM_SUSPEND); if (!allow_suspend) { @@ -2032,9 +2597,25 @@ static int qcom_ethqos_suspend(struct device *dev) } if (!ndev || !netif_running(ndev)) return -EINVAL; - + if (ethqos->current_phy_mode == DISABLE_PHY_AT_SUSPEND_ONLY || + ethqos->current_phy_mode == DISABLE_PHY_SUSPEND_ENABLE_RESUME) { + /*Backup phy related data*/ + if (priv->phydev->autoneg == AUTONEG_DISABLE) { + ethqos->backup_autoneg = priv->phydev->autoneg; + ethqos->backup_bmcr = ethqos_mdio_read(priv, + plat->phy_addr, + MII_BMCR); + } else { + ethqos->backup_autoneg = AUTONEG_ENABLE; + } + } ret = stmmac_suspend(dev); qcom_ethqos_phy_suspend_clks(ethqos); + if (ethqos->current_phy_mode == DISABLE_PHY_AT_SUSPEND_ONLY || + ethqos->current_phy_mode == DISABLE_PHY_SUSPEND_ENABLE_RESUME) { + ETHQOSINFO("disable phy at suspend\n"); + ethqos_phy_power_off(ethqos); + } ETHQOSDBG(" ret = %d\n", ret); return ret; @@ -2045,6 +2626,7 @@ static int qcom_ethqos_resume(struct device *dev) struct net_device *ndev = NULL; struct qcom_ethqos *ethqos; int ret; + struct stmmac_priv *priv; ETHQOSDBG("Resume Enter\n"); if (of_device_is_compatible(dev->of_node, "qcom,emac-smmu-embedded")) @@ -2056,6 +2638,7 @@ static int qcom_ethqos_resume(struct device *dev) return -ENODEV; ndev = dev_get_drvdata(dev); + priv = netdev_priv(ndev); if (!ndev || !netif_running(ndev)) { ETHQOSERR(" Resume not possible\n"); @@ -2068,10 +2651,39 @@ static int qcom_ethqos_resume(struct device *dev) return 0; } + if (ethqos->current_phy_mode == DISABLE_PHY_SUSPEND_ENABLE_RESUME) { + ETHQOSINFO("enable phy at resume\n"); + ethqos_phy_power_on(ethqos); + } qcom_ethqos_phy_resume_clks(ethqos); - ret = stmmac_resume(dev); + if (ethqos->current_phy_mode == DISABLE_PHY_SUSPEND_ENABLE_RESUME) { + ETHQOSINFO("reset phy after clock\n"); + ethqos_reset_phy_enable_interrupt(ethqos); + if (ethqos->backup_autoneg == AUTONEG_DISABLE) { + priv->phydev->autoneg = ethqos->backup_autoneg; + ethqos_mdio_write( + priv, priv->plat->phy_addr, + MII_BMCR, ethqos->backup_bmcr); + } + } + if (ethqos->current_phy_mode == DISABLE_PHY_AT_SUSPEND_ONLY) { + /* Temp Enable LOOPBACK_EN. + * TX clock needed for reset As Phy is off + */ + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + RGMII_CONFIG_LOOPBACK_EN, + RGMII_IO_MACRO_CONFIG); + ETHQOSINFO("Loopback EN Enabled\n"); + } + ret = stmmac_resume(dev); + if (ethqos->current_phy_mode == DISABLE_PHY_AT_SUSPEND_ONLY) { + //Disable LOOPBACK_EN + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG); + ETHQOSINFO("Loopback EN Disabled\n"); + } ethqos_ipa_offload_event_handler(NULL, EV_DPM_RESUME); ETHQOSDBG("<--Resume Exit\n"); diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h index 40dbd4392288..e275873aa250 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.h @@ -235,6 +235,10 @@ do {\ #define VOTE_IDX_100MBPS 2 #define VOTE_IDX_1000MBPS 3 +//Mac config +#define MAC_CONFIGURATION 0x0 +#define MAC_LM BIT(12) + #define TLMM_BASE_ADDRESS (tlmm_central_base_addr) #define TLMM_RGMII_HDRV_PULL_CTL1_ADDRESS_OFFSET\ @@ -329,9 +333,29 @@ static inline u32 PPSX_MASK(u32 x) } enum IO_MACRO_PHY_MODE { - RGMII_MODE, - RMII_MODE, - MII_MODE + RGMII_MODE, + RMII_MODE, + MII_MODE +}; + +enum loopback_mode { + DISABLE_LOOPBACK = 0, + ENABLE_IO_MACRO_LOOPBACK, + ENABLE_MAC_LOOPBACK, + ENABLE_PHY_LOOPBACK +}; + +enum phy_power_mode { + DISABLE_PHY_IMMEDIATELY = 1, + ENABLE_PHY_IMMEDIATELY, + DISABLE_PHY_AT_SUSPEND_ONLY, + DISABLE_PHY_SUSPEND_ENABLE_RESUME, + DISABLE_PHY_ON_OFF, +}; + +enum current_phy_state { + PHY_IS_ON = 0, + PHY_IS_OFF, }; #define RGMII_IO_BASE_ADDRESS ethqos->rgmii_base @@ -458,6 +482,19 @@ struct qcom_ethqos { bool ipa_enabled; /* Key Performance Indicators */ bool print_kpi; + unsigned int emac_phy_off_suspend; + int loopback_speed; + enum loopback_mode current_loopback; + enum phy_power_mode current_phy_mode; + enum current_phy_state phy_state; + /*Backup variable for phy loopback*/ + int backup_duplex; + int backup_speed; + u32 bmcr_backup; + /*Backup variable for suspend resume*/ + int backup_suspend_speed; + u32 backup_bmcr; + unsigned backup_autoneg:1; }; struct pps_cfg { @@ -513,6 +550,9 @@ bool qcom_ethqos_is_phy_link_up(struct qcom_ethqos *ethqos); void *qcom_ethqos_get_priv(struct qcom_ethqos *ethqos); int ppsout_config(struct stmmac_priv *priv, struct pps_cfg *eth_pps_cfg); +int ethqos_phy_power_on(struct qcom_ethqos *ethqos); +void ethqos_phy_power_off(struct qcom_ethqos *ethqos); +void ethqos_reset_phy_enable_interrupt(struct qcom_ethqos *ethqos); u16 dwmac_qcom_select_queue( struct net_device *dev, @@ -574,4 +614,6 @@ int dwmac_qcom_program_avb_algorithm( struct stmmac_priv *priv, struct ifr_data_struct *req); unsigned int dwmac_qcom_get_plat_tx_coal_frames( struct sk_buff *skb); + +unsigned int dwmac_qcom_get_eth_type(unsigned char *buf); #endif diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c index 76aafe700851..5ad0eddf9179 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-gpio.c @@ -183,6 +183,63 @@ void ethqos_disable_regulators(struct qcom_ethqos *ethqos) } } +void ethqos_reset_phy_enable_interrupt(struct qcom_ethqos *ethqos) +{ + struct stmmac_priv *priv = qcom_ethqos_get_priv(ethqos); + struct phy_device *phydev = priv->dev->phydev; + + /* reset the phy so that it's ready */ + if (priv->mii) { + ETHQOSERR("do mdio reset\n"); + stmmac_mdio_reset(priv->mii); + } + /*Enable phy interrupt*/ + if (phy_intr_en && phydev) { + ETHQOSDBG("PHY interrupt Mode enabled\n"); + phydev->irq = PHY_IGNORE_INTERRUPT; + phydev->interrupts = PHY_INTERRUPT_ENABLED; + + if (phydev->drv->config_intr && + !phydev->drv->config_intr(phydev)) { + ETHQOSERR("config_phy_intr successful after phy on\n"); + } + qcom_ethqos_request_phy_wol(priv->plat); + } else if (!phy_intr_en) { + phydev->irq = PHY_POLL; + ETHQOSDBG("PHY Polling Mode enabled\n"); + } else { + ETHQOSERR("phydev is null , intr value=%d\n", phy_intr_en); + } +} + +int ethqos_phy_power_on(struct qcom_ethqos *ethqos) +{ + int ret = 0; + + if (ethqos->reg_emac_phy) { + ret = regulator_enable(ethqos->reg_emac_phy); + if (ret) { + ETHQOSERR("Can not enable <%s>\n", + EMAC_VREG_EMAC_PHY_NAME); + return ret; + } + ethqos->phy_state = PHY_IS_ON; + } else { + ETHQOSERR("reg_emac_phy is NULL\n"); + } + return ret; +} + +void ethqos_phy_power_off(struct qcom_ethqos *ethqos) +{ + if (ethqos->reg_emac_phy) { + regulator_disable(ethqos->reg_emac_phy); + ethqos->phy_state = PHY_IS_OFF; + } else { + ETHQOSERR("reg_emac_phy is NULL\n"); + } +} + void ethqos_free_gpios(struct qcom_ethqos *ethqos) { if (gpio_is_valid(ethqos->gpio_phy_intr_redirect)) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa.c index fc6a346a4b7f..48285bb179a8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ipa.c @@ -1046,6 +1046,7 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, int stat = NET_RX_SUCCESS; struct platform_device *pdev; struct net_device *dev; + struct stmmac_priv *pdata; if (!ethqos || !skb) { ETHQOSERR("Null Param pdata %p skb %pK\n", ethqos, skb); @@ -1065,6 +1066,7 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, pdev = ethqos->pdev; dev = platform_get_drvdata(pdev); + pdata = netdev_priv(dev); if (evt == IPA_RECEIVE) { /*Exception packets to network stack*/ @@ -1075,6 +1077,8 @@ static void ntn_ipa_notify_cb(void *priv, enum ipa_dp_evt_type evt, skb->protocol = htons(ETH_P_IP); iph = (struct iphdr *)skb->data; } else { + if (ethqos->current_loopback > DISABLE_LOOPBACK) + swap_ip_port(skb, ETH_P_IP); skb->protocol = eth_type_trans(skb, skb->dev); iph = (struct iphdr *)(skb_mac_header(skb) + ETH_HLEN); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c index 08dd6a06ac58..74233c10537a 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c @@ -176,6 +176,9 @@ static void dwmac1000_set_filter(struct mac_device_info *hw, value = GMAC_FRAME_FILTER_PR; } else if (dev->flags & IFF_ALLMULTI) { value = GMAC_FRAME_FILTER_PM; /* pass all multi */ + } else if (!netdev_mc_empty(dev) && (mcbitslog2 == 0)) { + /* Fall back to all multicast if we've no filter */ + value = GMAC_FRAME_FILTER_PM; } else if (!netdev_mc_empty(dev)) { struct netdev_hw_addr *ha; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h index 0b2b4cbb26cc..52cdaa9c0c02 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h @@ -33,6 +33,10 @@ #include #endif #include "dwmac-qcom-ipa-offload.h" +#include +#include +#include +#include struct stmmac_resources { void __iomem *addr; @@ -149,6 +153,7 @@ struct stmmac_priv { void __iomem *ptpaddr; u32 mss; bool boot_kpi; + int current_loopback; #ifdef CONFIG_DEBUG_FS struct dentry *dbgfs_dir; struct dentry *dbgfs_rings_status; @@ -175,6 +180,8 @@ extern struct stmmac_emb_smmu_cb_ctx stmmac_emb_smmu_ctx; #define MICREL_PHY_ID 0x00221620 +#define MMC_CONFIG 0x24 + int ethqos_handle_prv_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); int ethqos_init_pps(struct stmmac_priv *priv); @@ -198,5 +205,7 @@ int stmmac_dvr_probe(struct device *device, void stmmac_disable_eee_mode(struct stmmac_priv *priv); bool stmmac_eee_init(struct stmmac_priv *priv); bool qcom_ethqos_ipa_enabled(void); - +u16 icmp_fast_csum(u16 old_csum); +void swap_ip_port(struct sk_buff *skb, unsigned int eth_type); +unsigned int dwmac_qcom_get_eth_type(unsigned char *buf); #endif /* __STMMAC_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c index 8875bfcdde16..9057ef572cf6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c @@ -544,6 +544,9 @@ static void stmmac_get_ethtool_stats(struct net_device *dev, u32 tx_queues_count = priv->plat->tx_queues_to_use; int i, j = 0; + /* enable reset on read for mmc counter */ + writel_relaxed(MMC_CONFIG, priv->mmcaddr); + /* Update the DMA HW counters for dwmac10/100 */ if (priv->hw->dma->dma_diagnostic_fr) priv->hw->dma->dma_diagnostic_fr(&dev->stats, @@ -647,6 +650,10 @@ static int stmmac_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) u32 emac_wol_support = 0; int ret; + if (ethqos->phy_state == PHY_IS_OFF) { + ETHQOSINFO("Phy is in off state Wol set not possible\n"); + return -EOPNOTSUPP; + } /* By default almost all GMAC devices support the WoL via * magic frame but we can disable it if the HW capability * register shows no support for pmt_magic_frame. */ diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index e23cf61e8479..85a4214f8e9c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -3519,6 +3519,47 @@ static inline void stmmac_rx_refill(struct stmmac_priv *priv, u32 queue) rx_q->dirty_rx = entry; } +static u16 csum(u16 old_csum) +{ + u16 new_checksum = 0; + + new_checksum = ~(~old_csum + (-8) + 0); + return new_checksum; +} + +void swap_ip_port(struct sk_buff *skb, unsigned int eth_type) +{ + __be32 temp_addr; + unsigned char *buf = skb->data; + struct icmphdr *icmp_hdr; + unsigned char eth_temp[ETH_ALEN] = {}; + struct ethhdr *eth = (struct ethhdr *)(buf); + struct iphdr *ip_header; + + if (eth_type == ETH_P_IP) { + ip_header = (struct iphdr *)(buf + sizeof(struct ethhdr)); + if (ip_header->protocol == IPPROTO_UDP || + ip_header->protocol == IPPROTO_ICMP) { + //swap mac address + memcpy(eth_temp, eth->h_dest, ETH_ALEN); + memcpy(eth->h_dest, eth->h_source, ETH_ALEN); + memcpy(eth->h_source, eth_temp, ETH_ALEN); + //swap ip address + temp_addr = ip_header->daddr; + ip_header->daddr = ip_header->saddr; + ip_header->saddr = temp_addr; + + icmp_hdr = (struct icmphdr *)(buf + + sizeof(struct ethhdr) + + sizeof(struct iphdr)); + if (icmp_hdr->type == ICMP_ECHO) { + icmp_hdr->type = ICMP_ECHOREPLY; + icmp_hdr->checksum = csum(icmp_hdr->checksum); + } + } + } +} + /** * stmmac_rx - manage the receive process * @priv: driver private structure @@ -3533,6 +3574,9 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) int coe = priv->hw->rx_csum; unsigned int next_entry = rx_q->cur_rx; unsigned int count = 0; +#ifndef CONFIG_ETH_IPA_OFFLOAD + unsigned int eth_type; +#endif if (netif_msg_rx_status(priv)) { void *rx_head; @@ -3707,7 +3751,13 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) stmmac_get_rx_hwtstamp(priv, p, np, skb); stmmac_rx_vlan(priv->dev, skb); +#ifndef CONFIG_ETH_IPA_OFFLOAD + eth_type = dwmac_qcom_get_eth_type(skb->data); + if (priv->current_loopback > 0 && + eth_type == ETH_P_IP) + swap_ip_port(skb, eth_type); +#endif skb->protocol = eth_type_trans(skb, priv->dev); if (unlikely(!coe)) diff --git a/drivers/net/ethernet/toshiba/spider_net.c b/drivers/net/ethernet/toshiba/spider_net.c index da136b8843dd..a0fed9035f53 100644 --- a/drivers/net/ethernet/toshiba/spider_net.c +++ b/drivers/net/ethernet/toshiba/spider_net.c @@ -296,8 +296,8 @@ spider_net_free_chain(struct spider_net_card *card, descr = descr->next; } while (descr != chain->ring); - dma_free_coherent(&card->pdev->dev, chain->num_desc, - chain->hwring, chain->dma_addr); + dma_free_coherent(&card->pdev->dev, chain->num_desc * sizeof(struct spider_net_hw_descr), + chain->hwring, chain->dma_addr); } /** diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 14451e14d99d..10c3480c2da8 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c @@ -532,12 +532,13 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) u32 hash; struct hv_page_buffer pb[MAX_PAGE_BUFFER_COUNT]; - /* if VF is present and up then redirect packets - * already called with rcu_read_lock_bh + /* If VF is present and up then redirect packets to it. + * Skip the VF if it is marked down or has no carrier. + * If netpoll is in uses, then VF can not be used either. */ vf_netdev = rcu_dereference_bh(net_device_ctx->vf_netdev); if (vf_netdev && netif_running(vf_netdev) && - !netpoll_tx_running(net)) + netif_carrier_ok(vf_netdev) && !netpoll_tx_running(net)) return netvsc_vf_xmit(net, vf_netdev, skb); /* We will atmost need two pages to describe the rndis diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 7988c41bff1d..0e3d13e192e3 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2272,12 +2272,14 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, minor = get_free_serial_index(); if (minor < 0) - goto exit; + goto exit2; /* register our minor number */ serial->parent->dev = tty_port_register_device_attr(&serial->port, tty_drv, minor, &serial->parent->interface->dev, serial->parent, hso_serial_dev_groups); + if (IS_ERR(serial->parent->dev)) + goto exit2; dev = serial->parent->dev; /* fill in specific data for later use */ @@ -2323,6 +2325,7 @@ static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, return 0; exit: hso_serial_tty_unregister(serial); +exit2: hso_serial_common_free(serial); return -1; } diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c index 17a571a32fab..037b3153bffc 100644 --- a/drivers/net/usb/lan78xx.c +++ b/drivers/net/usb/lan78xx.c @@ -363,10 +363,6 @@ struct lan78xx_net { struct tasklet_struct bh; struct delayed_work wq; - struct usb_host_endpoint *ep_blkin; - struct usb_host_endpoint *ep_blkout; - struct usb_host_endpoint *ep_intr; - int msg_enable; struct urb *urb_intr; @@ -2749,78 +2745,12 @@ lan78xx_start_xmit(struct sk_buff *skb, struct net_device *net) return NETDEV_TX_OK; } -static int -lan78xx_get_endpoints(struct lan78xx_net *dev, struct usb_interface *intf) -{ - int tmp; - struct usb_host_interface *alt = NULL; - struct usb_host_endpoint *in = NULL, *out = NULL; - struct usb_host_endpoint *status = NULL; - - for (tmp = 0; tmp < intf->num_altsetting; tmp++) { - unsigned ep; - - in = NULL; - out = NULL; - status = NULL; - alt = intf->altsetting + tmp; - - for (ep = 0; ep < alt->desc.bNumEndpoints; ep++) { - struct usb_host_endpoint *e; - int intr = 0; - - e = alt->endpoint + ep; - switch (e->desc.bmAttributes) { - case USB_ENDPOINT_XFER_INT: - if (!usb_endpoint_dir_in(&e->desc)) - continue; - intr = 1; - /* FALLTHROUGH */ - case USB_ENDPOINT_XFER_BULK: - break; - default: - continue; - } - if (usb_endpoint_dir_in(&e->desc)) { - if (!intr && !in) - in = e; - else if (intr && !status) - status = e; - } else { - if (!out) - out = e; - } - } - if (in && out) - break; - } - if (!alt || !in || !out) - return -EINVAL; - - dev->pipe_in = usb_rcvbulkpipe(dev->udev, - in->desc.bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - dev->pipe_out = usb_sndbulkpipe(dev->udev, - out->desc.bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - dev->ep_intr = status; - - return 0; -} - static int lan78xx_bind(struct lan78xx_net *dev, struct usb_interface *intf) { struct lan78xx_priv *pdata = NULL; int ret; int i; - ret = lan78xx_get_endpoints(dev, intf); - if (ret) { - netdev_warn(dev->net, "lan78xx_get_endpoints failed: %d\n", - ret); - return ret; - } - dev->data[0] = (unsigned long)kzalloc(sizeof(*pdata), GFP_KERNEL); pdata = (struct lan78xx_priv *)(dev->data[0]); @@ -3565,6 +3495,7 @@ static void lan78xx_stat_monitor(unsigned long param) static int lan78xx_probe(struct usb_interface *intf, const struct usb_device_id *id) { + struct usb_host_endpoint *ep_blkin, *ep_blkout, *ep_intr; struct lan78xx_net *dev; struct net_device *netdev; struct usb_device *udev; @@ -3615,6 +3546,34 @@ static int lan78xx_probe(struct usb_interface *intf, mutex_init(&dev->stats.access_lock); + if (intf->cur_altsetting->desc.bNumEndpoints < 3) { + ret = -ENODEV; + goto out2; + } + + dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE); + ep_blkin = usb_pipe_endpoint(udev, dev->pipe_in); + if (!ep_blkin || !usb_endpoint_is_bulk_in(&ep_blkin->desc)) { + ret = -ENODEV; + goto out2; + } + + dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE); + ep_blkout = usb_pipe_endpoint(udev, dev->pipe_out); + if (!ep_blkout || !usb_endpoint_is_bulk_out(&ep_blkout->desc)) { + ret = -ENODEV; + goto out2; + } + + ep_intr = &intf->cur_altsetting->endpoint[2]; + if (!usb_endpoint_is_int_in(&ep_intr->desc)) { + ret = -ENODEV; + goto out2; + } + + dev->pipe_intr = usb_rcvintpipe(dev->udev, + usb_endpoint_num(&ep_intr->desc)); + ret = lan78xx_bind(dev, intf); if (ret < 0) goto out2; @@ -3626,23 +3585,7 @@ static int lan78xx_probe(struct usb_interface *intf, netdev->max_mtu = MAX_SINGLE_PACKET_SIZE; netif_set_gso_max_size(netdev, MAX_SINGLE_PACKET_SIZE - MAX_HEADER); - if (intf->cur_altsetting->desc.bNumEndpoints < 3) { - ret = -ENODEV; - goto out3; - } - - dev->ep_blkin = (intf->cur_altsetting)->endpoint + 0; - dev->ep_blkout = (intf->cur_altsetting)->endpoint + 1; - dev->ep_intr = (intf->cur_altsetting)->endpoint + 2; - - dev->pipe_in = usb_rcvbulkpipe(udev, BULK_IN_PIPE); - dev->pipe_out = usb_sndbulkpipe(udev, BULK_OUT_PIPE); - - dev->pipe_intr = usb_rcvintpipe(dev->udev, - dev->ep_intr->desc.bEndpointAddress & - USB_ENDPOINT_NUMBER_MASK); - period = dev->ep_intr->desc.bInterval; - + period = ep_intr->desc.bInterval; maxp = usb_maxpacket(dev->udev, dev->pipe_intr, 0); buf = kmalloc(maxp, GFP_KERNEL); if (buf) { diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index afdc2c290fd0..82efa5bbf568 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -974,6 +974,7 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, for (h = 0; h < FDB_HASH_SIZE; ++h) { struct vxlan_fdb *f; + rcu_read_lock(); hlist_for_each_entry_rcu(f, &vxlan->fdb_head[h], hlist) { struct vxlan_rdst *rd; @@ -986,12 +987,15 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, cb->nlh->nlmsg_seq, RTM_NEWNEIGH, NLM_F_MULTI, rd); - if (err < 0) + if (err < 0) { + rcu_read_unlock(); goto out; + } skip: *idx += 1; } } + rcu_read_unlock(); } out: return err; @@ -2218,7 +2222,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, skb_dst_update_pmtu(skb, mtu); } - tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); + tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); err = vxlan_build_skb(skb, ndst, sizeof(struct iphdr), vni, md, flags, udp_sum); @@ -2259,7 +2263,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, skb_dst_update_pmtu(skb, mtu); } - tos = ip_tunnel_ecn_encap(RT_TOS(tos), old_iph, skb); + tos = ip_tunnel_ecn_encap(tos, old_iph, skb); ttl = ttl ? : ip6_dst_hoplimit(ndst); skb_scrub_packet(skb, xnet); err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr), diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index ac34257e9f20..c94dfa70f2a3 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -160,6 +160,12 @@ static netdev_tx_t lapbeth_xmit(struct sk_buff *skb, if (!netif_running(dev)) goto drop; + /* There should be a pseudo header of 1 byte added by upper layers. + * Check to make sure it is there before reading it. + */ + if (skb->len < 1) + goto drop; + switch (skb->data[0]) { case X25_IFACE_DATA: break; @@ -308,6 +314,7 @@ static void lapbeth_setup(struct net_device *dev) dev->netdev_ops = &lapbeth_netdev_ops; dev->needs_free_netdev = true; dev->type = ARPHRD_X25; + dev->hard_header_len = 0; dev->mtu = 1000; dev->addr_len = 0; } @@ -334,7 +341,8 @@ static int lapbeth_new_device(struct net_device *dev) * then this driver prepends a length field of 2 bytes, * then the underlying Ethernet device prepends its own header. */ - ndev->hard_header_len = -1 + 3 + 2 + dev->hard_header_len; + ndev->needed_headroom = -1 + 3 + 2 + dev->hard_header_len + + dev->needed_headroom; lapbeth = netdev_priv(ndev); lapbeth->axdev = ndev; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index a920660a114a..e9017d8894a8 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -8020,6 +8020,20 @@ static const struct ieee80211_iface_limit ath10k_tlv_if_limit_ibss[] = { }, }; +static const struct ieee80211_iface_limit ath10k_tlv_if_vap_limit[] = { + { + .max = 1, + .types = BIT(NL80211_IFTYPE_STATION), + }, + { + .max = 3, + .types = BIT(NL80211_IFTYPE_AP) +#ifdef CONFIG_MAC80211_MESH + | BIT(NL80211_IFTYPE_MESH_POINT) +#endif + }, +}; + /* FIXME: This is not thouroughly tested. These combinations may over- or * underestimate hw/fw capabilities. */ @@ -8036,6 +8050,14 @@ static struct ieee80211_iface_combination ath10k_tlv_if_comb[] = { .max_interfaces = 2, .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit_ibss), }, + { + .limits = ath10k_tlv_if_vap_limit, + .num_different_channels = 1, + .max_interfaces = 4, + .beacon_int_infra_match = true, + .beacon_int_min_gcd = 1, + .n_limits = ARRAY_SIZE(ath10k_tlv_if_vap_limit), + }, }; static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = { @@ -8057,6 +8079,12 @@ static struct ieee80211_iface_combination ath10k_tlv_qcs_if_comb[] = { .max_interfaces = 2, .n_limits = ARRAY_SIZE(ath10k_tlv_if_limit_ibss), }, + { + .limits = ath10k_tlv_if_vap_limit, + .num_different_channels = 1, + .max_interfaces = 4, + .n_limits = ARRAY_SIZE(ath10k_tlv_if_vap_limit), + }, }; static const struct ieee80211_iface_limit ath10k_10_4_if_limits[] = { diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 39eba6d6db3d..7c104ee0da7f 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2005-2011 Atheros Communications Inc. * Copyright (c) 2011-2017 Qualcomm Atheros, Inc. - * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -1579,7 +1579,7 @@ static struct sk_buff *ath10k_wmi_tlv_op_gen_init(struct ath10k *ar) cfg->max_frag_entries = __cpu_to_le32(2); cfg->num_tdls_vdevs = __cpu_to_le32(TARGET_TLV_NUM_TDLS_VDEVS); cfg->num_tdls_conn_table_entries = __cpu_to_le32(0x20); - cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(2); + cfg->beacon_tx_offload_max_vdev = __cpu_to_le32(3); cfg->num_multicast_filter_entries = __cpu_to_le32(5); cfg->num_wow_filters = __cpu_to_le32(ar->wow.max_num_patterns); cfg->num_keep_alive_pattern = __cpu_to_le32(6); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index e0d22fedb2b4..05bd636011ec 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h @@ -30,7 +30,7 @@ #define BRCMF_ARP_OL_PEER_AUTO_REPLY 0x00000008 #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */ -#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002 +#define BRCMF_BSS_RSSI_ON_CHANNEL 0x0004 #define BRCMF_STA_WME 0x00000002 /* WMM association */ #define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c index 2370060ef980..080733128489 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c @@ -653,6 +653,7 @@ static inline int brcmf_fws_hanger_poppkt(struct brcmf_fws_hanger *h, static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, int ifidx) { + struct brcmf_fws_hanger_item *hi; bool (*matchfn)(struct sk_buff *, void *) = NULL; struct sk_buff *skb; int prec; @@ -664,6 +665,9 @@ static void brcmf_fws_psq_flush(struct brcmf_fws_info *fws, struct pktq *q, skb = brcmu_pktq_pdeq_match(q, prec, matchfn, &ifidx); while (skb) { hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT); + hi = &fws->hanger.items[hslot]; + WARN_ON(skb != hi->pkt); + hi->state = BRCMF_FWS_HANGER_ITEM_STATE_FREE; brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true); brcmu_pkt_buf_free_skb(skb); diff --git a/drivers/net/wireless/cnss_utils/cnss_utils.c b/drivers/net/wireless/cnss_utils/cnss_utils.c index b3dfbb698019..296e444b63dd 100644 --- a/drivers/net/wireless/cnss_utils/cnss_utils.c +++ b/drivers/net/wireless/cnss_utils/cnss_utils.c @@ -31,7 +31,7 @@ #define LPASS_PMU_INT_EN0 0xC060084 #define LPASS_PMU_INT_CLR 0xC060034 #endif -#define CNSS_MAX_CH_NUM 45 +#define CNSS_MAX_CH_NUM 157 struct cnss_unsafe_channel_list { u16 unsafe_ch_count; u16 unsafe_ch_list[CNSS_MAX_CH_NUM]; diff --git a/drivers/net/wireless/intel/iwlegacy/common.c b/drivers/net/wireless/intel/iwlegacy/common.c index a77ec6ec80ac..41eabf6bdc6b 100644 --- a/drivers/net/wireless/intel/iwlegacy/common.c +++ b/drivers/net/wireless/intel/iwlegacy/common.c @@ -4302,8 +4302,8 @@ il_apm_init(struct il_priv *il) * power savings, even without L1. */ if (il->cfg->set_l0s) { - pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl); - if (lctl & PCI_EXP_LNKCTL_ASPM_L1) { + ret = pcie_capability_read_word(il->pci_dev, PCI_EXP_LNKCTL, &lctl); + if (!ret && (lctl & PCI_EXP_LNKCTL_ASPM_L1)) { /* L1-ASPM enabled; disable(!) L0S */ il_set_bit(il, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); diff --git a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c index 0fba5b10ef2d..19ce279df24d 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_cmdresp.c @@ -585,6 +585,11 @@ static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv, { struct host_cmd_ds_802_11_key_material *key = &resp->params.key_material; + int len; + + len = le16_to_cpu(key->key_param_set.key_len); + if (len > sizeof(key->key_param_set.key)) + return -EINVAL; if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { @@ -598,9 +603,8 @@ static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv, memset(priv->aes_key.key_param_set.key, 0, sizeof(key->key_param_set.key)); - priv->aes_key.key_param_set.key_len = key->key_param_set.key_len; - memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, - le16_to_cpu(priv->aes_key.key_param_set.key_len)); + priv->aes_key.key_param_set.key_len = cpu_to_le16(len); + memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, len); return 0; } @@ -615,9 +619,14 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, struct host_cmd_ds_command *resp) { struct host_cmd_ds_802_11_key_material_v2 *key_v2; - __le16 len; + int len; key_v2 = &resp->params.key_material_v2; + + len = le16_to_cpu(key_v2->key_param_set.key_params.aes.key_len); + if (len > WLAN_KEY_LEN_CCMP) + return -EINVAL; + if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) { if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) { mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n"); @@ -633,10 +642,9 @@ static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0, WLAN_KEY_LEN_CCMP); priv->aes_key_v2.key_param_set.key_params.aes.key_len = - key_v2->key_param_set.key_params.aes.key_len; - len = priv->aes_key_v2.key_param_set.key_params.aes.key_len; + cpu_to_le16(len); memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key, - key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len)); + key_v2->key_param_set.key_params.aes.key, len); return 0; } diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c index f5acd24d0e2b..988abb49771f 100644 --- a/drivers/net/wireless/ti/wl1251/event.c +++ b/drivers/net/wireless/ti/wl1251/event.c @@ -84,7 +84,7 @@ static int wl1251_event_ps_report(struct wl1251 *wl, break; } - return 0; + return ret; } static void wl1251_event_mbox_dump(struct event_mailbox *mbox) diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 5468490d2298..55b3274328eb 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1291,7 +1291,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** (one that doesn't overlap memory or LMMIO space) in the ** IBASE and IMASK registers. */ - ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE); + ioc->ibase = READ_REG(ioc->ioc_hpa + IOC_IBASE) & ~0x1fffffULL; iova_space_size = ~(READ_REG(ioc->ioc_hpa + IOC_IMASK) & 0xFFFFFFFFUL) + 1; if ((ioc->ibase < 0xfed00000UL) && ((ioc->ibase + iova_space_size) > 0xfee00000UL)) { diff --git a/drivers/pci/access.c b/drivers/pci/access.c index 913d6722ece9..8c585e7ca520 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -205,17 +205,13 @@ EXPORT_SYMBOL(pci_bus_set_ops); static DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait); static noinline void pci_wait_cfg(struct pci_dev *dev) + __must_hold(&pci_lock) { - DECLARE_WAITQUEUE(wait, current); - - __add_wait_queue(&pci_cfg_wait, &wait); do { - set_current_state(TASK_UNINTERRUPTIBLE); raw_spin_unlock_irq(&pci_lock); - schedule(); + wait_event(pci_cfg_wait, !dev->block_cfg_access); raw_spin_lock_irq(&pci_lock); } while (dev->block_cfg_access); - __remove_wait_queue(&pci_cfg_wait, &wait); } /* Returns 0 on success, negative values indicate error. */ diff --git a/drivers/pci/host/vmd.c b/drivers/pci/host/vmd.c index 05f191ae0ff1..79d56638878c 100644 --- a/drivers/pci/host/vmd.c +++ b/drivers/pci/host/vmd.c @@ -651,6 +651,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd) if (!vmd->bus) { pci_free_resource_list(&resources); irq_domain_remove(vmd->irq_domain); + irq_domain_free_fwnode(fn); return -ENODEV; } @@ -753,6 +754,7 @@ static void vmd_cleanup_srcu(struct vmd_dev *vmd) static void vmd_remove(struct pci_dev *dev) { struct vmd_dev *vmd = pci_get_drvdata(dev); + struct fwnode_handle *fn = vmd->irq_domain->fwnode; sysfs_remove_link(&vmd->dev->dev.kobj, "domain"); pci_stop_root_bus(vmd->bus); @@ -761,6 +763,7 @@ static void vmd_remove(struct pci_dev *dev) vmd_teardown_dma_ops(vmd); vmd_detach_resources(vmd); irq_domain_remove(vmd->irq_domain); + irq_domain_free_fwnode(fn); } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index 711875afdd70..f2c1008e0f76 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c @@ -136,13 +136,21 @@ static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev) struct acpiphp_context *context; acpi_lock_hp_context(); + context = acpiphp_get_context(adev); - if (!context || context->func.parent->is_going_away) { - acpi_unlock_hp_context(); - return NULL; + if (!context) + goto unlock; + + if (context->func.parent->is_going_away) { + acpiphp_put_context(context); + context = NULL; + goto unlock; } + get_bridge(context->func.parent); acpiphp_put_context(context); + +unlock: acpi_unlock_hp_context(); return context; } diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index 13bb1d5a4b49..7ba35a6b9398 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c @@ -1112,6 +1112,7 @@ static int pcie_aspm_get_policy(char *buffer, const struct kernel_param *kp) cnt += sprintf(buffer + cnt, "[%s] ", policy_str[i]); else cnt += sprintf(buffer + cnt, "%s ", policy_str[i]); + cnt += sprintf(buffer + cnt, "\n"); return cnt; } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 0eb863e15b18..11e5a14b6470 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4307,6 +4307,8 @@ static int pci_quirk_amd_sb_acs(struct pci_dev *dev, u16 acs_flags) if (ACPI_FAILURE(status)) return -ENODEV; + acpi_put_table(header); + /* Filter out flags not applicable to multifunction */ acs_flags &= (PCI_ACS_RR | PCI_ACS_CR | PCI_ACS_EC | PCI_ACS_DT); diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index 7c00775af758..fe114f079483 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c @@ -888,7 +888,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, /* If pinconf isn't supported, don't parse properties in below. */ if (!PCS_HAS_PINCONF) - return 0; + return -ENOTSUPP; /* cacluate how much properties are supported in current node */ for (i = 0; i < ARRAY_SIZE(prop2); i++) { @@ -900,7 +900,7 @@ static int pcs_parse_pinconf(struct pcs_device *pcs, struct device_node *np, nconfs++; } if (!nconfs) - return 0; + return -ENOTSUPP; func->conf = devm_kcalloc(pcs->dev, nconfs, sizeof(struct pcs_conf_vals), @@ -1024,9 +1024,12 @@ static int pcs_parse_one_pinctrl_entry(struct pcs_device *pcs, if (PCS_HAS_PINCONF) { res = pcs_parse_pinconf(pcs, np, function, map); - if (res) + if (res == 0) + *num_maps = 2; + else if (res == -ENOTSUPP) + *num_maps = 1; + else goto free_pingroups; - *num_maps = 2; } else { *num_maps = 1; } diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h index 4d3b594b8659..0eb76b2f1b3c 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h +++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h @@ -385,7 +385,6 @@ struct ep_pcie_dev_t { bool config_mmio_init; bool enumerated; enum ep_pcie_link_status link_status; - bool perst_deast; bool power_on; bool suspending; bool l23_ready; @@ -393,6 +392,8 @@ struct ep_pcie_dev_t { struct ep_pcie_msi_config msi_cfg; bool no_notify; bool client_ready; + atomic_t ep_pcie_dev_wake; + atomic_t perst_deast; struct ep_pcie_register_event *event_reg; struct work_struct handle_perst_work; diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c index 61c6e12c99e0..a3573189f65e 100644 --- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c +++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c @@ -1805,7 +1805,7 @@ int ep_pcie_core_enable_endpoint(enum ep_pcie_options opt) ret = EP_PCIE_ERROR; goto link_fail; } else { - dev->perst_deast = true; + atomic_set(&dev->perst_deast, 1); if (opt & EP_PCIE_OPT_AST_WAKE) { /* deassert PCIe WAKE# */ EP_PCIE_DBG(dev, @@ -1969,11 +1969,19 @@ out: int ep_pcie_core_disable_endpoint(void) { int rc = 0; + u32 val = 0; + unsigned long irqsave_flags; struct ep_pcie_dev_t *dev = &ep_pcie_dev; EP_PCIE_DBG(dev, "PCIe V%d\n", dev->rev); mutex_lock(&dev->setup_mtx); + if (atomic_read(&dev->perst_deast)) { + EP_PCIE_DBG(dev, + "PCIe V%d: PERST is de-asserted, exiting disable\n", + dev->rev); + goto out; + } if (!dev->power_on) { EP_PCIE_DBG(dev, @@ -1990,9 +1998,25 @@ int ep_pcie_core_disable_endpoint(void) dev->rev); } + val = readl_relaxed(dev->elbi + PCIE20_ELBI_SYS_STTS); + EP_PCIE_DBG(dev, "PCIe V%d: LTSSM_STATE during disable:0x%x\n", + dev->rev, (val >> 0xC) & 0x3f); ep_pcie_pipe_clk_deinit(dev); ep_pcie_clk_deinit(dev); ep_pcie_vreg_deinit(dev); + + spin_lock_irqsave(&dev->isr_lock, irqsave_flags); + if (atomic_read(&dev->ep_pcie_dev_wake) && + !atomic_read(&dev->perst_deast)) { + EP_PCIE_DBG(dev, "PCIe V%d: Released wakelock\n", dev->rev); + atomic_set(&dev->ep_pcie_dev_wake, 0); + pm_relax(&dev->pdev->dev); + } else { + EP_PCIE_DBG(dev, "PCIe V%d: Bail, Perst-assert:%d wake:%d\n", + dev->rev, atomic_read(&dev->perst_deast), + atomic_read(&dev->ep_pcie_dev_wake)); + } + spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); out: mutex_unlock(&dev->setup_mtx); return rc; @@ -2249,12 +2273,25 @@ static void handle_d3cold_func(struct work_struct *work) { struct ep_pcie_dev_t *dev = container_of(work, struct ep_pcie_dev_t, handle_d3cold_work); + unsigned long irqsave_flags; EP_PCIE_DBG(dev, "PCIe V%d: shutdown PCIe link due to PERST assertion before BME is set\n", dev->rev); ep_pcie_core_disable_endpoint(); dev->no_notify = false; + spin_lock_irqsave(&dev->isr_lock, irqsave_flags); + if (atomic_read(&dev->ep_pcie_dev_wake) && + !atomic_read(&dev->perst_deast)) { + atomic_set(&dev->ep_pcie_dev_wake, 0); + pm_relax(&dev->pdev->dev); + EP_PCIE_DBG(dev, "PCIe V%d: Released wakelock\n", dev->rev); + } else { + EP_PCIE_DBG(dev, "PCIe V%d: Bail, Perst-assert:%d wake:%d\n", + dev->rev, atomic_read(&dev->perst_deast), + atomic_read(&dev->ep_pcie_dev_wake)); + } + spin_unlock_irqrestore(&dev->isr_lock, irqsave_flags); } static void handle_bme_func(struct work_struct *work) @@ -2292,14 +2329,24 @@ static irqreturn_t ep_pcie_handle_perst_irq(int irq, void *data) } if (perst) { - dev->perst_deast = true; + atomic_set(&dev->perst_deast, 1); dev->perst_deast_counter++; + /* + * Hold a wakelock to avoid missing BME and other + * interrupts if apps goes into suspend before BME is set. + */ + if (!atomic_read(&dev->ep_pcie_dev_wake)) { + pm_stay_awake(&dev->pdev->dev); + atomic_set(&dev->ep_pcie_dev_wake, 1); + EP_PCIE_DBG(dev, "PCIe V%d: Acquired wakelock\n", + dev->rev); + } EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST deassertion\n", dev->rev, dev->perst_deast_counter); ep_pcie_notify_event(dev, EP_PCIE_EVENT_PM_RST_DEAST); } else { - dev->perst_deast = false; + atomic_set(&dev->perst_deast, 0); dev->perst_ast_counter++; EP_PCIE_DBG(dev, "PCIe V%d: No. %ld PERST assertion\n", @@ -2550,14 +2597,15 @@ perst_irq: * based on the next expected level of the gpio */ if (gpio_get_value(dev->gpio[EP_PCIE_GPIO_PERST].num) == 1) - dev->perst_deast = true; + atomic_set(&dev->perst_deast, 1); /* register handler for PERST interrupt */ perst_irq = gpio_to_irq(dev->gpio[EP_PCIE_GPIO_PERST].num); ret = devm_request_irq(pdev, perst_irq, ep_pcie_handle_perst_irq, - ((dev->perst_deast ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) - | IRQF_EARLY_RESUME), + ((atomic_read(&dev->perst_deast) ? + IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH) + | IRQF_EARLY_RESUME), "ep_pcie_perst", dev); if (ret) { EP_PCIE_ERR(dev, @@ -2951,7 +2999,7 @@ static int ep_pcie_core_wakeup_host(enum ep_pcie_event event) if (event == EP_PCIE_EVENT_PM_D3_HOT) ep_pcie_core_issue_inband_pme(); - if (dev->perst_deast && !dev->l23_ready) { + if (atomic_read(&dev->perst_deast) && !dev->l23_ready) { EP_PCIE_ERR(dev, "PCIe V%d: request to assert WAKE# when PERST is de-asserted and D3hot is not received\n", dev->rev); @@ -2962,7 +3010,7 @@ static int ep_pcie_core_wakeup_host(enum ep_pcie_event event) EP_PCIE_DBG(dev, "PCIe V%d: No. %ld to assert PCIe WAKE#; perst is %s de-asserted; D3hot is %s received\n", dev->rev, dev->wake_counter, - dev->perst_deast ? "" : "not", + atomic_read(&dev->perst_deast) ? "" : "not", dev->l23_ready ? "" : "not"); /* * Assert WAKE# GPIO until link is back to L0. @@ -3217,6 +3265,14 @@ static int ep_pcie_probe(struct platform_device *pdev) goto irq_failure; } + /* + * Wakelock is needed to avoid missing BME and other + * interrupts if apps goes into suspend before host + * sets them. + */ + device_init_wakeup(&ep_pcie_dev.pdev->dev, true); + atomic_set(&ep_pcie_dev.ep_pcie_dev_wake, 0); + if (ep_pcie_dev.perst_enum && !gpio_get_value(ep_pcie_dev.gpio[EP_PCIE_GPIO_PERST].num)) { EP_PCIE_DBG2(&ep_pcie_dev, diff --git a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c index 0199f038ebcb..2bf6185b5964 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c +++ b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -650,7 +650,8 @@ static netdev_tx_t ecm_ipa_start_xmit fail_tx_packet: out: - resource_release(ecm_ipa_ctx); + if (atomic_read(&ecm_ipa_ctx->outstanding_pkts) == 0) + resource_release(ecm_ipa_ctx); resource_busy: return status; } @@ -1322,6 +1323,9 @@ static void ecm_ipa_tx_complete_notify netif_wake_queue(ecm_ipa_ctx->net); } + if (atomic_read(&ecm_ipa_ctx->outstanding_pkts) == 0) + resource_release(ecm_ipa_ctx); + out: dev_kfree_skb_any(skb); } diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c index 7090b63f4cc3..67ed1fd76347 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_uc_offload.c @@ -540,20 +540,16 @@ int ipa_uc_ntn_conn_pipes(struct ipa_ntn_conn_in_params *inp, goto fail; } - if (ntn_ctx->conn.dl.smmu_enabled) { - result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.dl, - &inp->dl); - if (result) { - IPA_UC_OFFLOAD_ERR("alloc failure on TX\n"); - goto fail; - } - result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.ul, - &inp->ul); - if (result) { - ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl); - IPA_UC_OFFLOAD_ERR("alloc failure on RX\n"); - goto fail; - } + result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.dl, &inp->dl); + if (result) { + IPA_UC_OFFLOAD_ERR("alloc failure on TX\n"); + goto fail; + } + result = ipa_uc_ntn_alloc_conn_smmu_info(&ntn_ctx->conn.ul, &inp->ul); + if (result) { + ipa_uc_ntn_free_conn_smmu_info(&ntn_ctx->conn.dl); + IPA_UC_OFFLOAD_ERR("alloc failure on RX\n"); + goto fail; } fail: diff --git a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c index 9c0187f254df..e5df5e0c6bab 100644 --- a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c +++ b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2018,2020 The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -984,7 +984,8 @@ static netdev_tx_t rndis_ipa_start_xmit(struct sk_buff *skb, fail_tx_packet: rndis_ipa_xmit_error(skb); out: - resource_release(rndis_ipa_ctx); + if (atomic_read(&rndis_ipa_ctx->outstanding_pkts) == 0) + resource_release(rndis_ipa_ctx); resource_busy: RNDIS_IPA_DEBUG ("packet Tx done - %s\n", @@ -1057,6 +1058,10 @@ static void rndis_ipa_tx_complete_notify( RNDIS_IPA_DEBUG("send queue was awaken\n"); } + /*Release resource only when outstanding packets are zero*/ + if (atomic_read(&rndis_ipa_ctx->outstanding_pkts) == 0) + resource_release(rndis_ipa_ctx); + out: dev_kfree_skb_any(skb); } diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c index 8a64c5a6e7b1..71c7c6ffbad7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c +++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth.c @@ -571,9 +571,10 @@ static int ipa_eth_pm_notifier_event_suspend_prepare( * and reverts the device suspension by aborting the system suspend. */ if (ipa_eth_net_check_active(eth_dev)) { - pr_info("%s: %s is active, preventing suspend for some time", - IPA_ETH_SUBSYS, eth_dev->net_dev->name); - ipa_eth_dev_wakeup_event(eth_dev); + pr_info("%s: %s is active, preventing suspend for %u ms", + IPA_ETH_SUBSYS, eth_dev->net_dev->name, + IPA_ETH_WAKE_TIME_MS); + pm_wakeup_dev_event(eth_dev->dev, IPA_ETH_WAKE_TIME_MS, false); return NOTIFY_BAD; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h index f92da41cd7aa..2ffc31c27da7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_i.h @@ -35,8 +35,12 @@ #define IPA_ETH_IPC_LOGDBG_DEFAULT false #endif +/* Time to remain awake after a suspend abort due to NIC activity */ #define IPA_ETH_WAKE_TIME_MS 500 +/* Time for NIC HW to settle down (ex. receive link interrupt) after a resume */ +#define IPA_ETH_RESUME_SETTLE_MS 2000 + #define IPA_ETH_PFDEV (ipa3_ctx ? ipa3_ctx->pdev : NULL) #define IPA_ETH_SUBSYS "ipa_eth" @@ -161,9 +165,31 @@ extern bool ipa_eth_ipc_logdbg; bool ipa_eth_is_ready(void); bool ipa_eth_all_ready(void); -static inline void ipa_eth_dev_wakeup_event(struct ipa_eth_device *eth_dev) +static inline void ipa_eth_dev_assume_active_ms( + struct ipa_eth_device *eth_dev, + unsigned int msec) { - pm_wakeup_dev_event(eth_dev->dev, IPA_ETH_WAKE_TIME_MS, false); + eth_dev_priv(eth_dev)->assume_active += + DIV_ROUND_UP(msec, IPA_ETH_WAKE_TIME_MS); + pm_system_wakeup(); +} + +static inline void ipa_eth_dev_assume_active_inc( + struct ipa_eth_device *eth_dev, + unsigned int count) +{ + eth_dev_priv(eth_dev)->assume_active += count; + pm_system_wakeup(); +} + +static inline void ipa_eth_dev_assume_active_dec( + struct ipa_eth_device *eth_dev, + unsigned int count) +{ + if (eth_dev_priv(eth_dev)->assume_active > count) + eth_dev_priv(eth_dev)->assume_active -= count; + else + eth_dev_priv(eth_dev)->assume_active = 0; } struct ipa_eth_device *ipa_eth_alloc_device( diff --git a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c index 1095306b009f..80f4a80b7181 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c +++ b/drivers/platform/msm/ipa/ipa_v3/ethernet/ipa_eth_pci.c @@ -374,7 +374,7 @@ static int ipa_eth_pci_suspend_late_handler(struct device *dev) IPA_ETH_SUBSYS, eth_dev->net_dev->name); /* Have PM_SUSPEND_PREPARE give us one wakeup time quanta */ - eth_dev_priv(eth_dev)->assume_active++; + ipa_eth_dev_assume_active_inc(eth_dev, 1); return -EAGAIN; } @@ -428,8 +428,8 @@ static int ipa_eth_pci_resume_handler(struct device *dev) "Device resume delegated to net driver"); rc = eth_dev_pm_ops(eth_dev)->resume(dev); - /* Give some time after a resume for the device to settle */ - eth_dev_priv(eth_dev)->assume_active++; + /* Give some time for device to settle after a resume */ + ipa_eth_dev_assume_active_ms(eth_dev, IPA_ETH_RESUME_SETTLE_MS); } if (rc) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index d16590839e3c..72386cb1f5d8 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -1003,6 +1003,7 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) struct ipa_ioc_get_vlan_mode vlan_mode; struct ipa_ioc_wigig_fst_switch fst_switch; struct ipa_nat_in_sram_info nat_in_sram_info; + union ipa_ioc_uc_activation_entry uc_act; size_t sz; int pre_entry; int hdl; @@ -3052,6 +3053,39 @@ static long ipa3_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) } break; + case IPA_IOC_ADD_UC_ACT_ENTRY: + if (copy_from_user(&uc_act, (const void __user *)arg, + sizeof(union ipa_ioc_uc_activation_entry))) { + IPAERR_RL("copy_from_user fails\n"); + retval = -EFAULT; + break; + } + + /* first field in both structs is cmd id */ + if (uc_act.socks.cmd_id == IPA_SOCKSV5_ADD_COM_ID) { + retval = ipa3_add_socksv5_conn_usr(&uc_act.socks); + } else { + retval = ipa3_add_ipv6_nat_uc_activation_entry( + &uc_act.ipv6_nat); + } + if (retval) { + retval = -EFAULT; + break; + } + if (copy_to_user((void __user *)arg, &uc_act, + sizeof(union ipa_ioc_uc_activation_entry))) { + IPAERR_RL("copy_to_user fails\n"); + retval = -EFAULT; + break; + } + break; + case IPA_IOC_DEL_UC_ACT_ENTRY: + if (ipa3_del_uc_act_entry((uint16_t)arg)) { + retval = -EFAULT; + break; + } + break; + default: IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); return -ENOTTY; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 20911f34fd33..fa27d5263ea7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1543,6 +1543,7 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, struct gsi_chan_info ul_gsi_chan_info, dl_gsi_chan_info; int aggr_active_bitmap = 0; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; + struct ipa_ep_cfg_holb holb_cfg; /* In case of DPL, dl is the DPL channel/client */ @@ -1628,6 +1629,15 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, goto unsuspend_dl_and_exit; } + /*enable holb to discard the packets*/ + if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_5 && + IPA_CLIENT_IS_CONS(dl_ep->client) && !is_dpl) { + memset(&holb_cfg, 0, sizeof(holb_cfg)); + holb_cfg.en = IPA_HOLB_TMR_EN; + holb_cfg.tmr_val = IPA_HOLB_TMR_VAL_4_5; + result = ipa3_cfg_ep_holb(dl_clnt_hdl, &holb_cfg); + } + /* Stop DL channel */ result = ipa3_stop_gsi_channel(dl_clnt_hdl); if (result) { @@ -1657,6 +1667,14 @@ int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, start_dl_and_exit: gsi_start_channel(dl_ep->gsi_chan_hdl); ipa3_start_gsi_debug_monitor(dl_clnt_hdl); + /*disable holb to allow packets*/ + if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_5 && + IPA_CLIENT_IS_CONS(dl_ep->client) && !is_dpl) { + memset(&holb_cfg, 0, sizeof(holb_cfg)); + holb_cfg.en = IPA_HOLB_TMR_DIS; + holb_cfg.tmr_val = 0; + ipa3_cfg_ep_holb(dl_clnt_hdl, &holb_cfg); + } unsuspend_dl_and_exit: if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) { /* Unsuspend the DL EP */ @@ -1713,6 +1731,7 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) struct ipa3_ep_context *dl_ep = NULL; enum gsi_status gsi_res; struct ipa_ep_cfg_ctrl ep_cfg_ctrl; + struct ipa_ep_cfg_holb holb_cfg; /* In case of DPL, dl is the DPL channel/client */ @@ -1743,6 +1762,15 @@ int ipa3_xdci_resume(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool is_dpl) IPAERR("Error starting DL channel: %d\n", gsi_res); ipa3_start_gsi_debug_monitor(dl_clnt_hdl); + /*disable holb to allow packets*/ + if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_5 && + IPA_CLIENT_IS_CONS(dl_ep->client) && !is_dpl) { + memset(&holb_cfg, 0, sizeof(holb_cfg)); + holb_cfg.en = IPA_HOLB_TMR_DIS; + holb_cfg.tmr_val = 0; + ipa3_cfg_ep_holb(dl_clnt_hdl, &holb_cfg); + } + /* Start UL channel */ if (!is_dpl) { gsi_res = gsi_start_channel(ul_ep->gsi_chan_hdl); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index b09b69f20121..322aaa1c75ff 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -324,7 +324,7 @@ static ssize_t ipa3_read_ep_reg(struct file *file, char __user *ubuf, *ppos = pos; ret = simple_read_from_buffer(ubuf, count, ppos, dbg_buff, - nbytes); + nbytes); if (ret < 0) { IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); return ret; @@ -503,12 +503,12 @@ static int ipa3_attrib_dump(struct ipa_rule_attrib *attrib, if (attrib->attrib_mask & IPA_FLT_SRC_PORT_RANGE) { pr_err("src_port_range:%u %u ", attrib->src_port_lo, - attrib->src_port_hi); + attrib->src_port_hi); } if (attrib->attrib_mask & IPA_FLT_DST_PORT_RANGE) { pr_err("dst_port_range:%u %u ", attrib->dst_port_lo, - attrib->dst_port_hi); + attrib->dst_port_hi); } if (attrib->attrib_mask & IPA_FLT_TYPE) pr_err("type:%d ", attrib->type); @@ -2646,6 +2646,125 @@ static ssize_t ipa3_enable_ipc_low(struct file *file, return count; } +static ssize_t ipa3_read_uc_act_tbl(struct file *file, + char __user *ubuf, size_t count, loff_t *ppos) +{ + int nbytes; + int cnt = 0; + int i; + struct ipa_ipv6_nat_uc_tmpl *uc_entry_nat; + struct ipa_socksv5_uc_tmpl *uc_entry_socks; + struct iphdr_rsv *socks_iphdr; + struct ipv6hdr *socks_ipv6hdr; + + /* IPA version check */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) { + nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, + "This feature only support on IPA4.5+\n"); + cnt += nbytes; + goto done; + } + + if (!ipa3_ctx->uc_act_tbl_valid) { + IPAERR("uC act tbl wasn't allocated\n"); + return -ENOENT; + } + + if (sizeof(dbg_buff) < count + 1) + return -EFAULT; + + dbg_buff[count] = '\0'; + + mutex_lock(&ipa3_ctx->act_tbl_lock); + + uc_entry_nat = (struct ipa_ipv6_nat_uc_tmpl *) + (ipa3_ctx->uc_act_tbl.base); + nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, + "uc_act_tbl_total %d, uc_act_tbl_ipv6_nat_total %d uc_act_tbl_socksv5_total %d, uc_act_tbl_next_index %d\n" + "uC activation entries:" + , ipa3_ctx->uc_act_tbl_total, + ipa3_ctx->uc_act_tbl_ipv6_nat_total, + ipa3_ctx->uc_act_tbl_socksv5_total, + ipa3_ctx->uc_act_tbl_next_index); + cnt += nbytes; + for (i = 0; i < IPA_UC_ACT_TBL_SIZE; i++) { + if (uc_entry_nat[i].cmd_id == IPA_IPv6_NAT_COM_ID) { + nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN, + "\nentry %d:\n" + "cmd_id = IPV6_NAT\n" + "private_address_msb 0x%llX\n" + "private_address_lsb 0x%llX\n" + "private_port %u\n" + "public_address_msb 0x%llX\n" + "public_address_lsb 0x%llX\n" + "public_port %u\n", + i, + uc_entry_nat[i].private_address_msb, + uc_entry_nat[i].private_address_lsb, + uc_entry_nat[i].private_port, + uc_entry_nat[i].public_address_msb, + uc_entry_nat[i].public_address_lsb, + uc_entry_nat[i].public_port); + cnt += nbytes; + } else if (uc_entry_nat[i].cmd_id == IPA_SOCKSV5_ADD_COM_ID) { + uc_entry_socks = (struct ipa_socksv5_uc_tmpl *) + (uc_entry_nat); + nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN, + "\nentry %d:\n" + "cmd_id = SOCKSv5\n" + "cmd_param: %u\n" + "source_port: %u\n" + "dest_port: %u\n" + "ipa_socksv5_mask: %x\n", + i, + uc_entry_socks[i].cmd_param, + uc_entry_socks[i].src_port, + uc_entry_socks[i].dst_port, + uc_entry_socks[i].ipa_sockv5_mask); + cnt += nbytes; + + if (uc_entry_socks[i].cmd_param == + IPA_SOCKsv5_ADD_V6_V4_COM_PM) { + socks_iphdr = + &uc_entry_socks[i].ip_hdr.ipv4_rsv; + nbytes = scnprintf(dbg_buff + cnt, + IPA_MAX_MSG_LEN, + "ipv4_src_addr: 0x%X\n" + "ipv4_dst_addr: 0x%X\n", + socks_iphdr->ipv4_temp.saddr, + socks_iphdr->ipv4_temp.daddr); + cnt += nbytes; + } else { + socks_ipv6hdr = + &uc_entry_socks[i].ip_hdr.ipv6_temp; + nbytes = scnprintf(dbg_buff + cnt, + IPA_MAX_MSG_LEN, + "ipv6_src_addr[0]: 0x%X\n" + "ipv6_src_addr[1]: 0x%X\n" + "ipv6_src_addr[2]: 0x%X\n" + "ipv6_src_addr[3]: 0x%X\n" + "ipv6_dts_addr[0]: 0x%X\n" + "ipv6_dts_addr[1]: 0x%X\n" + "ipv6_dts_addr[2]: 0x%X\n" + "ipv6_dts_addr[3]: 0x%X\n", + socks_ipv6hdr->saddr.s6_addr32[0], + socks_ipv6hdr->saddr.s6_addr32[1], + socks_ipv6hdr->saddr.s6_addr32[2], + socks_ipv6hdr->saddr.s6_addr32[3], + socks_ipv6hdr->daddr.s6_addr32[0], + socks_ipv6hdr->daddr.s6_addr32[1], + socks_ipv6hdr->daddr.s6_addr32[2], + socks_ipv6hdr->daddr.s6_addr32[3]); + cnt += nbytes; + } + } + } + mutex_unlock(&ipa3_ctx->act_tbl_lock); +done: + return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt); + +} + static const struct ipa3_debugfs_file debugfs_files[] = { { "gen_reg", IPA_READ_ONLY_MODE, NULL, { @@ -2811,7 +2930,11 @@ static const struct ipa3_debugfs_file debugfs_files[] = { "app_clk_vote_cnt", IPA_READ_ONLY_MODE, NULL, { .read = ipa3_read_app_clk_vote, } - }, + }, { + "uc_act_table", IPA_READ_ONLY_MODE, NULL, { + .read = ipa3_read_uc_act_tbl, + } + } }; void ipa3_debugfs_pre_init(void) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index c2c6aa896859..9ea2adcd2ba3 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -2022,6 +2022,8 @@ struct ipa3_context { bool uc_act_tbl_valid; struct mutex act_tbl_lock; int uc_act_tbl_total; + int uc_act_tbl_socksv5_total; + int uc_act_tbl_ipv6_nat_total; int uc_act_tbl_next_index; bool manual_fw_load; }; @@ -2419,6 +2421,15 @@ int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info); int ipa3_del_socksv5_conn(uint32_t handle); +int ipa3_add_socksv5_conn_usr(struct ipa_kernel_tests_socksv5_uc_tmpl *tmpl); + +int ipa3_add_ipv6_nat_uc_activation_entry( + struct ipa_ioc_ipv6_nat_uc_act_entry *entry); + +int ipa3_del_ipv6_nat_uc_activation_entry(uint16_t index); + +int ipa3_del_uc_act_entry(uint16_t index); + /* * Header removal / addition */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c index 384a06520911..c0a0d1150060 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c @@ -627,7 +627,9 @@ static long ipa_adpl_ioctl(struct file *filp, switch (cmd) { case IPA_IOC_ODL_GET_AGG_BYTE_LIMIT: odl_pipe_info.agg_byte_limit = - ipa3_odl_ctx->odl_sys_param.ipa_ep_cfg.aggr.aggr_byte_limit; + /*Modem expecting value in bytes. so passing 15 = 15*1024*/ + (ipa3_odl_ctx->odl_sys_param.ipa_ep_cfg.aggr.aggr_byte_limit * + 1024); if (copy_to_user((void __user *)arg, &odl_pipe_info, sizeof(odl_pipe_info))) { retval = -EFAULT; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h index 2aedda4d6b28..c8fb2df487c0 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h @@ -13,7 +13,7 @@ #ifndef _IPA3_ODL_H_ #define _IPA3_ODL_H_ -#define IPA_ODL_AGGR_BYTE_LIMIT (15 * 1024) +#define IPA_ODL_AGGR_BYTE_LIMIT 15 #define IPA_ODL_RX_RING_SIZE 192 #define MAX_QUEUE_TO_ODL 1024 #define CONFIG_SUCCESS 1 diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 4490e0cc2db8..849b8cff87e1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -86,14 +86,16 @@ static int ipa_generate_rt_hw_rule(enum ipa_ip_type ip, if (entry->hdr) { hdr_entry = ipa3_id_find(entry->rule.hdr_hdl); - if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE) || + ipa3_check_idr_if_freed(entry->hdr)) { IPAERR_RL("Header entry already deleted\n"); return -EPERM; } } else if (entry->proc_ctx) { hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl); if (!hdr_proc_entry || - hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + (hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) || + ipa3_check_idr_if_freed(entry->proc_ctx)) { IPAERR_RL("Proc header entry already deleted\n"); return -EPERM; } @@ -1767,18 +1769,19 @@ int __ipa3_del_rt_rule(u32 rule_hdl) hdr_entry = ipa3_id_find(entry->rule.hdr_hdl); if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { IPAERR_RL("Header entry already deleted\n"); - return -EINVAL; + entry->hdr = NULL; } } else if (entry->proc_ctx) { hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl); if (!hdr_proc_entry || hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { IPAERR_RL("Proc header entry already deleted\n"); - return -EINVAL; + entry->proc_ctx = NULL; } } - if (entry->hdr) + if (entry->hdr && + (!ipa3_check_idr_if_freed(entry->hdr))) __ipa3_release_hdr(entry->hdr->id); else if (entry->proc_ctx && (!ipa3_check_idr_if_freed(entry->proc_ctx))) @@ -1955,7 +1958,6 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) if (!user_only || rule->ipacm_installed) { - list_del(&rule->link); if (rule->hdr) { hdr_entry = ipa3_id_find( rule->rule.hdr_hdl); @@ -1963,8 +1965,7 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) hdr_entry->cookie != IPA_HDR_COOKIE) { IPAERR_RL( "Header already deleted\n"); - mutex_unlock(&ipa3_ctx->lock); - return -EINVAL; + rule->hdr = NULL; } } else if (rule->proc_ctx) { hdr_proc_entry = @@ -1975,12 +1976,13 @@ int ipa3_reset_rt(enum ipa_ip_type ip, bool user_only) IPA_PROC_HDR_COOKIE) { IPAERR_RL( "Proc entry already deleted\n"); - mutex_unlock(&ipa3_ctx->lock); - return -EINVAL; + rule->proc_ctx = NULL; } } tbl->rule_cnt--; - if (rule->hdr) + list_del(&rule->link); + if (rule->hdr && + (!ipa3_check_idr_if_freed(rule->hdr))) __ipa3_release_hdr(rule->hdr->id); else if (rule->proc_ctx && (!ipa3_check_idr_if_freed( @@ -2157,20 +2159,8 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy_i *rtrule) struct ipa3_hdr_entry *hdr_entry; struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry; - if (rtrule->rule.hdr_hdl) { - hdr = ipa3_id_find(rtrule->rule.hdr_hdl); - if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) { - IPAERR_RL("rt rule does not point to valid hdr\n"); - goto error; - } - } else if (rtrule->rule.hdr_proc_ctx_hdl) { - proc_ctx = ipa3_id_find(rtrule->rule.hdr_proc_ctx_hdl); - if ((proc_ctx == NULL) || - (proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) { - IPAERR_RL("rt rule does not point to valid proc ctx\n"); - goto error; - } - } + if (__ipa_rt_validate_hndls(&rtrule->rule, &hdr, &proc_ctx)) + goto error; entry = ipa3_id_find(rtrule->rt_rule_hdl); if (entry == NULL) { @@ -2193,14 +2183,16 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy_i *rtrule) if (entry->hdr) { hdr_entry = ipa3_id_find(entry->rule.hdr_hdl); - if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) { + if (!hdr_entry || (hdr_entry->cookie != IPA_HDR_COOKIE) || + ipa3_check_idr_if_freed(entry->hdr)) { IPAERR_RL("Header entry already deleted\n"); return -EPERM; } } else if (entry->proc_ctx) { hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl); if (!hdr_proc_entry || - hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) { + (hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) || + ipa3_check_idr_if_freed(entry->proc_ctx)) { IPAERR_RL("Proc header entry already deleted\n"); return -EPERM; } @@ -2208,7 +2200,7 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy_i *rtrule) if (entry->hdr) entry->hdr->ref_cnt--; - if (entry->proc_ctx) + else if (entry->proc_ctx) entry->proc_ctx->ref_cnt--; entry->rule = rtrule->rule; diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 71e8572259dd..529c9e3ac1a6 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -2712,6 +2712,12 @@ static const struct ipa_ep_configuration ipa3_ep_mapping IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_PCIE, { 22, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, + [IPA_4_5_MHI][IPA_CLIENT_ODL_DPL_CONS] = { + true, IPA_v4_5_MHI_GROUP_DDR, + false, + IPA_DPS_HPS_SEQ_TYPE_INVALID, + QMB_MASTER_SELECT_DDR, + { 22, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY, 0 } }, [IPA_4_5_MHI][IPA_CLIENT_MHI_LOW_LAT_CONS] = { true, IPA_v4_5_MHI_GROUP_PCIE, false, @@ -9150,6 +9156,213 @@ int ipa3_setup_uc_act_tbl(void) return res; } +static inline bool is_free_socksv5(struct ipa_socksv5_uc_tmpl *socksv5_entry) +{ + if ((!socksv5_entry->cmd_id) || + (socksv5_entry->cmd_id == IPA_SOCKsv5_ADD_COM_ID && + !(socksv5_entry->ipa_sockv5_mask & IPA_SOCKSv5_ENTRY_VALID))) + return true; + return false; +} + +static int ipa3_get_free_uc_act_entry(void) +{ + struct ipa_socksv5_uc_tmpl *entry; + int orig_index = ipa3_ctx->uc_act_tbl_next_index; + int free_index = -1; + + IPADBG("\n"); + /* find a free spot*/ + do { + entry = ipa3_ctx->uc_act_tbl.base + + ipa3_ctx->uc_act_tbl_next_index + * sizeof(struct ipa_socksv5_uc_tmpl); + + /* check if entry is free */ + if (is_free_socksv5(entry)) { + free_index = ipa3_ctx->uc_act_tbl_next_index; + IPADBG("found free index at %d\n", free_index); + break; + } + + ipa3_ctx->uc_act_tbl_next_index++; + ipa3_ctx->uc_act_tbl_next_index %= + IPA_UC_ACT_TBL_SIZE; + } while (orig_index != ipa3_ctx->uc_act_tbl_next_index); + IPADBG("exit free_index %d\n", free_index); + return free_index; +} + +int ipa3_add_ipv6_nat_uc_activation_entry( + struct ipa_ioc_ipv6_nat_uc_act_entry *entry) +{ + int res = 0; + int index; + struct ipa_ipv6_nat_uc_tmpl *uc_entry; + + /* IPA version check */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) { + IPAERR("Not support !\n"); + return -EPERM; + } + + if (!ipa3_ctx->uc_act_tbl_valid) { + IPAERR("uC act tbl wasn't allocated\n"); + return -ENOENT; + } + + if (!entry) { + IPAERR("Null entry\n"); + return -EIO; + } + if (!entry->private_address_lsb || !entry->private_address_msb + || !entry->public_address_lsb || !entry->public_address_msb + || !entry->private_port || !entry->public_port) { + IPAERR("0 param 0x%llX 0x%llX 0x%llX 0x%llX %d %d\n", + entry->private_address_lsb, entry->private_address_msb, + entry->public_address_lsb, entry->public_address_msb, + entry->private_port, entry->public_port); + return -EFAULT; + } + + mutex_lock(&ipa3_ctx->act_tbl_lock); + /* check the left # of entries */ + if (ipa3_ctx->uc_act_tbl_total + >= IPA_UC_ACT_TBL_SIZE) { + IPAERR("uc act tbl is full!\n"); + res = -EFAULT; + goto error; + } + + index = ipa3_get_free_uc_act_entry(); + + uc_entry = (struct ipa_ipv6_nat_uc_tmpl *)(ipa3_ctx->uc_act_tbl.base + + index * sizeof(struct ipa_ipv6_nat_uc_tmpl)); + + uc_entry->private_address_lsb = entry->private_address_lsb; + uc_entry->private_address_msb = entry->private_address_msb; + uc_entry->public_address_lsb = entry->public_address_lsb; + uc_entry->public_address_msb = entry->public_address_msb; + uc_entry->private_port = entry->private_port; + uc_entry->public_port = entry->public_port; + uc_entry->cmd_id = IPA_IPv6_NAT_COM_ID; + + /* set output index */ + entry->index = (uint16_t)index; + + ipa3_ctx->uc_act_tbl_total++; + ipa3_ctx->uc_act_tbl_ipv6_nat_total++; + + if (ipa3_ctx->uc_act_tbl_total < IPA_UC_ACT_TBL_SIZE) { + /* + * find next free spot, this function shall update + * uc_act_tbl_next_index + */ + index = ipa3_get_free_uc_act_entry(); + + if (index < 0) { + /* set to max tbl size to debug */ + IPAERR("can't find available spot!\n"); + ipa3_ctx->uc_act_tbl_total = IPA_UC_ACT_TBL_SIZE; + res = -EFAULT; + } + } +error: + mutex_unlock(&ipa3_ctx->act_tbl_lock); + return res; +} + +int ipa3_del_uc_act_entry(uint16_t index) +{ + struct ipa_ipv6_nat_uc_tmpl *uc_entry; + uint16_t cmd_id; + + /* IPA version check */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) { + IPAERR_RL("Not support !\n"); + return -EPERM; + } + + if (!ipa3_ctx->uc_act_tbl_valid) { + IPAERR_RL("uC act tbl haven't allocated\n"); + return -ENOENT; + } + + if (index > IPA_UC_ACT_TBL_SIZE || index < 0) { + IPAERR_RL("invalid index!\n"); + return -EINVAL; + } + + if (!ipa3_ctx->uc_act_tbl_total) { + IPAERR_RL( + "invalid handle, no uc activation entries in table (total %d)\n" + , ipa3_ctx->uc_act_tbl_total); + return -EINVAL; + } + + uc_entry = (struct ipa_ipv6_nat_uc_tmpl *)(ipa3_ctx->uc_act_tbl.base + + index * sizeof(struct ipa_ipv6_nat_uc_tmpl)); + + mutex_lock(&ipa3_ctx->act_tbl_lock); + cmd_id = uc_entry->cmd_id; + mutex_unlock(&ipa3_ctx->act_tbl_lock); + + if (cmd_id == IPA_IPv6_NAT_COM_ID) + return ipa3_del_ipv6_nat_uc_activation_entry(index); + else + return ipa3_del_socksv5_conn(index); +} + +int ipa3_del_ipv6_nat_uc_activation_entry(uint16_t index) +{ + struct ipa_ipv6_nat_uc_tmpl *uc_entry; + int res = 0; + + /* IPA version check */ + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) { + IPAERR_RL("Not support !\n"); + return -EPERM; + } + + if (!ipa3_ctx->uc_act_tbl_valid) { + IPAERR_RL("uC act tbl haven't allocated\n"); + return -ENOENT; + } + + if (index > IPA_UC_ACT_TBL_SIZE || index < 0) { + IPAERR_RL("invalid index!\n"); + return -EINVAL; + } + + if (!ipa3_ctx->uc_act_tbl_ipv6_nat_total) { + IPAERR_RL( + "invalid handle, no IPv6 NAT entries in table (total %d)\n" + , ipa3_ctx->uc_act_tbl_total); + return -EINVAL; + } + + uc_entry = (struct ipa_ipv6_nat_uc_tmpl *)(ipa3_ctx->uc_act_tbl.base + + index * sizeof(struct ipa_ipv6_nat_uc_tmpl)); + + mutex_lock(&ipa3_ctx->act_tbl_lock); + if (uc_entry->cmd_id != IPA_IPv6_NAT_COM_ID) { + IPAERR_RL("entry %d wrong cmd id %d\n", uc_entry->cmd_id); + res = -EFAULT; + goto error; + } + uc_entry->cmd_id = 0; + ipa3_ctx->uc_act_tbl_total--; + ipa3_ctx->uc_act_tbl_ipv6_nat_total--; + + IPADBG("free entry %d, nat total %d, left total %d\n", + index, + ipa3_ctx->uc_act_tbl_ipv6_nat_total, + ipa3_ctx->uc_act_tbl_total); +error: + mutex_unlock(&ipa3_ctx->act_tbl_lock); + return res; +} + static void ipa3_socksv5_msg_free_cb(void *buff, u32 len, u32 type) { if (!buff) { @@ -9167,6 +9380,39 @@ static void ipa3_socksv5_msg_free_cb(void *buff, u32 len, u32 type) kfree(buff); } +static int ipa3_get_free_socksv5_entry(void) +{ + struct ipa_socksv5_uc_tmpl *first; + struct ipa_socksv5_uc_tmpl *next; + int orig_index = ipa3_ctx->uc_act_tbl_next_index; + int free_index = -1; + + IPADBG("\n"); + /* find a free spot with two contiguous entries*/ + do { + first = ipa3_ctx->uc_act_tbl.base + + ipa3_ctx->uc_act_tbl_next_index + * sizeof(struct ipa_socksv5_uc_tmpl); + next = ipa3_ctx->uc_act_tbl.base + + (ipa3_ctx->uc_act_tbl_next_index + 1) + * sizeof(struct ipa_socksv5_uc_tmpl); + + /* check if first entry and next entry are free */ + if (is_free_socksv5(first) && is_free_socksv5(next)) { + free_index = ipa3_ctx->uc_act_tbl_next_index; + IPADBG("found free index at %d\n", free_index); + break; + } + + ipa3_ctx->uc_act_tbl_next_index += 2; + ipa3_ctx->uc_act_tbl_next_index %= + IPA_UC_ACT_TBL_SIZE; + } while (orig_index != ipa3_ctx->uc_act_tbl_next_index); + + IPADBG("exit free_index %d\n", free_index); + return free_index; +} + /** * ipa3_add_socksv5_conn() - IPA add socksv5_conn * @@ -9176,8 +9422,8 @@ static void ipa3_socksv5_msg_free_cb(void *buff, u32 len, u32 type) */ int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info) { - int res = 0; - void *rp_va, *wp_va; + int res = 0, index; + void *wp_va; struct ipa_socksv5_msg *socksv5_msg; struct ipa_msg_meta msg_meta; @@ -9198,18 +9444,24 @@ int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info) } mutex_lock(&ipa3_ctx->act_tbl_lock); - /* check the left # of entries */ + /* check the left # of entries (need at least 2)*/ if (ipa3_ctx->uc_act_tbl_total - >= IPA_UC_ACT_TBL_SIZE) { + >= IPA_UC_ACT_TBL_SIZE - 1) { IPAERR("uc act tbl is full!\n"); res = -EFAULT; goto error; } + index = ipa3_get_free_socksv5_entry(); + if (index < 0) { + IPAERR("couldn't find free socksv5 entry\n"); + res = -EFAULT; + goto error; + } + /* Copied the act-info to tbl */ wp_va = ipa3_ctx->uc_act_tbl.base + - ipa3_ctx->uc_act_tbl_next_index - * sizeof(struct ipa_socksv5_uc_tmpl); + index * sizeof(struct ipa_socksv5_uc_tmpl); /* check entry valid */ if ((info->ul_out.cmd_id != IPA_SOCKsv5_ADD_COM_ID) @@ -9246,9 +9498,10 @@ int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info) &(info->dl_out), sizeof(info->dl_out)); /* set output handle */ - info->handle = (uint16_t) ipa3_ctx->uc_act_tbl_next_index; + info->handle = (uint16_t) index; ipa3_ctx->uc_act_tbl_total += 2; + ipa3_ctx->uc_act_tbl_socksv5_total += 2; /* send msg to ipacm */ socksv5_msg = kzalloc(sizeof(*socksv5_msg), GFP_KERNEL); @@ -9261,9 +9514,9 @@ int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info) memcpy(&(socksv5_msg->dl_in), &(info->dl_in), sizeof(info->dl_in)); socksv5_msg->handle = info->handle; socksv5_msg->ul_in.index = - (uint16_t) ipa3_ctx->uc_act_tbl_next_index; + (uint16_t) index; socksv5_msg->dl_in.index = - (uint16_t) ipa3_ctx->uc_act_tbl_next_index + 1; + (uint16_t) index + 1; memset(&msg_meta, 0, sizeof(struct ipa_msg_meta)); msg_meta.msg_type = IPA_SOCKV5_ADD; @@ -9276,27 +9529,14 @@ int ipa3_add_socksv5_conn(struct ipa_socksv5_info *info) goto error; } - if (ipa3_ctx->uc_act_tbl_total < IPA_UC_ACT_TBL_SIZE) { - /* find next free spot */ - do { - ipa3_ctx->uc_act_tbl_next_index += 2; - ipa3_ctx->uc_act_tbl_next_index %= - IPA_UC_ACT_TBL_SIZE; + if (ipa3_ctx->uc_act_tbl_total < IPA_UC_ACT_TBL_SIZE - 1) { + /* + * find next free spot, this function shall update + * uc_act_tbl_next_index + */ + index = ipa3_get_free_socksv5_entry(); - rp_va = ipa3_ctx->uc_act_tbl.base + - ipa3_ctx->uc_act_tbl_next_index - * sizeof(struct ipa_socksv5_uc_tmpl); - - if (!((((struct ipa_socksv5_uc_tmpl *) rp_va)-> - ipa_sockv5_mask) & IPA_SOCKSv5_ENTRY_VALID)) { - IPADBG("next available entry %d, total %d\n", - ipa3_ctx->uc_act_tbl_next_index, - ipa3_ctx->uc_act_tbl_total); - break; - } - } while (rp_va != wp_va); - - if (rp_va == wp_va) { + if (index < 0) { /* set to max tbl size to debug */ IPAERR("can't find available spot!\n"); ipa3_ctx->uc_act_tbl_total = IPA_UC_ACT_TBL_SIZE; @@ -9308,6 +9548,127 @@ error: mutex_unlock(&ipa3_ctx->act_tbl_lock); return res; } +/* + * ipa3_add_socksv5_conn_usr() - IPA copy and add socksv5 conn + * + * Returns: 0 on success, negative on failure + * + * Note : Should not be called from atomic context + */ +int ipa3_add_socksv5_conn_usr(struct ipa_kernel_tests_socksv5_uc_tmpl *tmpl) +{ + struct ipa_socksv5_info info; + int retval = 0; + + memset(&info, 0, sizeof(struct ipa_socksv5_info)); + + if (tmpl->direction == 0) { /* DL */ + info.dl_out.cmd_id = tmpl->cmd_id; + info.dl_out.cmd_param = tmpl->cmd_param; + info.dl_out.ip_hdr.ipv6_temp.version = 6; + info.dl_out.ip_hdr.ipv6_temp.nexthdr = 6; + info.dl_out.ip_hdr.ipv6_temp.saddr.s6_addr32[0] = + tmpl->ipv6_src_addr[0]; + info.dl_out.ip_hdr.ipv6_temp.saddr.s6_addr32[1] = + tmpl->ipv6_src_addr[1]; + info.dl_out.ip_hdr.ipv6_temp.saddr.s6_addr32[2] = + tmpl->ipv6_src_addr[2]; + info.dl_out.ip_hdr.ipv6_temp.saddr.s6_addr32[3] = + tmpl->ipv6_src_addr[3]; + info.dl_out.ip_hdr.ipv6_temp.daddr.s6_addr32[0] = + tmpl->ipv6_dst_addr[0]; + info.dl_out.ip_hdr.ipv6_temp.daddr.s6_addr32[1] = + tmpl->ipv6_dst_addr[1]; + info.dl_out.ip_hdr.ipv6_temp.daddr.s6_addr32[2] = + tmpl->ipv6_dst_addr[2]; + info.dl_out.ip_hdr.ipv6_temp.daddr.s6_addr32[3] = + tmpl->ipv6_dst_addr[3]; + info.dl_out.src_port = tmpl->src_port; + info.dl_out.dst_port = tmpl->dst_port; + info.dl_out.ipa_sockv5_mask = tmpl->ipa_sockv5_mask; + info.dl_out.out_irs = tmpl->out_irs; + info.dl_out.out_iss = tmpl->out_iss; + info.dl_out.in_irs = tmpl->in_irs; + info.dl_out.in_iss = tmpl->in_iss; + info.dl_out.out_ircv_tsval = tmpl->out_ircv_tsval; + info.dl_out.in_ircv_tsecr = tmpl->in_ircv_tsecr; + info.dl_out.out_ircv_tsecr = tmpl->out_ircv_tsecr; + info.dl_out.in_ircv_tsval = tmpl->in_ircv_tsval; + info.dl_out.in_isnd_wscale = tmpl->in_isnd_wscale; + info.dl_out.out_isnd_wscale = tmpl->out_isnd_wscale; + info.dl_out.in_ircv_wscale = tmpl->in_ircv_wscale; + info.dl_out.out_ircv_wscale = tmpl->out_ircv_wscale; + + /* for UL set default values to pass pair validity check */ + info.ul_out.cmd_id = IPA_SOCKsv5_ADD_COM_ID; + info.ul_out.cmd_param = IPA_SOCKsv5_ADD_V6_V4_COM_PM; + } else if (tmpl->direction == 1) { /* UL */ + info.ul_out.cmd_id = tmpl->cmd_id; + info.ul_out.cmd_param = tmpl->cmd_param; + if (info.ul_out.cmd_param == IPA_SOCKsv5_ADD_V6_V4_COM_PM) { + info.ul_out.ip_hdr.ipv4_rsv.ipv4_temp.version = 4; + info.ul_out.ip_hdr.ipv4_rsv.ipv4_temp.ihl = 5; + info.ul_out.ip_hdr.ipv4_rsv.ipv4_temp.saddr = + tmpl->ip_src_addr; + info.ul_out.ip_hdr.ipv4_rsv.ipv4_temp.daddr = + tmpl->ip_dst_addr; + info.ul_out.ip_hdr.ipv4_rsv.ipv4_temp.protocol = 6; + } + if (info.ul_out.cmd_param == IPA_SOCKsv5_ADD_V6_V6_COM_PM) { + info.ul_out.ip_hdr.ipv6_temp.version = 6; + info.ul_out.ip_hdr.ipv6_temp.nexthdr = 6; + info.ul_out.ip_hdr.ipv6_temp.saddr.s6_addr32[0] = + tmpl->ipv6_src_addr[0]; + info.ul_out.ip_hdr.ipv6_temp.saddr.s6_addr32[1] = + tmpl->ipv6_src_addr[1]; + info.ul_out.ip_hdr.ipv6_temp.saddr.s6_addr32[2] = + tmpl->ipv6_src_addr[2]; + info.ul_out.ip_hdr.ipv6_temp.saddr.s6_addr32[3] = + tmpl->ipv6_src_addr[3]; + info.ul_out.ip_hdr.ipv6_temp.daddr.s6_addr32[0] = + tmpl->ipv6_dst_addr[0]; + info.ul_out.ip_hdr.ipv6_temp.daddr.s6_addr32[1] = + tmpl->ipv6_dst_addr[1]; + info.ul_out.ip_hdr.ipv6_temp.daddr.s6_addr32[2] = + tmpl->ipv6_dst_addr[2]; + info.ul_out.ip_hdr.ipv6_temp.daddr.s6_addr32[3] = + tmpl->ipv6_dst_addr[3]; + } + info.ul_out.src_port = tmpl->src_port; + info.ul_out.dst_port = tmpl->dst_port; + info.ul_out.ipa_sockv5_mask = tmpl->ipa_sockv5_mask; + info.ul_out.out_irs = tmpl->out_irs; + info.ul_out.out_iss = tmpl->out_iss; + info.ul_out.in_irs = tmpl->in_irs; + info.ul_out.in_iss = tmpl->in_iss; + info.ul_out.out_ircv_tsval = tmpl->out_ircv_tsval; + info.ul_out.in_ircv_tsecr = tmpl->in_ircv_tsecr; + info.ul_out.out_ircv_tsecr = tmpl->out_ircv_tsecr; + info.ul_out.in_ircv_tsval = tmpl->in_ircv_tsval; + info.ul_out.in_isnd_wscale = tmpl->in_isnd_wscale; + info.ul_out.out_isnd_wscale = tmpl->out_isnd_wscale; + info.ul_out.in_ircv_wscale = tmpl->in_ircv_wscale; + info.ul_out.out_ircv_wscale = tmpl->out_ircv_wscale; + + /* for DL set default values to pass pair validity check */ + info.dl_out.cmd_param = IPA_SOCKsv5_ADD_V4_V6_COM_PM; + info.dl_out.cmd_id = IPA_SOCKsv5_ADD_COM_ID; + } else { + IPAERR("invalid socksv5 direction: %d\n", tmpl->direction); + return -EINVAL; + } + + retval = ipa3_add_socksv5_conn(&info); + if (retval) { + IPAERR("ipa3_add_socksv5_conn failed retval: %d\n", retval); + return retval; + } + + /* save uc handle */ + tmpl->handle = info.handle; + + return retval; +} /** * ipa3_del_socksv5_conn() - IPA add socksv5_conn @@ -9319,9 +9680,9 @@ error: int ipa3_del_socksv5_conn(uint32_t handle) { int res = 0; - void *rp_va; uint32_t *socksv5_handle; struct ipa_msg_meta msg_meta; + struct ipa_socksv5_uc_tmpl *entry, *next; /* IPA version check */ if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_5) { @@ -9339,43 +9700,44 @@ int ipa3_del_socksv5_conn(uint32_t handle) return -EINVAL; } - if ((handle % 2) != 0) { - IPAERR("invalid handle!\n"); + if (ipa3_ctx->uc_act_tbl_socksv5_total < 2) { + IPAERR("invalid handle, tbl doesn't have socksv5 entries!\n"); return -EINVAL; } - if (ipa3_ctx->uc_act_tbl_total < 2) { - IPAERR("invalid handle, all tbl is empty!\n"); - return -EINVAL; - } - - rp_va = ipa3_ctx->uc_act_tbl.base + - handle * sizeof(struct ipa_socksv5_uc_tmpl); + entry = (struct ipa_socksv5_uc_tmpl *)(ipa3_ctx->uc_act_tbl.base + + handle * sizeof(struct ipa_socksv5_uc_tmpl)); + next = (struct ipa_socksv5_uc_tmpl *)(ipa3_ctx->uc_act_tbl.base + + (handle + 1) * sizeof(struct ipa_socksv5_uc_tmpl)); /* check entry is valid or not */ mutex_lock(&ipa3_ctx->act_tbl_lock); - if (!((((struct ipa_socksv5_uc_tmpl *) rp_va)-> - ipa_sockv5_mask) & IPA_SOCKSv5_ENTRY_VALID)) { - IPADBG(" entry %d already free\n", handle); + if (entry->cmd_id != IPA_SOCKsv5_ADD_COM_ID) { + IPAERR(" entry %d not socksv5\n", handle); + res = -EINVAL; + goto error; } - - if (!((((struct ipa_socksv5_uc_tmpl *) (rp_va + - sizeof(struct ipa_socksv5_uc_tmpl)))-> - ipa_sockv5_mask) & IPA_SOCKSv5_ENTRY_VALID)) { - IPADBG(" entry %d already free\n", handle); + if (next->cmd_id != IPA_SOCKsv5_ADD_COM_ID) { + IPAERR(" entry %d not socksv5\n", handle + 1); + res = -EINVAL; + goto error; } + if (!(entry->ipa_sockv5_mask & IPA_SOCKSv5_ENTRY_VALID)) + IPADBG(" entry %d already free\n", handle); - ((struct ipa_socksv5_uc_tmpl *) rp_va)->ipa_sockv5_mask - &= ~IPA_SOCKSv5_ENTRY_VALID; - ((struct ipa_socksv5_uc_tmpl *) (rp_va + - sizeof(struct ipa_socksv5_uc_tmpl)))->ipa_sockv5_mask - &= ~IPA_SOCKSv5_ENTRY_VALID; + if (!(next->ipa_sockv5_mask & IPA_SOCKSv5_ENTRY_VALID)) + IPADBG(" entry %d already free\n", handle); + + entry->ipa_sockv5_mask &= ~IPA_SOCKSv5_ENTRY_VALID; + next->ipa_sockv5_mask &= ~IPA_SOCKSv5_ENTRY_VALID; ipa3_ctx->uc_act_tbl_total -= 2; + ipa3_ctx->uc_act_tbl_socksv5_total -= 2; - IPADBG("free entry %d and %d, left total %d\n", + IPADBG("free entry %d and %d, left total %d, socksv5 total %d\n", handle, handle + 1, - ipa3_ctx->uc_act_tbl_total); + ipa3_ctx->uc_act_tbl_total, + ipa3_ctx->uc_act_tbl_socksv5_total); /* send msg to ipacm */ socksv5_handle = kzalloc(sizeof(*socksv5_handle), GFP_KERNEL); diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 484fc1ec3b53..9a3e8bc04dc9 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -2143,25 +2143,34 @@ static void mhi_dev_transfer_completion_cb(void *mreq) { int rc = 0; struct mhi_req *req = mreq; - struct mhi_dev_channel *ch = req->client->channel; + struct mhi_dev_channel *ch; u32 snd_cmpl = req->snd_cmpl; + bool inbound = false; - if (mhi_ctx->ch_ctx_cache[ch->ch_id].ch_type == - MHI_DEV_CH_TYPE_INBOUND_CHANNEL) - ch->pend_wr_count--; + ch = &mhi_ctx->ch[req->chan]; dma_unmap_single(&mhi_ctx->pdev->dev, req->dma, - req->len, DMA_FROM_DEVICE); + req->len, DMA_FROM_DEVICE); + + if (mhi_ctx->ch_ctx_cache[ch->ch_id].ch_type == + MHI_DEV_CH_TYPE_INBOUND_CHANNEL) { + inbound = true; + ch->pend_wr_count--; + } /* - * Channel got stopped or closed with transfers pending + * Channel got closed with transfers pending * Do not trigger callback or send cmpl to host */ if (ch->state == MHI_DEV_CH_CLOSED || ch->state == MHI_DEV_CH_STOPPED) { - mhi_log(MHI_MSG_DBG, - "Ch %d not in started state, %d writes pending\n", + if (inbound) + mhi_log(MHI_MSG_DBG, + "Ch %d closed with %d writes pending\n", ch->ch_id, ch->pend_wr_count + 1); + else + mhi_log(MHI_MSG_DBG, + "Ch %d closed with read pending\n", ch->ch_id); return; } @@ -2749,6 +2758,7 @@ int mhi_dev_open_channel(uint32_t chan_id, ch->active_client = (*handle_client); (*handle_client)->channel = ch; (*handle_client)->event_trigger = mhi_dev_client_cb_reason; + ch->pend_wr_count = 0; if (ch->state == MHI_DEV_CH_UNINT) { ch->ring = &mhi_ctx->ring[chan_id + mhi_ctx->ch_ring_start]; diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index fe398cbc8c0f..5b8a7f5affc8 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -421,7 +421,8 @@ static inline void mhi_dev_ring_inc_index(struct mhi_dev_ring *ring, #define TRACE_DATA_MAX 128 #define MHI_DEV_DATA_MAX 512 -#define MHI_DEV_MMIO_RANGE 0xc80 +#define MHI_DEV_MMIO_RANGE 0xb80 +#define MHI_DEV_MMIO_OFFSET 0x100 struct ring_cache_req { struct completion *done; diff --git a/drivers/platform/msm/mhi_dev/mhi_dev_net.c b/drivers/platform/msm/mhi_dev/mhi_dev_net.c index a9ad33a9aa83..49b67640a3e1 100644 --- a/drivers/platform/msm/mhi_dev/mhi_dev_net.c +++ b/drivers/platform/msm/mhi_dev/mhi_dev_net.c @@ -700,8 +700,6 @@ static void mhi_dev_net_state_cb(struct mhi_dev_client_cb_data *cb_data) mhi_dev_net_free_reqs(&mhi_client->wr_req_buffers); free_netdev(mhi_client->dev); mhi_client->dev = NULL; - kfree(mhi_client); - kfree(mhi_net_ipc_log); } } } diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c index 7770ea694330..a9c724c51db6 100644 --- a/drivers/platform/msm/mhi_dev/mhi_mmio.c +++ b/drivers/platform/msm/mhi_dev/mhi_mmio.c @@ -607,7 +607,8 @@ int mhi_dev_restore_mmio(struct mhi_dev *dev) mhi_dev_mmio_mask_interrupts(dev); for (i = 0; i < (MHI_DEV_MMIO_RANGE/4); i++) { - reg_cntl_addr = dev->mmio_base_addr + (i * 4); + reg_cntl_addr = dev->mmio_base_addr + + MHI_DEV_MMIO_OFFSET + (i * 4); reg_cntl_value = dev->mmio_backup[i]; writel_relaxed(reg_cntl_value, reg_cntl_addr); } @@ -628,13 +629,16 @@ EXPORT_SYMBOL(mhi_dev_restore_mmio); int mhi_dev_backup_mmio(struct mhi_dev *dev) { uint32_t i = 0; + void __iomem *reg_cntl_addr; if (WARN_ON(!dev)) return -EINVAL; - for (i = 0; i < MHI_DEV_MMIO_RANGE/4; i++) - dev->mmio_backup[i] = - readl_relaxed(dev->mmio_base_addr + (i * 4)); + for (i = 0; i < MHI_DEV_MMIO_RANGE/4; i++) { + reg_cntl_addr = (void __iomem *) (dev->mmio_base_addr + + MHI_DEV_MMIO_OFFSET + (i * 4)); + dev->mmio_backup[i] = readl_relaxed(reg_cntl_addr); + } return 0; } diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index 73ac3bc1e527..a95df104d38c 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -33,8 +33,8 @@ #define MHI_SOFTWARE_CLIENT_LIMIT (MHI_MAX_SOFTWARE_CHANNELS/2) #define MHI_UCI_IPC_LOG_PAGES (100) -/* Max number of MHI write request structures (used in async writes) */ -#define MHI_UCI_NUM_WR_REQ_DEFAULT 10 +/* Max number of MHI read/write request structs (used in async transfers) */ +#define MHI_UCI_NUM_REQ_DEFAULT 10 #define MAX_NR_TRBS_PER_CHAN 9 #define MHI_QTI_IFACE_ID 4 #define MHI_ADPL_IFACE_ID 5 @@ -51,6 +51,8 @@ #define MHI_UCI_RELEASE_TIMEOUT_MAX 5100 #define MHI_UCI_RELEASE_TIMEOUT_COUNT 30 +#define MHI_UCI_IS_CHAN_DIR_IN(n) ((n % 2) ? true : false) + enum uci_dbg_level { UCI_DBG_VERBOSE = 0x0, UCI_DBG_INFO = 0x1, @@ -95,8 +97,7 @@ struct chan_attr { /* Skip node creation if not needed */ bool skip_node; /* Number of write request structs to allocate */ - u32 num_wr_reqs; - + u32 num_reqs; }; static void mhi_uci_generic_client_cb(struct mhi_dev_client_cb_data *cb_data); @@ -357,15 +358,19 @@ struct uci_client { struct mhi_uci_ctxt_t *uci_ctxt; struct mutex in_chan_lock; struct mutex out_chan_lock; - spinlock_t wr_req_lock; + spinlock_t req_lock; unsigned int f_flags; - struct mhi_req *wreqs; - struct list_head wr_req_list; + /* Pointer to dynamically allocated mhi_req structs */ + struct mhi_req *reqs; + /* Pointer to available (free) reqs */ + struct list_head req_list; + /* Pointer to in-use reqs */ + struct list_head in_use_list; struct completion read_done; struct completion at_ctrl_read_done; struct completion *write_done; int (*send)(struct uci_client*, void*, u32); - int (*read)(struct uci_client*, struct mhi_req*, int*); + int (*read)(struct uci_client*, int*); unsigned int tiocm; unsigned int at_ctrl_mask; }; @@ -501,23 +506,75 @@ free_memory: return rc; } +static struct mhi_req *mhi_uci_get_req(struct uci_client *uci_handle) +{ + struct mhi_req *req; + unsigned long flags; + + spin_lock_irqsave(&uci_handle->req_lock, flags); + if (list_empty(&uci_handle->req_list)) { + uci_log(UCI_DBG_ERROR, "Request pool empty for chans %d, %d\n", + uci_handle->in_chan, uci_handle->out_chan); + spin_unlock_irqrestore(&uci_handle->req_lock, flags); + return NULL; + } + /* Remove from free list and add to in-use list */ + req = container_of(uci_handle->req_list.next, + struct mhi_req, list); + list_del_init(&req->list); + /* + * If req is marked stale and if it was used for the write channel + * to host, free the previously allocated input buffer before the + * req is re-used + */ + if (req->is_stale && req->buf && MHI_UCI_IS_CHAN_DIR_IN(req->chan)) { + uci_log(UCI_DBG_VERBOSE, "Freeing write buf for chan %d\n", + req->chan); + kfree(req->buf); + } + req->is_stale = false; + uci_log(UCI_DBG_VERBOSE, "Adding req to in-use list\n"); + list_add_tail(&req->list, &uci_handle->in_use_list); + spin_unlock_irqrestore(&uci_handle->req_lock, flags); + + return req; +} + +static void mhi_uci_put_req(struct uci_client *uci_handle, struct mhi_req *req) +{ + unsigned long flags; + + spin_lock_irqsave(&uci_handle->req_lock, flags); + /* Remove from in-use list and add back to free list */ + list_del_init(&req->list); + list_add_tail(&req->list, &uci_handle->req_list); + spin_unlock_irqrestore(&uci_handle->req_lock, flags); +} + static void mhi_uci_write_completion_cb(void *req) { struct mhi_req *ureq = req; - struct uci_client *uci_handle; - unsigned long flags; + struct uci_client *uci_handle = (struct uci_client *)ureq->context; - uci_handle = (struct uci_client *)ureq->context; kfree(ureq->buf); ureq->buf = NULL; - spin_lock_irqsave(&uci_handle->wr_req_lock, flags); - list_add_tail(&ureq->list, &uci_handle->wr_req_list); - spin_unlock_irqrestore(&uci_handle->wr_req_lock, flags); + /* + * If this is a delayed write completion, just clear + * the stale flag and return. The ureq was added to + * the free list when client called release function. + */ + if (ureq->is_stale) { + uci_log(UCI_DBG_VERBOSE, + "Got stale completion for ch %d\n", ureq->chan); + ureq->is_stale = false; + return; + } if (uci_handle->write_done) complete(uci_handle->write_done); + mhi_uci_put_req(uci_handle, ureq); /* Write queue may be waiting for write request structs */ wake_up(&uci_handle->write_wq); } @@ -527,7 +584,19 @@ static void mhi_uci_read_completion_cb(void *req) struct mhi_req *ureq = req; struct uci_client *uci_handle; + if (ureq->is_stale) { + uci_log(UCI_DBG_VERBOSE, + "Got stale completion for ch %d, ignoring\n", + ureq->chan); + return; + } + uci_handle = (struct uci_client *)ureq->context; + + uci_handle->pkt_loc = (void *)ureq->buf; + uci_handle->pkt_size = ureq->transfer_len; + + mhi_uci_put_req(uci_handle, ureq); complete(&uci_handle->read_done); } @@ -537,6 +606,9 @@ static int mhi_uci_send_sync(struct uci_client *uci_handle, struct mhi_req ureq; int ret_val; + uci_log(UCI_DBG_VERBOSE, + "Sync write for ch %d size %d\n", uci_handle->out_chan, size); + ureq.client = uci_handle->out_handle; ureq.buf = data_loc; ureq.len = size; @@ -557,19 +629,12 @@ static int mhi_uci_send_async(struct uci_client *uci_handle, struct mhi_req *ureq; uci_log(UCI_DBG_VERBOSE, - "Got async write for ch %d of size %d\n", + "Async write for ch %d size %d\n", uci_handle->out_chan, size); - spin_lock_irq(&uci_handle->wr_req_lock); - if (list_empty(&uci_handle->wr_req_list)) { - uci_log(UCI_DBG_ERROR, "Write request pool empty\n"); - spin_unlock_irq(&uci_handle->wr_req_lock); + ureq = mhi_uci_get_req(uci_handle); + if (!ureq) return -EBUSY; - } - ureq = container_of(uci_handle->wr_req_list.next, - struct mhi_req, list); - list_del_init(&ureq->list); - spin_unlock_irq(&uci_handle->wr_req_lock); ureq->client = uci_handle->out_handle; ureq->context = uci_handle; @@ -588,9 +653,7 @@ static int mhi_uci_send_async(struct uci_client *uci_handle, error_async_transfer: ureq->buf = NULL; - spin_lock_irq(&uci_handle->wr_req_lock); - list_add_tail(&ureq->list, &uci_handle->wr_req_list); - spin_unlock_irq(&uci_handle->wr_req_lock); + mhi_uci_put_req(uci_handle, ureq); return bytes_to_write; } @@ -632,7 +695,7 @@ static int mhi_uci_send_packet(struct uci_client *uci_handle, void *data_loc, return -EAGAIN; ret_val = wait_event_interruptible_timeout( uci_handle->write_wq, - !list_empty(&uci_handle->wr_req_list), + !list_empty(&uci_handle->req_list), MHI_UCI_WRITE_REQ_AVAIL_TIMEOUT); if (ret_val > 0) { /* @@ -733,42 +796,62 @@ static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait) return mask; } -static int mhi_uci_alloc_write_reqs(struct uci_client *client) +static int mhi_uci_alloc_reqs(struct uci_client *client) { int i; - u32 num_wr_reqs; + u32 num_reqs; - num_wr_reqs = client->in_chan_attr->num_wr_reqs; - if (!num_wr_reqs) - num_wr_reqs = MHI_UCI_NUM_WR_REQ_DEFAULT; + if (client->reqs) { + uci_log(UCI_DBG_VERBOSE, "Reqs already allocated\n"); + return 0; + } - client->wreqs = kcalloc(num_wr_reqs, + num_reqs = client->in_chan_attr->num_reqs; + if (!num_reqs) + num_reqs = MHI_UCI_NUM_REQ_DEFAULT; + + client->reqs = kcalloc(num_reqs, sizeof(struct mhi_req), GFP_KERNEL); - if (!client->wreqs) { - uci_log(UCI_DBG_ERROR, "Write reqs alloc failed\n"); + if (!client->reqs) { + uci_log(UCI_DBG_ERROR, "Reqs alloc failed\n"); return -ENOMEM; } - INIT_LIST_HEAD(&client->wr_req_list); - for (i = 0; i < num_wr_reqs; ++i) - list_add_tail(&client->wreqs[i].list, &client->wr_req_list); + INIT_LIST_HEAD(&client->req_list); + INIT_LIST_HEAD(&client->in_use_list); + for (i = 0; i < num_reqs; ++i) + list_add_tail(&client->reqs[i].list, &client->req_list); uci_log(UCI_DBG_INFO, "Allocated %d write reqs for chan %d\n", - num_wr_reqs, client->out_chan); + num_reqs, client->out_chan); return 0; } -static int mhi_uci_read_async(struct uci_client *uci_handle, - struct mhi_req *ureq, int *bytes_avail) +static int mhi_uci_read_async(struct uci_client *uci_handle, int *bytes_avail) { int ret_val = 0; unsigned long compl_ret; + struct mhi_req *ureq; + struct mhi_dev_client *client_handle; uci_log(UCI_DBG_ERROR, "Async read for ch %d\n", uci_handle->in_chan); + ureq = mhi_uci_get_req(uci_handle); + if (!ureq) { + uci_log(UCI_DBG_ERROR, + "Out of reqs for chan %d\n", uci_handle->in_chan); + return -EBUSY; + } + + client_handle = uci_handle->in_handle; + ureq->chan = uci_handle->in_chan; + ureq->client = client_handle; + ureq->buf = uci_handle->in_buf_list[0].addr; + ureq->len = uci_handle->in_buf_list[0].buf_size; + ureq->mode = DMA_ASYNC; ureq->client_cb = mhi_uci_read_completion_cb; ureq->snd_cmpl = 1; @@ -777,14 +860,14 @@ static int mhi_uci_read_async(struct uci_client *uci_handle, reinit_completion(&uci_handle->read_done); *bytes_avail = mhi_dev_read_channel(ureq); - uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%lx bytes_read = 0x%x\n", - ureq->len, *bytes_avail); if (*bytes_avail < 0) { uci_log(UCI_DBG_ERROR, "Failed to read channel ret %dlu\n", *bytes_avail); + mhi_uci_put_req(uci_handle, ureq); return -EIO; } - + uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%lx bytes_read = 0x%x\n", + ureq->len, *bytes_avail); if (*bytes_avail > 0) { uci_log(UCI_DBG_VERBOSE, "Waiting for async read completion!\n"); @@ -792,7 +875,6 @@ static int mhi_uci_read_async(struct uci_client *uci_handle, wait_for_completion_interruptible_timeout( &uci_handle->read_done, MHI_UCI_ASYNC_READ_TIMEOUT); - if (compl_ret == -ERESTARTSYS) { uci_log(UCI_DBG_ERROR, "Exit signal caught\n"); return compl_ret; @@ -802,33 +884,41 @@ static int mhi_uci_read_async(struct uci_client *uci_handle, return -EIO; } uci_log(UCI_DBG_VERBOSE, - "wk up Read completed on ch %d\n", ureq->chan); - - uci_handle->pkt_loc = (void *)ureq->buf; - uci_handle->pkt_size = ureq->transfer_len; - + "wk up Read completed on ch %d\n", uci_handle->in_chan); uci_log(UCI_DBG_VERBOSE, "Got pkt of sz 0x%lx at adr %pK, ch %d\n", uci_handle->pkt_size, - ureq->buf, ureq->chan); + uci_handle->pkt_loc, uci_handle->in_chan); } else { uci_handle->pkt_loc = NULL; uci_handle->pkt_size = 0; + uci_log(UCI_DBG_VERBOSE, + "No read data available, return req to free liat\n"); + mhi_uci_put_req(uci_handle, ureq); } return ret_val; } -static int mhi_uci_read_sync(struct uci_client *uci_handle, - struct mhi_req *ureq, int *bytes_avail) +static int mhi_uci_read_sync(struct uci_client *uci_handle, int *bytes_avail) { int ret_val = 0; + struct mhi_req ureq; + struct mhi_dev_client *client_handle; - ureq->mode = DMA_SYNC; - *bytes_avail = mhi_dev_read_channel(ureq); + uci_log(UCI_DBG_ERROR, + "Sync read for ch %d\n", uci_handle->in_chan); + client_handle = uci_handle->in_handle; + ureq.chan = uci_handle->in_chan; + ureq.client = client_handle; + ureq.buf = uci_handle->in_buf_list[0].addr; + ureq.len = uci_handle->in_buf_list[0].buf_size; + ureq.mode = DMA_SYNC; + + *bytes_avail = mhi_dev_read_channel(&ureq); uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%lx bytes_read = 0x%x\n", - ureq->len, *bytes_avail); + ureq.len, *bytes_avail); if (*bytes_avail < 0) { uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n", @@ -837,13 +927,13 @@ static int mhi_uci_read_sync(struct uci_client *uci_handle, } if (*bytes_avail > 0) { - uci_handle->pkt_loc = (void *)ureq->buf; - uci_handle->pkt_size = ureq->transfer_len; + uci_handle->pkt_loc = (void *)ureq.buf; + uci_handle->pkt_size = ureq.transfer_len; uci_log(UCI_DBG_VERBOSE, "Got pkt of sz 0x%lx at adr %pK, ch %d\n", uci_handle->pkt_size, - ureq->buf, ureq->chan); + ureq.buf, ureq.chan); } else { uci_handle->pkt_loc = NULL; uci_handle->pkt_size = 0; @@ -868,7 +958,7 @@ static int open_client_mhi_channels(struct uci_client *uci_client) /* Allocate write requests for async operations */ if (!(uci_client->f_flags & O_SYNC)) { - rc = mhi_uci_alloc_write_reqs(uci_client); + rc = mhi_uci_alloc_reqs(uci_client); if (rc) goto handle_not_rdy_err; uci_client->send = mhi_uci_send_async; @@ -987,11 +1077,20 @@ static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle) { struct uci_client *uci_handle = file_handle->private_data; - int count = 0; + const struct chan_attr *in_chan_attr; + int count = 0, i; + struct mhi_req *ureq; if (!uci_handle) return -EINVAL; + in_chan_attr = uci_handle->in_chan_attr; + if (!in_chan_attr) { + uci_log(UCI_DBG_ERROR, "Null channel attributes for chan %d\n", + uci_handle->in_chan); + return -EINVAL; + } + if (atomic_sub_return(1, &uci_handle->ref_count)) { uci_log(UCI_DBG_DBG, "Client close chan %d, ref count 0x%x\n", iminor(mhi_inode), @@ -1018,9 +1117,6 @@ static int mhi_uci_client_release(struct inode *mhi_inode, if (atomic_read(&uci_handle->mhi_chans_open)) { atomic_set(&uci_handle->mhi_chans_open, 0); - - if (!(uci_handle->f_flags & O_SYNC)) - kfree(uci_handle->wreqs); mutex_lock(&uci_handle->out_chan_lock); mhi_dev_close_channel(uci_handle->out_handle); wake_up(&uci_handle->write_wq); @@ -1030,6 +1126,33 @@ static int mhi_uci_client_release(struct inode *mhi_inode, mhi_dev_close_channel(uci_handle->in_handle); wake_up(&uci_handle->read_wq); mutex_unlock(&uci_handle->in_chan_lock); + /* + * Add back reqs in in-use list, if any, to free list. + * Mark the ureq stale to avoid returning stale data + * to client if the transfer completes later. + */ + count = 0; + while (!(list_empty(&uci_handle->in_use_list))) { + ureq = container_of(uci_handle->in_use_list.next, + struct mhi_req, list); + list_del_init(&ureq->list); + ureq->is_stale = true; + uci_log(UCI_DBG_VERBOSE, + "Adding back req for chan %d to free list\n", + ureq->chan); + list_add_tail(&ureq->list, &uci_handle->req_list); + count++; + } + if (count) + uci_log(UCI_DBG_DBG, + "Client %d closed with %d transfers pending\n", + iminor(mhi_inode), count); + } + + for (i = 0; i < (in_chan_attr->nr_trbs); i++) { + kfree(uci_handle->in_buf_list[i].addr); + uci_handle->in_buf_list[i].addr = NULL; + uci_handle->in_buf_list[i].buf_size = 0; } atomic_set(&uci_handle->read_data_ready, 0); @@ -1146,20 +1269,11 @@ static int __mhi_uci_client_read(struct uci_client *uci_handle, int *bytes_avail) { int ret_val = 0; - struct mhi_dev_client *client_handle; - struct mhi_req ureq; - - client_handle = uci_handle->in_handle; - ureq.chan = uci_handle->in_chan; - ureq.client = client_handle; - ureq.buf = uci_handle->in_buf_list[0].addr; - ureq.len = uci_handle->in_buf_list[0].buf_size; do { if (!uci_handle->pkt_loc && !atomic_read(&uci_ctxt.mhi_disabled)) { - ret_val = uci_handle->read(uci_handle, &ureq, - bytes_avail); + ret_val = uci_handle->read(uci_handle, bytes_avail); if (ret_val) return ret_val; } @@ -1169,12 +1283,13 @@ static int __mhi_uci_client_read(struct uci_client *uci_handle, uci_log(UCI_DBG_VERBOSE, "No data read_data_ready %d, chan %d\n", atomic_read(&uci_handle->read_data_ready), - ureq.chan); + uci_handle->in_chan); if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY)) return -EAGAIN; ret_val = wait_event_interruptible(uci_handle->read_wq, - (!mhi_dev_channel_isempty(client_handle))); + (!mhi_dev_channel_isempty( + uci_handle->in_handle))); if (ret_val == -ERESTARTSYS) { uci_log(UCI_DBG_ERROR, "Exit signal caught\n"); @@ -1183,27 +1298,16 @@ static int __mhi_uci_client_read(struct uci_client *uci_handle, uci_log(UCI_DBG_VERBOSE, "wk up Got data on ch %d read_data_ready %d\n", - ureq.chan, + uci_handle->in_chan, atomic_read(&uci_handle->read_data_ready)); } else if (*bytes_avail > 0) { /* A valid packet was returned from MHI */ uci_log(UCI_DBG_VERBOSE, "Got packet: avail pkts %d phy_adr %pK, ch %d\n", atomic_read(&uci_handle->read_data_ready), - ureq.buf, - ureq.chan); + uci_handle->pkt_loc, + uci_handle->in_chan); break; - } else { - /* - * MHI did not return a valid packet, but we have one - * which we did not finish returning to user - */ - uci_log(UCI_DBG_CRITICAL, - "chan %d err: avail pkts %d phy_adr %pK", - ureq.chan, - atomic_read(&uci_handle->read_data_ready), - ureq.buf); - return -EIO; } } while (!uci_handle->pkt_loc); @@ -1465,7 +1569,7 @@ static int mhi_register_client(struct uci_client *mhi_client, int index) mutex_init(&mhi_client->in_chan_lock); mutex_init(&mhi_client->out_chan_lock); - spin_lock_init(&mhi_client->wr_req_lock); + spin_lock_init(&mhi_client->req_lock); /* Init the completion event for AT ctrl read */ init_completion(&mhi_client->at_ctrl_read_done); @@ -1833,6 +1937,7 @@ static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data) { struct uci_client *client = cb_data->user_data; int rc; + struct mhi_req *ureq; uci_log(UCI_DBG_VERBOSE, " Rcvd MHI cb for channel %d, state %d\n", cb_data->channel, cb_data->ctrl_info); @@ -1859,10 +1964,17 @@ static void mhi_uci_at_ctrl_client_cb(struct mhi_dev_client_cb_data *cb_data) } destroy_workqueue(uci_ctxt.at_ctrl_wq); uci_ctxt.at_ctrl_wq = NULL; - if (!(client->f_flags & O_SYNC)) - kfree(client->wreqs); mhi_dev_close_channel(client->out_handle); mhi_dev_close_channel(client->in_handle); + + /* Add back reqs in in-use list, if any, to free list */ + while (!(list_empty(&client->in_use_list))) { + ureq = container_of(client->in_use_list.next, + struct mhi_req, list); + list_del_init(&ureq->list); + /* Add to in-use list */ + list_add_tail(&ureq->list, &client->req_list); + } } } diff --git a/drivers/platform/msm/qcom-geni-se.c b/drivers/platform/msm/qcom-geni-se.c index a3ca53d4a11a..61190191efed 100644 --- a/drivers/platform/msm/qcom-geni-se.c +++ b/drivers/platform/msm/qcom-geni-se.c @@ -505,9 +505,12 @@ static int geni_se_select_dma_mode(void __iomem *base) geni_write_reg(0xFFFFFFFF, base, SE_IRQ_EN); common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN); - if (proto != UART) + if (proto != UART) { common_geni_m_irq_en &= ~(M_TX_FIFO_WATERMARK_EN | M_RX_FIFO_WATERMARK_EN); + if (proto != I3C) + common_geni_m_irq_en &= ~M_CMD_DONE_EN; + } geni_write_reg(common_geni_m_irq_en, base, SE_GENI_M_IRQ_EN); geni_dma_mode = geni_read_reg(base, SE_GENI_DMA_MODE_EN); @@ -626,6 +629,14 @@ EXPORT_SYMBOL(geni_setup_s_cmd); */ void geni_cancel_m_cmd(void __iomem *base) { + unsigned int common_geni_m_irq_en; + int proto = get_se_proto(base); + + if (proto != UART && proto != I3C) { + common_geni_m_irq_en = geni_read_reg(base, SE_GENI_M_IRQ_EN); + common_geni_m_irq_en &= ~M_CMD_DONE_EN; + geni_write_reg(common_geni_m_irq_en, base, SE_GENI_M_IRQ_EN); + } geni_write_reg(M_GENI_CMD_CANCEL, base, SE_GENI_M_CMD_CTRL_REG); } EXPORT_SYMBOL(geni_cancel_m_cmd); diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index e34fd70b67af..3add7b3f9658 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -366,7 +366,7 @@ check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; if (acpi_match_device_ids(dev, ids) == 0) - if (acpi_create_platform_device(dev, NULL)) + if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL))) dev_info(&dev->dev, "intel-hid: created platform device\n"); diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index 58c5ff36523a..d7fa2b88d27a 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -178,7 +178,7 @@ check_acpi_dev(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; if (acpi_match_device_ids(dev, ids) == 0) - if (acpi_create_platform_device(dev, NULL)) + if (!IS_ERR_OR_NULL(acpi_create_platform_device(dev, NULL))) dev_info(&dev->dev, "intel-vbtn: created platform device\n"); diff --git a/drivers/power/supply/88pm860x_battery.c b/drivers/power/supply/88pm860x_battery.c index 63c57dc82ac1..4eda5065b5bb 100644 --- a/drivers/power/supply/88pm860x_battery.c +++ b/drivers/power/supply/88pm860x_battery.c @@ -436,7 +436,7 @@ static void pm860x_init_battery(struct pm860x_battery_info *info) int ret; int data; int bat_remove; - int soc; + int soc = 0; /* measure enable on GPADC1 */ data = MEAS1_GP1; @@ -499,7 +499,9 @@ static void pm860x_init_battery(struct pm860x_battery_info *info) } mutex_unlock(&info->lock); - calc_soc(info, OCV_MODE_ACTIVE, &soc); + ret = calc_soc(info, OCV_MODE_ACTIVE, &soc); + if (ret < 0) + goto out; data = pm860x_reg_read(info->i2c, PM8607_POWER_UP_LOG); bat_remove = data & BAT_WU_LOG; diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c index 9807c42e572c..d54a2240f75b 100644 --- a/drivers/power/supply/qcom/smb-lib.c +++ b/drivers/power/supply/qcom/smb-lib.c @@ -725,6 +725,7 @@ static void smblib_uusb_removal(struct smb_charger *chg) vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0); vote(chg->hvdcp_hw_inov_dis_votable, OV_VOTER, false, 0); + vote(chg->usb_icl_votable, USBIN_USBIN_BOOST_VOTER, false, 0); cancel_delayed_work_sync(&chg->hvdcp_detect_work); @@ -1718,6 +1719,8 @@ int smblib_vbus_regulator_enable(struct regulator_dev *rdev) rc = _smblib_vbus_regulator_enable(rdev); if (rc >= 0) chg->otg_en = true; + else + vote(chg->usb_icl_votable, USBIN_USBIN_BOOST_VOTER, false, 0); unlock: mutex_unlock(&chg->otg_oc_lock); @@ -4390,6 +4393,7 @@ static void smblib_handle_typec_removal(struct smb_charger *chg) vote(chg->pl_enable_votable_indirect, USBIN_V_VOTER, false, 0); vote(chg->awake_votable, PL_DELAY_VOTER, false, 0); + vote(chg->usb_icl_votable, USBIN_USBIN_BOOST_VOTER, false, 0); chg->vconn_attempts = 0; chg->otg_attempts = 0; chg->pulse_cnt = 0; diff --git a/drivers/power/supply/qcom/smb1398-charger.c b/drivers/power/supply/qcom/smb1398-charger.c index d52d1410d7eb..62396c59a32e 100644 --- a/drivers/power/supply/qcom/smb1398-charger.c +++ b/drivers/power/supply/qcom/smb1398-charger.c @@ -1755,7 +1755,7 @@ static void smb1398_taper_work(struct work_struct *work) struct smb1398_chip *chip = container_of(work, struct smb1398_chip, taper_work); union power_supply_propval pval = {0}; - int rc, fcc_ua, fv_uv, stepper_ua, main_fcc_ua, min_ilim_ua; + int rc, fcc_ua, fv_uv, stepper_ua, main_fcc_ua = 0, min_ilim_ua; bool slave_en; if (!is_psy_voter_available(chip)) diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c index 31b01035d0ab..8cfba3614e60 100644 --- a/drivers/pwm/pwm-bcm-iproc.c +++ b/drivers/pwm/pwm-bcm-iproc.c @@ -85,8 +85,6 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, u64 tmp, multi, rate; u32 value, prescale; - rate = clk_get_rate(ip->clk); - value = readl(ip->base + IPROC_PWM_CTRL_OFFSET); if (value & BIT(IPROC_PWM_CTRL_EN_SHIFT(pwm->hwpwm))) @@ -99,6 +97,13 @@ static void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm, else state->polarity = PWM_POLARITY_INVERSED; + rate = clk_get_rate(ip->clk); + if (rate == 0) { + state->period = 0; + state->duty_cycle = 0; + return; + } + value = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET); prescale = value >> IPROC_PWM_PRESCALE_SHIFT(pwm->hwpwm); prescale &= IPROC_PWM_PRESCALE_MAX; diff --git a/drivers/rpmsg/rpm-smd.c b/drivers/rpmsg/rpm-smd.c index 42d77077bf01..2584dce47cb3 100644 --- a/drivers/rpmsg/rpm-smd.c +++ b/drivers/rpmsg/rpm-smd.c @@ -707,6 +707,24 @@ static struct msm_rpm_driver_data msm_rpm_data = { .smd_open = COMPLETION_INITIALIZER(msm_rpm_data.smd_open), }; +static int trysend_count = 20; +module_param(trysend_count, int, 0664); +static int msm_rpm_trysend_smd_buffer(char *buf, uint32_t size) +{ + int ret; + int count = 0; + + do { + ret = rpmsg_trysend(rpm->rpm_channel, buf, size); + if (!ret) + break; + udelay(10); + count++; + } while (count < trysend_count); + + return ret; +} + static int msm_rpm_flush_requests(bool print) { struct rb_node *t; @@ -724,7 +742,7 @@ static int msm_rpm_flush_requests(bool print) set_msg_id(s->buf, msm_rpm_get_next_msg_id()); - ret = rpmsg_send(rpm->rpm_channel, s->buf, get_buf_len(s->buf)); + ret = msm_rpm_trysend_smd_buffer(s->buf, get_buf_len(s->buf)); WARN_ON(ret != 0); trace_rpm_smd_send_sleep_set(get_msg_id(s->buf), type, id); diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 6fa07c246915..ae310d5ced10 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1559,6 +1559,10 @@ static void qeth_bridge_state_change(struct qeth_card *card, int extrasize; QETH_CARD_TEXT(card, 2, "brstchng"); + if (qports->num_entries == 0) { + QETH_CARD_TEXT(card, 2, "BPempty"); + return; + } if (qports->entry_length != sizeof(struct qeth_sbp_port_entry)) { QETH_CARD_TEXT_(card, 2, "BPsz%04x", qports->entry_length); return; diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c index edce5f3cfdba..93ba83e3148e 100644 --- a/drivers/scsi/arm/cumana_2.c +++ b/drivers/scsi/arm/cumana_2.c @@ -454,7 +454,7 @@ static int cumanascsi2_probe(struct expansion_card *ec, if (info->info.scsi.dma != NO_DMA) free_dma(info->info.scsi.dma); - free_irq(ec->irq, host); + free_irq(ec->irq, info); out_release: fas216_release(host); diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c index e93e047f4316..65bb34ce93b9 100644 --- a/drivers/scsi/arm/eesox.c +++ b/drivers/scsi/arm/eesox.c @@ -575,7 +575,7 @@ static int eesoxscsi_probe(struct expansion_card *ec, const struct ecard_id *id) if (info->info.scsi.dma != NO_DMA) free_dma(info->info.scsi.dma); - free_irq(ec->irq, host); + free_irq(ec->irq, info); out_remove: fas216_remove(host); diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c index 79aa88911b7f..b5e4a25ea1ef 100644 --- a/drivers/scsi/arm/powertec.c +++ b/drivers/scsi/arm/powertec.c @@ -382,7 +382,7 @@ static int powertecscsi_probe(struct expansion_card *ec, if (info->info.scsi.dma != NO_DMA) free_dma(info->info.scsi.dma); - free_irq(ec->irq, host); + free_irq(ec->irq, info); out_release: fas216_release(host); diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index 1753e42826dd..a880abf5abaa 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1044,6 +1044,8 @@ static void handle_error(struct mesh_state *ms) while ((in_8(&mr->bus_status1) & BS1_RST) != 0) udelay(1); printk("done\n"); + if (ms->dma_started) + halt_dma(ms); handle_reset(ms); /* request_q is empty, no point in mesh_start() */ return; @@ -1356,7 +1358,8 @@ static void halt_dma(struct mesh_state *ms) ms->conn_tgt, ms->data_ptr, scsi_bufflen(cmd), ms->tgts[ms->conn_tgt].data_goes_out); } - scsi_dma_unmap(cmd); + if (cmd) + scsi_dma_unmap(cmd); ms->dma_started = 0; } @@ -1711,6 +1714,9 @@ static int mesh_host_reset(struct scsi_cmnd *cmd) spin_lock_irqsave(ms->host->host_lock, flags); + if (ms->dma_started) + halt_dma(ms); + /* Reset the controller & dbdma channel */ out_le32(&md->control, (RUN|PAUSE|FLUSH|WAKE) << 16); /* stop dma */ out_8(&mr->exception, 0xff); /* clear all exception bits */ diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 30f77ca780fc..bfcfaadf28cc 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -4993,6 +4993,12 @@ static int __init scsi_debug_init(void) pr_err("submit_queues must be 1 or more\n"); return -EINVAL; } + + if ((sdebug_max_queue > SDEBUG_CANQUEUE) || (sdebug_max_queue < 1)) { + pr_err("max_queue must be in range [1, %d]\n", SDEBUG_CANQUEUE); + return -EINVAL; + } + sdebug_q_arr = kcalloc(submit_queues, sizeof(struct sdebug_queue), GFP_KERNEL); if (sdebug_q_arr == NULL) diff --git a/drivers/soc/qcom/hgsl/hgsl.c b/drivers/soc/qcom/hgsl/hgsl.c index 80f9b7436ca5..f459774e3911 100644 --- a/drivers/soc/qcom/hgsl/hgsl.c +++ b/drivers/soc/qcom/hgsl/hgsl.c @@ -31,7 +31,9 @@ #define HGSL_DEVICE_NAME "hgsl" #define HGSL_DEV_NUM 1 -#define MAX_DB_QUEUE 4 + +/* Support upto 3 GVMs: 3 DBQs(Low/Medium/High priority) per GVM */ +#define MAX_DB_QUEUE 9 #define IORESOURCE_HWINF "hgsl_reg_hwinf" #define IORESOURCE_GMUCX "hgsl_reg_gmucx" diff --git a/drivers/spi/spi-lantiq-ssc.c b/drivers/spi/spi-lantiq-ssc.c index d5976615d924..dc740b5f720b 100644 --- a/drivers/spi/spi-lantiq-ssc.c +++ b/drivers/spi/spi-lantiq-ssc.c @@ -187,6 +187,7 @@ struct lantiq_ssc_spi { unsigned int tx_fifo_size; unsigned int rx_fifo_size; unsigned int base_cs; + unsigned int fdx_tx_level; }; static u32 lantiq_ssc_readl(const struct lantiq_ssc_spi *spi, u32 reg) @@ -484,6 +485,7 @@ static void tx_fifo_write(struct lantiq_ssc_spi *spi) u32 data; unsigned int tx_free = tx_fifo_free(spi); + spi->fdx_tx_level = 0; while (spi->tx_todo && tx_free) { switch (spi->bits_per_word) { case 2 ... 8: @@ -512,6 +514,7 @@ static void tx_fifo_write(struct lantiq_ssc_spi *spi) lantiq_ssc_writel(spi, data, LTQ_SPI_TB); tx_free--; + spi->fdx_tx_level++; } } @@ -523,6 +526,13 @@ static void rx_fifo_read_full_duplex(struct lantiq_ssc_spi *spi) u32 data; unsigned int rx_fill = rx_fifo_level(spi); + /* + * Wait until all expected data to be shifted in. + * Otherwise, rx overrun may occur. + */ + while (rx_fill != spi->fdx_tx_level) + rx_fill = rx_fifo_level(spi); + while (rx_fill) { data = lantiq_ssc_readl(spi, LTQ_SPI_RB); diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c index 6044aacb7c79..fdf599f8974c 100644 --- a/drivers/spi/spidev.c +++ b/drivers/spi/spidev.c @@ -232,6 +232,11 @@ static int spidev_message(struct spidev_data *spidev, for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; n; n--, k_tmp++, u_tmp++) { + /* Ensure that also following allocations from rx_buf/tx_buf will meet + * DMA alignment requirements. + */ + unsigned int len_aligned = ALIGN(u_tmp->len, ARCH_KMALLOC_MINALIGN); + k_tmp->len = u_tmp->len; total += k_tmp->len; @@ -247,17 +252,17 @@ static int spidev_message(struct spidev_data *spidev, if (u_tmp->rx_buf) { /* this transfer needs space in RX bounce buffer */ - rx_total += k_tmp->len; + rx_total += len_aligned; if (rx_total > bufsiz) { status = -EMSGSIZE; goto done; } k_tmp->rx_buf = rx_buf; - rx_buf += k_tmp->len; + rx_buf += len_aligned; } if (u_tmp->tx_buf) { /* this transfer needs space in TX bounce buffer */ - tx_total += k_tmp->len; + tx_total += len_aligned; if (tx_total > bufsiz) { status = -EMSGSIZE; goto done; @@ -267,7 +272,7 @@ static int spidev_message(struct spidev_data *spidev, (uintptr_t) u_tmp->tx_buf, u_tmp->len)) goto done; - tx_buf += k_tmp->len; + tx_buf += len_aligned; } k_tmp->cs_change = !!u_tmp->cs_change; @@ -297,16 +302,16 @@ static int spidev_message(struct spidev_data *spidev, goto done; /* copy any rx data out of bounce buffer */ - rx_buf = spidev->rx_buffer; - for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) { + for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; + n; + n--, k_tmp++, u_tmp++) { if (u_tmp->rx_buf) { if (copy_to_user((u8 __user *) - (uintptr_t) u_tmp->rx_buf, rx_buf, + (uintptr_t) u_tmp->rx_buf, k_tmp->rx_buf, u_tmp->len)) { status = -EFAULT; goto done; } - rx_buf += u_tmp->len; } } status = total; diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 7b1c3843176a..3d1d6e379828 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -100,6 +100,15 @@ static DEFINE_MUTEX(ashmem_mutex); static struct kmem_cache *ashmem_area_cachep __read_mostly; static struct kmem_cache *ashmem_range_cachep __read_mostly; +/* + * A separate lockdep class for the backing shmem inodes to resolve the lockdep + * warning about the race between kswapd taking fs_reclaim before inode_lock + * and write syscall taking inode_lock and then fs_reclaim. + * Note that such race is impossible because ashmem does not support write + * syscalls operating on the backing shmem. + */ +static struct lock_class_key backing_shmem_inode_class; + static inline unsigned long range_size(struct ashmem_range *range) { return range->pgend - range->pgstart + 1; @@ -406,6 +415,7 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) if (!asma->file) { char *name = ASHMEM_NAME_DEF; struct file *vmfile; + struct inode *inode; if (asma->name[ASHMEM_NAME_PREFIX_LEN] != '\0') name = asma->name; @@ -417,6 +427,8 @@ static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) goto out; } vmfile->f_mode |= FMODE_LSEEK; + inode = file_inode(vmfile); + lockdep_set_class(&inode->i_rwsem, &backing_shmem_inode_class); asma->file = vmfile; /* * override mmap operation of the vmfile so that it can't be diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 614144927da9..4d44b61fde83 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -2,7 +2,7 @@ * drivers/staging/android/ion/ion_system_heap.c * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2020, The Linux Foundation. All rights reserved. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -423,11 +423,13 @@ err_free_sg2: buffer->private_flags |= ION_PRIV_FLAG_SHRINKER_FREE; if (vmid > 0) - ion_hyp_unassign_sg(table, &vmid, 1, true, false); + if (ion_hyp_unassign_sg(table, &vmid, 1, true, false)) + goto err_free_table_sync; for_each_sg(table->sgl, sg, table->nents, i) free_buffer_page(sys_heap, buffer, sg_page(sg), get_order(sg->length)); +err_free_table_sync: if (nents_sync) sg_free_table(&table_sync); err_free_sg: diff --git a/drivers/staging/fw-api/fw/htt.h b/drivers/staging/fw-api/fw/htt.h index da9101e4e106..f92938dfdffe 100644 --- a/drivers/staging/fw-api/fw/htt.h +++ b/drivers/staging/fw-api/fw/htt.h @@ -205,9 +205,10 @@ * 3.81 Add ppdu_start_tsf field in HTT_TX_WBM_COMPLETION_V2. * 3.82 Add WIN_SIZE field to HTT_T2H_MSG_TYPE_RX_DELBA msg. * 3.83 Shrink seq_idx field in HTT PPDU ID from 3 bits to 2. + * 3.84 Add fisa_control_bits_v2 def. */ #define HTT_CURRENT_VERSION_MAJOR 3 -#define HTT_CURRENT_VERSION_MINOR 83 +#define HTT_CURRENT_VERSION_MINOR 84 #define HTT_NUM_TX_FRAG_DESC 1024 @@ -6054,6 +6055,10 @@ PREPACK struct htt_h2t_msg_type_fisa_config_t { * [17:0] */ union { + /* + * fisa_control_bits structure is deprecated. + * Please use fisa_control_bits_v2 going forward. + */ struct { A_UINT32 fisa_enable: 1, ipsec_skip_search: 1, @@ -6072,6 +6077,11 @@ PREPACK struct htt_h2t_msg_type_fisa_config_t { fisa_aggr_limit: 4, reserved: 14; } fisa_control_bits; + struct { + A_UINT32 fisa_enable: 1, + fisa_aggr_limit: 4, + reserved: 27; + } fisa_control_bits_v2; A_UINT32 fisa_control_value; } u_fisa_control; @@ -6277,6 +6287,29 @@ PREPACK struct htt_h2t_msg_type_fisa_config_t { ((_var) |= ((_val) << HTT_RX_FISA_CONFIG_FISA_AGGR_LIMIT_S)); \ } while (0) +/* Dword 1: fisa_control_value fisa config */ +#define HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_M 0x00000001 +#define HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_S 0 +#define HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_GET(_var) \ + (((_var) & HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_M) >> \ + HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_S) +#define HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FISA_CONFIG_FISA_V2_ENABLE, _val); \ + ((_var) |= ((_val) << HTT_RX_FISA_CONFIG_FISA_V2_ENABLE_S)); \ + } while (0) + +/* Dword 1: fisa_control_value fisa_aggr_limit */ +#define HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_M 0x0000001e +#define HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_S 1 +#define HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_GET(_var) \ + (((_var) & HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_M) >> \ + HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_S) +#define HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_SET(_var, _val) \ + do { \ + HTT_CHECK_SET_VAL(HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT, _val); \ + ((_var) |= ((_val) << HTT_RX_FISA_CONFIG_FISA_V2_AGGR_LIMIT_S)); \ + } while (0) PREPACK struct htt_h2t_msg_rx_fse_setup_t { A_UINT32 msg_type:8, /* HTT_H2T_MSG_TYPE_RX_FSE_SETUP_CFG */ diff --git a/drivers/staging/fw-api/fw/wmi_unified.h b/drivers/staging/fw-api/fw/wmi_unified.h index d7f1ec7b3946..6bb8e967e5aa 100644 --- a/drivers/staging/fw-api/fw/wmi_unified.h +++ b/drivers/staging/fw-api/fw/wmi_unified.h @@ -8052,8 +8052,14 @@ typedef struct { A_UINT32 center_freq1; /** msecs the radio is awake (32 bits number accruing over time) */ A_UINT32 radio_awake_time; - /** msecs the CCA register is busy (32 bits number accruing over time) */ + /** msecs the CCA register is busy (32 bits number accruing over time) + * Includes rx_time but not tx_time. + */ A_UINT32 cca_busy_time; + /** msecs the radio is transmitting (32 bits number accruing over time) */ + A_UINT32 tx_time; + /** msecs the radio is in active receive (32 bits number accruing over time) */ + A_UINT32 rx_time; } wmi_channel_stats; /* @@ -9638,6 +9644,12 @@ typedef struct { * of assoc request/response */ #define WMI_UNIFIED_VDEV_START_LDPC_RX_ENABLED (1<<3) +/** Indicates HW encryption is disabled, and SW encryption is enabled. + * If This flag is set, indicates that HW encryption will be disabled + * and SW encryption will be enabled. + * If SW encryption is enabled, key plumbing will not happen in FW. + */ +#define WMI_UNIFIED_VDEV_START_HW_ENCRYPTION_DISABLED (1<<4) /* BSS color 0-6 */ #define WMI_HEOPS_COLOR_GET_D2(he_ops) WMI_GET_BITS(he_ops, 0, 6) @@ -14529,6 +14541,30 @@ typedef struct { A_UINT32 btk[ROAM_OFFLOAD_BTK_BYTES>>2]; /* BTK offload. As this 4 byte aligned, we don't declare it as tlv array */ } wmi_roam_ese_offload_tlv_param; +typedef enum { + WMI_BL_REASON_NUD_FAILURE = 1, + WMI_BL_REASON_STA_KICKOUT, + WMI_BL_REASON_ROAM_HO_FAILURE, + /* Assoc resp with status code 71 - POOR RSSI CONDITIONS */ + WMI_BL_REASON_ASSOC_REJECT_POOR_RSSI, + /* Assoc resp with status code 34 - DENIED_POOR_CHANNEL_CONDITIONS */ + WMI_BL_REASON_ASSOC_REJECT_OCE, + WMI_BL_REASON_USERSPACE_BL, + WMI_BL_REASON_USERSPACE_AVOID_LIST, + WMI_BL_REASON_BTM_DIASSOC_IMMINENT, + WMI_BL_REASON_BTM_BSS_TERMINATION, + WMI_BL_REASON_BTM_MBO_RETRY, + /* Reassoc resp with status code 34 - DENIED_POOR_CHANNEL_CONDITIONS */ + WMI_BL_REASON_REASSOC_RSSI_REJECT, + /* Reassoc resp with status code 17 - DENIED_NO_MORE_STAS */ + WMI_BL_REASON_REASSOC_NO_MORE_STAS, +} WMI_BLACKLIST_REASON_ID; + +typedef enum { + WMI_BL_SOURCE_HOST = 1, + WMI_BL_SOURCE_FW, +} WMI_BLACKLIST_SOURCE_ID; + typedef struct { /** TLV tag and len; tag equals WMITLV_TAG_STRUC_wmi_roam_blacklist_with_timeout_tlv_param */ A_UINT32 tlv_header; @@ -14538,6 +14574,18 @@ typedef struct { A_UINT32 timeout; /** rssi (dBm units) when put in blacklist */ A_INT32 rssi; + /* Blacklist reason from WMI_BLACKLIST_REASON_ID */ + A_UINT32 reason; + /* Source of adding AP to BL from WMI_BLACKLIST_SOURCE_ID */ + A_UINT32 source; + /* + * timestamp is the absolute time w.r.t host timer which is synchronized + * between the host and target. + * This timestamp indicates the time when AP added to blacklist. + */ + A_UINT32 timestamp; + /* Original timeout value in milli seconds when AP added to BL */ + A_UINT32 original_timeout; } wmi_roam_blacklist_with_timeout_tlv_param; /** WMI_ROAM_BLACKLIST_EVENT: generated whenever STA needs to move AP to blacklist for a particluar time @@ -28156,6 +28204,18 @@ typedef struct { A_UINT32 remaining_disallow_duration; /** AP will be allowed for candidate, when AP RSSI better than expected RSSI units in dBm */ A_INT32 expected_rssi; + /* Blacklist reason from WMI_BLACKLIST_REASON_ID */ + A_UINT32 reason; + /* Source of adding AP to BL from WMI_BLACKLIST_SOURCE_ID */ + A_UINT32 source; + /* + * timestamp is the absolute time w.r.t host timer which is synchronized + * between the host and target. + * This timestamp indicates the time when AP added to blacklist. + */ + A_UINT32 timestamp; + /* Original timeout value in milli seconds when AP added to BL */ + A_UINT32 original_timeout; } wmi_pdev_bssid_disallow_list_config_param; typedef enum { @@ -28390,6 +28450,10 @@ typedef struct { A_UINT32 vendor_specific1[7]; }; }; + /* BTM BSS termination timeout value in milli seconds */ + A_UINT32 btm_bss_termination_timeout; + /* BTM MBO assoc retry timeout value in milli seconds */ + A_UINT32 btm_mbo_assoc_retry_timeout; } wmi_roam_trigger_reason; typedef struct { @@ -28436,6 +28500,18 @@ typedef struct { A_UINT32 cu_score; /* AP current cu score */ A_UINT32 total_score; /* AP total score */ A_UINT32 etp; /* AP Estimated Throughput (ETP) value in mbps */ + /* Blacklist reason from WMI_BLACKLIST_REASON_ID */ + A_UINT32 bl_reason; + /* Source of adding AP to BL from WMI_BLACKLIST_SOURCE_ID */ + A_UINT32 bl_source; + /* + * timestamp is the absolute time w.r.t host timer which is synchronized + * between the host and target. + * This timestamp indicates the time when AP added to blacklist. + */ + A_UINT32 bl_timestamp; + /* Original timeout value in milli seconds when AP added to BL */ + A_UINT32 bl_original_timeout; } wmi_roam_ap_info; typedef enum { diff --git a/drivers/staging/fw-api/fw/wmi_version.h b/drivers/staging/fw-api/fw/wmi_version.h index 6be23827697f..1c9ece2f85a5 100644 --- a/drivers/staging/fw-api/fw/wmi_version.h +++ b/drivers/staging/fw-api/fw/wmi_version.h @@ -36,7 +36,7 @@ #define __WMI_VER_MINOR_ 0 /** WMI revision number has to be incremented when there is a * change that may or may not break compatibility. */ -#define __WMI_REVISION_ 869 +#define __WMI_REVISION_ 872 /** The Version Namespace should not be normally changed. Only * host and firmware of the same WMI namespace will work diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services.c b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services.c index f1551c36f80f..1baca29531a2 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/core/src/reg_services.c @@ -1911,6 +1911,11 @@ static uint16_t reg_compute_chan_to_freq(struct wlan_objmgr_pdev *pdev, return 0; } + if (min_chan_range < MIN_CHANNEL || max_chan_range > MAX_CHANNEL) { + reg_err("Channel range is invalid"); + return 0; + } + chan_list = pdev_priv_obj->mas_chan_list; for (count = min_chan_range; count <= max_chan_range; count++) { diff --git a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h index b1de2cf75b62..41bcc03473cb 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/regulatory/dispatcher/inc/reg_services_public_struct.h @@ -167,6 +167,9 @@ enum channel_enum { NUM_CHANNELS, + MIN_CHANNEL = CHAN_ENUM_1, + MAX_CHANNEL = (NUM_CHANNELS - 1), + MIN_24GHZ_CHANNEL = CHAN_ENUM_1, MAX_24GHZ_CHANNEL = CHAN_ENUM_14, NUM_24GHZ_CHANNELS = (MAX_24GHZ_CHANNEL - MIN_24GHZ_CHANNEL + 1), @@ -235,6 +238,9 @@ enum channel_enum { NUM_CHANNELS, + MIN_CHANNEL = CHAN_ENUM_1, + MAX_CHANNEL = (NUM_CHANNELS - 1), + MIN_24GHZ_CHANNEL = CHAN_ENUM_1, MAX_24GHZ_CHANNEL = CHAN_ENUM_14, NUM_24GHZ_CHANNELS = (MAX_24GHZ_CHANNEL - MIN_24GHZ_CHANNEL + 1), diff --git a/drivers/staging/qca-wifi-host-cmn/umac/tdls/core/src/wlan_tdls_cmds_process.c b/drivers/staging/qca-wifi-host-cmn/umac/tdls/core/src/wlan_tdls_cmds_process.c index a39954f01c3b..6ea0df8e2619 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/tdls/core/src/wlan_tdls_cmds_process.c +++ b/drivers/staging/qca-wifi-host-cmn/umac/tdls/core/src/wlan_tdls_cmds_process.c @@ -1718,12 +1718,23 @@ static QDF_STATUS tdls_config_force_peer( } feature = soc_obj->tdls_configs.tdls_feature_flags; - if (!TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) || + if (!(TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) || + TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(feature)) || !TDLS_IS_IMPLICIT_TRIG_ENABLED(feature)) { tdls_err("TDLS ext ctrl or Imp Trig not enabled, %x", feature); return QDF_STATUS_E_NOSUPPORT; } + /* + * In case of liberal external mode, supplicant will provide peer mac + * address but driver has to behave similar to implict mode ie. + * establish tdls link with any peer that supports tdls and meets stats. + */ + if (TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(feature)) { + tdls_debug("liberal mode set"); + return QDF_STATUS_SUCCESS; + } + peer_update_param = qdf_mem_malloc(sizeof(*peer_update_param)); if (!peer_update_param) { tdls_err("memory allocation failed"); @@ -1860,7 +1871,8 @@ QDF_STATUS tdls_process_remove_force_peer(struct tdls_oper_request *req) } feature = soc_obj->tdls_configs.tdls_feature_flags; - if (!TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) || + if (!(TDLS_IS_EXTERNAL_CONTROL_ENABLED(feature) || + TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(feature)) || !TDLS_IS_IMPLICIT_TRIG_ENABLED(feature)) { tdls_err("TDLS ext ctrl or Imp Trig not enabled, %x", feature); status = QDF_STATUS_E_NOSUPPORT; diff --git a/drivers/staging/qca-wifi-host-cmn/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h b/drivers/staging/qca-wifi-host-cmn/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h index 76d8498392f8..e645f6e1e522 100644 --- a/drivers/staging/qca-wifi-host-cmn/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h +++ b/drivers/staging/qca-wifi-host-cmn/umac/tdls/dispatcher/inc/wlan_tdls_public_structs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018, 2020 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -379,6 +379,11 @@ struct tx_frame { qdf_timer_t tx_timer; }; +enum tdls_configured_external_control { + TDLS_STRICT_EXTERNAL_CONTROL = 1, + TDLS_LIBERAL_EXTERNAL_CONTROL = 2, +}; + /** * enum tdls_feature_bit * @TDLS_FEATURE_OFF_CHANNEL: tdls off channel @@ -388,7 +393,8 @@ struct tx_frame { * @TDLS_FEATURE_SCAN: tdls scan * @TDLS_FEATURE_ENABLE: tdls enabled * @TDLS_FEAUTRE_IMPLICIT_TRIGGER: tdls implicit trigger - * @TDLS_FEATURE_EXTERNAL_CONTROL: tdls external control + * @TDLS_FEATURE_EXTERNAL_CONTROL: enforce strict tdls external control + * @TDLS_FEATURE_LIBERAL_EXTERNAL_CONTROL: liberal external tdls control */ enum tdls_feature_bit { TDLS_FEATURE_OFF_CHANNEL, @@ -398,7 +404,8 @@ enum tdls_feature_bit { TDLS_FEATURE_SCAN, TDLS_FEATURE_ENABLE, TDLS_FEAUTRE_IMPLICIT_TRIGGER, - TDLS_FEATURE_EXTERNAL_CONTROL + TDLS_FEATURE_EXTERNAL_CONTROL, + TDLS_FEATURE_LIBERAL_EXTERNAL_CONTROL, }; #define TDLS_IS_OFF_CHANNEL_ENABLED(flags) \ @@ -417,6 +424,8 @@ enum tdls_feature_bit { CHECK_BIT(flags, TDLS_FEAUTRE_IMPLICIT_TRIGGER) #define TDLS_IS_EXTERNAL_CONTROL_ENABLED(flags) \ CHECK_BIT(flags, TDLS_FEATURE_EXTERNAL_CONTROL) +#define TDLS_IS_LIBERAL_EXTERNAL_CONTROL_ENABLED(flags) \ + CHECK_BIT(flags, TDLS_FEATURE_LIBERAL_EXTERNAL_CONTROL) /** * struct tdls_user_config - TDLS user configuration diff --git a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c index 015484e47c06..410fa1cea5cb 100644 --- a/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c +++ b/drivers/staging/qca-wifi-host-cmn/wmi/src/wmi_unified_tlv.c @@ -6465,12 +6465,61 @@ wmi_fill_sae_single_pmk_param(struct roam_offload_scan_params *params, roam_offload_11i->flags |= 1 << WMI_ROAM_OFFLOAD_FLAG_SAE_SAME_PMKID; } + +/** + * fill_roam_offload_11r_params() - Fill roam scan params to send it to fw + * @auth_mode: Authentication mode + * @roam_offload_11r: TLV to be filled with 11r params + * @roam_req: roam request param + */ +static void +fill_roam_offload_11r_params(u32 auth_mode, + wmi_roam_11r_offload_tlv_param *roam_offload_11r, + struct roam_offload_scan_params *roam_req) +{ + u8 *psk_msk, len; + + if (auth_mode == WMI_AUTH_FT_RSNA_FILS_SHA256 || + auth_mode == WMI_AUTH_FT_RSNA_FILS_SHA384) { + psk_msk = roam_req->roam_fils_params.fils_ft; + len = roam_req->roam_fils_params.fils_ft_len; + } else { + psk_msk = roam_req->psk_pmk; + len = roam_req->pmk_len; + } + + /* + * For SHA384 based akm, the pmk length is 48 bytes. So fill + * first 32 bytes in roam_offload_11r->psk_msk and the remaining + * bytes in roam_offload_11r->psk_msk_ext buffer + */ + roam_offload_11r->psk_msk_len = len > ROAM_OFFLOAD_PSK_MSK_BYTES ? + ROAM_OFFLOAD_PSK_MSK_BYTES : len; + qdf_mem_copy(roam_offload_11r->psk_msk, psk_msk, + roam_offload_11r->psk_msk_len); + roam_offload_11r->psk_msk_ext_len = 0; + + if (len > ROAM_OFFLOAD_PSK_MSK_BYTES) { + roam_offload_11r->psk_msk_ext_len = + len - roam_offload_11r->psk_msk_len; + qdf_mem_copy(roam_offload_11r->psk_msk_ext, + &psk_msk[roam_offload_11r->psk_msk_len], + roam_offload_11r->psk_msk_ext_len); + } +} #else static inline void wmi_fill_sae_single_pmk_param(struct roam_offload_scan_params *params, wmi_roam_11i_offload_tlv_param *roam_offload_11i) { } + +static void +fill_roam_offload_11r_params(u32 auth_mode, + wmi_roam_11r_offload_tlv_param *roam_offload_11r, + struct roam_offload_scan_params *roam_req) +{ +} #endif #define ROAM_OFFLOAD_PMK_EXT_BYTES 16 @@ -6486,10 +6535,10 @@ wmi_fill_sae_single_pmk_param(struct roam_offload_scan_params *params, * * Return: QDF status */ -static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, - wmi_start_scan_cmd_fixed_param * - scan_cmd_fp, - struct roam_offload_scan_params *roam_req) +static QDF_STATUS +send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, + wmi_start_scan_cmd_fixed_param *scan_cmd_fp, + struct roam_offload_scan_params *roam_req) { wmi_buf_t buf = NULL; QDF_STATUS status; @@ -6517,58 +6566,61 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, sizeof(wmi_start_scan_cmd_fixed_param); #ifdef WLAN_FEATURE_ROAM_OFFLOAD wmi_debug("auth_mode = %d", auth_mode); - if (roam_req->is_roam_req_valid && - roam_req->roam_offload_enabled) { - len += sizeof(wmi_roam_offload_tlv_param); + if (roam_req->is_roam_req_valid && + roam_req->roam_offload_enabled) { + len += sizeof(wmi_roam_offload_tlv_param); + len += WMI_TLV_HDR_SIZE; + if ((auth_mode != WMI_AUTH_NONE) && + ((auth_mode != WMI_AUTH_OPEN) || + (auth_mode == WMI_AUTH_OPEN && + roam_req->mdid.mdie_present && + roam_req->is_11r_assoc) || + roam_req->is_ese_assoc)) { len += WMI_TLV_HDR_SIZE; - if ((auth_mode != WMI_AUTH_NONE) && - ((auth_mode != WMI_AUTH_OPEN) || + if (roam_req->is_ese_assoc) + len += sizeof(wmi_roam_ese_offload_tlv_param); + else if ((auth_mode == WMI_AUTH_FT_RSNA) || + (auth_mode == WMI_AUTH_FT_RSNA_PSK) || + (auth_mode == WMI_AUTH_FT_RSNA_SAE) || + (auth_mode == + WMI_AUTH_FT_RSNA_SUITE_B_8021X_SHA384) || + (auth_mode == + WMI_AUTH_FT_RSNA_FILS_SHA256) || + (auth_mode == + WMI_AUTH_FT_RSNA_FILS_SHA384) || (auth_mode == WMI_AUTH_OPEN && roam_req->mdid.mdie_present && - roam_req->is_11r_assoc) || - roam_req->is_ese_assoc)) { - len += WMI_TLV_HDR_SIZE; - if (roam_req->is_ese_assoc) - len += - sizeof(wmi_roam_ese_offload_tlv_param); - else if (auth_mode == WMI_AUTH_FT_RSNA || - auth_mode == WMI_AUTH_FT_RSNA_PSK || - (auth_mode == WMI_AUTH_OPEN && - roam_req->mdid.mdie_present && - roam_req->is_11r_assoc)) - len += - sizeof(wmi_roam_11r_offload_tlv_param); - else - len += - sizeof(wmi_roam_11i_offload_tlv_param); - } else { - len += WMI_TLV_HDR_SIZE; - } - - len += (sizeof(*assoc_ies) + (2*WMI_TLV_HDR_SIZE) - + roundup(roam_req->assoc_ie_length, - sizeof(uint32_t))); - - if (roam_req->add_fils_tlv) { - fils_tlv_len = sizeof( - wmi_roam_fils_offload_tlv_param); - len += WMI_TLV_HDR_SIZE + fils_tlv_len; - } + roam_req->is_11r_assoc)) + len += sizeof(wmi_roam_11r_offload_tlv_param); + else + len += sizeof(wmi_roam_11i_offload_tlv_param); } else { - if (roam_req->is_roam_req_valid) - WMI_LOGD("%s : roam offload = %d", - __func__, roam_req->roam_offload_enabled); - len += (4 * WMI_TLV_HDR_SIZE); + len += WMI_TLV_HDR_SIZE; } - if (roam_req->is_roam_req_valid && - roam_req->roam_offload_enabled) { - roam_req->mode = roam_req->mode | - WMI_ROAM_SCAN_MODE_ROAMOFFLOAD; + + len += (sizeof(*assoc_ies) + (2 * WMI_TLV_HDR_SIZE) + + roundup(roam_req->assoc_ie_length, sizeof(uint32_t))); + + if (roam_req->add_fils_tlv) { + fils_tlv_len = sizeof(wmi_roam_fils_offload_tlv_param); + len += WMI_TLV_HDR_SIZE + fils_tlv_len; } + } else { + if (roam_req->is_roam_req_valid) + WMI_LOGD("%s : roam offload = %d", __func__, + roam_req->roam_offload_enabled); + else + WMI_LOGD("%s : roam_req is NULL", __func__); + + len += (4 * WMI_TLV_HDR_SIZE); + } + + if (roam_req->is_roam_req_valid && roam_req->roam_offload_enabled) + roam_req->mode |= WMI_ROAM_SCAN_MODE_ROAMOFFLOAD; #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ - if (roam_req->mode == (WMI_ROAM_SCAN_MODE_NONE - |WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) + if (roam_req->mode == + (WMI_ROAM_SCAN_MODE_NONE | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) len = sizeof(wmi_roam_scan_mode_fixed_param); buf = wmi_buf_alloc(wmi_handle, len); @@ -6582,7 +6634,7 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, WMITLV_SET_HDR(&roam_scan_mode_fp->tlv_header, WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param, WMITLV_GET_STRUCT_TLVLEN - (wmi_roam_scan_mode_fixed_param)); + (wmi_roam_scan_mode_fixed_param)); roam_scan_mode_fp->min_delay_roam_trigger_reason_bitmask = roam_req->roam_trigger_reason_bitmask; @@ -6590,8 +6642,8 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, WMI_SEC_TO_MSEC(roam_req->min_delay_btw_roam_scans); roam_scan_mode_fp->roam_scan_mode = roam_req->mode; roam_scan_mode_fp->vdev_id = roam_req->vdev_id; - if (roam_req->mode == (WMI_ROAM_SCAN_MODE_NONE | - WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) { + if (roam_req->mode == + (WMI_ROAM_SCAN_MODE_NONE | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) { roam_scan_mode_fp->flags |= WMI_ROAM_SCAN_MODE_FLAG_REPORT_STATUS; goto send_roam_scan_mode_cmd; @@ -6607,7 +6659,7 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, WMITLV_GET_STRUCT_TLVLEN - (wmi_start_scan_cmd_fixed_param)); + (wmi_start_scan_cmd_fixed_param)); #ifdef WLAN_FEATURE_ROAM_OFFLOAD buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param); if (roam_req->is_roam_req_valid && roam_req->roam_offload_enabled) { @@ -6688,11 +6740,18 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, (wmi_roam_ese_offload_tlv_param)); buf_ptr += sizeof(wmi_roam_ese_offload_tlv_param); - } else if (auth_mode == WMI_AUTH_FT_RSNA - || auth_mode == WMI_AUTH_FT_RSNA_PSK - || (auth_mode == WMI_AUTH_OPEN - && roam_req->mdid.mdie_present && - roam_req->is_11r_assoc)) { + } else if (auth_mode == WMI_AUTH_FT_RSNA || + auth_mode == WMI_AUTH_FT_RSNA_PSK || + auth_mode == WMI_AUTH_FT_RSNA_SAE || + (auth_mode == + WMI_AUTH_FT_RSNA_SUITE_B_8021X_SHA384) || + (auth_mode == + WMI_AUTH_FT_RSNA_FILS_SHA256) || + (auth_mode == + WMI_AUTH_FT_RSNA_FILS_SHA384) || + (auth_mode == WMI_AUTH_OPEN && + roam_req->mdid.mdie_present && + roam_req->is_11r_assoc)) { WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); buf_ptr += WMI_TLV_HDR_SIZE; @@ -6706,11 +6765,9 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, qdf_mem_copy(roam_offload_11r->r0kh_id, roam_req->rokh_id, roam_offload_11r->r0kh_id_len); - qdf_mem_copy(roam_offload_11r->psk_msk, - roam_req->psk_pmk, - sizeof(roam_req->psk_pmk)); - roam_offload_11r->psk_msk_len = - roam_req->pmk_len; + fill_roam_offload_11r_params(auth_mode, + roam_offload_11r, + roam_req); roam_offload_11r->mdie_present = roam_req->mdid.mdie_present; roam_offload_11r->mdid = @@ -6732,8 +6789,9 @@ static QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, WMITLV_GET_STRUCT_TLVLEN(0)); buf_ptr += WMI_TLV_HDR_SIZE; - WMI_LOGD("psk_msk_len = %d", - roam_offload_11r->psk_msk_len); + WMI_LOGD("psk_msk_len = %d psk_msk_ext:%d", + roam_offload_11r->psk_msk_len, + roam_offload_11r->psk_msk_ext_len); if (roam_offload_11r->psk_msk_len) QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, @@ -6866,12 +6924,8 @@ send_roam_scan_mode_cmd: wmi_mtrace(WMI_ROAM_SCAN_MODE, NO_SESSION, 0); status = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_ROAM_SCAN_MODE); - if (QDF_IS_STATUS_ERROR(status)) { - WMI_LOGE( - "wmi_unified_cmd_send WMI_ROAM_SCAN_MODE returned Error %d", - status); + if (QDF_IS_STATUS_ERROR(status)) wmi_buf_free(buf); - } return status; } @@ -9815,6 +9869,14 @@ static QDF_STATUS send_stats_ext_req_cmd_tlv(wmi_unified_t wmi_handle, wmi_buf_t buf; size_t len; uint8_t *buf_ptr; + uint16_t max_wmi_msg_size = wmi_get_max_msg_len(wmi_handle); + + if (preq->request_data_len > (max_wmi_msg_size - WMI_TLV_HDR_SIZE - + sizeof(*cmd))) { + wmi_err("Data length=%d is greater than max wmi msg size", + preq->request_data_len); + return QDF_STATUS_E_FAILURE; + } len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + preq->request_data_len; diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mon_thread.h b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mon_thread.h index 006fa0a0854e..630d92201d98 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mon_thread.h +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/inc/wlan_pkt_capture_mon_thread.h @@ -28,6 +28,7 @@ #define PKT_CAPTURE_RX_POST_EVENT 0x01 #define PKT_CAPTURE_RX_SUSPEND_EVENT 0x02 #define PKT_CAPTURE_RX_SHUTDOWN_EVENT 0x04 +#define PKT_CAPTURE_REGISTER_EVENT 0x08 /* * Maximum number of packets to be allocated for @@ -81,6 +82,7 @@ struct pkt_capture_mon_pkt { * @suspend_mon_event: Completion to suspend packet capture MON thread * @resume_mon_event: Completion to resume packet capture MON thread * @mon_shutdown: Completion for packet capture MON thread shutdown + * @mon_register_event: Completion for packet capture register * @mon_wait_queue: Waitq for packet capture MON thread * @mon_event_flag: Mon event flag * @mon_thread_queue: MON buffer queue @@ -97,6 +99,7 @@ struct pkt_capture_mon_context { struct completion suspend_mon_event; struct completion resume_mon_event; struct completion mon_shutdown; + struct completion mon_register_event; wait_queue_head_t mon_wait_queue; unsigned long mon_event_flag; struct list_head mon_thread_queue; diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c index 8bd6de1ed1bf..2f62dcd1628c 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_main.c @@ -99,6 +99,13 @@ pkt_capture_register_callbacks(struct wlan_objmgr_vdev *vdev, if (QDF_IS_STATUS_ERROR(status)) goto register_ev_handlers_fail; + /* + * set register event bit so that mon thread will start + * processing packets in queue. + */ + set_bit(PKT_CAPTURE_REGISTER_EVENT, + &vdev_priv->mon_ctx->mon_event_flag); + mode = pkt_capture_get_mode(psoc); status = tgt_pkt_capture_send_mode(vdev, mode); if (QDF_IS_STATUS_ERROR(status)) { @@ -149,6 +156,23 @@ QDF_STATUS pkt_capture_deregister_callbacks(struct wlan_objmgr_vdev *vdev) if (QDF_IS_STATUS_ERROR(status)) pkt_capture_err("Unable to send packet capture mode to fw"); + /* + * Clear packet capture register event so that mon thread will + * stop processing packets in queue. + */ + clear_bit(PKT_CAPTURE_REGISTER_EVENT, + &vdev_priv->mon_ctx->mon_event_flag); + set_bit(PKT_CAPTURE_RX_POST_EVENT, + &vdev_priv->mon_ctx->mon_event_flag); + wake_up_interruptible(&vdev_priv->mon_ctx->mon_wait_queue); + + /* + * Wait till current packet process completes in mon thread and + * flush the remaining packet in queue. + */ + wait_for_completion(&vdev_priv->mon_ctx->mon_register_event); + pkt_capture_drop_monpkt(vdev_priv->mon_ctx); + status = tgt_pkt_capture_unregister_ev_handler(vdev); if (QDF_IS_STATUS_ERROR(status)) pkt_capture_err("Unable to unregister event handlers"); diff --git a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c index f8c2a62a191e..a37eb1963732 100644 --- a/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c +++ b/drivers/staging/qcacld-3.0/components/pkt_capture/core/src/wlan_pkt_capture_mon_thread.c @@ -324,7 +324,17 @@ static int pkt_capture_mon_thread(void *arg) shutdown = true; break; } - pkt_capture_process_from_queue(mon_ctx); + + /* + * if packet capture deregistratin happens stop + * processing packets in queue because mon cb will + * be set to NULL. + */ + if (test_bit(PKT_CAPTURE_REGISTER_EVENT, + &mon_ctx->mon_event_flag)) + pkt_capture_process_from_queue(mon_ctx); + else + complete(&mon_ctx->mon_register_event); if (test_bit(PKT_CAPTURE_RX_SUSPEND_EVENT, &mon_ctx->mon_event_flag)) { @@ -351,7 +361,7 @@ void pkt_capture_close_mon_thread(struct pkt_capture_mon_context *mon_ctx) if (!mon_ctx->mon_thread) return; - /* Shut down Tlshim Rx thread */ + /* Shut down mon thread */ set_bit(PKT_CAPTURE_RX_SHUTDOWN_EVENT, &mon_ctx->mon_event_flag); set_bit(PKT_CAPTURE_RX_POST_EVENT, @@ -487,6 +497,7 @@ pkt_capture_alloc_mon_thread(struct pkt_capture_mon_context *mon_ctx) init_completion(&mon_ctx->suspend_mon_event); init_completion(&mon_ctx->resume_mon_event); init_completion(&mon_ctx->mon_shutdown); + init_completion(&mon_ctx->mon_register_event); mon_ctx->mon_event_flag = 0; spin_lock_init(&mon_ctx->mon_queue_lock); spin_lock_init(&mon_ctx->mon_pkt_freeq_lock); diff --git a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfg.h b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfg.h index 29aa08e1e0b5..5bdec5d1a6d8 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfg.h +++ b/drivers/staging/qcacld-3.0/core/hdd/inc/wlan_hdd_cfg.h @@ -6932,7 +6932,7 @@ enum hdd_link_speed_rpt_type { * * gTDLSExternalControl - Enable external TDLS control. * @Min: 0 - * @Max: 1 + * @Max: 2 * @Default: 1 * * This ini is used to enable/disable external TDLS control. @@ -6940,6 +6940,12 @@ enum hdd_link_speed_rpt_type { * control allows a user to add a MAC address of potential TDLS peers so * that the CLD driver can initiate implicit TDLS setup to only those peers * when criteria for TDLS setup (throughput and RSSI threshold) is met. + * There are two flavors of external control supported. If control default + * is set 1 it means strict external control where only for configured + * tdls peer mac address tdls link will be established. If control default + * is set 2 it means liberal tdls external control needed. It means + * tdls link will be established with configured peer mac address as well + * as any other peer which supports tdls. * * Related: gEnableTDLSSupport, gEnableTDLSImplicitTrigger. * @@ -6951,7 +6957,7 @@ enum hdd_link_speed_rpt_type { */ #define CFG_TDLS_EXTERNAL_CONTROL "gTDLSExternalControl" #define CFG_TDLS_EXTERNAL_CONTROL_MIN (0) -#define CFG_TDLS_EXTERNAL_CONTROL_MAX (1) +#define CFG_TDLS_EXTERNAL_CONTROL_MAX (2) #define CFG_TDLS_EXTERNAL_CONTROL_DEFAULT (1) /* @@ -18166,7 +18172,7 @@ struct hdd_config { uint32_t fTDLSRxFrameThreshold; uint32_t fTDLSPuapsdPTIWindow; uint32_t fTDLSPuapsdPTRTimeout; - bool fTDLSExternalControl; + uint8_t fTDLSExternalControl; uint32_t fEnableTDLSOffChannel; uint32_t fEnableTDLSWmmMode; uint8_t fTDLSPrefOffChanNum; diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c index 56b8df7012cd..85fd7885052a 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_cfg80211.c @@ -21600,7 +21600,7 @@ static int __wlan_hdd_cfg80211_connect(struct wiphy *wiphy, * Check if this is reassoc to same bssid, if reassoc is success, return */ status = wlan_hdd_reassoc_bssid_hint(adapter, req); - if (!status) + if (!status || status == -EPERM) return status; /* Try disconnecting if already in connected state */ diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c index d1df160920cf..d5c658f8091e 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_driver_ops.c @@ -1519,12 +1519,10 @@ static void wlan_hdd_set_the_pld_uevent(struct pld_uevent_data *uevent) { switch (uevent->uevent) { case PLD_RECOVERY: - cds_set_target_ready(false); - cds_set_recovery_in_progress(true); - break; case PLD_FW_DOWN: cds_set_target_ready(false); cds_set_recovery_in_progress(true); + qdf_complete_wait_events(); break; case PLD_FW_HANG_EVENT: break; @@ -1565,17 +1563,13 @@ static void wlan_hdd_handle_the_pld_uevent(struct pld_uevent_data *uevent) switch (uevent->uevent) { case PLD_RECOVERY: - cds_set_target_ready(false); hdd_pld_ipa_uc_shutdown_pipes(); - qdf_complete_wait_events(); break; case PLD_FW_DOWN: - cds_set_target_ready(false); wlan_cfg80211_cleanup_scan_queue(hdd_ctx->pdev, NULL); if (pld_is_fw_rejuvenate(hdd_ctx->parent_dev) && ucfg_ipa_is_enabled()) ucfg_ipa_fw_rejuvenate_send_msg(hdd_ctx->pdev); - qdf_complete_wait_events(); break; case PLD_FW_HANG_EVENT: hdd_info("Received fimrware hang event"); @@ -1633,6 +1627,7 @@ static void wlan_hdd_pld_uevent(struct device *dev, wlan_hdd_set_the_pld_uevent(uevent); hdd_psoc_idle_timer_stop(hdd_ctx); + mutex_lock(&hdd_init_deinit_lock); wlan_hdd_handle_the_pld_uevent(uevent); mutex_unlock(&hdd_init_deinit_lock); diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c index 05bab5bf5a2a..98e24282c5c3 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_ioctl.c @@ -831,6 +831,31 @@ QDF_STATUS hdd_wma_send_fastreassoc_cmd(struct hdd_adapter *adapter, } #endif +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 9, 0)) +/** + * hdd_is_fast_reassoc_allowed - check if roam offload is enabled on the given + * vdev else, don't allow roam invoke to be triggered. + * @mac_handle: Opaque mac handle + * @vdev_id: vdev_id + * + * This API should return true if kernel version is less than 4.9, because + * the earlier versions don't have the fix to handle reassociation failure. + * + * Return: true if roaming module initialization is done else false + */ +static bool +hdd_is_fast_reassoc_allowed(mac_handle_t mac_handle, uint8_t vdev_id) +{ + return sme_is_fast_reassoc_allowed(mac_handle, vdev_id); +} +#else +static inline bool +hdd_is_fast_reassoc_allowed(mac_handle_t mac_handle, uint8_t vdev_id) +{ + return true; +} +#endif + /** * hdd_reassoc() - perform a userspace-directed reassoc * @adapter: Adapter upon which the command was received @@ -901,6 +926,13 @@ int hdd_reassoc(struct hdd_adapter *adapter, const uint8_t *bssid, /* Proceed with reassoc */ if (roaming_offload_enabled(hdd_ctx)) { + if (!hdd_is_fast_reassoc_allowed(adapter->hdd_ctx->mac_handle, + adapter->session_id)) { + hdd_err("LFR3: vdev[%d] RSO is not enabled", + adapter->session_id); + ret = -EPERM; + goto exit; + } status = hdd_wma_send_fastreassoc_cmd(adapter, bssid, (int)channel); if (status != QDF_STATUS_SUCCESS) { diff --git a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c index 492ba06ea00a..565a8458f82d 100644 --- a/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c +++ b/drivers/staging/qcacld-3.0/core/hdd/src/wlan_hdd_main.c @@ -1165,8 +1165,10 @@ static int hdd_update_tdls_config(struct hdd_context *hdd_ctx) (cfg->fEnableTDLSSupport ? 1 << TDLS_FEATURE_ENABLE : 0) | (cfg->fEnableTDLSImplicitTrigger ? 1 << TDLS_FEAUTRE_IMPLICIT_TRIGGER : 0) | - (cfg->fTDLSExternalControl ? - 1 << TDLS_FEATURE_EXTERNAL_CONTROL : 0)); + (cfg->fTDLSExternalControl & TDLS_STRICT_EXTERNAL_CONTROL ? + 1 << TDLS_FEATURE_EXTERNAL_CONTROL : 0) | + (cfg->fTDLSExternalControl & TDLS_LIBERAL_EXTERNAL_CONTROL ? + 1 << TDLS_FEATURE_LIBERAL_EXTERNAL_CONTROL : 0 )); config->tdls_vdev_nss_2g = GET_VDEV_NSS_CHAIN(cfg->rx_nss_2g, QDF_TDLS_MODE); config->tdls_vdev_nss_5g = GET_VDEV_NSS_CHAIN(cfg->rx_nss_5g, @@ -7443,8 +7445,20 @@ QDF_STATUS hdd_start_all_adapters(struct hdd_context *hdd_ctx) } hdd_start_station_adapter(adapter); hdd_set_mon_rx_cb(adapter->dev); - wlan_hdd_set_mon_chan(adapter, adapter->mon_chan, - adapter->mon_bandwidth); + + /* + * Do not set channel for monitor mode if monitor iface + * went down during SSR, as for set channels host sends + * vdev start command to FW. For the interfaces went + * down during SSR, host stops those adapters by sending + * vdev stop/down/delete commands to FW. So FW doesn't + * sends response for vdev start and vdev start response + * timer expires and thus host triggers ASSERT. + */ + if (!test_bit(DOWN_DURING_SSR, &adapter->event_flags)) + wlan_hdd_set_mon_chan( + adapter, adapter->mon_chan, + adapter->mon_bandwidth); break; default: break; @@ -14056,6 +14070,17 @@ static int wlan_hdd_state_ctrl_param_open(struct inode *inode, return 0; } +static void hdd_inform_wifi_off(void) +{ + struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD); + + if (!hdd_ctx || !hdd_ctx->mac_handle) { + hdd_err("Invalid hdd/pdev context"); + return; + } + sme_free_blacklist(hdd_ctx->mac_handle); +} + static int hdd_driver_load(void); static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp, const char __user *user_buf, @@ -14075,6 +14100,7 @@ static ssize_t wlan_hdd_state_ctrl_param_write(struct file *filp, if (strncmp(buf, wlan_off_str, strlen(wlan_off_str)) == 0) { pr_debug("Wifi turning off from UI\n"); + hdd_inform_wifi_off(); goto exit; } @@ -16458,7 +16484,6 @@ bool wlan_hdd_check_mon_concurrency(void) void wlan_hdd_del_monitor(struct hdd_context *hdd_ctx, struct hdd_adapter *adapter, bool rtnl_held) { - ucfg_pkt_capture_deregister_callbacks(adapter->vdev); wlan_hdd_release_intf_addr(hdd_ctx, adapter->mac_addr.bytes); hdd_stop_adapter(hdd_ctx, adapter); hdd_close_adapter(hdd_ctx, adapter, true); diff --git a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h index cf9473de94f2..0c905b94a313 100644 --- a/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h +++ b/drivers/staging/qcacld-3.0/core/mac/inc/qwlan_version.h @@ -32,9 +32,9 @@ #define QWLAN_VERSION_MAJOR 5 #define QWLAN_VERSION_MINOR 2 #define QWLAN_VERSION_PATCH 03 -#define QWLAN_VERSION_EXTRA "I" +#define QWLAN_VERSION_EXTRA "X" #define QWLAN_VERSION_BUILD 29 -#define QWLAN_VERSIONSTR "5.2.03.29I" +#define QWLAN_VERSIONSTR "5.2.03.29X" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/qcacld-3.0/core/mac/src/cfg/cfgUtil/dot11f.frms b/drivers/staging/qcacld-3.0/core/mac/src/cfg/cfgUtil/dot11f.frms index 2a26f1c2e3e9..45acee437934 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/cfg/cfgUtil/dot11f.frms +++ b/drivers/staging/qcacld-3.0/core/mac/src/cfg/cfgUtil/dot11f.frms @@ -4031,7 +4031,7 @@ FRAME RadioMeasurementRequest FF DialogToken; FF NumOfRepetitions; //Measurement Request IE. - MANDIE MeasurementRequest[1..2]; + MANDIE MeasurementRequest[1..5]; } FRAME RadioMeasurementReport diff --git a/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h b/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h index 2700c0f6332a..ae403351014c 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/include/dot11f.h @@ -26,7 +26,7 @@ * * * This file was automatically generated by 'framesc' - * Wed Feb 12 20:42:23 2020 from the following file(s): + * Mon Jun 8 09:41:47 2020 from the following file(s): * * dot11f.frms * @@ -10347,7 +10347,7 @@ typedef struct sDot11fRadioMeasurementRequest{ tDot11fFfDialogToken DialogToken; tDot11fFfNumOfRepetitions NumOfRepetitions; uint16_t num_MeasurementRequest; - tDot11fIEMeasurementRequest MeasurementRequest[2]; + tDot11fIEMeasurementRequest MeasurementRequest[5]; } tDot11fRadioMeasurementRequest; #define DOT11F_RADIOMEASUREMENTREQUEST (25) diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_api.h b/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_api.h index f154666d42fd..34bd6f0f64c8 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_api.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_api.h @@ -101,4 +101,22 @@ rrm_process_beacon_report_xmit(tpAniSirGlobal pMac, void lim_update_rrm_capability(tpAniSirGlobal mac_ctx, tpSirSmeJoinReq join_req); +/** + * rrm_reject_req - Reject rrm request + * @radiomes_report: radio measurement report + * @rrm_req: Array of Measurement request IEs + * @num_report: Num of report + * @index: Measurement index + * @measurement_type: Measurement Type + * + * Reject the Radio Resource Measurement request, if one is + * already in progress + * + * Return: QDF_STATUS + */ +QDF_STATUS rrm_reject_req(tpSirMacRadioMeasureReport *radiomes_report, + tDot11fRadioMeasurementRequest *rrm_req, + uint8_t *num_report, uint8_t index, + uint8_t measurement_type); + #endif diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_global.h b/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_global.h index 057eab251cc6..378f37afe315 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_global.h +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/include/rrm_global.h @@ -27,7 +27,9 @@ ========================================================================*/ -#define MAX_MEASUREMENT_REQUEST 2 +#define MAX_MEASUREMENT_REQUEST 5 +#define MAX_NUM_CHANNELS 255 + #define DEFAULT_RRM_IDX 0 typedef enum eRrmRetStatus { @@ -218,6 +220,8 @@ typedef struct sRrmPEContext { uint8_t DialogToken; uint16_t prev_rrm_report_seq_num; tpRRMReq pCurrentReq[MAX_MEASUREMENT_REQUEST]; + uint8_t beacon_rpt_chan_list[MAX_NUM_CHANNELS]; + uint8_t beacon_rpt_chan_num; } tRrmPEContext, *tpRrmPEContext; /* 2008 11k spec reference: 18.4.8.5 RCPI Measurement */ diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c index 78ab23f5b9b1..5cf505bd1af2 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/lim/lim_process_assoc_req_frame.c @@ -1854,7 +1854,7 @@ void lim_process_assoc_cleanup(tpAniSirGlobal mac_ctx, qdf_mem_free(assoc_req); /* to avoid double free */ - if (assoc_req_copied && session->parsedAssocReq) + if (sta_ds && assoc_req_copied && session->parsedAssocReq) session->parsedAssocReq[sta_ds->assocId] = NULL; } diff --git a/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c b/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c index c24bb529de42..a9a8898ea47e 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/pe/rrm/rrm_api.c @@ -1112,58 +1112,33 @@ QDF_STATUS rrm_process_beacon_req(tpAniSirGlobal mac_ctx, tSirMacAddr peer, tRrmRetStatus rrm_status = eRRM_SUCCESS; tpSirMacRadioMeasureReport report; tpRRMReq curr_req; + QDF_STATUS status = QDF_STATUS_SUCCESS; - if (index >= MAX_MEASUREMENT_REQUEST || - mac_ctx->rrm.rrmPEContext.pCurrentReq[index]) { - if (*radiomes_report == NULL) { - /* - * Allocate memory to send reports for - * any subsequent requests. - */ - *radiomes_report = qdf_mem_malloc(sizeof(*report) * - (rrm_req->num_MeasurementRequest - index)); - if (NULL == *radiomes_report) { - pe_err("Unable to allocate memory during RRM Req processing"); - return QDF_STATUS_E_NOMEM; - } - pe_debug("rrm beacon type refused of %d report in beacon table", - *num_report); - } - report = *radiomes_report; - report[*num_report].refused = 1; - report[*num_report].type = SIR_MAC_RRM_BEACON_TYPE; - report[*num_report].token = - rrm_req->MeasurementRequest[index].measurement_token; - (*num_report)++; - return QDF_STATUS_SUCCESS; - } else { - curr_req = mac_ctx->rrm.rrmPEContext.pCurrentReq[index]; - if (curr_req) { - qdf_mem_free(curr_req); - mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; - } + if (index >= MAX_MEASUREMENT_REQUEST) { + status = rrm_reject_req(&report, rrm_req, num_report, index, + rrm_req->MeasurementRequest[index]. + measurement_type); + return status; + } - curr_req = qdf_mem_malloc(sizeof(*curr_req)); - if (NULL == curr_req) { - pe_err("Unable to allocate memory during RRM Req processing"); - qdf_mem_free(*radiomes_report); - mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; - return QDF_STATUS_E_NOMEM; - } - pe_debug("Processing Beacon Report request idx:%d", index); - curr_req->dialog_token = rrm_req->DialogToken.token; - curr_req->token = rrm_req-> - MeasurementRequest[index].measurement_token; - curr_req->sendEmptyBcnRpt = true; - curr_req->measurement_idx = index; - mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req; - rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req, - &rrm_req->MeasurementRequest[index], session_entry); - if (eRRM_SUCCESS != rrm_status) { - rrm_process_beacon_request_failure(mac_ctx, - session_entry, peer, rrm_status, index); - rrm_cleanup(mac_ctx, index); - } + curr_req = qdf_mem_malloc(sizeof(*curr_req)); + if (!curr_req) { + mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = NULL; + return QDF_STATUS_E_NOMEM; + } + pe_debug("Processing Beacon Report request %d", index); + curr_req->dialog_token = rrm_req->DialogToken.token; + curr_req->token = + rrm_req->MeasurementRequest[index].measurement_token; + curr_req->sendEmptyBcnRpt = true; + curr_req->measurement_idx = index; + mac_ctx->rrm.rrmPEContext.pCurrentReq[index] = curr_req; + rrm_status = rrm_process_beacon_report_req(mac_ctx, curr_req, + &rrm_req->MeasurementRequest[index], session_entry); + if (eRRM_SUCCESS != rrm_status) { + rrm_process_beacon_request_failure(mac_ctx, + session_entry, peer, rrm_status, index); + rrm_cleanup(mac_ctx, index); } return QDF_STATUS_SUCCESS; @@ -1212,6 +1187,36 @@ QDF_STATUS update_rrm_report(tpAniSirGlobal mac_ctx, return QDF_STATUS_SUCCESS; } +QDF_STATUS rrm_reject_req(tpSirMacRadioMeasureReport *radiomes_report, + tDot11fRadioMeasurementRequest *rrm_req, + uint8_t *num_report, uint8_t index, + uint8_t measurement_type) +{ + tpSirMacRadioMeasureReport report; + + if (!*radiomes_report) { + /* + * Allocate memory to send reports for + * any subsequent requests. + */ + *radiomes_report = qdf_mem_malloc(sizeof(*report) * + (rrm_req->num_MeasurementRequest - index)); + if (!*radiomes_report) + return QDF_STATUS_E_NOMEM; + + pe_debug("rrm beacon refused of %d report, index: %d in beacon table", + *num_report, index); + } + report = *radiomes_report; + report[*num_report].refused = 1; + report[*num_report].type = measurement_type; + report[*num_report].token = + rrm_req->MeasurementRequest[index].measurement_token; + (*num_report)++; + + return QDF_STATUS_SUCCESS; +} + /* -------------------------------------------------------------------- */ /** * rrm_process_radio_measurement_request - Process rrm request @@ -1230,10 +1235,11 @@ rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx, tDot11fRadioMeasurementRequest *rrm_req, tpPESession session_entry) { - uint8_t i; + uint8_t i, index; QDF_STATUS status = QDF_STATUS_SUCCESS; tpSirMacRadioMeasureReport report = NULL; uint8_t num_report = 0; + bool reject = false; if (!rrm_req->num_MeasurementRequest) { report = qdf_mem_malloc(sizeof(tSirMacRadioMeasureReport)); @@ -1268,6 +1274,39 @@ rrm_process_radio_measurement_request(tpAniSirGlobal mac_ctx, goto end; } + for (index = 0; index < MAX_MEASUREMENT_REQUEST; index++) { + if (mac_ctx->rrm.rrmPEContext.pCurrentReq[index]) { + reject = true; + pe_debug("RRM req for index: %d is already in progress", + index); + break; + } + } + + if (reject == true) { + for (i = 0; i < rrm_req->num_MeasurementRequest; i++) { + status = + rrm_reject_req(&report, rrm_req, &num_report, i, + rrm_req->MeasurementRequest[i]. + measurement_type); + if (QDF_IS_STATUS_ERROR(status)) { + pe_debug("Fail to Reject rrm req for index: %d", + i); + return status; + } + } + + goto end; + } + + /* + * Clear global beacon_rpt_chan_list before processing every new + * beacon report request. + */ + qdf_mem_zero(mac_ctx->rrm.rrmPEContext.beacon_rpt_chan_list, + sizeof(uint8_t) * MAX_NUM_CHANNELS); + mac_ctx->rrm.rrmPEContext.beacon_rpt_chan_num = 0; + for (i = 0; i < rrm_req->num_MeasurementRequest; i++) { switch (rrm_req->MeasurementRequest[i].measurement_type) { case SIR_MAC_RRM_BEACON_TYPE: @@ -1388,9 +1427,10 @@ tpRRMCaps rrm_get_capabilities(tpAniSirGlobal pMac, tpPESession pSessionEntry) QDF_STATUS rrm_initialize(tpAniSirGlobal pMac) { tpRRMCaps pRRMCaps = &pMac->rrm.rrmPEContext.rrmEnabledCaps; + uint8_t i; - pMac->rrm.rrmPEContext.pCurrentReq[0] = NULL; - pMac->rrm.rrmPEContext.pCurrentReq[1] = NULL; + for (i = 0; i < MAX_MEASUREMENT_REQUEST; i++) + pMac->rrm.rrmPEContext.pCurrentReq[i] = NULL; pMac->rrm.rrmPEContext.txMgmtPower = 0; pMac->rrm.rrmPEContext.DialogToken = 0; diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c index 7de2c0093a1e..638f5ea0c0ff 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/dot11f.c @@ -24,7 +24,7 @@ * * * This file was automatically generated by 'framesc' - * Wed Feb 12 20:42:23 2020 from the following file(s): + * Mon Jun 8 09:41:47 2020 from the following file(s): * * dot11f.frms * @@ -11281,7 +11281,7 @@ static const tIEDefn IES_RadioMeasurementRequest[] = { { offsetof(tDot11fRadioMeasurementRequest, MeasurementRequest), offsetof(tDot11fIEMeasurementRequest, present), offsetof(tDot11fRadioMeasurementRequest, num_MeasurementRequest), - "MeasurementRequest", 2, 6, 18, SigIeMeasurementRequest, {0, 0, 0, 0, 0}, + "MeasurementRequest", 5, 6, 18, SigIeMeasurementRequest, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MEASUREMENTREQUEST, 0, 1, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, },}; diff --git a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c index d8cac206e072..72e4c43930aa 100644 --- a/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c +++ b/drivers/staging/qcacld-3.0/core/mac/src/sys/legacy/src/utils/src/parser_api.c @@ -3080,12 +3080,16 @@ QDF_STATUS wlan_parse_ftie_sha384(uint8_t *frame, uint32_t frame_len, QDF_STATUS sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, tpPESession session_entry, - uint8_t *pFrame, uint32_t nFrame, + u8 *frame, u32 frame_len, tpSirAssocRsp pAssocRsp) { tDot11fAssocResponse *ar; - uint32_t status; + enum ani_akm_type auth_type; + u32 status, ie_len; + QDF_STATUS qdf_status; uint8_t cnt = 0; + bool sha384_akm; + u8 *ie_ptr; ar = qdf_mem_malloc(sizeof(*ar)); if (!ar) { @@ -3096,7 +3100,7 @@ sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, /* decrypt the cipher text using AEAD decryption */ if (lim_is_fils_connection(session_entry)) { status = aead_decrypt_assoc_rsp(pMac, session_entry, - ar, pFrame, &nFrame); + ar, frame, &frame_len); if (!QDF_IS_STATUS_SUCCESS(status)) { pe_err("FILS assoc rsp AEAD decrypt fails"); qdf_mem_free(ar); @@ -3104,13 +3108,12 @@ sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, } } - status = dot11f_parse_assoc_response(pMac, pFrame, nFrame, ar, false); + status = dot11f_parse_assoc_response(pMac, frame, frame_len, ar, false); if (QDF_STATUS_SUCCESS != status) { qdf_mem_free(ar); return status; } - /* Capabilities */ pAssocRsp->capabilityInfo.ess = ar->Capabilities.ess; pAssocRsp->capabilityInfo.ibss = ar->Capabilities.ibss; @@ -3195,13 +3198,40 @@ sir_convert_assoc_resp_frame2_struct(tpAniSirGlobal pMac, (unsigned int)pAssocRsp->mdie[2]); } - if (ar->FTInfo.present) { - pe_debug("FT Info present %d %d %d", - ar->FTInfo.R0KH_ID.num_PMK_R0_ID, - ar->FTInfo.R0KH_ID.present, ar->FTInfo.R1KH_ID.present); + /* + * If the connection is based on SHA384 AKM suite, + * then the length of MIC is 24 bytes, but frame parser + * has FTIE MIC of 16 bytes only. This results in parsing FTIE + * failure and R0KH and R1KH are not sent to firmware over RSO + * command. Frame parser doesn't have + * info on the connected AKM. So parse the FTIE again if + * AKM is sha384 based and extract the R0KH and R1KH using the new + * parsing logic. + */ + auth_type = session_entry->connected_akm; + sha384_akm = lim_is_sha384_akm(auth_type); + if (sha384_akm) { + ie_ptr = frame + FIXED_PARAM_OFFSET_ASSOC_RSP; + ie_len = frame_len - FIXED_PARAM_OFFSET_ASSOC_RSP; + qdf_status = wlan_parse_ftie_sha384(ie_ptr, ie_len, pAssocRsp); + if (QDF_IS_STATUS_ERROR(qdf_status)) { + pe_err("FT IE parsing failed status:%d", status); + } else { + pe_debug("FT: R0KH present:%d len:%d R1KH present%d", + pAssocRsp->sha384_ft_subelem.r0kh_id.present, + pAssocRsp-> + sha384_ft_subelem.r0kh_id.num_PMK_R0_ID, + pAssocRsp->sha384_ft_subelem.r1kh_id.present); + ar->FTInfo.present = false; + } + } else if (ar->FTInfo.present) { + pe_debug("FT: R0KH present:%d, len:%d R1KH present:%d", + ar->FTInfo.R0KH_ID.present, + ar->FTInfo.R0KH_ID.num_PMK_R0_ID, + ar->FTInfo.R1KH_ID.present); pAssocRsp->ftinfoPresent = 1; qdf_mem_copy(&pAssocRsp->FTInfo, &ar->FTInfo, - sizeof(tDot11fIEFTInfo)); + sizeof(tDot11fIEFTInfo)); } if (ar->num_RICDataDesc && ar->num_RICDataDesc <= 2) { diff --git a/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h b/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h index db51bfad0a28..42466639fbba 100644 --- a/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h +++ b/drivers/staging/qcacld-3.0/core/sme/inc/csr_api.h @@ -1818,6 +1818,7 @@ typedef void (*tCsrTsmStatsCallback)(tAniTrafStrmMetrics tsmMetrics, #endif /* FEATURE_WLAN_ESE */ typedef void (*tCsrSnrCallback)(int8_t snr, uint32_t staId, void *pContext); +void csr_assoc_rej_free_rssi_disallow_list(struct sAniSirGlobal *mac); /** * csr_roam_issue_ft_preauth_req() - Initiate Preauthentication request * @max_ctx: Global MAC context diff --git a/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h b/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h index 61add962964c..f73b17ec3fe2 100644 --- a/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h +++ b/drivers/staging/qcacld-3.0/core/sme/inc/sme_api.h @@ -1058,6 +1058,8 @@ uint8_t sme_get_roam_bmiss_final_bcnt(tHalHandle hHal); QDF_STATUS sme_set_roam_beacon_rssi_weight(tHalHandle hHal, uint8_t sessionId, const uint8_t nRoamBeaconRssiWeight); uint8_t sme_get_roam_beacon_rssi_weight(tHalHandle hHal); +void sme_free_blacklist(tHalHandle mac_handle); + /** * sme_get_roam_rssi_diff() - get Roam rssi diff * @mac_handle: The handle returned by mac_open @@ -2092,6 +2094,18 @@ QDF_STATUS sme_get_beacon_frm(tHalHandle hal, struct csr_roam_profile *profile, int *channel); #ifdef WLAN_FEATURE_ROAM_OFFLOAD + +/** + * sme_is_fast_reassoc_allowed - API to check if roam invoke is + * allowed. Get the roam enabled vdev id and allow roaming only on + * that vdev id. + * @mac_handle: Opaque mac handle + * @vdev_id: vdev id + * + * Return: true if roam invoke is allowed, else return false + */ +bool sme_is_fast_reassoc_allowed(mac_handle_t mac_handle, uint8_t vdev_id); + /** * sme_fast_reassoc() - invokes FAST REASSOC command * @hal: handle returned by mac_open @@ -2106,6 +2120,12 @@ QDF_STATUS sme_get_beacon_frm(tHalHandle hal, struct csr_roam_profile *profile, QDF_STATUS sme_fast_reassoc(tHalHandle hal, struct csr_roam_profile *profile, const tSirMacAddr bssid, int channel, uint8_t vdev_id, const tSirMacAddr connected_bssid); +#else +static inline +bool sme_is_fast_reassoc_allowed(mac_handle_t mac_handle, uint8_t vdev_id) +{ + return true; +} #endif /** * sme_congestion_register_callback() - registers congestion callback diff --git a/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c b/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c index d1c4ebafab6f..c91453a01103 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/common/sme_api.c @@ -10572,6 +10572,13 @@ QDF_STATUS sme_set_auto_shutdown_timer(tHalHandle hHal, uint32_t timer_val) } #endif +void sme_free_blacklist(tHalHandle mac_handle) +{ + tpAniSirGlobal mac_ctx = PMAC_STRUCT(mac_handle); + + csr_assoc_rej_free_rssi_disallow_list(mac_ctx); +} + #ifdef FEATURE_WLAN_CH_AVOID /* * sme_ch_avoid_update_req() - @@ -15668,6 +15675,19 @@ free_scan_flter: } #ifdef WLAN_FEATURE_ROAM_OFFLOAD +bool sme_is_fast_reassoc_allowed(mac_handle_t mac_handle, uint8_t vdev_id) +{ + tpAniSirGlobal mac = MAC_CONTEXT(mac_handle); + uint8_t roam_enabled_session_id; + + roam_enabled_session_id = csr_get_roam_enabled_sta_sessionid(mac); + if (roam_enabled_session_id != CSR_SESSION_ID_INVALID && + roam_enabled_session_id != vdev_id) + return false; + + return true; +} + QDF_STATUS sme_fast_reassoc(tHalHandle hal, struct csr_roam_profile *profile, const tSirMacAddr bssid, int channel, uint8_t vdev_id, const tSirMacAddr connected_bssid) @@ -15692,7 +15712,6 @@ QDF_STATUS sme_fast_reassoc(tHalHandle hal, struct csr_roam_profile *profile, return status; } - #endif QDF_STATUS sme_set_del_pmkid_cache(tHalHandle hal, uint8_t session_id, diff --git a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c index eb55076d5c07..b12c8e2fc82a 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/csr/csr_api_roam.c @@ -584,7 +584,7 @@ static void csr_close_stats_ll(struct sAniSirGlobal *mac_ctx) * * Return: void */ -static void csr_assoc_rej_free_rssi_disallow_list(struct sAniSirGlobal *mac) +void csr_assoc_rej_free_rssi_disallow_list(struct sAniSirGlobal *mac) { QDF_STATUS status; struct sir_rssi_disallow_lst *cur_node; @@ -603,7 +603,6 @@ static void csr_assoc_rej_free_rssi_disallow_list(struct sAniSirGlobal *mac) cur_lst = next_lst; next_lst = NULL; } - qdf_list_destroy(list); qdf_mutex_release(&mac->roam.rssi_disallow_bssid_lock); } @@ -635,6 +634,7 @@ static QDF_STATUS csr_roam_rssi_disallow_bssid_deinit( struct sAniSirGlobal *mac_ctx) { csr_assoc_rej_free_rssi_disallow_list(mac_ctx); + qdf_list_destroy(&mac_ctx->roam.rssi_disallow_bssid); qdf_mutex_destroy(&mac_ctx->roam.rssi_disallow_bssid_lock); return QDF_STATUS_SUCCESS; } diff --git a/drivers/staging/qcacld-3.0/core/sme/src/rrm/sme_rrm.c b/drivers/staging/qcacld-3.0/core/sme/src/rrm/sme_rrm.c index e53ebae4dbf8..02804f6a62c1 100644 --- a/drivers/staging/qcacld-3.0/core/sme/src/rrm/sme_rrm.c +++ b/drivers/staging/qcacld-3.0/core/sme/src/rrm/sme_rrm.c @@ -1072,13 +1072,19 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, { tpSirBeaconReportReqInd pBeaconReq = (tpSirBeaconReportReqInd) pMsgBuf; tpRrmSMEContext pSmeRrmContext; - uint32_t len = 0, i = 0; + uint32_t len = 0, i = 0, j = 0; uint8_t country[WNI_CFG_COUNTRY_CODE_LEN]; uint32_t session_id; struct csr_roam_session *session; QDF_STATUS status; + uint8_t local_num_channel, local_bcn_chan_freq; + uint8_t *local_rrm_freq_list; + tRrmPEContext rrm_context; + bool chan_valid = true; pSmeRrmContext = &pMac->rrm.rrmSmeContext[pBeaconReq->measurement_idx]; + rrm_context = pMac->rrm.rrmPEContext; + status = csr_roam_get_session_id_from_bssid(pMac, (struct qdf_mac_addr *) pBeaconReq->bssId, &session_id); @@ -1192,6 +1198,50 @@ QDF_STATUS sme_rrm_process_beacon_report_req_ind(tpAniSirGlobal pMac, } } + local_rrm_freq_list = pSmeRrmContext->channelList.ChannelList; + local_num_channel = 0; + for (i = 0; i < pSmeRrmContext->channelList.numOfChannels; i++) { + local_bcn_chan_freq = local_rrm_freq_list[i]; + chan_valid = true; + + if (pBeaconReq->measurement_idx > 0) { + for (j = 0; j < rrm_context.beacon_rpt_chan_num; j++) { + if (rrm_context.beacon_rpt_chan_list[j] == + local_bcn_chan_freq) { + /* + * Ignore this channel, As this is already + * included in previous request + */ + chan_valid = false; + break; + } + } + } + + if (chan_valid) { + rrm_context. + beacon_rpt_chan_list[rrm_context.beacon_rpt_chan_num] = + local_bcn_chan_freq; + rrm_context.beacon_rpt_chan_num++; + + if (rrm_context.beacon_rpt_chan_num >= + MAX_NUM_CHANNELS) { + /* this should never happen */ + sme_err("Reset beacon_rpt_chan_num : %d", + rrm_context.beacon_rpt_chan_num); + rrm_context.beacon_rpt_chan_num = 0; + } + local_rrm_freq_list[local_num_channel] = + local_bcn_chan_freq; + local_num_channel++; + } + } + + if (local_num_channel == 0) + goto cleanup; + + pSmeRrmContext->channelList.numOfChannels = local_num_channel; + /* Copy session bssid */ qdf_mem_copy(pSmeRrmContext->sessionBssId.bytes, pBeaconReq->bssId, sizeof(tSirMacAddr)); diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c index dd2ed4495b12..3271058a770f 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_scan_roam.c @@ -1954,7 +1954,8 @@ QDF_STATUS wma_process_roaming_config(tp_wma_handle wma_handle, if (roam_req->reason == REASON_ROAM_STOP_ALL || roam_req->reason == REASON_DISCONNECTED || - roam_req->reason == REASON_ROAM_SYNCH_FAILED) { + roam_req->reason == REASON_ROAM_SYNCH_FAILED || + roam_req->reason == REASON_SUPPLICANT_DISABLED_ROAMING) { mode = WMI_ROAM_SCAN_MODE_NONE; } else { if (csr_roamIsRoamOffloadEnabled(pMac)) @@ -3402,8 +3403,16 @@ wma_get_trigger_detail_str(struct wmi_roam_trigger_info *roam_info, char *buf) return; case WMI_ROAM_TRIGGER_REASON_LOW_RSSI: case WMI_ROAM_TRIGGER_REASON_PERIODIC: - buf_cons = qdf_snprint(temp, buf_left, "Cur_rssi_threshold: %d", - roam_info->rssi_trig_data.threshold); + /* + * Use roam_info->current_rssi get the RSSI of current AP after + * roam scan is triggered. This avoids discrepency with the + * next rssi threshold value printed in roam scan details. + * roam_info->rssi_trig_data.threshold gives the rssi of AP + * before the roam scan was triggered. + */ + buf_cons = qdf_snprint(temp, buf_left, + " Current AP RSSI: %d", + roam_info->current_rssi); temp += buf_cons; buf_left -= buf_cons; return; diff --git a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c index a9504c7c0360..c484ac3117e4 100644 --- a/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c +++ b/drivers/staging/qcacld-3.0/core/wma/src/wma_utils.c @@ -4712,7 +4712,8 @@ static void wma_update_roam_offload_flag(tp_wma_handle wma, uint8_t vdev_id, } for (id = 0; id < wma->max_bssid; id++) { - if (wma->interfaces[id].roam_offload_enabled) + if (wma_is_vdev_valid(id) && + wma->interfaces[id].roam_offload_enabled) roam_offload_vdev_id = id; } diff --git a/drivers/staging/rtl8192u/r8192U_core.c b/drivers/staging/rtl8192u/r8192U_core.c index bbc2fadf65f5..726c1e2f4a89 100644 --- a/drivers/staging/rtl8192u/r8192U_core.c +++ b/drivers/staging/rtl8192u/r8192U_core.c @@ -2519,7 +2519,7 @@ static int rtl8192_read_eeprom_info(struct net_device *dev) ret = eprom_read(dev, (EEPROM_TxPwIndex_CCK >> 1)); if (ret < 0) return ret; - priv->EEPROMTxPowerLevelCCK = ((u16)ret & 0xff) >> 8; + priv->EEPROMTxPowerLevelCCK = ((u16)ret & 0xff00) >> 8; } else priv->EEPROMTxPowerLevelCCK = 0x10; RT_TRACE(COMP_EPROM, "CCK Tx Power Levl: 0x%02x\n", priv->EEPROMTxPowerLevelCCK); diff --git a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c index fa98c398d70f..d43fbe4ad767 100644 --- a/drivers/thermal/ti-soc-thermal/ti-thermal-common.c +++ b/drivers/thermal/ti-soc-thermal/ti-thermal-common.c @@ -183,7 +183,7 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id, data = ti_bandgap_get_sensor_data(bgp, id); - if (!IS_ERR_OR_NULL(data)) + if (IS_ERR_OR_NULL(data)) data = ti_thermal_build_data(bgp, id); if (!data) diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c index 442cb93935dd..405dccf92a31 100644 --- a/drivers/usb/dwc2/platform.c +++ b/drivers/usb/dwc2/platform.c @@ -459,6 +459,7 @@ static int dwc2_driver_probe(struct platform_device *dev) if (hsotg->gadget_enabled) { retval = usb_add_gadget_udc(hsotg->dev, &hsotg->gadget); if (retval) { + hsotg->gadget.udc = NULL; dwc2_hsotg_remove(hsotg); goto error; } @@ -467,7 +468,8 @@ static int dwc2_driver_probe(struct platform_device *dev) return 0; error: - dwc2_lowlevel_hw_disable(hsotg); + if (hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) + dwc2_lowlevel_hw_disable(hsotg); return retval; } diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c index 1ef97d80654d..3d4fb028175c 100644 --- a/drivers/usb/dwc3/dwc3-msm.c +++ b/drivers/usb/dwc3/dwc3-msm.c @@ -2256,7 +2256,7 @@ static void dwc3_msm_block_reset(struct dwc3_msm *mdwc, bool core_reset) static void dwc3_msm_power_collapse_por(struct dwc3_msm *mdwc) { struct dwc3 *dwc = platform_get_drvdata(mdwc->dwc3); - u32 val, val1; + u32 val = 0, val1 = 0; int ret; /* Configure AHB2PHY for one wait state read/write */ diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index be24a8c83acf..5ccc15fcee5c 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -57,11 +57,8 @@ #define BRIDGE_RX_QUEUE_SIZE 8 #define BRIDGE_RX_BUF_SIZE 2048 #define BRIDGE_TX_QUEUE_SIZE 8 -#if IS_ENABLED(CONFIG_ARCH_SM8150) -#define BRIDGE_TX_BUF_SIZE (50 * 1024) -#else -#define BRIDGE_TX_BUF_SIZE 2048 -#endif +#define BRIDGE_TX_BUF_SIZE 2048 + #define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ #define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */ diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c index 7a8af4b916cf..58ba04d858ba 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_core.c +++ b/drivers/usb/gadget/udc/bdc/bdc_core.c @@ -288,6 +288,7 @@ static void bdc_mem_init(struct bdc *bdc, bool reinit) * in that case reinit is passed as 1 */ if (reinit) { + int i; /* Enable interrupts */ temp = bdc_readl(bdc->regs, BDC_BDCSC); temp |= BDC_GIE; @@ -297,6 +298,9 @@ static void bdc_mem_init(struct bdc *bdc, bool reinit) /* Initialize SRR to 0 */ memset(bdc->srr.sr_bds, 0, NUM_SR_ENTRIES * sizeof(struct bdc_bd)); + /* clear ep flags to avoid post disconnect stops/deconfigs */ + for (i = 1; i < bdc->num_eps; ++i) + bdc->bdc_ep_array[i]->flags = 0; } else { /* One time initiaization only */ /* Enable status report function pointers */ @@ -609,9 +613,14 @@ static int bdc_remove(struct platform_device *pdev) static int bdc_suspend(struct device *dev) { struct bdc *bdc = dev_get_drvdata(dev); + int ret; - clk_disable_unprepare(bdc->clk); - return 0; + /* Halt the controller */ + ret = bdc_stop(bdc); + if (!ret) + clk_disable_unprepare(bdc->clk); + + return ret; } static int bdc_resume(struct device *dev) diff --git a/drivers/usb/gadget/udc/bdc/bdc_ep.c b/drivers/usb/gadget/udc/bdc/bdc_ep.c index 642f7912f6de..2e2db91d7f32 100644 --- a/drivers/usb/gadget/udc/bdc/bdc_ep.c +++ b/drivers/usb/gadget/udc/bdc/bdc_ep.c @@ -621,7 +621,6 @@ int bdc_ep_enable(struct bdc_ep *ep) } bdc_dbg_bd_list(bdc, ep); /* only for ep0: config ep is called for ep0 from connect event */ - ep->flags |= BDC_EP_ENABLED; if (ep->ep_num == 1) return ret; @@ -765,10 +764,13 @@ static int ep_dequeue(struct bdc_ep *ep, struct bdc_req *req) __func__, ep->name, start_bdi, end_bdi); dev_dbg(bdc->dev, "ep_dequeue ep=%p ep->desc=%p\n", ep, (void *)ep->usb_ep.desc); - /* Stop the ep to see where the HW is ? */ - ret = bdc_stop_ep(bdc, ep->ep_num); - /* if there is an issue with stopping ep, then no need to go further */ - if (ret) + /* if still connected, stop the ep to see where the HW is ? */ + if (!(bdc_readl(bdc->regs, BDC_USPC) & BDC_PST_MASK)) { + ret = bdc_stop_ep(bdc, ep->ep_num); + /* if there is an issue, then no need to go further */ + if (ret) + return 0; + } else return 0; /* @@ -1917,7 +1919,9 @@ static int bdc_gadget_ep_disable(struct usb_ep *_ep) __func__, ep->name, ep->flags); if (!(ep->flags & BDC_EP_ENABLED)) { - dev_warn(bdc->dev, "%s is already disabled\n", ep->name); + if (bdc->gadget.speed != USB_SPEED_UNKNOWN) + dev_warn(bdc->dev, "%s is already disabled\n", + ep->name); return 0; } spin_lock_irqsave(&bdc->lock, flags); diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c index 170327f84ea1..f1ac9a49e2bf 100644 --- a/drivers/usb/gadget/udc/net2280.c +++ b/drivers/usb/gadget/udc/net2280.c @@ -3786,8 +3786,10 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) return 0; done: - if (dev) + if (dev) { net2280_remove(pdev); + kfree(dev); + } return retval; } diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index d4e29039305b..72c3ba0824f7 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -59,7 +59,10 @@ #define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba #define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb #define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc +#define PCI_DEVICE_ID_ASMEDIA_1042_XHCI 0x1042 #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 +#define PCI_DEVICE_ID_ASMEDIA_1142_XHCI 0x1242 +#define PCI_DEVICE_ID_ASMEDIA_2142_XHCI 0x2142 static const char hcd_name[] = "xhci_hcd"; @@ -230,13 +233,14 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_BROKEN_STREAMS; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == 0x1042) + pdev->device == PCI_DEVICE_ID_ASMEDIA_1042_XHCI) xhci->quirks |= XHCI_BROKEN_STREAMS; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == 0x1142) + pdev->device == PCI_DEVICE_ID_ASMEDIA_1042A_XHCI) xhci->quirks |= XHCI_TRUST_TX_LENGTH; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && - pdev->device == 0x2142) + (pdev->device == PCI_DEVICE_ID_ASMEDIA_1142_XHCI || + pdev->device == PCI_DEVICE_ID_ASMEDIA_2142_XHCI)) xhci->quirks |= XHCI_NO_64BIT_SUPPORT; if (pdev->vendor == PCI_VENDOR_ID_ASMEDIA && diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index 1ec32e5aa004..27e1ab9e1b07 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -1,8 +1,9 @@ /* * Native support for the I/O-Warrior USB devices * - * Copyright (c) 2003-2005 Code Mercenaries GmbH - * written by Christian Lucht + * Copyright (c) 2003-2005, 2020 Code Mercenaries GmbH + * written by Christian Lucht and + * Christoph Jung * * based on @@ -821,14 +822,28 @@ static int iowarrior_probe(struct usb_interface *interface, /* we have to check the report_size often, so remember it in the endianness suitable for our machine */ dev->report_size = usb_endpoint_maxp(dev->int_in_endpoint); - if ((dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) && - ((dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56) || - (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW56AM) || - (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28) || - (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW28L) || - (dev->product_id == USB_DEVICE_ID_CODEMERCS_IOW100))) - /* IOWarrior56 has wMaxPacketSize different from report size */ - dev->report_size = 7; + + /* + * Some devices need the report size to be different than the + * endpoint size. + */ + if (dev->interface->cur_altsetting->desc.bInterfaceNumber == 0) { + switch (dev->product_id) { + case USB_DEVICE_ID_CODEMERCS_IOW56: + case USB_DEVICE_ID_CODEMERCS_IOW56AM: + dev->report_size = 7; + break; + + case USB_DEVICE_ID_CODEMERCS_IOW28: + case USB_DEVICE_ID_CODEMERCS_IOW28L: + dev->report_size = 4; + break; + + case USB_DEVICE_ID_CODEMERCS_IOW100: + dev->report_size = 13; + break; + } + } /* create the urb and buffer for reading */ dev->int_in_urb = usb_alloc_urb(0, GFP_KERNEL); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 8dd9852f399d..630c8338d791 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -271,6 +271,8 @@ static struct usb_serial_driver cp210x_device = { .break_ctl = cp210x_break_ctl, .set_termios = cp210x_set_termios, .tx_empty = cp210x_tx_empty, + .throttle = usb_serial_generic_throttle, + .unthrottle = usb_serial_generic_unthrottle, .tiocmget = cp210x_tiocmget, .tiocmset = cp210x_tiocmset, .attach = cp210x_attach, @@ -925,6 +927,7 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, u32 baud; u16 bits; u32 ctl_hs; + u32 flow_repl; cp210x_read_u32_reg(port, CP210X_GET_BAUDRATE, &baud); @@ -1025,6 +1028,22 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, ctl_hs = le32_to_cpu(flow_ctl.ulControlHandshake); if (ctl_hs & CP210X_SERIAL_CTS_HANDSHAKE) { dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); + /* + * When the port is closed, the CP210x hardware disables + * auto-RTS and RTS is deasserted but it leaves auto-CTS when + * in hardware flow control mode. When re-opening the port, if + * auto-CTS is enabled on the cp210x, then auto-RTS must be + * re-enabled in the driver. + */ + flow_repl = le32_to_cpu(flow_ctl.ulFlowReplace); + flow_repl &= ~CP210X_SERIAL_RTS_MASK; + flow_repl |= CP210X_SERIAL_RTS_SHIFT(CP210X_SERIAL_RTS_FLOW_CTL); + flow_ctl.ulFlowReplace = cpu_to_le32(flow_repl); + cp210x_write_reg_block(port, + CP210X_SET_FLOW, + &flow_ctl, + sizeof(flow_ctl)); + cflag |= CRTSCTS; } else { dev_dbg(dev, "%s - flow control = NONE\n", __func__); diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index a962065227c4..8abb30c797d3 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2042,12 +2042,11 @@ static int ftdi_prepare_write_buffer(struct usb_serial_port *port, #define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE) static int ftdi_process_packet(struct usb_serial_port *port, - struct ftdi_private *priv, char *packet, int len) + struct ftdi_private *priv, unsigned char *buf, int len) { + unsigned char status; int i; - char status; char flag; - char *ch; if (len < 2) { dev_dbg(&port->dev, "malformed packet\n"); @@ -2057,7 +2056,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, /* Compare new line status to the old one, signal if different/ N.B. packet may be processed more than once, but differences are only processed once. */ - status = packet[0] & FTDI_STATUS_B0_MASK; + status = buf[0] & FTDI_STATUS_B0_MASK; if (status != priv->prev_status) { char diff_status = status ^ priv->prev_status; @@ -2083,13 +2082,12 @@ static int ftdi_process_packet(struct usb_serial_port *port, } /* save if the transmitter is empty or not */ - if (packet[1] & FTDI_RS_TEMT) + if (buf[1] & FTDI_RS_TEMT) priv->transmit_empty = 1; else priv->transmit_empty = 0; - len -= 2; - if (!len) + if (len == 2) return 0; /* status only */ /* @@ -2097,40 +2095,41 @@ static int ftdi_process_packet(struct usb_serial_port *port, * data payload to avoid over-reporting. */ flag = TTY_NORMAL; - if (packet[1] & FTDI_RS_ERR_MASK) { + if (buf[1] & FTDI_RS_ERR_MASK) { /* Break takes precedence over parity, which takes precedence * over framing errors */ - if (packet[1] & FTDI_RS_BI) { + if (buf[1] & FTDI_RS_BI) { flag = TTY_BREAK; port->icount.brk++; usb_serial_handle_break(port); - } else if (packet[1] & FTDI_RS_PE) { + } else if (buf[1] & FTDI_RS_PE) { flag = TTY_PARITY; port->icount.parity++; - } else if (packet[1] & FTDI_RS_FE) { + } else if (buf[1] & FTDI_RS_FE) { flag = TTY_FRAME; port->icount.frame++; } /* Overrun is special, not associated with a char */ - if (packet[1] & FTDI_RS_OE) { + if (buf[1] & FTDI_RS_OE) { port->icount.overrun++; tty_insert_flip_char(&port->port, 0, TTY_OVERRUN); } } - port->icount.rx += len; - ch = packet + 2; + port->icount.rx += len - 2; if (port->port.console && port->sysrq) { - for (i = 0; i < len; i++, ch++) { - if (!usb_serial_handle_sysrq_char(port, *ch)) - tty_insert_flip_char(&port->port, *ch, flag); + for (i = 2; i < len; i++) { + if (usb_serial_handle_sysrq_char(port, buf[i])) + continue; + tty_insert_flip_char(&port->port, buf[i], flag); } } else { - tty_insert_flip_string_fixed_flag(&port->port, ch, flag, len); + tty_insert_flip_string_fixed_flag(&port->port, buf + 2, flag, + len - 2); } - return len; + return len - 2; } static void ftdi_process_read_urb(struct urb *urb) diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index f7bdc2578fb7..4407617c5d66 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -359,10 +359,11 @@ static void iuu_led_activity_on(struct urb *urb) struct usb_serial_port *port = urb->context; int result; char *buf_ptr = port->write_urb->transfer_buffer; - *buf_ptr++ = IUU_SET_LED; + if (xmas) { - get_random_bytes(buf_ptr, 6); - *(buf_ptr+7) = 1; + buf_ptr[0] = IUU_SET_LED; + get_random_bytes(buf_ptr + 1, 6); + buf_ptr[7] = 1; } else { iuu_rgbf_fill_buffer(buf_ptr, 255, 255, 0, 0, 0, 0, 255); } @@ -380,13 +381,14 @@ static void iuu_led_activity_off(struct urb *urb) struct usb_serial_port *port = urb->context; int result; char *buf_ptr = port->write_urb->transfer_buffer; + if (xmas) { iuu_rxcmd(urb); return; - } else { - *buf_ptr++ = IUU_SET_LED; - iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255); } + + iuu_rgbf_fill_buffer(buf_ptr, 0, 0, 255, 255, 0, 0, 255); + usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 27b4082f4d19..7662b2eb50d8 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -159,6 +159,7 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x1199, 0x9056)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9060)}, /* Sierra Wireless Modem */ {DEVICE_SWI(0x1199, 0x9061)}, /* Sierra Wireless Modem */ + {DEVICE_SWI(0x1199, 0x9062)}, /* Sierra Wireless EM7305 QDL */ {DEVICE_SWI(0x1199, 0x9063)}, /* Sierra Wireless EM7305 */ {DEVICE_SWI(0x1199, 0x9070)}, /* Sierra Wireless MC74xx */ {DEVICE_SWI(0x1199, 0x9071)}, /* Sierra Wireless MC74xx */ diff --git a/drivers/video/console/newport_con.c b/drivers/video/console/newport_con.c index 7f2526b43b33..cc2fb5043184 100644 --- a/drivers/video/console/newport_con.c +++ b/drivers/video/console/newport_con.c @@ -31,6 +31,8 @@ #include #include +#define NEWPORT_LEN 0x10000 + #define FONT_DATA ((unsigned char *)font_vga_8x16.data) /* borrowed from fbcon.c */ @@ -42,6 +44,7 @@ static unsigned char *font_data[MAX_NR_CONSOLES]; static struct newport_regs *npregs; +static unsigned long newport_addr; static int logo_active; static int topscan; @@ -701,7 +704,6 @@ const struct consw newport_con = { static int newport_probe(struct gio_device *dev, const struct gio_device_id *id) { - unsigned long newport_addr; int err; if (!dev->resource.start) @@ -711,7 +713,7 @@ static int newport_probe(struct gio_device *dev, return -EBUSY; /* we only support one Newport as console */ newport_addr = dev->resource.start + 0xF0000; - if (!request_mem_region(newport_addr, 0x10000, "Newport")) + if (!request_mem_region(newport_addr, NEWPORT_LEN, "Newport")) return -ENODEV; npregs = (struct newport_regs *)/* ioremap cannot fail */ @@ -719,6 +721,11 @@ static int newport_probe(struct gio_device *dev, console_lock(); err = do_take_over_console(&newport_con, 0, MAX_NR_CONSOLES - 1, 1); console_unlock(); + + if (err) { + iounmap((void *)npregs); + release_mem_region(newport_addr, NEWPORT_LEN); + } return err; } @@ -726,6 +733,7 @@ static void newport_remove(struct gio_device *dev) { give_up_console(&newport_con); iounmap((void *)npregs); + release_mem_region(newport_addr, NEWPORT_LEN); } static struct gio_device_id newport_ids[] = { diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 0fdd6761d6c3..2cf91fcde7a3 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -246,6 +246,10 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count) p = (void *) (c->vc_origin + t * c->vc_size_row); while (count--) { + if ((vgacon_scrollback_cur->tail + c->vc_size_row) > + vgacon_scrollback_cur->size) + vgacon_scrollback_cur->tail = 0; + scr_memcpyw(vgacon_scrollback_cur->data + vgacon_scrollback_cur->tail, p, c->vc_size_row); diff --git a/drivers/video/fbdev/neofb.c b/drivers/video/fbdev/neofb.c index 5d3a444083f7..2018e1ca33eb 100644 --- a/drivers/video/fbdev/neofb.c +++ b/drivers/video/fbdev/neofb.c @@ -1820,6 +1820,7 @@ static int neo_scan_monitor(struct fb_info *info) #else printk(KERN_ERR "neofb: Only 640x480, 800x600/480 and 1024x768 panels are currently supported\n"); + kfree(info->monspecs.modedb); return -1; #endif default: diff --git a/drivers/video/fbdev/omap2/omapfb/dss/dss.c b/drivers/video/fbdev/omap2/omapfb/dss/dss.c index 48c6500c24e1..4429ad37b64c 100644 --- a/drivers/video/fbdev/omap2/omapfb/dss/dss.c +++ b/drivers/video/fbdev/omap2/omapfb/dss/dss.c @@ -843,7 +843,7 @@ static const struct dss_features omap34xx_dss_feats = { }; static const struct dss_features omap3630_dss_feats = { - .fck_div_max = 32, + .fck_div_max = 31, .dss_fck_multiplier = 1, .parent_clk_name = "dpll4_ck", .dpi_select_source = &dss_dpi_select_source_omap2_omap3, diff --git a/drivers/video/fbdev/pxafb.c b/drivers/video/fbdev/pxafb.c index 29f00eccdd01..08ee77d5df8b 100644 --- a/drivers/video/fbdev/pxafb.c +++ b/drivers/video/fbdev/pxafb.c @@ -2449,8 +2449,8 @@ static int pxafb_remove(struct platform_device *dev) free_pages_exact(fbi->video_mem, fbi->video_mem_size); - dma_free_wc(&dev->dev, fbi->dma_buff_size, fbi->dma_buff, - fbi->dma_buff_phys); + dma_free_coherent(&dev->dev, fbi->dma_buff_size, fbi->dma_buff, + fbi->dma_buff_phys); iounmap(fbi->mmio_base); diff --git a/drivers/video/fbdev/sm712fb.c b/drivers/video/fbdev/sm712fb.c index f1dcc6766d1e..1781ca697f66 100644 --- a/drivers/video/fbdev/sm712fb.c +++ b/drivers/video/fbdev/sm712fb.c @@ -1429,6 +1429,8 @@ static int smtc_map_smem(struct smtcfb_info *sfb, static void smtc_unmap_smem(struct smtcfb_info *sfb) { if (sfb && sfb->fb->screen_base) { + if (sfb->chip_id == 0x720) + sfb->fb->screen_base -= 0x00200000; iounmap(sfb->fb->screen_base); sfb->fb->screen_base = NULL; } diff --git a/drivers/watchdog/f71808e_wdt.c b/drivers/watchdog/f71808e_wdt.c index 88cd2a52d8d3..ae4974701e5c 100644 --- a/drivers/watchdog/f71808e_wdt.c +++ b/drivers/watchdog/f71808e_wdt.c @@ -688,9 +688,9 @@ static int __init watchdog_init(int sioaddr) * into the module have been registered yet. */ watchdog.sioaddr = sioaddr; - watchdog.ident.options = WDIOC_SETTIMEOUT - | WDIOF_MAGICCLOSE - | WDIOF_KEEPALIVEPING; + watchdog.ident.options = WDIOF_MAGICCLOSE + | WDIOF_KEEPALIVEPING + | WDIOF_CARDRESET; snprintf(watchdog.ident.identity, sizeof(watchdog.ident.identity), "%s watchdog", @@ -704,6 +704,13 @@ static int __init watchdog_init(int sioaddr) wdt_conf = superio_inb(sioaddr, F71808FG_REG_WDT_CONF); watchdog.caused_reboot = wdt_conf & BIT(F71808FG_FLAG_WDTMOUT_STS); + /* + * We don't want WDTMOUT_STS to stick around till regular reboot. + * Write 1 to the bit to clear it to zero. + */ + superio_outb(sioaddr, F71808FG_REG_WDT_CONF, + wdt_conf | BIT(F71808FG_FLAG_WDTMOUT_STS)); + superio_exit(sioaddr); err = watchdog_set_timeout(timeout); diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index 3f9260af701f..a8e0836dffd4 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -633,11 +633,13 @@ static int add_ballooned_pages(int nr_pages) if (xen_hotplug_unpopulated) { st = reserve_additional_memory(); if (st != BP_ECANCELED) { + int rc; + mutex_unlock(&balloon_mutex); - wait_event(balloon_wq, + rc = wait_event_interruptible(balloon_wq, !list_empty(&ballooned_pages)); mutex_lock(&balloon_mutex); - return 0; + return rc ? -ENOMEM : 0; } } @@ -695,6 +697,12 @@ int alloc_xenballooned_pages(int nr_pages, struct page **pages) out_undo: mutex_unlock(&balloon_mutex); free_xenballooned_pages(pgno, pages); + /* + * NB: free_xenballooned_pages will only subtract pgno pages, but since + * target_unpopulated is incremented with nr_pages at the start we need + * to remove the remaining ones also, or accounting will be screwed. + */ + balloon_stats.target_unpopulated -= nr_pages - pgno; return ret; } EXPORT_SYMBOL(alloc_xenballooned_pages); diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index c52f10efdc9c..b4dbe7b71151 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -513,10 +513,9 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) } #ifdef CONFIG_9P_FSCACHE - if (v9ses->fscache) { + if (v9ses->fscache) v9fs_cache_session_put_cookie(v9ses); - kfree(v9ses->cachetag); - } + kfree(v9ses->cachetag); #endif kfree(v9ses->uname); kfree(v9ses->aname); diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 096c015b22a4..893066970c68 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -1509,9 +1509,16 @@ int btrfs_init_fs_root(struct btrfs_root *root) spin_lock_init(&root->ino_cache_lock); init_waitqueue_head(&root->ino_cache_wait); - ret = get_anon_bdev(&root->anon_dev); - if (ret) - goto fail; + /* + * Don't assign anonymous block device to roots that are not exposed to + * userspace, the id pool is limited to 1M + */ + if (is_fstree(root->root_key.objectid) && + btrfs_root_refs(&root->root_item) > 0) { + ret = get_anon_bdev(&root->anon_dev); + if (ret) + goto fail; + } mutex_lock(&root->objectid_mutex); ret = btrfs_find_highest_objectid(root, diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 60e82b7899d2..9fbbeb6ec054 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -4312,6 +4312,8 @@ int try_release_extent_mapping(struct extent_map_tree *map, /* once for us */ free_extent_map(em); + + cond_resched(); /* Allow large-extent preemption. */ } } return try_release_extent_state(map, tree, page, mask); diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index abeb26d48d0a..57f89708fab1 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c @@ -2169,7 +2169,7 @@ out: static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl, struct btrfs_free_space *info, bool update_stat) { - struct btrfs_free_space *left_info; + struct btrfs_free_space *left_info = NULL; struct btrfs_free_space *right_info; bool merged = false; u64 offset = info->offset; @@ -2184,7 +2184,7 @@ static bool try_merge_free_space(struct btrfs_free_space_ctl *ctl, if (right_info && rb_prev(&right_info->offset_index)) left_info = rb_entry(rb_prev(&right_info->offset_index), struct btrfs_free_space, offset_index); - else + else if (!right_info) left_info = tree_search_offset(ctl, offset - 1, 0, 0); if (right_info && !right_info->bitmap) { diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index bcfb7a772c8e..3d30bf90d59e 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3854,11 +3854,8 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, fs_info->csum_root, ds + cs, ds + cs + cl - 1, &ordered_sums, 0); - if (ret) { - btrfs_release_path(dst_path); - kfree(ins_data); - return ret; - } + if (ret) + break; } } } @@ -3871,7 +3868,6 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, * we have to do this after the loop above to avoid changing the * log tree while trying to change the log tree. */ - ret = 0; while (!list_empty(&ordered_sums)) { struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next, struct btrfs_ordered_sum, diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c index 58dc8496a145..2dfd36343e3b 100644 --- a/fs/cifs/smb2pdu.c +++ b/fs/cifs/smb2pdu.c @@ -942,6 +942,8 @@ SMB2_auth_kerberos(struct SMB2_sess_data *sess_data) spnego_key = cifs_get_spnego_key(ses); if (IS_ERR(spnego_key)) { rc = PTR_ERR(spnego_key); + if (rc == -ENOKEY) + cifs_dbg(VFS, "Verify user has a krb5 ticket and keyutils is installed\n"); spnego_key = NULL; goto out; } diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c index f1261fa0af8a..244b87e4dfe7 100644 --- a/fs/dlm/lockspace.c +++ b/fs/dlm/lockspace.c @@ -633,6 +633,9 @@ static int new_lockspace(const char *name, const char *cluster, wait_event(ls->ls_recover_lock_wait, test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags)); + /* let kobject handle freeing of ls if there's an error */ + do_unreg = 1; + ls->ls_kobj.kset = dlm_kset; error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL, "%s", ls->ls_name); @@ -640,9 +643,6 @@ static int new_lockspace(const char *name, const char *cluster, goto out_recoverd; kobject_uevent(&ls->ls_kobj, KOBJ_ADD); - /* let kobject handle freeing of ls if there's an error */ - do_unreg = 1; - /* This uevent triggers dlm_controld in userspace to add us to the group of nodes that are members of this lockspace (managed by the cluster infrastructure.) Once it's done that, it tells us who the diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index a1fc3dabca41..6d5fce776d8e 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -80,6 +80,7 @@ static void ext2_release_inode(struct super_block *sb, int group, int dir) if (dir) le16_add_cpu(&desc->bg_used_dirs_count, -1); spin_unlock(sb_bgl_lock(EXT2_SB(sb), group)); + percpu_counter_inc(&EXT2_SB(sb)->s_freeinodes_counter); if (dir) percpu_counter_dec(&EXT2_SB(sb)->s_dirs_counter); mark_buffer_dirty(bh); @@ -531,7 +532,7 @@ got: goto fail; } - percpu_counter_add(&sbi->s_freeinodes_counter, -1); + percpu_counter_dec(&sbi->s_freeinodes_counter); if (S_ISDIR(mode)) percpu_counter_inc(&sbi->s_dirs_counter); diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index 11dce21b767b..9a604f5ca174 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1258,8 +1258,6 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type) DEFINE_WAIT(wait); for (;;) { - prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); - if (!get_pages(sbi, type)) break; @@ -1271,6 +1269,8 @@ void f2fs_wait_on_all_pages(struct f2fs_sb_info *sbi, int type) FS_CP_META_IO); else if (type == F2FS_WB_CP_DATA) f2fs_submit_merged_write(sbi, DATA); + + prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); io_schedule_timeout(DEFAULT_IO_TIMEOUT); } finish_wait(&sbi->cp_wait, &wait); diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index a683ce26c12c..38ceeb007e75 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2661,7 +2661,7 @@ static inline void __mark_inode_dirty_flag(struct inode *inode, static inline void set_inode_flag(struct inode *inode, int flag) { - test_and_set_bit(flag, F2FS_I(inode)->flags); + set_bit(flag, F2FS_I(inode)->flags); __mark_inode_dirty_flag(inode, flag, true); } @@ -2672,7 +2672,7 @@ static inline int is_inode_flag_set(struct inode *inode, int flag) static inline void clear_inode_flag(struct inode *inode, int flag) { - test_and_clear_bit(flag, F2FS_I(inode)->flags); + clear_bit(flag, F2FS_I(inode)->flags); __mark_inode_dirty_flag(inode, flag, false); } diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 2b9002d0d662..dd519d68e064 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -3386,14 +3386,14 @@ static int f2fs_release_compress_blocks(struct file *filp, unsigned long arg) if (ret) goto out; - if (!F2FS_I(inode)->i_compr_blocks) - goto out; - F2FS_I(inode)->i_flags |= F2FS_IMMUTABLE_FL; f2fs_set_inode_flags(inode); inode->i_ctime = current_time(inode); f2fs_mark_inode_dirty_sync(inode, true); + if (!F2FS_I(inode)->i_compr_blocks) + goto out; + down_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]); down_write(&F2FS_I(inode)->i_mmap_sem); diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c index 8d2d8726d65f..393ad8be35f4 100644 --- a/fs/f2fs/inode.c +++ b/fs/f2fs/inode.c @@ -774,6 +774,14 @@ no_delete: else f2fs_inode_synced(inode); + /* + * Make sure evicted inode should not wait for writeback again. + */ + if (!list_empty_careful(&inode->i_io_list)) { + WARN_ON(1); + inode_io_list_del(inode); + } + /* for the case f2fs_new_inode() was failed, .i_ino is zero, skip it */ if (inode->i_ino) invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c index 91f39b7f78b0..4feba309911b 100644 --- a/fs/f2fs/segment.c +++ b/fs/f2fs/segment.c @@ -2166,7 +2166,7 @@ static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) new_vblocks = se->valid_blocks + del; offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); - f2fs_bug_on(sbi, (new_vblocks >> (sizeof(unsigned short) << 3) || + f2fs_bug_on(sbi, (new_vblocks < 0 || (new_vblocks > sbi->blocks_per_seg))); se->valid_blocks = new_vblocks; diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1d33d0035265..9adb9177a4b4 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -1045,6 +1045,7 @@ void inode_io_list_del(struct inode *inode) spin_unlock(&inode->i_lock); spin_unlock(&wb->list_lock); } +EXPORT_SYMBOL(inode_io_list_del); /* * mark an inode as under writeback on the sb diff --git a/fs/minix/inode.c b/fs/minix/inode.c index b6829d679643..d49337b5abfa 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c @@ -155,6 +155,23 @@ static int minix_remount (struct super_block * sb, int * flags, char * data) return 0; } +static bool minix_check_superblock(struct minix_sb_info *sbi) +{ + if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0) + return false; + + /* + * s_max_size must not exceed the block mapping limitation. This check + * is only needed for V1 filesystems, since V2/V3 support an extra level + * of indirect blocks which places the limit well above U32_MAX. + */ + if (sbi->s_version == MINIX_V1 && + sbi->s_max_size > (7 + 512 + 512*512) * BLOCK_SIZE) + return false; + + return true; +} + static int minix_fill_super(struct super_block *s, void *data, int silent) { struct buffer_head *bh; @@ -233,11 +250,12 @@ static int minix_fill_super(struct super_block *s, void *data, int silent) } else goto out_no_fs; + if (!minix_check_superblock(sbi)) + goto out_illegal_sb; + /* * Allocate the buffer map to keep the superblock small. */ - if (sbi->s_imap_blocks == 0 || sbi->s_zmap_blocks == 0) - goto out_illegal_sb; i = (sbi->s_imap_blocks + sbi->s_zmap_blocks) * sizeof(bh); map = kzalloc(i, GFP_KERNEL); if (!map) @@ -471,6 +489,13 @@ static struct inode *V1_minix_iget(struct inode *inode) iget_failed(inode); return ERR_PTR(-EIO); } + if (raw_inode->i_nlinks == 0) { + printk("MINIX-fs: deleted inode referenced: %lu\n", + inode->i_ino); + brelse(bh); + iget_failed(inode); + return ERR_PTR(-ESTALE); + } inode->i_mode = raw_inode->i_mode; i_uid_write(inode, raw_inode->i_uid); i_gid_write(inode, raw_inode->i_gid); @@ -504,6 +529,13 @@ static struct inode *V2_minix_iget(struct inode *inode) iget_failed(inode); return ERR_PTR(-EIO); } + if (raw_inode->i_nlinks == 0) { + printk("MINIX-fs: deleted inode referenced: %lu\n", + inode->i_ino); + brelse(bh); + iget_failed(inode); + return ERR_PTR(-ESTALE); + } inode->i_mode = raw_inode->i_mode; i_uid_write(inode, raw_inode->i_uid); i_gid_write(inode, raw_inode->i_gid); diff --git a/fs/minix/itree_common.c b/fs/minix/itree_common.c index 043c3fdbc8e7..446148792f41 100644 --- a/fs/minix/itree_common.c +++ b/fs/minix/itree_common.c @@ -75,6 +75,7 @@ static int alloc_branch(struct inode *inode, int n = 0; int i; int parent = minix_new_block(inode); + int err = -ENOSPC; branch[0].key = cpu_to_block(parent); if (parent) for (n = 1; n < num; n++) { @@ -85,6 +86,11 @@ static int alloc_branch(struct inode *inode, break; branch[n].key = cpu_to_block(nr); bh = sb_getblk(inode->i_sb, parent); + if (!bh) { + minix_free_block(inode, nr); + err = -ENOMEM; + break; + } lock_buffer(bh); memset(bh->b_data, 0, bh->b_size); branch[n].bh = bh; @@ -103,7 +109,7 @@ static int alloc_branch(struct inode *inode, bforget(branch[i].bh); for (i = 0; i < n; i++) minix_free_block(inode, block_to_cpu(branch[i].key)); - return -ENOSPC; + return err; } static inline int splice_branch(struct inode *inode, diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 83361242e84e..bc936d1e373e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -5325,8 +5325,6 @@ static int _nfs4_get_security_label(struct inode *inode, void *buf, return ret; if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) return -ENOENT; - if (buflen < label.len) - return -ERANGE; return 0; } diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 0b2d051990e9..3cd04c98da6b 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -4258,7 +4258,11 @@ static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, goto out_overflow; if (len < NFS4_MAXLABELLEN) { if (label) { - memcpy(label->label, p, len); + if (label->len) { + if (label->len < len) + return -ERANGE; + memcpy(label->label, p, len); + } label->len = len; label->pi = pi; label->lfs = lfs; diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h index 9a50f222ac97..b15537a76516 100644 --- a/fs/ocfs2/ocfs2.h +++ b/fs/ocfs2/ocfs2.h @@ -336,8 +336,8 @@ struct ocfs2_super spinlock_t osb_lock; u32 s_next_generation; unsigned long osb_flags; - s16 s_inode_steal_slot; - s16 s_meta_steal_slot; + u16 s_inode_steal_slot; + u16 s_meta_steal_slot; atomic_t s_num_inodes_stolen; atomic_t s_num_meta_stolen; diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 4ca2f71565f9..8d03630dfd59 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -895,9 +895,9 @@ static void __ocfs2_set_steal_slot(struct ocfs2_super *osb, int slot, int type) { spin_lock(&osb->osb_lock); if (type == INODE_ALLOC_SYSTEM_INODE) - osb->s_inode_steal_slot = slot; + osb->s_inode_steal_slot = (u16)slot; else if (type == EXTENT_ALLOC_SYSTEM_INODE) - osb->s_meta_steal_slot = slot; + osb->s_meta_steal_slot = (u16)slot; spin_unlock(&osb->osb_lock); } diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 24ab735d91dd..8216550faf45 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c @@ -92,7 +92,7 @@ struct mount_options unsigned long commit_interval; unsigned long mount_opt; unsigned int atime_quantum; - signed short slot; + unsigned short slot; int localalloc_opt; unsigned int resv_level; int dir_resv_level; @@ -1369,7 +1369,7 @@ static int ocfs2_parse_options(struct super_block *sb, goto bail; } if (option) - mopt->slot = (s16)option; + mopt->slot = (u16)option; break; case Opt_commit: if (match_int(&args[0], &option)) { diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 9837c67dd032..2b6134cd4948 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c @@ -99,7 +99,7 @@ static struct inode *ufs_nfs_get_inode(struct super_block *sb, u64 ino, u32 gene struct ufs_sb_private_info *uspi = UFS_SB(sb)->s_uspi; struct inode *inode; - if (ino < UFS_ROOTINO || ino > uspi->s_ncg * uspi->s_ipg) + if (ino < UFS_ROOTINO || ino > (u64)uspi->s_ncg * uspi->s_ipg) return ERR_PTR(-ESTALE); inode = ufs_iget(sb, ino); diff --git a/fs/xattr.c b/fs/xattr.c index ca362c155af8..0154195a4405 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -204,10 +204,22 @@ int __vfs_setxattr_noperm(struct dentry *dentry, const char *name, return error; } - +/** + * __vfs_setxattr_locked: set an extended attribute while holding the inode + * lock + * + * @dentry - object to perform setxattr on + * @name - xattr name to set + * @value - value to set @name to + * @size - size of @value + * @flags - flags to pass into filesystem operations + * @delegated_inode - on return, will contain an inode pointer that + * a delegation was broken on, NULL if none. + */ int -vfs_setxattr(struct dentry *dentry, const char *name, const void *value, - size_t size, int flags) +__vfs_setxattr_locked(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, + struct inode **delegated_inode) { struct inode *inode = dentry->d_inode; int error; @@ -216,15 +228,40 @@ vfs_setxattr(struct dentry *dentry, const char *name, const void *value, if (error) return error; - inode_lock(inode); error = security_inode_setxattr(dentry, name, value, size, flags); if (error) goto out; + error = try_break_deleg(inode, delegated_inode); + if (error) + goto out; + error = __vfs_setxattr_noperm(dentry, name, value, size, flags); out: + return error; +} +EXPORT_SYMBOL_GPL(__vfs_setxattr_locked); + +int +vfs_setxattr(struct dentry *dentry, const char *name, const void *value, + size_t size, int flags) +{ + struct inode *inode = dentry->d_inode; + struct inode *delegated_inode = NULL; + int error; + +retry_deleg: + inode_lock(inode); + error = __vfs_setxattr_locked(dentry, name, value, size, flags, + &delegated_inode); inode_unlock(inode); + + if (delegated_inode) { + error = break_deleg_wait(&delegated_inode); + if (!error) + goto retry_deleg; + } return error; } EXPORT_SYMBOL_GPL(vfs_setxattr); @@ -389,8 +426,18 @@ __vfs_removexattr(struct dentry *dentry, const char *name) } EXPORT_SYMBOL(__vfs_removexattr); +/** + * __vfs_removexattr_locked: set an extended attribute while holding the inode + * lock + * + * @dentry - object to perform setxattr on + * @name - name of xattr to remove + * @delegated_inode - on return, will contain an inode pointer that + * a delegation was broken on, NULL if none. + */ int -vfs_removexattr(struct dentry *dentry, const char *name) +__vfs_removexattr_locked(struct dentry *dentry, const char *name, + struct inode **delegated_inode) { struct inode *inode = dentry->d_inode; int error; @@ -399,11 +446,14 @@ vfs_removexattr(struct dentry *dentry, const char *name) if (error) return error; - inode_lock(inode); error = security_inode_removexattr(dentry, name); if (error) goto out; + error = try_break_deleg(inode, delegated_inode); + if (error) + goto out; + error = __vfs_removexattr(dentry, name); if (!error) { @@ -412,12 +462,32 @@ vfs_removexattr(struct dentry *dentry, const char *name) } out: + return error; +} +EXPORT_SYMBOL_GPL(__vfs_removexattr_locked); + +int +vfs_removexattr(struct dentry *dentry, const char *name) +{ + struct inode *inode = dentry->d_inode; + struct inode *delegated_inode = NULL; + int error; + +retry_deleg: + inode_lock(inode); + error = __vfs_removexattr_locked(dentry, name, &delegated_inode); inode_unlock(inode); + + if (delegated_inode) { + error = break_deleg_wait(&delegated_inode); + if (!error) + goto retry_deleg; + } + return error; } EXPORT_SYMBOL_GPL(vfs_removexattr); - /* * Extended attribute SET operations */ diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index db7f9fdd20a3..4d37f1b59436 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c @@ -1076,6 +1076,7 @@ xfs_reflink_remap_extent( xfs_filblks_t rlen; xfs_filblks_t unmap_len; xfs_off_t newlen; + int64_t qres; int error; unmap_len = irec->br_startoff + irec->br_blockcount - destoff; @@ -1098,13 +1099,19 @@ xfs_reflink_remap_extent( xfs_ilock(ip, XFS_ILOCK_EXCL); xfs_trans_ijoin(tp, ip, 0); - /* If we're not just clearing space, then do we have enough quota? */ - if (real_extent) { - error = xfs_trans_reserve_quota_nblks(tp, ip, - irec->br_blockcount, 0, XFS_QMOPT_RES_REGBLKS); - if (error) - goto out_cancel; - } + /* + * Reserve quota for this operation. We don't know if the first unmap + * in the dest file will cause a bmap btree split, so we always reserve + * at least enough blocks for that split. If the extent being mapped + * in is written, we need to reserve quota for that too. + */ + qres = XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK); + if (real_extent) + qres += irec->br_blockcount; + error = xfs_trans_reserve_quota_nblks(tp, ip, qres, 0, + XFS_QMOPT_RES_REGBLKS); + if (error) + goto out_cancel; trace_xfs_reflink_remap(ip, irec->br_startoff, irec->br_blockcount, irec->br_startblock); diff --git a/include/linux/bitfield.h b/include/linux/bitfield.h index f2deb71958b2..a0675db325e0 100644 --- a/include/linux/bitfield.h +++ b/include/linux/bitfield.h @@ -71,7 +71,7 @@ */ #define FIELD_FIT(_mask, _val) \ ({ \ - __BF_FIELD_CHECK(_mask, 0ULL, _val, "FIELD_FIT: "); \ + __BF_FIELD_CHECK(_mask, 0ULL, 0ULL, "FIELD_FIT: "); \ !((((typeof(_mask))_val) << __bf_shf(_mask)) & ~(_mask)); \ }) diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h index 8d3ca6da3342..63cd81e5610d 100644 --- a/include/linux/hyperv.h +++ b/include/linux/hyperv.h @@ -422,6 +422,8 @@ enum vmbus_channel_message_type { CHANNELMSG_19 = 19, CHANNELMSG_20 = 20, CHANNELMSG_TL_CONNECT_REQUEST = 21, + CHANNELMSG_22 = 22, + CHANNELMSG_TL_CONNECT_RESULT = 23, CHANNELMSG_COUNT }; diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index 4def15c32a01..d2364ba99f6c 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -304,8 +304,8 @@ enum { #define QI_DEV_EIOTLB_ADDR(a) ((u64)(a) & VTD_PAGE_MASK) #define QI_DEV_EIOTLB_SIZE (((u64)1) << 11) -#define QI_DEV_EIOTLB_GLOB(g) ((u64)g) -#define QI_DEV_EIOTLB_PASID(p) (((u64)p) << 32) +#define QI_DEV_EIOTLB_GLOB(g) ((u64)(g) & 0x1) +#define QI_DEV_EIOTLB_PASID(p) ((u64)((p) & 0xfffff) << 32) #define QI_DEV_EIOTLB_SID(sid) ((u64)((sid) & 0xffff) << 16) #define QI_DEV_EIOTLB_QDEP(qd) ((u64)((qd) & 0x1f) << 4) #define QI_DEV_EIOTLB_PFSID(pfsid) (((u64)(pfsid & 0xf) << 12) | \ diff --git a/include/linux/ipa.h b/include/linux/ipa.h index eee92b0cabe2..32e513fbb397 100644 --- a/include/linux/ipa.h +++ b/include/linux/ipa.h @@ -1425,9 +1425,35 @@ struct ipa_socksv5_info { struct ipacm_socksv5_info dl_in; /* output: handle (index) */ - uint32_t handle; + uint16_t handle; }; +struct ipa_ipv6_nat_uc_tmpl { + uint16_t cmd_id; + uint16_t rsv; + uint32_t cmd_param; + uint16_t pkt_count; + uint16_t rsv2; + uint32_t byte_count; + uint64_t private_address_lsb; + uint64_t private_address_msb; + uint64_t public_address_lsb; + uint64_t public_address_msb; + uint16_t private_port; + uint16_t public_port; + uint32_t rsv3; + uint64_t rsv4; + uint64_t rsv5; + uint64_t rsv6; + uint64_t rsv7; + uint64_t rsv8; + uint64_t rsv9; + uint64_t rsv10; + uint64_t rsv11; + uint64_t rsv12; +} __packed; + + #if defined CONFIG_IPA || defined CONFIG_IPA3 diff --git a/include/linux/ipa_wdi3.h b/include/linux/ipa_wdi3.h index 4036becd4fcf..8d87ac4e3f0b 100644 --- a/include/linux/ipa_wdi3.h +++ b/include/linux/ipa_wdi3.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved. +/* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -89,6 +89,7 @@ struct ipa_wdi_hdr_info { * @is_meta_data_valid: if meta data is valid * @meta_data: meta data if any * @meta_data_mask: meta data mask + * @is_tx1_used: to indicate whether 2.4g or 5g iface */ struct ipa_wdi_reg_intf_in_params { const char *netdev_name; @@ -97,6 +98,7 @@ struct ipa_wdi_reg_intf_in_params { u8 is_meta_data_valid; u32 meta_data; u32 meta_data_mask; + u8 is_tx1_used; }; /** @@ -189,6 +191,9 @@ struct ipa_wdi_pipe_setup_info_smmu { * @tx_smmu: smmu parameters to connect TX pipe(from IPA to WLAN) * @rx: parameters to connect RX pipe(from WLAN to IPA) * @rx_smmu: smmu parameters to connect RX pipe(from WLAN to IPA) + * @is_tx1_used: to notify extra pipe required/not + * @tx1: parameters to connect TX1 pipe(from IPA to WLAN second pipe) + * @tx1_smmu: smmu parameters to connect TX1 pipe(from IPA to WLAN second pipe) */ struct ipa_wdi_conn_in_params { ipa_notify_cb notify; @@ -204,6 +209,11 @@ struct ipa_wdi_conn_in_params { struct ipa_wdi_pipe_setup_info rx; struct ipa_wdi_pipe_setup_info_smmu rx_smmu; } u_rx; + bool is_tx1_used; + union { + struct ipa_wdi_pipe_setup_info tx; + struct ipa_wdi_pipe_setup_info_smmu tx_smmu; + } u_tx1; }; /** @@ -211,10 +221,12 @@ struct ipa_wdi_conn_in_params { * to WLAN driver * @tx_uc_db_pa: physical address of IPA uC doorbell for TX * @rx_uc_db_pa: physical address of IPA uC doorbell for RX + * @tx1_uc_db_pa: physical address of IPA uC doorbell for TX1 */ struct ipa_wdi_conn_out_params { phys_addr_t tx_uc_db_pa; phys_addr_t rx_uc_db_pa; + phys_addr_t tx1_uc_db_pa; }; /** diff --git a/include/linux/irq.h b/include/linux/irq.h index 0d53626405bf..c08758a63d26 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -212,6 +212,8 @@ struct irq_data { * mask. Applies only to affinity managed irqs. * IRQD_SINGLE_TARGET - IRQ allows only a single affinity target * IRQD_DEFAULT_TRIGGER_SET - Expected trigger already been set + * IRQD_AFFINITY_ON_ACTIVATE - Affinity is set on activation. Don't call + * irq_chip::irq_set_affinity() when deactivated. */ enum { IRQD_TRIGGER_MASK = 0xf, @@ -233,6 +235,7 @@ enum { IRQD_MANAGED_SHUTDOWN = (1 << 23), IRQD_SINGLE_TARGET = (1 << 24), IRQD_DEFAULT_TRIGGER_SET = (1 << 25), + IRQD_AFFINITY_ON_ACTIVATE = (1 << 29), }; #define __irqd_to_state(d) ACCESS_PRIVATE((d)->common, state_use_accessors) @@ -377,6 +380,15 @@ static inline bool irqd_is_managed_and_shutdown(struct irq_data *d) return __irqd_to_state(d) & IRQD_MANAGED_SHUTDOWN; } +static inline void irqd_set_affinity_on_activate(struct irq_data *d) +{ + __irqd_to_state(d) |= IRQD_AFFINITY_ON_ACTIVATE; +} + +static inline bool irqd_affinity_on_activate(struct irq_data *d) +{ + return __irqd_to_state(d) & IRQD_AFFINITY_ON_ACTIVATE; +} #undef __irqd_to_state static inline irq_hw_number_t irqd_to_hwirq(struct irq_data *d) diff --git a/include/linux/msm_mhi_dev.h b/include/linux/msm_mhi_dev.h index f086e848327f..42eb9fa05405 100644 --- a/include/linux/msm_mhi_dev.h +++ b/include/linux/msm_mhi_dev.h @@ -73,6 +73,7 @@ struct mhi_req { struct list_head list; union mhi_dev_ring_element_type *el; void (*client_cb)(void *req); + bool is_stale; }; /* SW channel client list */ diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h index a26ffbe09e71..06cb9184a42a 100644 --- a/include/linux/tracepoint.h +++ b/include/linux/tracepoint.h @@ -318,7 +318,7 @@ extern void syscall_unregfunc(void); static const char *___tp_str __tracepoint_string = str; \ ___tp_str; \ }) -#define __tracepoint_string __attribute__((section("__tracepoint_str"))) +#define __tracepoint_string __attribute__((section("__tracepoint_str"), used)) #else /* * tracepoint_string() is used to save the string address for userspace diff --git a/include/linux/writeback.h b/include/linux/writeback.h index e12d92808e98..43c702e22e04 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -192,6 +192,7 @@ bool try_to_writeback_inodes_sb_nr(struct super_block *, unsigned long nr, void sync_inodes_sb(struct super_block *); void wakeup_flusher_threads(long nr_pages, enum wb_reason reason); void inode_wait_for_writeback(struct inode *inode); +void inode_io_list_del(struct inode *inode); /* writeback.h requires fs.h; it, too, is not included from here. */ static inline void wait_on_inode(struct inode *inode) diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 7f538d232179..fa663c2a7187 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -55,8 +55,10 @@ ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); int __vfs_setxattr(struct dentry *, struct inode *, const char *, const void *, size_t, int); int __vfs_setxattr_noperm(struct dentry *, const char *, const void *, size_t, int); +int __vfs_setxattr_locked(struct dentry *, const char *, const void *, size_t, int, struct inode **); int vfs_setxattr(struct dentry *, const char *, const void *, size_t, int); int __vfs_removexattr(struct dentry *, const char *); +int __vfs_removexattr_locked(struct dentry *, const char *, struct inode **); int vfs_removexattr(struct dentry *, const char *); ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size); diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 4e5316a8fbf2..bcdca2e323fd 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -272,6 +272,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr); int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr); +void __ipv6_sock_ac_close(struct sock *sk); void ipv6_sock_ac_close(struct sock *sk); int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr); diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h index 2a196e82dffd..a0cb284bf755 100644 --- a/include/net/inet_connection_sock.h +++ b/include/net/inet_connection_sock.h @@ -321,6 +321,10 @@ int inet_csk_compat_getsockopt(struct sock *sk, int level, int optname, int inet_csk_compat_setsockopt(struct sock *sk, int level, int optname, char __user *optval, unsigned int optlen); +/* update the fast reuse flag when adding a socket */ +void inet_csk_update_fastreuse(struct inet_bind_bucket *tb, + struct sock *sk); + struct dst_entry *inet_csk_update_pmtu(struct sock *sk, u32 mtu); #define TCP_PINGPONG_THRESH 3 diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h index f4e5ac8aa366..1fb79c78e200 100644 --- a/include/net/ip_vs.h +++ b/include/net/ip_vs.h @@ -1607,18 +1607,16 @@ static inline void ip_vs_conn_drop_conntrack(struct ip_vs_conn *cp) } #endif /* CONFIG_IP_VS_NFCT */ -/* Really using conntrack? */ -static inline bool ip_vs_conn_uses_conntrack(struct ip_vs_conn *cp, - struct sk_buff *skb) +/* Using old conntrack that can not be redirected to another real server? */ +static inline bool ip_vs_conn_uses_old_conntrack(struct ip_vs_conn *cp, + struct sk_buff *skb) { #ifdef CONFIG_IP_VS_NFCT enum ip_conntrack_info ctinfo; struct nf_conn *ct; - if (!(cp->flags & IP_VS_CONN_F_NFCT)) - return false; ct = nf_ct_get(skb, &ctinfo); - if (ct) + if (ct && nf_ct_is_confirmed(ct)) return true; #endif return false; diff --git a/include/net/sock.h b/include/net/sock.h index a460e3ec35c8..2651682b5454 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -834,6 +834,8 @@ static inline int sk_memalloc_socks(void) { return static_key_false(&memalloc_socks); } + +void __receive_sock(struct file *file); #else static inline int sk_memalloc_socks(void) @@ -841,6 +843,8 @@ static inline int sk_memalloc_socks(void) return 0; } +static inline void __receive_sock(struct file *file) +{ } #endif static inline gfp_t sk_gfp_mask(const struct sock *sk, gfp_t gfp_mask) diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 00b293065977..6d86d7357807 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -127,6 +127,8 @@ #define IPA_IOCTL_APP_CLOCK_VOTE 79 #define IPA_IOCTL_PDN_CONFIG 80 #define IPA_IOCTL_SET_MAC_FLT 81 +#define IPA_IOCTL_ADD_UC_ACT_ENTRY 82 +#define IPA_IOCTL_DEL_UC_ACT_ENTRY 83 /** * max size of the header to be inserted @@ -2515,6 +2517,73 @@ struct ipa_wan_msg { uint32_t ipv6_addr_gw[IPA_WAN_MSG_IPv6_ADDR_GW_LEN]; }; +/* uc activation command Ids */ +#define IPA_SOCKSV5_ADD_COM_ID 15 +#define IPA_IPv6_NAT_COM_ID 16 + +/** + * ipa_kernel_tests_socksv5_uc_tmpl - uc activation entry info + * @cmd_id: uc command id + * @cmd_param: uC command param + * @ipa_kernel_tests_ip_hdr_temp: ip header + * @src_port: source port + * @dst_port: destination port + * @ipa_sockv5_mask: uc attribute mask for options/etc + * @out_irs: 4B/4B Seq/Ack/SACK + * @out_iss + * @in_irs + * @in_iss + * @out_ircv_tsval: timestamp attributes + * @in_ircv_tsecr + * @out_ircv_tsecr + * @in_ircv_tsval + * @in_isnd_wscale: window scale attributes + * @out_isnd_wscale + * @in_ircv_wscale + * @out_ircv_wscale + * @direction: 1 for UL 0 for DL + * @handle: uc activation table index + */ +struct ipa_kernel_tests_socksv5_uc_tmpl { + uint16_t cmd_id; + uint32_t cmd_param; + __be32 ip_src_addr; + __be32 ip_dst_addr; + __be32 ipv6_src_addr[4]; + __be32 ipv6_dst_addr[4]; + + /* 2B src/dst port */ + uint16_t src_port; + uint16_t dst_port; + + /* attribute mask */ + uint32_t ipa_sockv5_mask; + + /* required update 4B/4B Seq/Ack/SACK */ + uint32_t out_irs; + uint32_t out_iss; + uint32_t in_irs; + uint32_t in_iss; + + /* option 10B: time-stamp */ + uint32_t out_ircv_tsval; + uint32_t in_ircv_tsecr; + uint32_t out_ircv_tsecr; + uint32_t in_ircv_tsval; + + /* option 2B: window-scaling/dynamic */ + uint16_t in_isnd_wscale : 4; + uint16_t out_isnd_wscale : 4; + uint16_t in_ircv_wscale : 4; + uint16_t out_ircv_wscale : 4; + + /* direction 1 = UL, 0 = DL */ + uint8_t direction; + + /* output: handle (index) */ + uint16_t handle; +}; + /** * struct ipacm_socksv5_info - To hold information about socksv5 connections * @ip_type: ip type @@ -2565,6 +2634,41 @@ struct ipa_socksv5_msg { uint16_t handle; }; +/** + * struct ipa_ioc_ipv6_nat_uc_act_entry - To hold information about IPv6 NAT + * uC entry + * @cmd_id[in]: IPv6 NAT uC CMD ID - used for identifying uc activation type + * @private_address_lsb[in]: client private address lsb + * @private_address_msb[in]: client private address msb + * @public_address_lsb[in]: client public address lsb + * @public_address_msb[in]: client public address msb + * @private_port[in]: client private port + * @public_port[in]: client public port + * @index[out]: uC activation entry index + */ +struct ipa_ioc_ipv6_nat_uc_act_entry { + uint16_t cmd_id; + uint64_t private_address_lsb; + uint64_t private_address_msb; + uint64_t public_address_lsb; + uint64_t public_address_msb; + uint32_t private_port; + uint32_t public_port; + uint16_t index; +}; + +/** + * union ipa_ioc_uc_activation_entry - To hold information about uC activation + * entry + * @socks[in]: fill here if entry is Socksv5 entry + * @ipv6_nat[in]: fill here if entry is IPv6 NAT entry + */ +union ipa_ioc_uc_activation_entry { + struct ipa_kernel_tests_socksv5_uc_tmpl socks; + struct ipa_ioc_ipv6_nat_uc_act_entry ipv6_nat; +}; + + /** * struct ipa_ioc_rm_dependency - parameters for add/delete dependency * @resource_name: name of dependent resource @@ -3084,6 +3188,14 @@ struct ipa_ioc_mac_client_list_type { IPA_IOCTL_SET_MAC_FLT, \ struct ipa_ioc_mac_client_list_type) +#define IPA_IOC_ADD_UC_ACT_ENTRY _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_ADD_UC_ACT_ENTRY, \ + union ipa_ioc_uc_activation_entry) + +#define IPA_IOC_DEL_UC_ACT_ENTRY _IOWR(IPA_IOC_MAGIC, \ + IPA_IOCTL_DEL_UC_ACT_ENTRY, \ + uint16_t) + /* * unique magic number of the Tethering bridge ioctls */ diff --git a/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h index 2bff30d6e7ca..aefb75661bc7 100644 --- a/include/uapi/media/cam_req_mgr.h +++ b/include/uapi/media/cam_req_mgr.h @@ -269,6 +269,7 @@ struct cam_req_mgr_link_control { #define CAM_MEM_FLAG_CACHE (1<<10) #define CAM_MEM_FLAG_HW_SHARED_ACCESS (1<<11) #define CAM_MEM_FLAG_CDSP_OUTPUT (1<<12) +#define CAM_MEM_FLAG_CP_PIXEL (1<<13) #define CAM_MEM_MMU_MAX_HANDLE 16 diff --git a/kernel/cgroup/cgroup.c b/kernel/cgroup/cgroup.c index 3a5ea06b28b7..b09c3f4d4557 100644 --- a/kernel/cgroup/cgroup.c +++ b/kernel/cgroup/cgroup.c @@ -5957,6 +5957,8 @@ void cgroup_sk_clone(struct sock_cgroup_data *skcd) { /* Socket clone path */ if (skcd->val) { + if (skcd->no_refcnt) + return; /* * We might be cloning a socket which is left in an empty * cgroup and the cgroup might have already been rmdir'd. diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 639a6de48b4c..80f0776a66b7 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -179,9 +179,9 @@ void irq_set_thread_affinity(struct irq_desc *desc) set_bit(IRQTF_AFFINITY, &action->thread_flags); } +#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK static void irq_validate_effective_affinity(struct irq_data *data) { -#ifdef CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK const struct cpumask *m = irq_data_get_effective_affinity_mask(data); struct irq_chip *chip = irq_data_get_irq_chip(data); @@ -189,9 +189,19 @@ static void irq_validate_effective_affinity(struct irq_data *data) return; pr_warn_once("irq_chip %s did not update eff. affinity mask of irq %u\n", chip->name, data->irq); -#endif } +static inline void irq_init_effective_affinity(struct irq_data *data, + const struct cpumask *mask) +{ + cpumask_copy(irq_data_get_effective_affinity_mask(data), mask); +} +#else +static inline void irq_validate_effective_affinity(struct irq_data *data) { } +static inline void irq_init_effective_affinity(struct irq_data *data, + const struct cpumask *mask) { } +#endif + int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { @@ -218,6 +228,30 @@ int irq_do_set_affinity(struct irq_data *data, const struct cpumask *mask, return ret; } +static bool irq_set_affinity_deactivated(struct irq_data *data, + const struct cpumask *mask, bool force) +{ + struct irq_desc *desc = irq_data_to_desc(data); + + /* + * Handle irq chips which can handle affinity only in activated + * state correctly + * + * If the interrupt is not yet activated, just store the affinity + * mask and do not call the chip driver at all. On activation the + * driver has to make sure anyway that the interrupt is in a + * useable state so startup works. + */ + if (!IS_ENABLED(CONFIG_IRQ_DOMAIN_HIERARCHY) || + irqd_is_activated(data) || !irqd_affinity_on_activate(data)) + return false; + + cpumask_copy(desc->irq_common_data.affinity, mask); + irq_init_effective_affinity(data, mask); + irqd_set(data, IRQD_AFFINITY_SET); + return true; +} + int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, bool force) { @@ -228,6 +262,9 @@ int irq_set_affinity_locked(struct irq_data *data, const struct cpumask *mask, if (!chip || !chip->irq_set_affinity) return -EINVAL; + if (irq_set_affinity_deactivated(data, mask, force)) + return 0; + if (irq_can_move_pcntxt(data)) { ret = irq_do_set_affinity(data, mask, force); } else { diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 856a07317ef4..1235aaefdd85 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2134,6 +2134,13 @@ static void kill_kprobe(struct kprobe *p) * the original probed function (which will be freed soon) any more. */ arch_remove_kprobe(p); + + /* + * The module is going away. We should disarm the kprobe which + * is using ftrace. + */ + if (kprobe_ftrace(p)) + disarm_kprobe_ftrace(p); } /* Disable one kprobe */ diff --git a/kernel/power/qos.c b/kernel/power/qos.c index 95c48e007413..70d591dde70d 100644 --- a/kernel/power/qos.c +++ b/kernel/power/qos.c @@ -881,6 +881,9 @@ static ssize_t pm_qos_power_write(struct file *filp, const char __user *buf, s32 value; struct pm_qos_request *req; + /* Don't let userspace impose restrictions on CPU idle levels */ + return count; + if (count == sizeof(s32)) { if (copy_from_user(&value, buf, sizeof(s32))) return -EFAULT; diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 79919ba439ce..e4d9ff30e9be 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -1269,7 +1269,7 @@ sd_init(struct sched_domain_topology_level *tl, sd_flags = (*tl->sd_flags)(); if (WARN_ONCE(sd_flags & ~TOPOLOGY_SD_FLAGS, "wrong sd_flags in topology description\n")) - sd_flags &= ~TOPOLOGY_SD_FLAGS; + sd_flags &= TOPOLOGY_SD_FLAGS; *sd = (struct sched_domain){ .min_interval = sd_weight, diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 03eed9b1a717..953fd804f648 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -5722,8 +5722,11 @@ static int referenced_filters(struct dyn_ftrace *rec) int cnt = 0; for (ops = ftrace_ops_list; ops != &ftrace_list_end; ops = ops->next) { - if (ops_references_rec(ops, rec)) - cnt++; + if (ops_references_rec(ops, rec)) { + cnt++; + if (ops->flags & FTRACE_OPS_FL_SAVE_REGS) + rec->flags |= FTRACE_FL_REGS; + } } return cnt; @@ -5872,8 +5875,8 @@ void ftrace_module_enable(struct module *mod) if (ftrace_start_up) cnt += referenced_filters(rec); - /* This clears FTRACE_FL_DISABLED */ - rec->flags = cnt; + rec->flags &= ~FTRACE_FL_DISABLED; + rec->flags += cnt; if (ftrace_start_up && cnt) { int failed = __ftrace_replace_code(rec, 1); @@ -6241,12 +6244,12 @@ void ftrace_pid_follow_fork(struct trace_array *tr, bool enable) if (enable) { register_trace_sched_process_fork(ftrace_pid_follow_sched_process_fork, tr); - register_trace_sched_process_exit(ftrace_pid_follow_sched_process_exit, + register_trace_sched_process_free(ftrace_pid_follow_sched_process_exit, tr); } else { unregister_trace_sched_process_fork(ftrace_pid_follow_sched_process_fork, tr); - unregister_trace_sched_process_exit(ftrace_pid_follow_sched_process_exit, + unregister_trace_sched_process_free(ftrace_pid_follow_sched_process_exit, tr); } } diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 421166a39253..e72a44ecb81d 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c @@ -533,12 +533,12 @@ void trace_event_follow_fork(struct trace_array *tr, bool enable) if (enable) { register_trace_prio_sched_process_fork(event_filter_pid_sched_process_fork, tr, INT_MIN); - register_trace_prio_sched_process_exit(event_filter_pid_sched_process_exit, + register_trace_prio_sched_process_free(event_filter_pid_sched_process_exit, tr, INT_MAX); } else { unregister_trace_sched_process_fork(event_filter_pid_sched_process_fork, tr); - unregister_trace_sched_process_exit(event_filter_pid_sched_process_exit, + unregister_trace_sched_process_free(event_filter_pid_sched_process_exit, tr); } } diff --git a/kernel/trace/trace_hwlat.c b/kernel/trace/trace_hwlat.c index bff6c033d70e..64a98a5bb641 100644 --- a/kernel/trace/trace_hwlat.c +++ b/kernel/trace/trace_hwlat.c @@ -272,6 +272,7 @@ static bool disable_migrate; static void move_to_next_cpu(void) { struct cpumask *current_mask = &save_cpumask; + struct trace_array *tr = hwlat_trace; int next_cpu; if (disable_migrate) @@ -285,7 +286,7 @@ static void move_to_next_cpu(void) goto disable; get_online_cpus(); - cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask); + cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask); next_cpu = cpumask_next(smp_processor_id(), current_mask); put_online_cpus(); @@ -359,7 +360,7 @@ static int start_kthread(struct trace_array *tr) /* Just pick the first CPU on first iteration */ current_mask = &save_cpumask; get_online_cpus(); - cpumask_and(current_mask, cpu_online_mask, tracing_buffer_mask); + cpumask_and(current_mask, cpu_online_mask, tr->tracing_cpumask); put_online_cpus(); next_cpu = cpumask_first(current_mask); diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 3f4a49c3c03b..0f4059b39b72 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -85,22 +85,22 @@ static struct { unsigned flag:8; char opt_char; } opt_array[] = { { _DPRINTK_FLAGS_NONE, '_' }, }; +struct flagsbuf { char buf[ARRAY_SIZE(opt_array)+1]; }; + /* format a string into buf[] which describes the _ddebug's flags */ -static char *ddebug_describe_flags(struct _ddebug *dp, char *buf, - size_t maxlen) +static char *ddebug_describe_flags(unsigned int flags, struct flagsbuf *fb) { - char *p = buf; + char *p = fb->buf; int i; - BUG_ON(maxlen < 6); for (i = 0; i < ARRAY_SIZE(opt_array); ++i) - if (dp->flags & opt_array[i].flag) + if (flags & opt_array[i].flag) *p++ = opt_array[i].opt_char; - if (p == buf) + if (p == fb->buf) *p++ = '_'; *p = '\0'; - return buf; + return fb->buf; } #define vpr_info(fmt, ...) \ @@ -142,7 +142,7 @@ static int ddebug_change(const struct ddebug_query *query, struct ddebug_table *dt; unsigned int newflags; unsigned int nfound = 0; - char flagbuf[10]; + struct flagsbuf fbuf; /* search for matching ddebugs */ mutex_lock(&ddebug_lock); @@ -199,8 +199,7 @@ static int ddebug_change(const struct ddebug_query *query, vpr_info("changed %s:%d [%s]%s =%s\n", trim_prefix(dp->filename), dp->lineno, dt->mod_name, dp->function, - ddebug_describe_flags(dp, flagbuf, - sizeof(flagbuf))); + ddebug_describe_flags(dp->flags, &fbuf)); } } mutex_unlock(&ddebug_lock); @@ -779,7 +778,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) { struct ddebug_iter *iter = m->private; struct _ddebug *dp = p; - char flagsbuf[10]; + struct flagsbuf flags; vpr_info("called m=%p p=%p\n", m, p); @@ -792,7 +791,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p) seq_printf(m, "%s:%u [%s]%s =%s \"", trim_prefix(dp->filename), dp->lineno, iter->table->mod_name, dp->function, - ddebug_describe_flags(dp, flagsbuf, sizeof(flagsbuf))); + ddebug_describe_flags(dp->flags, &flags)); seq_escape(m, dp->format, "\t\r\n\""); seq_puts(m, "\"\n"); diff --git a/lib/test_kmod.c b/lib/test_kmod.c index dc1c2248ceda..c588f9889b36 100644 --- a/lib/test_kmod.c +++ b/lib/test_kmod.c @@ -747,7 +747,7 @@ static int trigger_config_run_type(struct kmod_test_device *test_dev, break; case TEST_KMOD_FS_TYPE: kfree_const(config->test_fs); - config->test_driver = NULL; + config->test_fs = NULL; copied = config_copy_test_fs(config, test_str, strlen(test_str)); break; diff --git a/mm/khugepaged.c b/mm/khugepaged.c index e47c6cdb5cbd..6666cc93990a 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -1257,6 +1257,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot) static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) { struct vm_area_struct *vma; + struct mm_struct *mm; unsigned long addr; pmd_t *pmd, _pmd; @@ -1270,7 +1271,8 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) continue; if (vma->vm_end < addr + HPAGE_PMD_SIZE) continue; - pmd = mm_find_pmd(vma->vm_mm, addr); + mm = vma->vm_mm; + pmd = mm_find_pmd(mm, addr); if (!pmd) continue; /* @@ -1279,14 +1281,16 @@ static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff) * re-fault. Not ideal, but it's more important to not disturb * the system too much. */ - if (down_write_trylock(&vma->vm_mm->mmap_sem)) { - spinlock_t *ptl = pmd_lock(vma->vm_mm, pmd); - /* assume page table is clear */ - _pmd = pmdp_collapse_flush(vma, addr, pmd); - spin_unlock(ptl); - up_write(&vma->vm_mm->mmap_sem); - mm_dec_nr_ptes(vma->vm_mm); - pte_free(vma->vm_mm, pmd_pgtable(_pmd)); + if (down_write_trylock(&mm->mmap_sem)) { + if (!khugepaged_test_exit(mm)) { + spinlock_t *ptl = pmd_lock(mm, pmd); + /* assume page table is clear */ + _pmd = pmdp_collapse_flush(vma, addr, pmd); + spin_unlock(ptl); + mm_dec_nr_ptes(vma->vm_mm); + pte_free(mm, pmd_pgtable(_pmd)); + } + up_write(&mm->mmap_sem); } } i_mmap_unlock_write(mapping); diff --git a/mm/mmap.c b/mm/mmap.c index 573e0ac6f1f5..a0462ff67e2d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -3180,6 +3180,7 @@ void exit_mmap(struct mm_struct *mm) if (vma->vm_flags & VM_ACCOUNT) nr_accounted += vma_pages(vma); vma = remove_vma(vma); + cond_resched(); } vm_unacct_memory(nr_accounted); } diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 32de8afbfbf8..9f020559c192 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -829,20 +829,28 @@ static int p9_fd_open(struct p9_client *client, int rfd, int wfd) return -ENOMEM; ts->rd = fget(rfd); + if (!ts->rd) + goto out_free_ts; + if (!(ts->rd->f_mode & FMODE_READ)) + goto out_put_rd; ts->wr = fget(wfd); - if (!ts->rd || !ts->wr) { - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); - return -EIO; - } + if (!ts->wr) + goto out_put_rd; + if (!(ts->wr->f_mode & FMODE_WRITE)) + goto out_put_wr; client->trans = ts; client->status = Connected; return 0; + +out_put_wr: + fput(ts->wr); +out_put_rd: + fput(ts->rd); +out_free_ts: + kfree(ts); + return -EIO; } static int p9_socket_open(struct p9_client *client, struct socket *csocket) diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 357475cceec6..9a75f9b00b51 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -57,6 +57,7 @@ static bool enable_6lowpan; /* We are listening incoming connections via this channel */ static struct l2cap_chan *listen_chan; +static DEFINE_MUTEX(set_lock); struct lowpan_peer { struct list_head list; @@ -1082,12 +1083,14 @@ static void do_enable_set(struct work_struct *work) enable_6lowpan = set_enable->flag; + mutex_lock(&set_lock); if (listen_chan) { l2cap_chan_close(listen_chan, 0); l2cap_chan_put(listen_chan); } listen_chan = bt_6lowpan_listen(); + mutex_unlock(&set_lock); kfree(set_enable); } @@ -1139,11 +1142,13 @@ static ssize_t lowpan_control_write(struct file *fp, if (ret == -EINVAL) return ret; + mutex_lock(&set_lock); if (listen_chan) { l2cap_chan_close(listen_chan, 0); l2cap_chan_put(listen_chan); listen_chan = NULL; } + mutex_unlock(&set_lock); if (conn) { struct lowpan_peer *peer; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 56e4ae7d7f63..70b8e2de40cf 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2094,7 +2094,7 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s num_rsp %d", hdev->name, num_rsp); - if (!num_rsp) + if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) return; if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) @@ -3623,6 +3623,9 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct inquiry_info_with_rssi_and_pscan_mode *info; info = (void *) (skb->data + 1); + if (skb->len < num_rsp * sizeof(*info) + 1) + goto unlock; + for (; num_rsp; num_rsp--, info++) { u32 flags; @@ -3644,6 +3647,9 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, } else { struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); + if (skb->len < num_rsp * sizeof(*info) + 1) + goto unlock; + for (; num_rsp; num_rsp--, info++) { u32 flags; @@ -3664,6 +3670,7 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, } } +unlock: hci_dev_unlock(hdev); } @@ -3826,7 +3833,7 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, BT_DBG("%s num_rsp %d", hdev->name, num_rsp); - if (!num_rsp) + if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) return; if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) diff --git a/net/compat.c b/net/compat.c index 790851e70dab..45349658ed01 100644 --- a/net/compat.c +++ b/net/compat.c @@ -289,6 +289,7 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm) break; } /* Bump the usage count and install the file. */ + __receive_sock(fp[i]); fd_install(new_fd, get_file(fp[i])); } diff --git a/net/core/sock.c b/net/core/sock.c index c2b72bce0eb7..7d4be6623235 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2566,6 +2566,27 @@ int sock_no_mmap(struct file *file, struct socket *sock, struct vm_area_struct * } EXPORT_SYMBOL(sock_no_mmap); +/* + * When a file is received (via SCM_RIGHTS, etc), we must bump the + * various sock-based usage counts. + */ +void __receive_sock(struct file *file) +{ + struct socket *sock; + int error; + + /* + * The resulting value of "error" is ignored here since we only + * need to take action when the file is a socket and testing + * "sock" for NULL is sufficient. + */ + sock = sock_from_file(file, &error); + if (sock) { + sock_update_netprioidx(&sock->sk->sk_cgrp_data); + sock_update_classid(&sock->sk->sk_cgrp_data); + } +} + ssize_t sock_no_sendpage(struct socket *sock, struct page *page, int offset, size_t size, int flags) { ssize_t res; diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 00f7af43c89c..35028eec7683 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c @@ -1735,7 +1735,7 @@ struct fib_table *fib_trie_unmerge(struct fib_table *oldtb) while ((l = leaf_walk_rcu(&tp, key)) != NULL) { struct key_vector *local_l = NULL, *local_tp; - hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) { + hlist_for_each_entry(fa, &l->leaf, fa_list) { struct fib_alias *new_fa; if (local_tb->tb_id != fa->tb_id) diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index 6a7d980105f6..095c30863745 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c @@ -19,12 +19,12 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, netdev_features_t features) { int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); + bool need_csum, need_recompute_csum, gso_partial; struct sk_buff *segs = ERR_PTR(-EINVAL); u16 mac_offset = skb->mac_header; __be16 protocol = skb->protocol; u16 mac_len = skb->mac_len; int gre_offset, outer_hlen; - bool need_csum, gso_partial; if (!skb->encapsulation) goto out; @@ -45,6 +45,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, skb->protocol = skb->inner_protocol; need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_GRE_CSUM); + need_recompute_csum = skb->csum_not_inet; skb->encap_hdr_csum = need_csum; features &= skb->dev->hw_enc_features; @@ -102,7 +103,15 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, } *(pcsum + 1) = 0; - *pcsum = gso_make_checksum(skb, 0); + if (need_recompute_csum && !skb_is_gso(skb)) { + __wsum csum; + + csum = skb_checksum(skb, gre_offset, + skb->len - gre_offset, 0); + *pcsum = csum_fold(csum); + } else { + *pcsum = gso_make_checksum(skb, 0); + } } while ((skb = skb->next)); out: return segs; diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index a403001c50af..08ba0f91f2ab 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c @@ -276,58 +276,12 @@ static inline int sk_reuseport_match(struct inet_bind_bucket *tb, ipv6_only_sock(sk), true); } -/* Obtain a reference to a local port for the given sock, - * if snum is zero it means select any available local port. - * We try to allocate an odd port (and leave even ports for connect()) - */ -int inet_csk_get_port(struct sock *sk, unsigned short snum) +void inet_csk_update_fastreuse(struct inet_bind_bucket *tb, + struct sock *sk) { - bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; - struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo; - int ret = 1, port = snum; - struct inet_bind_hashbucket *head; - struct net *net = sock_net(sk); - struct inet_bind_bucket *tb = NULL; kuid_t uid = sock_i_uid(sk); + bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; - if (!port) { - head = inet_csk_find_open_port(sk, &tb, &port); - if (!head) - return ret; - if (!tb) - goto tb_not_found; - goto success; - } - head = &hinfo->bhash[inet_bhashfn(net, port, - hinfo->bhash_size)]; - spin_lock_bh(&head->lock); - - if (inet_is_local_reserved_port(net, snum) && - !sysctl_reserved_port_bind) { - ret = 1; - goto fail_unlock; - } - - inet_bind_bucket_for_each(tb, &head->chain) - if (net_eq(ib_net(tb), net) && tb->port == port) - goto tb_found; -tb_not_found: - tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, - net, head, port); - if (!tb) - goto fail_unlock; -tb_found: - if (!hlist_empty(&tb->owners)) { - if (sk->sk_reuse == SK_FORCE_REUSE) - goto success; - - if ((tb->fastreuse > 0 && reuse) || - sk_reuseport_match(tb, sk)) - goto success; - if (inet_csk_bind_conflict(sk, tb, true, true)) - goto fail_unlock; - } -success: if (hlist_empty(&tb->owners)) { tb->fastreuse = reuse; if (sk->sk_reuseport) { @@ -371,6 +325,54 @@ success: tb->fastreuseport = 0; } } +} + +/* Obtain a reference to a local port for the given sock, + * if snum is zero it means select any available local port. + * We try to allocate an odd port (and leave even ports for connect()) + */ +int inet_csk_get_port(struct sock *sk, unsigned short snum) +{ + bool reuse = sk->sk_reuse && sk->sk_state != TCP_LISTEN; + struct inet_hashinfo *hinfo = sk->sk_prot->h.hashinfo; + int ret = 1, port = snum; + struct inet_bind_hashbucket *head; + struct net *net = sock_net(sk); + struct inet_bind_bucket *tb = NULL; + + if (!port) { + head = inet_csk_find_open_port(sk, &tb, &port); + if (!head) + return ret; + if (!tb) + goto tb_not_found; + goto success; + } + head = &hinfo->bhash[inet_bhashfn(net, port, + hinfo->bhash_size)]; + spin_lock_bh(&head->lock); + inet_bind_bucket_for_each(tb, &head->chain) + if (net_eq(ib_net(tb), net) && tb->port == port) + goto tb_found; +tb_not_found: + tb = inet_bind_bucket_create(hinfo->bind_bucket_cachep, + net, head, port); + if (!tb) + goto fail_unlock; +tb_found: + if (!hlist_empty(&tb->owners)) { + if (sk->sk_reuse == SK_FORCE_REUSE) + goto success; + + if ((tb->fastreuse > 0 && reuse) || + sk_reuseport_match(tb, sk)) + goto success; + if (inet_csk_bind_conflict(sk, tb, true, true)) + goto fail_unlock; + } +success: + inet_csk_update_fastreuse(tb, sk); + if (!inet_csk(sk)->icsk_bind_hash) inet_bind_hash(sk, tb, port); WARN_ON(inet_csk(sk)->icsk_bind_hash != tb); diff --git a/net/ipv4/inet_hashtables.c b/net/ipv4/inet_hashtables.c index 0af13f5bdc9a..8a54babf5c90 100644 --- a/net/ipv4/inet_hashtables.c +++ b/net/ipv4/inet_hashtables.c @@ -160,6 +160,7 @@ int __inet_inherit_port(const struct sock *sk, struct sock *child) return -ENOMEM; } } + inet_csk_update_fastreuse(tb, child); } inet_bind_hash(child, tb, port); spin_unlock(&head->lock); diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 0bbab8a4b5d8..4d8b3d1d530b 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -170,7 +170,7 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) return 0; } -void ipv6_sock_ac_close(struct sock *sk) +void __ipv6_sock_ac_close(struct sock *sk) { struct ipv6_pinfo *np = inet6_sk(sk); struct net_device *dev = NULL; @@ -178,10 +178,7 @@ void ipv6_sock_ac_close(struct sock *sk) struct net *net = sock_net(sk); int prev_index; - if (!np->ipv6_ac_list) - return; - - rtnl_lock(); + ASSERT_RTNL(); pac = np->ipv6_ac_list; np->ipv6_ac_list = NULL; @@ -198,6 +195,16 @@ void ipv6_sock_ac_close(struct sock *sk) sock_kfree_s(sk, pac, sizeof(*pac)); pac = next; } +} + +void ipv6_sock_ac_close(struct sock *sk) +{ + struct ipv6_pinfo *np = inet6_sk(sk); + + if (!np->ipv6_ac_list) + return; + rtnl_lock(); + __ipv6_sock_ac_close(sk); rtnl_unlock(); } diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index c183222967d0..3f44316db51b 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c @@ -207,6 +207,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, fl6_free_socklist(sk); __ipv6_sock_mc_close(sk); + __ipv6_sock_ac_close(sk); /* * Sock is moving from IPv6 to IPv4 (sk_prot), so diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 77ab9cc1a230..6af5fda6461c 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -952,7 +952,7 @@ static void __sta_info_destroy_part2(struct sta_info *sta) might_sleep(); lockdep_assert_held(&local->sta_mtx); - while (sta->sta_state == IEEE80211_STA_AUTHORIZED) { + if (sta->sta_state == IEEE80211_STA_AUTHORIZED) { ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC); WARN_ON_ONCE(ret); } diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 2156571455db..a95fe5fe9f04 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c @@ -1916,14 +1916,14 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int conn_reuse_mode = sysctl_conn_reuse_mode(ipvs); if (conn_reuse_mode && !iph.fragoffs && is_new_conn(skb, &iph) && cp) { - bool uses_ct = false, resched = false; + bool old_ct = false, resched = false; if (unlikely(sysctl_expire_nodest_conn(ipvs)) && cp->dest && unlikely(!atomic_read(&cp->dest->weight))) { resched = true; - uses_ct = ip_vs_conn_uses_conntrack(cp, skb); + old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); } else if (is_new_conn_expected(cp, conn_reuse_mode)) { - uses_ct = ip_vs_conn_uses_conntrack(cp, skb); + old_ct = ip_vs_conn_uses_old_conntrack(cp, skb); if (!atomic_read(&cp->n_control)) { resched = true; } else { @@ -1931,15 +1931,17 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, int * that uses conntrack while it is still * referenced by controlled connection(s). */ - resched = !uses_ct; + resched = !old_ct; } } if (resched) { + if (!old_ct) + cp->flags &= ~IP_VS_CONN_F_NFCT; if (!atomic_read(&cp->n_control)) ip_vs_conn_expire_now(cp); __ip_vs_conn_put(cp); - if (uses_ct) + if (old_ct) return NF_DROP; cp = NULL; } diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c index e2188deb08dc..b927730d9ab0 100644 --- a/net/nfc/rawsock.c +++ b/net/nfc/rawsock.c @@ -344,10 +344,13 @@ static int rawsock_create(struct net *net, struct socket *sock, if ((sock->type != SOCK_SEQPACKET) && (sock->type != SOCK_RAW)) return -ESOCKTNOSUPPORT; - if (sock->type == SOCK_RAW) + if (sock->type == SOCK_RAW) { + if (!capable(CAP_NET_RAW)) + return -EPERM; sock->ops = &rawsock_raw_ops; - else + } else { sock->ops = &rawsock_ops; + } sk = sk_alloc(net, PF_NFC, GFP_ATOMIC, nfc_proto->proto, kern); if (!sk) diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 737e37b28d93..a39ef1a048fd 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -255,10 +255,6 @@ void ovs_ct_fill_key(const struct sk_buff *skb, struct sw_flow_key *key) ovs_ct_update_key(skb, NULL, key, false, false); } -#define IN6_ADDR_INITIALIZER(ADDR) \ - { (ADDR).s6_addr32[0], (ADDR).s6_addr32[1], \ - (ADDR).s6_addr32[2], (ADDR).s6_addr32[3] } - int ovs_ct_put_key(const struct sw_flow_key *swkey, const struct sw_flow_key *output, struct sk_buff *skb) { @@ -280,24 +276,30 @@ int ovs_ct_put_key(const struct sw_flow_key *swkey, if (swkey->ct_orig_proto) { if (swkey->eth.type == htons(ETH_P_IP)) { - struct ovs_key_ct_tuple_ipv4 orig = { - output->ipv4.ct_orig.src, - output->ipv4.ct_orig.dst, - output->ct.orig_tp.src, - output->ct.orig_tp.dst, - output->ct_orig_proto, - }; + struct ovs_key_ct_tuple_ipv4 orig; + + memset(&orig, 0, sizeof(orig)); + orig.ipv4_src = output->ipv4.ct_orig.src; + orig.ipv4_dst = output->ipv4.ct_orig.dst; + orig.src_port = output->ct.orig_tp.src; + orig.dst_port = output->ct.orig_tp.dst; + orig.ipv4_proto = output->ct_orig_proto; + if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV4, sizeof(orig), &orig)) return -EMSGSIZE; } else if (swkey->eth.type == htons(ETH_P_IPV6)) { - struct ovs_key_ct_tuple_ipv6 orig = { - IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.src), - IN6_ADDR_INITIALIZER(output->ipv6.ct_orig.dst), - output->ct.orig_tp.src, - output->ct.orig_tp.dst, - output->ct_orig_proto, - }; + struct ovs_key_ct_tuple_ipv6 orig; + + memset(&orig, 0, sizeof(orig)); + memcpy(orig.ipv6_src, output->ipv6.ct_orig.src.s6_addr32, + sizeof(orig.ipv6_src)); + memcpy(orig.ipv6_dst, output->ipv6.ct_orig.dst.s6_addr32, + sizeof(orig.ipv6_dst)); + orig.src_port = output->ct.orig_tp.src; + orig.dst_port = output->ct.orig_tp.dst; + orig.ipv6_proto = output->ct_orig_proto; + if (nla_put(skb, OVS_KEY_ATTR_CT_ORIG_TUPLE_IPV6, sizeof(orig), &orig)) return -EMSGSIZE; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 6ee5988b44f8..25771d54d9db 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -989,6 +989,7 @@ static int prb_queue_frozen(struct tpacket_kbdq_core *pkc) } static void prb_clear_blk_fill_status(struct packet_ring_buffer *rb) + __releases(&pkc->blk_fill_in_prog_lock) { struct tpacket_kbdq_core *pkc = GET_PBDQC_FROM_RB(rb); atomic_dec(&pkc->blk_fill_in_prog); @@ -1036,6 +1037,7 @@ static void prb_fill_curr_block(char *curr, struct tpacket_kbdq_core *pkc, struct tpacket_block_desc *pbd, unsigned int len) + __acquires(&pkc->blk_fill_in_prog_lock) { struct tpacket3_hdr *ppd; @@ -2311,8 +2313,11 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, if (do_vnet && virtio_net_hdr_from_skb(skb, h.raw + macoff - sizeof(struct virtio_net_hdr), - vio_le(), true, 0)) + vio_le(), true, 0)) { + if (po->tp_version == TPACKET_V3) + prb_clear_blk_fill_status(&po->rx_ring); goto drop_n_account; + } if (po->tp_version <= TPACKET_V2) { packet_increment_rx_head(po, &po->rx_ring); @@ -2418,7 +2423,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, __clear_bit(slot_id, po->rx_ring.rx_owner_map); spin_unlock(&sk->sk_receive_queue.lock); sk->sk_data_ready(sk); - } else { + } else if (po->tp_version == TPACKET_V3) { prb_clear_blk_fill_status(&po->rx_ring); } diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 7021725fa38a..1c98a026b41a 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -275,7 +275,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, */ ret = rxrpc_connect_call(call, cp, srx, gfp); if (ret < 0) - goto error; + goto error_attached_to_socket; trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage), here, NULL); @@ -295,18 +295,29 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, error_dup_user_ID: write_unlock(&rx->call_lock); release_sock(&rx->sk); - ret = -EEXIST; - -error: __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, - RX_CALL_DEAD, ret); + RX_CALL_DEAD, -EEXIST); trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), - here, ERR_PTR(ret)); + here, ERR_PTR(-EEXIST)); rxrpc_release_call(rx, call); mutex_unlock(&call->user_mutex); rxrpc_put_call(call, rxrpc_call_put); - _leave(" = %d", ret); - return ERR_PTR(ret); + _leave(" = -EEXIST"); + return ERR_PTR(-EEXIST); + + /* We got an error, but the call is attached to the socket and is in + * need of release. However, we might now race with recvmsg() when + * completing the call queues it. Return 0 from sys_sendmsg() and + * leave the error to recvmsg() to deal with. + */ +error_attached_to_socket: + trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage), + here, ERR_PTR(ret)); + set_bit(RXRPC_CALL_DISCONNECTED, &call->flags); + __rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR, + RX_CALL_DEAD, ret); + _leave(" = c=%08x [err]", call->debug_id); + return call; } /* diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c index af0232820597..0e5087b9e07c 100644 --- a/net/rxrpc/conn_object.c +++ b/net/rxrpc/conn_object.c @@ -196,9 +196,11 @@ void rxrpc_disconnect_call(struct rxrpc_call *call) call->peer->cong_cwnd = call->cong_cwnd; - spin_lock_bh(&conn->params.peer->lock); - hlist_del_init(&call->error_link); - spin_unlock_bh(&conn->params.peer->lock); + if (!hlist_unhashed(&call->error_link)) { + spin_lock_bh(&conn->params.peer->lock); + hlist_del_init(&call->error_link); + spin_unlock_bh(&conn->params.peer->lock); + } if (rxrpc_is_client_call(call)) return rxrpc_disconnect_client_call(call); diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index e82e91fe6178..1cdd8b380d47 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -522,7 +522,7 @@ try_again: goto error_unlock_call; } - if (msg->msg_name) { + if (msg->msg_name && call->peer) { struct sockaddr_rxrpc *srx = msg->msg_name; size_t len = sizeof(call->peer->srx); diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index f4386ad975cf..8f9a2a7eeb7c 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -579,6 +579,9 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len) if (IS_ERR(call)) return PTR_ERR(call); /* ... and we have the call lock. */ + ret = 0; + if (READ_ONCE(call->state) == RXRPC_CALL_COMPLETE) + goto out_put_unlock; } else { switch (READ_ONCE(call->state)) { case RXRPC_CALL_UNINITIALISED: diff --git a/net/socket.c b/net/socket.c index 1e415a5fc352..0ed86939b690 100644 --- a/net/socket.c +++ b/net/socket.c @@ -508,7 +508,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) if (f.file) { sock = sock_from_file(f.file, err); if (likely(sock)) { - *fput_needed = f.flags; + *fput_needed = f.flags & FDPUT_FPUT; return sock; } fdput(f); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 04e021398fce..53cf059e846c 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -12142,13 +12142,13 @@ static int nl80211_vendor_cmd(struct sk_buff *skb, struct genl_info *info) if (!wdev_running(wdev)) return -ENETDOWN; } - - if (!vcmd->doit) - return -EOPNOTSUPP; } else { wdev = NULL; } + if (!vcmd->doit) + return -EOPNOTSUPP; + if (info->attrs[NL80211_ATTR_VENDOR_DATA]) { data = nla_data(info->attrs[NL80211_ATTR_VENDOR_DATA]); len = nla_len(info->attrs[NL80211_ATTR_VENDOR_DATA]); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 4dc00983fa14..6800bc1abbf6 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -870,7 +870,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, !strcmp(sb->s_type->name, "tracefs") || !strcmp(sb->s_type->name, "sysfs") || !strcmp(sb->s_type->name, "pstore") || - !strcmp(sb->s_type->name, "binder") || !strcmp(sb->s_type->name, "cgroup") || !strcmp(sb->s_type->name, "cgroup2")) sbsec->flags |= SE_SBGENFS; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index b2dd31100a80..2761f47efbe8 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -912,7 +912,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, } ret = sscanf(rule, "%d", &maplevel); - if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) + if (ret != 1 || maplevel < 0 || maplevel > SMACK_CIPSO_MAXLEVEL) goto out; rule += SMK_DIGITLEN; @@ -933,6 +933,10 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, for (i = 0; i < catlen; i++) { rule += SMK_DIGITLEN; + if (rule > data + count) { + rc = -EOVERFLOW; + goto out; + } ret = sscanf(rule, "%u", &cat); if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM) goto out; @@ -2746,7 +2750,6 @@ static int smk_open_relabel_self(struct inode *inode, struct file *file) static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - struct task_smack *tsp = current_security(); char *data; int rc; LIST_HEAD(list_tmp); @@ -2771,11 +2774,21 @@ static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, kfree(data); if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) { + struct cred *new; + struct task_smack *tsp; + + new = prepare_creds(); + if (!new) { + rc = -ENOMEM; + goto out; + } + tsp = new->security; smk_destroy_label_list(&tsp->smk_relabel); list_splice(&list_tmp, &tsp->smk_relabel); + commit_creds(new); return count; } - +out: smk_destroy_label_list(&list_tmp); return rc; } diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c index 8cdf489df80e..4b7897959913 100644 --- a/sound/core/seq/oss/seq_oss.c +++ b/sound/core/seq/oss/seq_oss.c @@ -181,10 +181,16 @@ static long odev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct seq_oss_devinfo *dp; + long rc; + dp = file->private_data; if (snd_BUG_ON(!dp)) return -ENXIO; - return snd_seq_oss_ioctl(dp, cmd, arg); + + mutex_lock(®ister_mutex); + rc = snd_seq_oss_ioctl(dp, cmd, arg); + mutex_unlock(®ister_mutex); + return rc; } #ifdef CONFIG_COMPAT diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c index e1f0bcd45c37..b58a098a7270 100644 --- a/sound/pci/echoaudio/echoaudio.c +++ b/sound/pci/echoaudio/echoaudio.c @@ -2215,7 +2215,6 @@ static int snd_echo_resume(struct device *dev) if (err < 0) { kfree(commpage_bak); dev_err(dev, "resume init_hw err=%d\n", err); - snd_echo_free(chip); return err; } @@ -2242,7 +2241,6 @@ static int snd_echo_resume(struct device *dev) if (request_irq(pci->irq, snd_echo_interrupt, IRQF_SHARED, KBUILD_MODNAME, chip)) { dev_err(chip->card->dev, "cannot grab irq\n"); - snd_echo_free(chip); return -EBUSY; } chip->irq = pci->irq; diff --git a/sound/soc/intel/boards/bxt_rt298.c b/sound/soc/intel/boards/bxt_rt298.c index 7843104fadcb..1b01bc318fd2 100644 --- a/sound/soc/intel/boards/bxt_rt298.c +++ b/sound/soc/intel/boards/bxt_rt298.c @@ -529,6 +529,7 @@ static int bxt_card_late_probe(struct snd_soc_card *card) /* broxton audio machine driver for SPT + RT298S */ static struct snd_soc_card broxton_rt298 = { .name = "broxton-rt298", + .owner = THIS_MODULE, .dai_link = broxton_rt298_dais, .num_links = ARRAY_SIZE(broxton_rt298_dais), .controls = broxton_controls, @@ -544,6 +545,7 @@ static struct snd_soc_card broxton_rt298 = { static struct snd_soc_card geminilake_rt298 = { .name = "geminilake-rt298", + .owner = THIS_MODULE, .dai_link = broxton_rt298_dais, .num_links = ARRAY_SIZE(broxton_rt298_dais), .controls = broxton_controls, diff --git a/sound/usb/card.h b/sound/usb/card.h index 63090b6af8be..61c4d2664355 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h @@ -126,6 +126,7 @@ struct snd_usb_substream { unsigned int tx_length_quirk:1; /* add length specifier to transfers */ unsigned int fmt_type; /* USB audio format type (1-3) */ unsigned int pkt_offset_adj; /* Bytes to drop from beginning of packets (for non-compliant devices) */ + unsigned int stream_offset_adj; /* Bytes to drop from beginning of stream (for non-compliant devices) */ unsigned int running: 1; /* running status */ diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 5604cce30a58..d7878ed5ecc0 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -196,6 +196,7 @@ static const struct rc_config { { USB_ID(0x041e, 0x3042), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 */ { USB_ID(0x041e, 0x30df), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ { USB_ID(0x041e, 0x3237), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ + { USB_ID(0x041e, 0x3263), 0, 1, 1, 1, 1, 0x000d }, /* Usb X-Fi S51 Pro */ { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ }; diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index ff4a89af9368..6e84581a15c9 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1443,6 +1443,12 @@ static void retire_capture_urb(struct snd_usb_substream *subs, // continue; } bytes = urb->iso_frame_desc[i].actual_length; + if (subs->stream_offset_adj > 0) { + unsigned int adj = min(subs->stream_offset_adj, bytes); + cp += adj; + bytes -= adj; + subs->stream_offset_adj -= adj; + } frames = bytes / stride; if (!subs->txfr_quirk) bytes = frames * stride; diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index ec56ce382061..689fd3103e5b 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -3335,7 +3335,13 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), * with. */ { - USB_DEVICE(0x534d, 0x2109), + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | + USB_DEVICE_ID_MATCH_INT_CLASS | + USB_DEVICE_ID_MATCH_INT_SUBCLASS, + .idVendor = 0x534d, + .idProduct = 0x2109, + .bInterfaceClass = USB_CLASS_AUDIO, + .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { .vendor_name = "MacroSilicon", .product_name = "MS2109", @@ -3374,5 +3380,61 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"), } } }, +{ + /* + * PIONEER DJ DDJ-RB + * PCM is 4 channels out, 2 dummy channels in @ 44.1 fixed + * The feedback for the output is the dummy input. + */ + USB_DEVICE_VENDOR_SPEC(0x2b73, 0x000e), + .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) { + .ifnum = QUIRK_ANY_INTERFACE, + .type = QUIRK_COMPOSITE, + .data = (const struct snd_usb_audio_quirk[]) { + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 4, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x01, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC, + .rates = SNDRV_PCM_RATE_44100, + .rate_min = 44100, + .rate_max = 44100, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 44100 } + } + }, + { + .ifnum = 0, + .type = QUIRK_AUDIO_FIXED_ENDPOINT, + .data = &(const struct audioformat) { + .formats = SNDRV_PCM_FMTBIT_S24_3LE, + .channels = 2, + .iface = 0, + .altsetting = 1, + .altset_idx = 1, + .endpoint = 0x82, + .ep_attr = USB_ENDPOINT_XFER_ISOC| + USB_ENDPOINT_SYNC_ASYNC| + USB_ENDPOINT_USAGE_IMPLICIT_FB, + .rates = SNDRV_PCM_RATE_44100, + .rate_min = 44100, + .rate_max = 44100, + .nr_rates = 1, + .rate_table = (unsigned int[]) { 44100 } + } + }, + { + .ifnum = -1 + } + } + } +}, #undef USB_DEVICE_VENDOR_SPEC diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index cd36394e27ae..4f4dc43e56a7 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -1120,6 +1120,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs, case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */ set_format_emu_quirk(subs, fmt); break; + case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */ + subs->stream_offset_adj = 2; + break; } } diff --git a/sound/usb/stream.c b/sound/usb/stream.c index b46af30f375c..784cc2af304e 100644 --- a/sound/usb/stream.c +++ b/sound/usb/stream.c @@ -101,6 +101,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as, subs->tx_length_quirk = as->chip->tx_length_quirk; subs->speed = snd_usb_get_speed(subs->dev); subs->pkt_offset_adj = 0; + subs->stream_offset_adj = 0; snd_usb_set_pcm_ops(as->pcm, stream); diff --git a/tools/build/Build.include b/tools/build/Build.include index d9048f145f97..63bb9752612a 100644 --- a/tools/build/Build.include +++ b/tools/build/Build.include @@ -74,7 +74,8 @@ dep-cmd = $(if $(wildcard $(fixdep)), # dependencies in the cmd file if_changed_dep = $(if $(strip $(any-prereq) $(arg-check)), \ @set -e; \ - $(echo-cmd) $(cmd_$(1)) && $(dep-cmd)) + $(echo-cmd) $(cmd_$(1)); \ + $(dep-cmd)) # if_changed - execute command if any prerequisite is newer than # target, or command line has changed diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature index c71a05b9c984..79427b09590c 100644 --- a/tools/build/Makefile.feature +++ b/tools/build/Makefile.feature @@ -7,7 +7,7 @@ endif feature_check = $(eval $(feature_check_code)) define feature_check_code - feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) + feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CC="$(CC)" CXX="$(CXX)" CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) endef feature_set = $(eval $(feature_set_code)) diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile index 96982640fbf8..26316749e594 100644 --- a/tools/build/feature/Makefile +++ b/tools/build/feature/Makefile @@ -55,8 +55,6 @@ FILES= \ FILES := $(addprefix $(OUTPUT),$(FILES)) -CC ?= $(CROSS_COMPILE)gcc -CXX ?= $(CROSS_COMPILE)g++ PKG_CONFIG ?= $(CROSS_COMPILE)pkg-config LLVM_CONFIG ?= llvm-config diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index 8211e8010e09..d260ca680f07 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c @@ -2780,6 +2780,7 @@ process_dynamic_array_len(struct event_format *event, struct print_arg *arg, if (read_expected(EVENT_DELIM, ")") < 0) goto out_err; + free_token(token); type = read_token(&token); *tok = token; diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c index 0251dd348124..4864fc67d01b 100644 --- a/tools/perf/bench/mem-functions.c +++ b/tools/perf/bench/mem-functions.c @@ -222,12 +222,8 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info * return 0; } -static u64 do_memcpy_cycles(const struct function *r, size_t size, void *src, void *dst) +static void memcpy_prefault(memcpy_t fn, size_t size, void *src, void *dst) { - u64 cycle_start = 0ULL, cycle_end = 0ULL; - memcpy_t fn = r->fn.memcpy; - int i; - /* Make sure to always prefault zero pages even if MMAP_THRESH is crossed: */ memset(src, 0, size); @@ -236,6 +232,15 @@ static u64 do_memcpy_cycles(const struct function *r, size_t size, void *src, vo * to not measure page fault overhead: */ fn(dst, src, size); +} + +static u64 do_memcpy_cycles(const struct function *r, size_t size, void *src, void *dst) +{ + u64 cycle_start = 0ULL, cycle_end = 0ULL; + memcpy_t fn = r->fn.memcpy; + int i; + + memcpy_prefault(fn, size, src, dst); cycle_start = get_cycles(); for (i = 0; i < nr_loops; ++i) @@ -251,11 +256,7 @@ static double do_memcpy_gettimeofday(const struct function *r, size_t size, void memcpy_t fn = r->fn.memcpy; int i; - /* - * We prefault the freshly allocated memory range here, - * to not measure page fault overhead: - */ - fn(dst, src, size); + memcpy_prefault(fn, size, src, dst); BUG_ON(gettimeofday(&tv_start, NULL)); for (i = 0; i < nr_loops; ++i) diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c index 4357141c7c92..6522b6513895 100644 --- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c @@ -1129,6 +1129,7 @@ static int intel_pt_walk_fup(struct intel_pt_decoder *decoder) return 0; if (err == -EAGAIN || intel_pt_fup_with_nlip(decoder, &intel_pt_insn, ip, err)) { + decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; if (intel_pt_fup_event(decoder)) return 0; return -EAGAIN; @@ -1780,17 +1781,13 @@ next: } if (decoder->set_fup_mwait) no_tip = true; + if (no_tip) + decoder->pkt_state = INTEL_PT_STATE_FUP_NO_TIP; + else + decoder->pkt_state = INTEL_PT_STATE_FUP; err = intel_pt_walk_fup(decoder); - if (err != -EAGAIN) { - if (err) - return err; - if (no_tip) - decoder->pkt_state = - INTEL_PT_STATE_FUP_NO_TIP; - else - decoder->pkt_state = INTEL_PT_STATE_FUP; - return 0; - } + if (err != -EAGAIN) + return err; if (no_tip) { no_tip = false; break; @@ -2375,15 +2372,11 @@ const struct intel_pt_state *intel_pt_decode(struct intel_pt_decoder *decoder) err = intel_pt_walk_tip(decoder); break; case INTEL_PT_STATE_FUP: - decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; err = intel_pt_walk_fup(decoder); if (err == -EAGAIN) err = intel_pt_walk_fup_tip(decoder); - else if (!err) - decoder->pkt_state = INTEL_PT_STATE_FUP; break; case INTEL_PT_STATE_FUP_NO_TIP: - decoder->pkt_state = INTEL_PT_STATE_IN_SYNC; err = intel_pt_walk_fup(decoder); if (err == -EAGAIN) err = intel_pt_walk_trace(decoder); diff --git a/tools/testing/selftests/net/msg_zerocopy.c b/tools/testing/selftests/net/msg_zerocopy.c index e11fe84de0fd..6184d2a4c4a6 100644 --- a/tools/testing/selftests/net/msg_zerocopy.c +++ b/tools/testing/selftests/net/msg_zerocopy.c @@ -121,9 +121,8 @@ static int do_setcpu(int cpu) CPU_ZERO(&mask); CPU_SET(cpu, &mask); if (sched_setaffinity(0, sizeof(mask), &mask)) - error(1, 0, "setaffinity %d", cpu); - - if (cfg_verbose) + fprintf(stderr, "cpu: unable to pin, may increase variance.\n"); + else if (cfg_verbose) fprintf(stderr, "cpu: %u\n", cpu); return 0; diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c index f4241339edd2..7136eae2170b 100644 --- a/tools/testing/selftests/powerpc/benchmarks/context_switch.c +++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -97,8 +98,9 @@ static void start_thread_on(void *(*fn)(void *), void *arg, unsigned long cpu) static void start_process_on(void *(*fn)(void *), void *arg, unsigned long cpu) { - int pid; - cpu_set_t cpuset; + int pid, ncpus; + cpu_set_t *cpuset; + size_t size; pid = fork(); if (pid == -1) { @@ -109,14 +111,23 @@ static void start_process_on(void *(*fn)(void *), void *arg, unsigned long cpu) if (pid) return; - CPU_ZERO(&cpuset); - CPU_SET(cpu, &cpuset); + ncpus = get_nprocs(); + size = CPU_ALLOC_SIZE(ncpus); + cpuset = CPU_ALLOC(ncpus); + if (!cpuset) { + perror("malloc"); + exit(1); + } + CPU_ZERO_S(size, cpuset); + CPU_SET_S(cpu, size, cpuset); - if (sched_setaffinity(0, sizeof(cpuset), &cpuset)) { + if (sched_setaffinity(0, size, cpuset)) { perror("sched_setaffinity"); + CPU_FREE(cpuset); exit(1); } + CPU_FREE(cpuset); fn(arg); exit(0); diff --git a/tools/testing/selftests/powerpc/utils.c b/tools/testing/selftests/powerpc/utils.c index d46916867a6f..77db4f6ecf2f 100644 --- a/tools/testing/selftests/powerpc/utils.c +++ b/tools/testing/selftests/powerpc/utils.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -81,26 +82,38 @@ void *get_auxv_entry(int type) int pick_online_cpu(void) { - cpu_set_t mask; - int cpu; + int ncpus, cpu = -1; + cpu_set_t *mask; + size_t size; - CPU_ZERO(&mask); - - if (sched_getaffinity(0, sizeof(mask), &mask)) { - perror("sched_getaffinity"); + ncpus = get_nprocs_conf(); + size = CPU_ALLOC_SIZE(ncpus); + mask = CPU_ALLOC(ncpus); + if (!mask) { + perror("malloc"); return -1; } + CPU_ZERO_S(size, mask); + + if (sched_getaffinity(0, size, mask)) { + perror("sched_getaffinity"); + goto done; + } + /* We prefer a primary thread, but skip 0 */ - for (cpu = 8; cpu < CPU_SETSIZE; cpu += 8) - if (CPU_ISSET(cpu, &mask)) - return cpu; + for (cpu = 8; cpu < ncpus; cpu += 8) + if (CPU_ISSET_S(cpu, size, mask)) + goto done; /* Search for anything, but in reverse */ - for (cpu = CPU_SETSIZE - 1; cpu >= 0; cpu--) - if (CPU_ISSET(cpu, &mask)) - return cpu; + for (cpu = ncpus - 1; cpu >= 0; cpu--) + if (CPU_ISSET_S(cpu, size, mask)) + goto done; printf("No cpus in affinity mask?!\n"); - return -1; + +done: + CPU_FREE(mask); + return cpu; }