diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2019-09-10 06:02:22 -0700 |
---|---|---|
committer | Linux Build Service Account <lnxbuild@localhost> | 2019-09-10 06:02:22 -0700 |
commit | b0ef8a19f8c882c966e14aac17beb5e26da57c0f (patch) | |
tree | 14d1821277a5f6a1ed9b772a80d99a872527042e | |
parent | 38af877d3c2a39fdbf0eecfe655c0530520e6610 (diff) | |
parent | e0da3764cdc9608a0cfc330636afb2340ca8b97a (diff) |
Merge e0da3764cdc9608a0cfc330636afb2340ca8b97a on remote branchLA.UM.8.6.2.r1-04100-89xx.0
Change-Id: I1124263843b67a2faff8fa0eb76e7304be8418b6
660 files changed, 8344 insertions, 5201 deletions
diff --git a/AndroidKernel.mk b/AndroidKernel.mk index 790e713c42f5..1c2f92cb9f74 100644 --- a/AndroidKernel.mk +++ b/AndroidKernel.mk @@ -210,14 +210,31 @@ $(KERNEL_CONFIG): $(KERNEL_OUT) echo $(KERNEL_CONFIG_OVERRIDE) >> $(KERNEL_OUT)/.config; \ $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) oldconfig; fi -$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL) +ifeq ($(TARGET_KERNEL_APPEND_DTB), true) +TARGET_PREBUILT_INT_KERNEL_IMAGE := $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/Image +$(TARGET_PREBUILT_INT_KERNEL_IMAGE): $(KERNEL_USR) +$(TARGET_PREBUILT_INT_KERNEL_IMAGE): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL) + $(hide) echo "Building kernel modules..." + $(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_CFLAGS) Image + $(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_CFLAGS) modules + $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) INSTALL_MOD_PATH=$(BUILD_ROOT_LOC)../$(KERNEL_MODULES_INSTALL) INSTALL_MOD_STRIP=1 $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) modules_install + $(mv-modules) + $(clean-module-folder) + +$(TARGET_PREBUILT_INT_KERNEL): $(TARGET_PREBUILT_INT_KERNEL_IMAGE) $(hide) echo "Building kernel..." $(hide) rm -rf $(KERNEL_OUT)/arch/$(KERNEL_ARCH)/boot/dts $(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_CFLAGS) +else +TARGET_PREBUILT_INT_KERNEL_IMAGE := $(TARGET_PREBUILT_INT_KERNEL) +$(TARGET_PREBUILT_INT_KERNEL): $(KERNEL_OUT) $(KERNEL_HEADERS_INSTALL) + $(hide) echo "Building kernel..." + $(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_CFLAGS) $(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_CFLAGS) modules $(MAKE) -C $(TARGET_KERNEL_SOURCE) O=$(BUILD_ROOT_LOC)$(KERNEL_OUT) INSTALL_MOD_PATH=$(BUILD_ROOT_LOC)../$(KERNEL_MODULES_INSTALL) INSTALL_MOD_STRIP=1 $(KERNEL_MAKE_ENV) ARCH=$(KERNEL_ARCH) CROSS_COMPILE=$(KERNEL_CROSS_COMPILE) $(real_cc) modules_install $(mv-modules) $(clean-module-folder) +endif $(KERNEL_HEADERS_INSTALL): $(KERNEL_OUT) $(hide) if [ ! -z "$(KERNEL_HEADER_DEFCONFIG)" ]; then \ diff --git a/Documentation/conf.py b/Documentation/conf.py index d769cd89a9f7..da7b54388eff 100644 --- a/Documentation/conf.py +++ b/Documentation/conf.py @@ -37,7 +37,7 @@ from load_config import loadConfig extensions = ['kernel-doc', 'rstFlatTable', 'kernel_include', 'cdomain'] # The name of the math extension changed on Sphinx 1.4 -if major == 1 and minor > 3: +if (major == 1 and minor > 3) or (major > 1): extensions.append("sphinx.ext.imgmath") else: extensions.append("sphinx.ext.pngmath") diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt index 67060d309164..2f91abe04b0f 100644 --- a/Documentation/devicetree/bindings/arm/msm/msm.txt +++ b/Documentation/devicetree/bindings/arm/msm/msm.txt @@ -152,6 +152,9 @@ SoCs: - QM215 compatible = "qcom, qm215" +- QCM2150 + compatible = "qcom, qcm2150" + - MDM9640 compatible = "qcom,mdm9640" @@ -378,6 +381,7 @@ compatible = "qcom,sdm439-qrd" compatible = "qcom,sda439-cdp" compatible = "qcom,sda439-mtp" compatible = "qcom,qm215-qrd" +compatible = "qcom,qcm2150-qrd" compatible = "qcom,msm8953-rumi" compatible = "qcom,msm8953-sim" compatible = "qcom,msm8953-cdp" diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-ppi.txt b/Documentation/devicetree/bindings/media/video/msm-cam-ppi.txt new file mode 100644 index 000000000000..aeed60fa6055 --- /dev/null +++ b/Documentation/devicetree/bindings/media/video/msm-cam-ppi.txt @@ -0,0 +1,102 @@ +* Qualcomm Technologies, Inc. MSM camera PPI + +======================= +Required Node Structure +======================= +The camera PPI node must be described in First level of device nodes. The +first level describe the overall PPI node structure. + +====================================== +First Level Node - PPI device +====================================== + +- compatible + Usage: required + Value type: <string> + Definition: Should be "qcom,ppi-v1.0", + "qcom,ppi-v1.1", "qcom,ppi-v1.2", + "qcom,ppi-v2.0", "qcom,ppi". + +- cell-index: ppi hardware core index + Usage: required + Value type: <u32> + Definition: Should specify the Hardware index id. + +- reg + Usage: required + Value type: <u32> + Definition: offset and length of the register set + for the device for the ppi operating in + compatible mode. + +- reg-names + Usage: required + Value type: <string> + Definition: Should specify relevant names to each + reg property defined. + +- reg-cam-base + Usage: required + Value type: <string> + Definition: offset of PPI in camera hw block + +- interrupts + Usage: required + Value type: <u32> + Definition: Interrupt associated with PPI HW. + +- interrupt-names + Usage: required + Value type: <string> + Definition: Name of the interrupt. + +- clock-names + Usage: required + Value type: <string> + Definition: List of clock names required for PPI HW. + +- clock-rates + Usage: required + Value type: <u32> + Definition: List of clock rates in Hz for PPI HW. + +- clock-cntl-level + Usage: required + Value type: <string> + Definition: All different clock level node can support. + +- clocks + Usage: required + Value type: <phandle> + Definition: all clock phandle and source clocks. + +- regulator-names + Usage: required + Value type: <string> + Definition: name of the voltage regulators required for the device. + +- gdscr-supply + Usage: required + Value type: <phandle> + Definition: should contain gdsr regulator used for PPI clocks. + +Example: + qcom,ppi0@ace0000 { + cell-index = <0>; + compatible = "qcom,ppi170"; + reg-names = "ppi"; + reg = <0xace0000 0x200>; + reg-cam-base = <0xe0000>; + interrupt-names = "ppi"; + interrupts = <0 202 0>; + regulator-names = "gdscr", "refgen"; + gdscr-supply = <&titan_top_gdsc>; + clocks = <&clock_camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&clock_camcc CAM_CC_PPI0_CLK>, + <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK_SRC>, + <&clock_camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "cphy_rx_clk_src", "ppi0_clk" + clock-rates = <400000000 0 300000000 0>; + clock-cntl-level = "turbo"; + status = "ok"; +}; diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt b/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt index ee3723beb701..33b38716b77f 100644 --- a/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt +++ b/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt @@ -4,6 +4,7 @@ Required properties: - compatible: Should be one of the following: - "microchip,mcp2510" for MCP2510. - "microchip,mcp2515" for MCP2515. + - "microchip,mcp25625" for MCP25625. - reg: SPI chip select. - clocks: The clock feeding the CAN controller. - interrupt-parent: The parent interrupt controller. diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt index c88a0a833735..12d9a6878fe2 100644 --- a/Documentation/networking/ip-sysctl.txt +++ b/Documentation/networking/ip-sysctl.txt @@ -230,6 +230,14 @@ tcp_base_mss - INTEGER Path MTU discovery (MTU probing). If MTU probing is enabled, this is the initial MSS used by the connection. +tcp_min_snd_mss - INTEGER + TCP SYN and SYNACK messages usually advertise an ADVMSS option, + as described in RFC 1122 and RFC 6691. + If this ADVMSS option is smaller than tcp_min_snd_mss, + it is silently capped to tcp_min_snd_mss. + + Default : 48 (at least 8 bytes of payload per segment) + tcp_congestion_control - STRING Set the congestion control algorithm to be used for new connections. The algorithm "reno" is always available, but @@ -1,6 +1,6 @@ VERSION = 4 PATCHLEVEL = 9 -SUBLEVEL = 179 +SUBLEVEL = 186 EXTRAVERSION = NAME = Roaring Lionus @@ -694,6 +694,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) +KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias) ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION @@ -812,7 +813,6 @@ ifeq ($(cc-name),clang) KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,) KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier) KBUILD_CFLAGS += $(call cc-disable-warning, gnu) -KBUILD_CFLAGS += $(call cc-disable-warning, address-of-packed-member) KBUILD_CFLAGS += $(call cc-disable-warning, duplicate-decl-specifier) # Quiet clang warning: comparison of unsigned expression < 0 is always false KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare) diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index c7a081c583b9..2de75779a247 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -23,7 +23,7 @@ config ARC select GENERIC_SMP_IDLE_THREAD select HAVE_ARCH_KGDB select HAVE_ARCH_TRACEHOOK - select HAVE_FUTEX_CMPXCHG + select HAVE_FUTEX_CMPXCHG if FUTEX select HAVE_IOREMAP_PROT select HAVE_KPROBES select HAVE_KRETPROBES diff --git a/arch/arc/include/asm/bug.h b/arch/arc/include/asm/bug.h index ea022d47896c..21ec82466d62 100644 --- a/arch/arc/include/asm/bug.h +++ b/arch/arc/include/asm/bug.h @@ -23,7 +23,8 @@ void die(const char *str, struct pt_regs *regs, unsigned long address); #define BUG() do { \ pr_warn("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ - dump_stack(); \ + barrier_before_unreachable(); \ + __builtin_trap(); \ } while (0) #define HAVE_ARCH_BUG diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h index d819de1c5d10..3ea4112c8302 100644 --- a/arch/arc/include/asm/cmpxchg.h +++ b/arch/arc/include/asm/cmpxchg.h @@ -92,8 +92,11 @@ __cmpxchg(volatile void *ptr, unsigned long expected, unsigned long new) #endif /* CONFIG_ARC_HAS_LLSC */ -#define cmpxchg(ptr, o, n) ((typeof(*(ptr)))__cmpxchg((ptr), \ - (unsigned long)(o), (unsigned long)(n))) +#define cmpxchg(ptr, o, n) ({ \ + (typeof(*(ptr)))__cmpxchg((ptr), \ + (unsigned long)(o), \ + (unsigned long)(n)); \ +}) /* * atomic_cmpxchg is same as cmpxchg @@ -198,8 +201,11 @@ static inline unsigned long __xchg(unsigned long val, volatile void *ptr, return __xchg_bad_pointer(); } -#define xchg(ptr, with) ((typeof(*(ptr)))__xchg((unsigned long)(with), (ptr), \ - sizeof(*(ptr)))) +#define xchg(ptr, with) ({ \ + (typeof(*(ptr)))__xchg((unsigned long)(with), \ + (ptr), \ + sizeof(*(ptr))); \ +}) #endif /* CONFIG_ARC_PLAT_EZNPS */ diff --git a/arch/arc/kernel/traps.c b/arch/arc/kernel/traps.c index c927aa84e652..2fb0cd39a31c 100644 --- a/arch/arc/kernel/traps.c +++ b/arch/arc/kernel/traps.c @@ -155,3 +155,11 @@ void do_insterror_or_kprobe(unsigned long address, struct pt_regs *regs) insterror_is_error(address, regs); } + +/* + * abort() call generated by older gcc for __builtin_trap() + */ +void abort(void) +{ + __asm__ __volatile__("trap_s 5\n"); +} diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index 61fd1ce63c56..6bb9f8ea9291 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -185,11 +185,6 @@ static void *__init unw_hdr_alloc_early(unsigned long sz) MAX_DMA_ADDRESS); } -static void *unw_hdr_alloc(unsigned long sz) -{ - return kmalloc(sz, GFP_KERNEL); -} - static void init_unwind_table(struct unwind_table *table, const char *name, const void *core_start, unsigned long core_size, const void *init_start, unsigned long init_size, @@ -370,6 +365,10 @@ ret_err: } #ifdef CONFIG_MODULES +static void *unw_hdr_alloc(unsigned long sz) +{ + return kmalloc(sz, GFP_KERNEL); +} static struct unwind_table *last_table; diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c index a4dc881da277..3c88ccbe01af 100644 --- a/arch/arc/mm/tlb.c +++ b/arch/arc/mm/tlb.c @@ -890,9 +890,11 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, struct pt_regs *regs) { struct cpuinfo_arc_mmu *mmu = &cpuinfo_arc700[smp_processor_id()].mmu; - unsigned int pd0[mmu->ways]; unsigned long flags; - int set; + int set, n_ways = mmu->ways; + + n_ways = min(n_ways, 4); + BUG_ON(mmu->ways > 4); local_irq_save(flags); @@ -900,9 +902,10 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, for (set = 0; set < mmu->sets; set++) { int is_valid, way; + unsigned int pd0[4]; /* read out all the ways of current set */ - for (way = 0, is_valid = 0; way < mmu->ways; way++) { + for (way = 0, is_valid = 0; way < n_ways; way++) { write_aux_reg(ARC_REG_TLBINDEX, SET_WAY_TO_IDX(mmu, set, way)); write_aux_reg(ARC_REG_TLBCOMMAND, TLBRead); @@ -916,14 +919,14 @@ void do_tlb_overlap_fault(unsigned long cause, unsigned long address, continue; /* Scan the set for duplicate ways: needs a nested loop */ - for (way = 0; way < mmu->ways - 1; way++) { + for (way = 0; way < n_ways - 1; way++) { int n; if (!pd0[way]) continue; - for (n = way + 1; n < mmu->ways; n++) { + for (n = way + 1; n < n_ways; n++) { if (pd0[way] != pd0[n]) continue; diff --git a/arch/arm/boot/dts/exynos5420-arndale-octa.dts b/arch/arm/boot/dts/exynos5420-arndale-octa.dts index 9cc83c51c925..e664c33c3c64 100644 --- a/arch/arm/boot/dts/exynos5420-arndale-octa.dts +++ b/arch/arm/boot/dts/exynos5420-arndale-octa.dts @@ -110,6 +110,7 @@ regulator-name = "PVDD_APIO_1V8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; }; ldo3_reg: LDO3 { @@ -148,6 +149,7 @@ regulator-name = "PVDD_ABB_1V8"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; }; ldo9_reg: LDO9 { diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi index b13b0b2db881..8ccafdfbe87c 100644 --- a/arch/arm/boot/dts/imx6qdl.dtsi +++ b/arch/arm/boot/dts/imx6qdl.dtsi @@ -875,7 +875,7 @@ compatible = "fsl,imx6q-sdma", "fsl,imx35-sdma"; reg = <0x020ec000 0x4000>; interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6QDL_CLK_SDMA>, + clocks = <&clks IMX6QDL_CLK_IPG>, <&clks IMX6QDL_CLK_SDMA>; clock-names = "ipg", "ahb"; #dma-cells = <3>; diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi index 02378db3f5fc..a2c76797e871 100644 --- a/arch/arm/boot/dts/imx6sl.dtsi +++ b/arch/arm/boot/dts/imx6sl.dtsi @@ -704,7 +704,7 @@ reg = <0x020ec000 0x4000>; interrupts = <0 2 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6SL_CLK_SDMA>, - <&clks IMX6SL_CLK_SDMA>; + <&clks IMX6SL_CLK_AHB>; clock-names = "ipg", "ahb"; #dma-cells = <3>; /* imx6sl reuses imx6q sdma firmware */ diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index a885052157f0..5834194b62e1 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -751,7 +751,7 @@ compatible = "fsl,imx6sx-sdma", "fsl,imx6q-sdma"; reg = <0x020ec000 0x4000>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SX_CLK_SDMA>, + clocks = <&clks IMX6SX_CLK_IPG>, <&clks IMX6SX_CLK_SDMA>; clock-names = "ipg", "ahb"; #dma-cells = <3>; diff --git a/arch/arm/boot/dts/imx6ul.dtsi b/arch/arm/boot/dts/imx6ul.dtsi index c5c05fdccc78..200d9082caa4 100644 --- a/arch/arm/boot/dts/imx6ul.dtsi +++ b/arch/arm/boot/dts/imx6ul.dtsi @@ -332,7 +332,7 @@ pwm1: pwm@02080000 { compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm"; reg = <0x02080000 0x4000>; - interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 83 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6UL_CLK_PWM1>, <&clks IMX6UL_CLK_PWM1>; clock-names = "ipg", "per"; @@ -343,7 +343,7 @@ pwm2: pwm@02084000 { compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm"; reg = <0x02084000 0x4000>; - interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6UL_CLK_PWM2>, <&clks IMX6UL_CLK_PWM2>; clock-names = "ipg", "per"; @@ -354,7 +354,7 @@ pwm3: pwm@02088000 { compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm"; reg = <0x02088000 0x4000>; - interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6UL_CLK_PWM3>, <&clks IMX6UL_CLK_PWM3>; clock-names = "ipg", "per"; @@ -365,7 +365,7 @@ pwm4: pwm@0208c000 { compatible = "fsl,imx6ul-pwm", "fsl,imx27-pwm"; reg = <0x0208c000 0x4000>; - interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>; + interrupts = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clks IMX6UL_CLK_PWM4>, <&clks IMX6UL_CLK_PWM4>; clock-names = "ipg", "per"; @@ -669,7 +669,7 @@ "fsl,imx35-sdma"; reg = <0x020ec000 0x4000>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6UL_CLK_SDMA>, + clocks = <&clks IMX6UL_CLK_IPG>, <&clks IMX6UL_CLK_SDMA>; clock-names = "ipg", "ahb"; #dma-cells = <3>; diff --git a/arch/arm/boot/dts/imx7s.dtsi b/arch/arm/boot/dts/imx7s.dtsi index 2b6cb05bc01a..edc5ddeb851a 100644 --- a/arch/arm/boot/dts/imx7s.dtsi +++ b/arch/arm/boot/dts/imx7s.dtsi @@ -962,8 +962,8 @@ compatible = "fsl,imx7d-sdma", "fsl,imx35-sdma"; reg = <0x30bd0000 0x10000>; interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX7D_SDMA_CORE_CLK>, - <&clks IMX7D_AHB_CHANNEL_ROOT_CLK>; + clocks = <&clks IMX7D_IPG_ROOT_CLK>, + <&clks IMX7D_SDMA_CORE_CLK>; clock-names = "ipg", "ahb"; #dma-cells = <3>; fsl,sdma-ram-script-name = "imx/sdma/sdma-imx7d.bin"; diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index ff0ae9a96e54..d1edfd97372b 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -3,7 +3,6 @@ dtb-$(CONFIG_ARCH_SDXPOORWILLS) += sdxpoorwills-rumi.dtb \ sdxpoorwills-cdp.dtb \ sdxpoorwills-mtp.dtb \ sdxpoorwills-atp.dtb \ - sa415m-ttp.dtb \ sdxpoorwills-cdp-256.dtb \ sdxpoorwills-mtp-256.dtb \ sdxpoorwills-dualwifi-cdp.dtb \ @@ -16,12 +15,17 @@ dtb-$(CONFIG_ARCH_SDXPOORWILLS) += sdxpoorwills-rumi.dtb \ sdxpoorwills-v2-cdp.dtb \ sdxpoorwills-v2-dualwifi-mtp.dtb \ sdxpoorwills-v2-dualwifi-cdp.dtb \ + sdxpoorwills-v2-pcie-ep-mtp-256.dtb \ + sdxpoorwills-v2-pcie-ep-mtp.dtb \ + sa415m-ttp.dtb \ sa415m-ccard.dtb \ sa415m-ccard-pcie-ep.dtb \ sa415m-ccard-usb-ep.dtb \ sa415m-ttp-usb-ep.dtb \ - sdxpoorwills-v2-pcie-ep-mtp-256.dtb \ - sdxpoorwills-v2-pcie-ep-mtp.dtb + sa415m-mtp-256.dtb \ + sa415m-cdp.dtb \ + sa415m-v2-cdp.dtb \ + sa415m-v2-mtp.dtb dtb-$(CONFIG_ARCH_MDM9650) += mdm9650-nand-mtp.dtb \ mdm9650-ttp.dtb \ diff --git a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts index 10ee58cc58a0..2eaca0282ab2 100644 --- a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts +++ b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts @@ -32,7 +32,7 @@ &ipa_hw { qcom,use-ipa-in-mhi-mode; qcom,ipa-config-is-auto; - qcom,mhi-event-ring-id-limits = <9 13>; /* start and end */ + qcom,mhi-event-ring-id-limits = <7 11>; /* start and end */ }; &cnss_pcie { diff --git a/arch/arm/boot/dts/qcom/sa415m-cdp.dts b/arch/arm/boot/dts/qcom/sa415m-cdp.dts new file mode 100644 index 000000000000..b9e7d4947c6e --- /dev/null +++ b/arch/arm/boot/dts/qcom/sa415m-cdp.dts @@ -0,0 +1,32 @@ +/* Copyright (c) 2019, 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 "sdxpoorwills-cdp.dtsi" +#include "sdxpoorwills-display.dtsi" +#include "qpic-panel-ili-hvga.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA415M CDP"; + compatible = "qcom,sdxpoorwills-cdp", + "qcom,sdxpoorwills", "qcom,cdp"; + qcom,board-id = <1 0x104>; +}; + +&blsp1_uart2b_hs { + status = "okay"; +}; + +&mss_mem { + reg = <0x86400000 0x9300000>; +}; diff --git a/arch/arm/boot/dts/qcom/sa415m-mtp-256.dts b/arch/arm/boot/dts/qcom/sa415m-mtp-256.dts new file mode 100644 index 000000000000..09a8ea0a3b5c --- /dev/null +++ b/arch/arm/boot/dts/qcom/sa415m-mtp-256.dts @@ -0,0 +1,30 @@ +/* Copyright (c) 2019, 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 "sdxpoorwills-mtp-256.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA415M MTP (256MB)"; + compatible = "qcom,sdxpoorwills-mtp", + "qcom,sdxpoorwills", "qcom,mtp"; + qcom,board-id = <8 0x106>; +}; + +&blsp1_uart2b_hs { + status = "okay"; +}; + +&mss_mem { + reg = <0x86400000 0x9300000>; +}; diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi index 1cf499e858a5..b0d746a372ac 100644 --- a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi +++ b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi @@ -20,6 +20,10 @@ status = "okay"; }; +&sdhc_1 { + qcom,nonremovable; +}; + &usb { status = "okay"; qcom,connector-type-uAB; diff --git a/arch/arm/boot/dts/qcom/sa415m-v2-cdp.dts b/arch/arm/boot/dts/qcom/sa415m-v2-cdp.dts new file mode 100644 index 000000000000..c8b78915dac0 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sa415m-v2-cdp.dts @@ -0,0 +1,33 @@ +/* Copyright (c) 2019, 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 "sdxpoorwills-cdp.dtsi" +#include "sdxpoorwills-v2.dtsi" +#include "sdxpoorwills-display.dtsi" +#include "qpic-panel-ili-hvga.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA415M CDP V2"; + compatible = "qcom,sdxpoorwills-cdp", + "qcom,sdxpoorwills", "qcom,cdp"; + qcom,board-id = <1 0x104>; +}; + +&blsp1_uart2b_hs { + status = "okay"; +}; + +&mss_mem { + reg = <0x86400000 0x9300000>; +}; diff --git a/arch/arm/boot/dts/qcom/sa415m-v2-mtp.dts b/arch/arm/boot/dts/qcom/sa415m-v2-mtp.dts new file mode 100644 index 000000000000..c7cbbd1ba1f5 --- /dev/null +++ b/arch/arm/boot/dts/qcom/sa415m-v2-mtp.dts @@ -0,0 +1,35 @@ +/* Copyright (c) 2019, 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 "sdxpoorwills-mtp.dtsi" +#include "sdxpoorwills-v2.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. SA415M MTP V2"; + compatible = "qcom,sdxpoorwills-mtp", + "qcom,sdxpoorwills", "qcom,mtp"; + qcom,board-id = <8 0x106>; +}; + +&qcom_seecom { + status = "okay"; +}; + +&blsp1_uart2b_hs { + status = "okay"; +}; + +&mss_mem { + reg = <0x86400000 0x9300000>; +}; diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi index abbc8b5a7f65..c74425344aa0 100644 --- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi +++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi @@ -522,7 +522,6 @@ mhi_net_device: qcom,mhi_net_dev { compatible = "qcom,msm-mhi-dev-net"; - qcom,mhi-ethernet-interface; status = "disabled"; }; diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig index b903f859fd8d..575cf5e649e6 100755 --- a/arch/arm/configs/msm8909_defconfig +++ b/arch/arm/configs/msm8909_defconfig @@ -384,6 +384,8 @@ CONFIG_USB_EHCI_MSM=y CONFIG_USB_ACM=y CONFIG_USB_STORAGE=y CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CP210X=y +CONFIG_USB_SERIAL_FTDI_SIO=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_USB_GADGET=y CONFIG_USB_GADGET_DEBUG_FILES=y diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig index 7a0bc4ad0f4f..15bd01dbe3d7 100755 --- a/arch/arm/configs/msm8937-perf_defconfig +++ b/arch/arm/configs/msm8937-perf_defconfig @@ -559,6 +559,7 @@ CONFIG_USB_BAM=y CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MAILBOX=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig index 9e29b18d459c..12254aa89478 100755 --- a/arch/arm/configs/msm8937_defconfig +++ b/arch/arm/configs/msm8937_defconfig @@ -570,6 +570,7 @@ CONFIG_MSM_EXT_DISPLAY=y CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MAILBOX=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/msm8937go-perf_defconfig b/arch/arm/configs/msm8937go-perf_defconfig index 3790e25b07ce..8420285b9075 100755 --- a/arch/arm/configs/msm8937go-perf_defconfig +++ b/arch/arm/configs/msm8937go-perf_defconfig @@ -554,6 +554,7 @@ CONFIG_USB_BAM=y CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MAILBOX=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/msm8937go_defconfig b/arch/arm/configs/msm8937go_defconfig index 57c500383c0a..b9cdd7ea3035 100755 --- a/arch/arm/configs/msm8937go_defconfig +++ b/arch/arm/configs/msm8937go_defconfig @@ -563,6 +563,7 @@ CONFIG_MSM_EXT_DISPLAY=y CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MAILBOX=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig index 2b2b128b25bc..714cab163fda 100755 --- a/arch/arm/configs/msm8953-perf_defconfig +++ b/arch/arm/configs/msm8953-perf_defconfig @@ -561,6 +561,7 @@ CONFIG_USB_BAM=y CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MAILBOX=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig index ffe49c1b34a1..0697744030b0 100755 --- a/arch/arm/configs/msm8953_defconfig +++ b/arch/arm/configs/msm8953_defconfig @@ -571,6 +571,7 @@ CONFIG_MSM_EXT_DISPLAY=y CONFIG_MSM_RMNET_BAM=y CONFIG_MSM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MAILBOX=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/sa415m-perf_defconfig b/arch/arm/configs/sa415m-perf_defconfig index 5a9b777ec74b..326cc4abc432 100644 --- a/arch/arm/configs/sa415m-perf_defconfig +++ b/arch/arm/configs/sa415m-perf_defconfig @@ -414,6 +414,8 @@ CONFIG_PWM=y CONFIG_PWM_QPNP=y CONFIG_QCOM_SHOW_RESUME_IRQ=y CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_IPC_32BIT=y CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_UBIFS_FS=y diff --git a/arch/arm/configs/sa415m_defconfig b/arch/arm/configs/sa415m_defconfig index 604602396195..96b3cb9e74b0 100644 --- a/arch/arm/configs/sa415m_defconfig +++ b/arch/arm/configs/sa415m_defconfig @@ -445,6 +445,9 @@ CONFIG_PWM=y CONFIG_PWM_QPNP=y CONFIG_QCOM_SHOW_RESUME_IRQ=y CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_BINDER_IPC_32BIT=y +CONFIG_MSM_TZ_LOG=y CONFIG_EXT3_FS=y CONFIG_EXT4_FS_SECURITY=y CONFIG_VFAT_FS=y diff --git a/arch/arm/configs/sdm670-perf_defconfig b/arch/arm/configs/sdm670-perf_defconfig index c67ee518542d..a4d16315303c 100755 --- a/arch/arm/configs/sdm670-perf_defconfig +++ b/arch/arm/configs/sdm670-perf_defconfig @@ -468,6 +468,7 @@ CONFIG_MSM_GPUCC_SDM845=y CONFIG_MSM_CLK_AOP_QMP=y CONFIG_QCOM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MSM_QMP=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/configs/sdm670_defconfig b/arch/arm/configs/sdm670_defconfig index 6a92eb410bcd..8d9d85b9dd14 100755 --- a/arch/arm/configs/sdm670_defconfig +++ b/arch/arm/configs/sdm670_defconfig @@ -480,6 +480,7 @@ CONFIG_MSM_GPUCC_SDM845=y CONFIG_MSM_CLK_AOP_QMP=y CONFIG_QCOM_MDSS_PLL=y CONFIG_REMOTE_SPINLOCK_MSM=y +CONFIG_MSM_TIMER_LEAP=y CONFIG_MSM_QMP=y CONFIG_ARM_SMMU=y CONFIG_QCOM_LAZY_MAPPING=y diff --git a/arch/arm/include/asm/arch_timer.h b/arch/arm/include/asm/arch_timer.h index d4ebf5679f1f..1d85857771fd 100644 --- a/arch/arm/include/asm/arch_timer.h +++ b/arch/arm/include/asm/arch_timer.h @@ -92,7 +92,14 @@ static inline u64 arch_counter_get_cntvct(void) u64 cval; isb(); +#if IS_ENABLED(CONFIG_MSM_TIMER_LEAP) +#define L32_BITS 0x00000000FFFFFFFF + do { + asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); + } while ((cval & L32_BITS) == L32_BITS); +#else asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (cval)); +#endif return cval; } diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h index b74b174ac9fc..b458e4122794 100644 --- a/arch/arm/include/asm/cp15.h +++ b/arch/arm/include/asm/cp15.h @@ -67,6 +67,8 @@ #define BPIALL __ACCESS_CP15(c7, 0, c5, 6) #define ICIALLU __ACCESS_CP15(c7, 0, c5, 0) +#define CNTVCT __ACCESS_CP15_64(1, c14) + extern unsigned long cr_alignment; /* defined in entry-armv.S */ static inline unsigned long get_cr(void) diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h index 3d7351c844aa..2fd0a2619b0b 100644 --- a/arch/arm/include/asm/hardirq.h +++ b/arch/arm/include/asm/hardirq.h @@ -5,6 +5,7 @@ #include <linux/threads.h> #include <asm/irq.h> +/* number of IPIS _not_ including IPI_CPU_BACKTRACE */ #define NR_IPI 7 typedef struct { diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index 931630042905..7ba363b28ef8 100644..100755 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -76,6 +76,10 @@ enum ipi_msg_type { IPI_CPU_STOP, IPI_IRQ_WORK, IPI_COMPLETION, + /* + * CPU_BACKTRACE is special and not included in NR_IPI + * or tracable with trace_ipi_* + */ IPI_CPU_BACKTRACE, /* * SGI8-15 can be reserved by secure firmware, and thus may @@ -825,7 +829,7 @@ static void raise_nmi(cpumask_t *mask) if (cpumask_test_cpu(smp_processor_id(), mask) && irqs_disabled()) nmi_cpu_backtrace(NULL); - smp_cross_call_common(mask, IPI_CPU_BACKTRACE); + __smp_cross_call(mask, IPI_CPU_BACKTRACE); } void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self) diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c index 8e4539f69fdc..3bdf0d588238 100644 --- a/arch/arm/mach-davinci/board-da850-evm.c +++ b/arch/arm/mach-davinci/board-da850-evm.c @@ -1479,6 +1479,8 @@ static __init void da850_evm_init(void) if (ret) pr_warn("%s: dsp/rproc registration failed: %d\n", __func__, ret); + + regulator_has_full_constraints(); } #ifdef CONFIG_SERIAL_8250_CONSOLE diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c index 9a22d40602aa..24779504f489 100644 --- a/arch/arm/mach-davinci/devices-da8xx.c +++ b/arch/arm/mach-davinci/devices-da8xx.c @@ -706,6 +706,9 @@ static struct platform_device da8xx_lcdc_device = { .id = 0, .num_resources = ARRAY_SIZE(da8xx_lcdc_resources), .resource = da8xx_lcdc_resources, + .dev = { + .coherent_dma_mask = DMA_BIT_MASK(32), + } }; int __init da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata) diff --git a/arch/arm/mach-exynos/suspend.c b/arch/arm/mach-exynos/suspend.c index 81c935ce089b..b406c12077b9 100644 --- a/arch/arm/mach-exynos/suspend.c +++ b/arch/arm/mach-exynos/suspend.c @@ -500,8 +500,27 @@ early_wakeup: static void exynos5420_prepare_pm_resume(void) { + unsigned int mpidr, cluster; + + mpidr = read_cpuid_mpidr(); + cluster = MPIDR_AFFINITY_LEVEL(mpidr, 1); + if (IS_ENABLED(CONFIG_EXYNOS5420_MCPM)) WARN_ON(mcpm_cpu_powered_up()); + + if (IS_ENABLED(CONFIG_HW_PERF_EVENTS) && cluster != 0) { + /* + * When system is resumed on the LITTLE/KFC core (cluster 1), + * the DSCR is not properly updated until the power is turned + * on also for the cluster 0. Enable it for a while to + * propagate the SPNIDEN and SPIDEN signals from Secure JTAG + * block and avoid undefined instruction issue on CP14 reset. + */ + pmu_raw_writel(S5P_CORE_LOCAL_PWR_EN, + EXYNOS_COMMON_CONFIGURATION(0)); + pmu_raw_writel(0, + EXYNOS_COMMON_CONFIGURATION(0)); + } } static void exynos5420_pm_resume(void) diff --git a/arch/arm/mach-imx/cpuidle-imx6sx.c b/arch/arm/mach-imx/cpuidle-imx6sx.c index edb888ac5ad3..c6aa77dfd00a 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sx.c +++ b/arch/arm/mach-imx/cpuidle-imx6sx.c @@ -15,6 +15,7 @@ #include "common.h" #include "cpuidle.h" +#include "hardware.h" static int imx6sx_idle_finish(unsigned long val) { @@ -108,7 +109,7 @@ int __init imx6sx_cpuidle_init(void) * except for power up sw2iso which need to be * larger than LDO ramp up time. */ - imx_gpc_set_arm_power_up_timing(0xf, 1); + imx_gpc_set_arm_power_up_timing(cpu_is_imx6sx() ? 0xf : 0x2, 1); imx_gpc_set_arm_power_down_timing(1, 1); return cpuidle_register(&imx6sx_cpuidle_driver, NULL); diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 718981bb80cd..0aec48c1736b 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -433,7 +433,7 @@ static void omap3_prm_reconfigure_io_chain(void) * registers, and omap3xxx_prm_reconfigure_io_chain() must be called. * No return value. */ -static void __init omap3xxx_prm_enable_io_wakeup(void) +static void omap3xxx_prm_enable_io_wakeup(void) { if (prm_features & PRM_HAS_IO_WAKEUP) omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, diff --git a/arch/arm/vdso/vgettimeofday.c b/arch/arm/vdso/vgettimeofday.c index 79214d5ff097..3af02d2a0b7f 100644 --- a/arch/arm/vdso/vgettimeofday.c +++ b/arch/arm/vdso/vgettimeofday.c @@ -18,9 +18,9 @@ #include <linux/compiler.h> #include <linux/hrtimer.h> #include <linux/time.h> -#include <asm/arch_timer.h> #include <asm/barrier.h> #include <asm/bug.h> +#include <asm/cp15.h> #include <asm/page.h> #include <asm/unistd.h> #include <asm/vdso_datapage.h> @@ -123,7 +123,8 @@ static notrace u64 get_ns(struct vdso_data *vdata) u64 cycle_now; u64 nsec; - cycle_now = arch_counter_get_cntvct(); + isb(); + cycle_now = read_sysreg(CNTVCT); cycle_delta = (cycle_now - vdata->cs_cycle_last) & vdata->cs_mask; diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile index cccc3e94ea8d..2156cb6ed535 100644 --- a/arch/arm64/boot/dts/qcom/Makefile +++ b/arch/arm64/boot/dts/qcom/Makefile @@ -351,7 +351,8 @@ dtbo-$(CONFIG_ARCH_MSM8917) += msm8917-mtp-overlay.dtbo \ apq8017-cdp-overlay.dtbo \ apq8017-cdp-wcd-rome-overlay.dtbo -dtbo-$(CONFIG_ARCH_QM215) +=qm215-qrd-overlay.dtbo +dtbo-$(CONFIG_ARCH_QM215) +=qm215-qrd-overlay.dtbo \ + qcm2150-qrd-overlay.dtbo dtbo-$(CONFIG_ARCH_QM215) +=qm215-qrd-smb1360-overlay.dtbo dtbo-$(CONFIG_ARCH_MSM8953) += msm8953-mtp-overlay.dtbo \ @@ -434,6 +435,7 @@ apq8017-cdp-wcd-rome-overlay.dtbo-base := apq8017-pmi8950.dtb \ apq8017-pmi8937.dtb qm215-qrd-overlay.dtbo-base := qm215.dtb +qcm2150-qrd-overlay.dtbo-base := qcm2150.dtb qm215-qrd-smb1360-overlay.dtbo-base := qm215.dtb msm8953-mtp-overlay.dtbo-base := sdm450.dtb \ @@ -583,7 +585,8 @@ dtb-$(CONFIG_ARCH_MSM8917) += msm8917-pmi8950-mtp.dtb \ msm8917-pmi8940-cdp.dtb \ msm8917-pmi8940-rcm.dtb -dtb-$(CONFIG_ARCH_QM215) += qm215-qrd.dtb +dtb-$(CONFIG_ARCH_QM215) += qm215-qrd.dtb \ + qcm2150-qrd.dtb dtb-$(CONFIG_ARCH_QM215) += qm215-qrd-smb1360.dtb dtb-$(CONFIG_ARCH_MSM8909) += msm8909-pm8916-mtp.dtb \ @@ -641,6 +644,7 @@ dtb-$(CONFIG_ARCH_SDM439) += sdm439-mtp.dtb \ sdm439-external-codec-mtp.dtb \ sdm439-rcm.dtb \ qm215-qrd.dtb \ + qcm2150-qrd.dtb \ qm215-qrd-smb1360.dtb dtb-$(CONFIG_ARCH_SDM429) += sdm429-mtp.dtb \ diff --git a/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi index 6d384fc794c8..010694d02938 100644 --- a/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi @@ -19,9 +19,9 @@ qcom,hpm-min-load = <100000>; status = "disabled"; - regulator-s2 { + regulator-s1 { compatible = "qcom,rpm-smd-regulator"; - regulator-name = "pm660_s2"; + regulator-name = "pm660_s1"; qcom,set = <3>; status = "disabled"; }; diff --git a/arch/arm64/boot/dts/qcom/qcm2150-qrd-overlay.dts b/arch/arm64/boot/dts/qcom/qcm2150-qrd-overlay.dts new file mode 100644 index 000000000000..d8101504af9b --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcm2150-qrd-overlay.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, 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/; +/plugin/; + +#include "qcm2150-qrd.dtsi" + +/ { + model = "QRD"; + qcom,board-id = <0x01000b 4>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm2150-qrd.dts b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dts new file mode 100644 index 000000000000..5d1e1c5fdd46 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, 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 "qcm2150.dtsi" +#include "qcm2150-qrd.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCM2150 QRD"; + compatible = "qcom,qcm2150-qrd", "qcom,qcm2150", "qcom,qrd"; + qcom,board-id = <0x01000b 4>; + qcom,pmic-id = <0x010016 0x25 0x0 0x0>; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm2150-qrd.dtsi b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dtsi new file mode 100644 index 000000000000..05af319cf83a --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, 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. + */ + +#include "qm215-qrd.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCM2150 QRD"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm2150.dts b/arch/arm64/boot/dts/qcom/qcm2150.dts new file mode 100644 index 000000000000..179d0edc2696 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcm2150.dts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2019, 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 "qcm2150.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCM2150"; + compatible = "qcom,qcm2150"; + qcom,pmic-name = "PM8916"; +}; diff --git a/arch/arm64/boot/dts/qcom/qcm2150.dtsi b/arch/arm64/boot/dts/qcom/qcm2150.dtsi new file mode 100644 index 000000000000..eac04e1f6ba1 --- /dev/null +++ b/arch/arm64/boot/dts/qcom/qcm2150.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019, 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. + */ + +#include "qm215.dtsi" +#include "qm215-pm8916.dtsi" +#include "qm215-audio.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. QCM2150"; + compatible = "qcom,qcm2150"; + qcom,msm-id = <436 0x0>; + qcom,msm-name = "QCM2150"; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt-camera.dtsi index 5c1594888f6b..8d047caccc39 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt-camera.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt-camera.dtsi @@ -203,82 +203,40 @@ eeprom_spyro1: qcom,eeprom@1 { cell-index = <1>; reg = <0x1>; - qcom,eeprom-name = "sunny_8865"; compatible = "qcom,eeprom"; - qcom,slave-addr = <0x6c>; - qcom,cci-master = <0>; - qcom,num-blocks = <8>; - - qcom,page0 = <1 0x0100 2 0x01 1 1>; - qcom,poll0 = <0 0x0 2 0x0 1 0>; - qcom,mem0 = <0 0x0 2 0x0 1 0>; - - qcom,page1 = <1 0x5002 2 0x00 1 0>; - qcom,poll1 = <0 0x0 2 0x0 1 0>; - qcom,mem1 = <0 0x0 2 0x0 1 0>; - - qcom,page2 = <1 0x3d84 2 0xc0 1 0>; - qcom,poll2 = <0 0x0 2 0x0 1 0>; - qcom,mem2 = <0 0x0 2 0x0 1 0>; - - qcom,page3 = <1 0x3d88 2 0x70 1 0>; - qcom,poll3 = <0 0x0 2 0x0 1 0>; - qcom,mem3 = <0 0x0 2 0x0 1 0>; - - qcom,page4 = <1 0x3d89 2 0x10 1 0>; - qcom,poll4 = <0 0x0 2 0x0 1 0>; - qcom,mem4 = <0 0x0 2 0x0 1 0>; - - qcom,page5 = <1 0x3d8a 2 0x70 1 0>; - qcom,poll5 = <0 0x0 2 0x0 1 0>; - qcom,mem5 = <0 0x0 2 0x0 1 0>; - - qcom,page6 = <1 0x3d8b 2 0xf4 1 0>; - qcom,poll6 = <0 0x0 2 0x0 1 0>; - qcom,mem6 = <0 0x0 2 0x0 1 0>; - - qcom,page7 = <1 0x3d81 2 0x01 1 10>; - qcom,poll7 = <0 0x0 2 0x0 1 1>; - qcom,mem7 = <1536 0x7010 2 0 1 0>; + qcom,cci-master = <1>; cam_vdig-supply = <&pm660_l3>; - cam_vana-supply = <&pm660_l7>; - cam_vio-supply = <&pm660_l6>; + cam_vio-supply = <&pm660_l14>; + cam_vana-supply = <&pm660_s5>; cam_vaf-supply = <&pm660_l17>; - qcom,cam-vreg-name = "cam_vdig", "cam_vio", - "cam_vana", "cam_vaf"; - qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; - qcom,cam-vreg-max-voltage = <1200000 0 2800000 3200000>; - qcom,cam-vreg-op-mode = <105000 0 80000 100000>; - qcom,gpio-no-mux = <0>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 1800000 1420000>; + qcom,cam-vreg-max-voltage = <1200000 1800000 1420000>; + qcom,cam-vreg-op-mode = <200000 80000 80000>; pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_default - &cam_sensor_front1_default>; - pinctrl-1 = <&cam_sensor_mclk2_sleep - &cam_sensor_front1_sleep>; - gpios = <&tlmm 28 0>, - <&tlmm 40 0>, - <&tlmm 39 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_STANDBY2"; - qcom,cam-power-seq-type = "sensor_vreg", "sensor_vreg", - "sensor_vreg", - "sensor_gpio", "sensor_gpio" , "sensor_clk"; - qcom,cam-power-seq-val = "cam_vdig", "cam_vana", "cam_vio", - "sensor_gpio_reset", "sensor_gpio_standby", - "sensor_cam_mclk"; - qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>; - qcom,cam-power-seq-delay = <1 1 1 30 30 5>; - status = "disabled"; - clocks = <&clock_gcc clk_mclk2_clk_src>, - <&clock_gcc clk_gcc_camss_mclk2_clk>; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 33 0>, + <&tlmm 66 0>, + <&tlmm 38 0>; + qcom,gpio-vana= <1>; + qcom,gpio-vdig= <2>; + qcom,gpio-reset = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_AVDD1", + "CAM_DVDD1", + "CAM_RESET1"; + status = "ok"; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <19200000 0>; + qcom,clock-rates = <24000000 0>; }; qcom,camera@0 { @@ -337,6 +295,8 @@ qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <270>; + qcom,eeprom-src = <&eeprom_spyro1>; + cam_vdig-supply = <&pm660_l3>; cam_vio-supply = <&pm660_l14>; cam_vana-supply = <&pm660_s5>; @@ -378,7 +338,6 @@ qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <270>; - qcom,eeprom-src = <&eeprom_spyro1>; qcom,actuator-src = <&actuator_spyro1>; cam_vdig-supply = <&pm660_l3>; cam_vana-supply = <&pm660_l7>; diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt.dtsi b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt.dtsi index 4c92642b071f..9014166c228a 100644 --- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt.dtsi @@ -14,6 +14,7 @@ #include "sdm429-spyro-qrd-mdss-panels.dtsi" #include "sdm429-spyro-qrd-evt-camera.dtsi" #include "sdm429-spyro-qrd-evt-audio.dtsi" +#include <dt-bindings/thermal/thermal.h> &tlmm { sd_eldo_active { @@ -232,7 +233,7 @@ &secure_mem { alignment = <0 0x400000>; - size = <0 0x400000>; + size = <0 0x800000>; status = "okay"; }; @@ -434,3 +435,661 @@ }; }; + +&pm660_vadc { + chan@50 { + label = "pmic_therm"; + reg = <0x50>; + qcom,decimation = <2>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,fast-avg-setup = <0>; + }; +}; + +&pm660_adc_tm { + chan@50 { + label = "pmic_therm"; + reg = <0x50>; + qcom,pre-div-channel-scaling = <0>; + qcom,calibration-type = "ratiometric"; + qcom,scale-function = <2>; + qcom,hw-settle-time = <2>; + qcom,btm-channel-number = <0x48>; + qcom,thermal-node; + }; +}; + +&thermal_zones { + + emmc-therm-adc { + status = "disabled"; + }; + + aoss0-lowf { + status = "disabled"; + }; + + mdm-core-lowf { + status = "disabled"; + }; + + lpass-lowf { + status = "disabled"; + }; + + camera-lowf { + status = "disabled"; + }; + + cpuss1-lowf { + status = "disabled"; + }; + + apc1-cpu0-lowf { + status = "disabled"; + }; + + apc1-cpu1-lowf { + status = "disabled"; + }; + + apc1-cpu2-lowf { + status = "disabled"; + }; + + apc1-cpu3-lowf { + status = "disabled"; + }; + + cpuss0-lowf { + status = "disabled"; + }; + + gpu-lowf { + status = "disabled"; + }; + + aoss0-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 0>; + tracks-low; + + trips { + aoss0_trip: aoss-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&aoss0_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&aoss0_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&aoss0_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + mdm-core-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 1>; + tracks-low; + + trips { + mdm_core_trip: mdm-core-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&mdm_core_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&mdm_core_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&mdm_core_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + lpass-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 2>; + tracks-low; + + trips { + qdsp_trip: qdsp-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&qdsp_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&qdsp_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&qdsp_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + camera-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 3>; + tracks-low; + + trips { + camera_trip: camera-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&camera_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&camera_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&camera_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + cpuss1-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 4>; + tracks-low; + + trips { + cpuss1_trip: cpuss1-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpuss1_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&cpuss1_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&cpuss1_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu0-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 5>; + tracks-low; + + trips { + cpu0_trip: apc1-cpu0-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu0_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&cpu0_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&cpu0_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu1-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 6>; + tracks-low; + + trips { + cpu1_trip: apc1-cpu1-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu1_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&cpu1_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&cpu1_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu2-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 7>; + tracks-low; + + trips { + cpu2_trip: apc1-cpu2-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu2_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&cpu2_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&cpu2_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + apc1-cpu3-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 8>; + tracks-low; + + trips { + cpu3_trip: apc1-cpu3-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpu3_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&cpu3_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&cpu3_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + cpuss0-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 9>; + tracks-low; + + trips { + cpuss0_lowf_trip: cpuss0-lowf-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&cpuss0_lowf_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&cpuss0_lowf_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&cpuss0_lowf_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + gpu-lowfr { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-governor = "low_limits_floor"; + thermal-sensors = <&tsens0 10>; + tracks-low; + + trips { + gpu_lowf_trip: gpu-lowf-trip { + temperature = <5000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + cpu0_vdd_cdev { + trip = <&gpu_lowf_trip>; + cooling-device = <&CPU0 (THERMAL_MAX_LIMIT-2) + (THERMAL_MAX_LIMIT-2)>; + }; + + cx_vdd_cdev { + trip = <&gpu_lowf_trip>; + cooling-device = <&pm660_cx_cdev 0 0>; + }; + + modem_vdd_cdev { + trip = <&gpu_lowf_trip>; + cooling-device = <&modem_vdd 0 0>; + }; + }; + }; + + camera-therm-adc { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&pm660_adc_tm 0x4e>; + wake-capable-sensor; + thermal-governor = "user_space"; + + trips { + active-config0 { + temperature = <65000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + pmic-therm-adc { + polling-delay-passive = <0>; + polling-delay = <0>; + thermal-sensors = <&pm660_adc_tm 0x50>; + wake-capable-sensor; + thermal-governor = "user_space"; + + trips { + active-config0 { + temperature = <65000>; + hysteresis = <1000>; + type = "passive"; + }; + }; + }; + + quiet-therm-step { + polling-delay-passive = <1000>; + polling-delay = <0>; + thermal-sensors = <&pm660_adc_tm 0x51>; + thermal-governor = "step_wise"; + + trips { + quiet_batt_439_trip1: quiet-batt-trip1 { + temperature = <38000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_batt_439_trip2: quiet-batt-trip2 { + temperature = <40000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_batt_439_trip3: quiet-batt-trip3 { + temperature = <42000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_batt_439_trip4: quiet-batt-trip4 { + temperature = <44000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_modem_439_trip1: quiet-modem-trip0 { + temperature = <44000>; + hysteresis = <4000>; + type = "passive"; + }; + + quiet_modem_439_trip2: quiet-modem-trip1 { + temperature = <46000>; + hysteresis = <4000>; + type = "passive"; + }; + + quiet_batt_439_trip5: quiet-batt-trip5 { + temperature = <46000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_439_batt_trip6_mdm_trip3: quiet-bt-trp6-mdm-trp3 { + temperature = <48000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_cpus_439_trip: quiet-cpus-trip { + temperature = <48000>; + hysteresis = <0>; + type = "passive"; + }; + + quiet_gpu_439_trip: quiet-gpu-trip { + temperature = <50000>; + hysteresis = <0>; + type = "passive"; + }; + + quiet_batt_439_trip7: quiet-batt-trip7 { + temperature = <50000>; + hysteresis = <2000>; + type = "passive"; + }; + + quiet_modem_439_trip4: quiet-modem-trip3 { + temperature = <55000>; + hysteresis = <5000>; + type = "passive"; + }; + }; + + cooling-maps { + skin_cpu0 { + trip = <&quiet_cpus_439_trip>; + /* throttle from fmax to 1497600KHz */ + cooling-device = <&CPU0 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_cpu1 { + trip = <&quiet_cpus_439_trip>; + cooling-device = <&CPU1 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_cpu2 { + trip = <&quiet_cpus_439_trip>; + cooling-device = <&CPU2 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_cpu3 { + trip = <&quiet_cpus_439_trip>; + cooling-device = <&CPU3 THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-3)>; + }; + + skin_gpu { + trip = <&quiet_gpu_439_trip>; + /* throttle from fmax to 510000000Hz */ + cooling-device = <&msm_gpu THERMAL_NO_LIMIT + (THERMAL_MAX_LIMIT-2)>; + }; + + modem_proc_lvl1 { + trip = <&quiet_modem_439_trip1>; + cooling-device = <&modem_proc 1 1>; + }; + + modem_proc_lvl2 { + trip = <&quiet_modem_439_trip4>; + cooling-device = <&modem_proc 3 3>; + }; + + modem_lvl1 { + trip = <&quiet_modem_439_trip2>; + cooling-device = <&modem_pa 1 1>; + }; + + modem_lvl2 { + trip = <&quiet_439_batt_trip6_mdm_trip3>; + cooling-device = <&modem_pa 2 2>; + }; + + modem_lvl3 { + trip = <&quiet_modem_439_trip4>; + cooling-device = <&modem_pa 3 3>; + }; + + battery_lvl1 { + trip = <&quiet_batt_439_trip1>; + cooling-device = <&pm660_charger 1 1>; + }; + + battery_lvl2 { + trip = <&quiet_batt_439_trip2>; + cooling-device = <&pm660_charger 2 2>; + }; + + battery_lvl3 { + trip = <&quiet_batt_439_trip3>; + cooling-device = <&pm660_charger 3 3>; + }; + + battery_lvl4 { + trip = <&quiet_batt_439_trip4>; + cooling-device = <&pm660_charger 4 4>; + }; + + battery_lvl5 { + trip = <&quiet_batt_439_trip5>; + cooling-device = <&pm660_charger 5 5>; + }; + + battery_lvl6 { + trip = <&quiet_439_batt_trip6_mdm_trip3>; + cooling-device = <&pm660_charger 6 6>; + }; + + battery_lvl7 { + trip = <&quiet_batt_439_trip7>; + cooling-device = <&pm660_charger 7 7>; + }; + }; + }; +}; diff --git a/arch/arm64/boot/dts/qcom/sdm429w-camera-sensor-spyro.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-camera-sensor-spyro.dtsi index 45756f77791a..c032db594262 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-camera-sensor-spyro.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-camera-sensor-spyro.dtsi @@ -109,82 +109,40 @@ eeprom_spyro1: qcom,eeprom@1 { cell-index = <1>; reg = <0x1>; - qcom,eeprom-name = "sunny_8865"; compatible = "qcom,eeprom"; - qcom,slave-addr = <0x6c>; - qcom,cci-master = <0>; - qcom,num-blocks = <8>; - - qcom,page0 = <1 0x0100 2 0x01 1 1>; - qcom,poll0 = <0 0x0 2 0x0 1 0>; - qcom,mem0 = <0 0x0 2 0x0 1 0>; - - qcom,page1 = <1 0x5002 2 0x00 1 0>; - qcom,poll1 = <0 0x0 2 0x0 1 0>; - qcom,mem1 = <0 0x0 2 0x0 1 0>; - - qcom,page2 = <1 0x3d84 2 0xc0 1 0>; - qcom,poll2 = <0 0x0 2 0x0 1 0>; - qcom,mem2 = <0 0x0 2 0x0 1 0>; - - qcom,page3 = <1 0x3d88 2 0x70 1 0>; - qcom,poll3 = <0 0x0 2 0x0 1 0>; - qcom,mem3 = <0 0x0 2 0x0 1 0>; - - qcom,page4 = <1 0x3d89 2 0x10 1 0>; - qcom,poll4 = <0 0x0 2 0x0 1 0>; - qcom,mem4 = <0 0x0 2 0x0 1 0>; - - qcom,page5 = <1 0x3d8a 2 0x70 1 0>; - qcom,poll5 = <0 0x0 2 0x0 1 0>; - qcom,mem5 = <0 0x0 2 0x0 1 0>; - - qcom,page6 = <1 0x3d8b 2 0xf4 1 0>; - qcom,poll6 = <0 0x0 2 0x0 1 0>; - qcom,mem6 = <0 0x0 2 0x0 1 0>; - - qcom,page7 = <1 0x3d81 2 0x01 1 10>; - qcom,poll7 = <0 0x0 2 0x0 1 1>; - qcom,mem7 = <1536 0x7010 2 0 1 0>; + qcom,cci-master = <1>; cam_vdig-supply = <&pm660_l3>; - cam_vana-supply = <&pm660_l7>; - cam_vio-supply = <&pm660_l6>; + cam_vio-supply = <&pm660_l14>; + cam_vana-supply = <&pm660_s5>; cam_vaf-supply = <&pm660_l17>; - qcom,cam-vreg-name = "cam_vdig", "cam_vio", - "cam_vana", "cam_vaf"; - qcom,cam-vreg-min-voltage = <1200000 0 2800000 2850000>; - qcom,cam-vreg-max-voltage = <1200000 0 2800000 3200000>; - qcom,cam-vreg-op-mode = <105000 0 80000 100000>; - qcom,gpio-no-mux = <0>; + qcom,cam-vreg-name = "cam_vdig", "cam_vio", "cam_vana"; + qcom,cam-vreg-min-voltage = <1200000 1800000 1420000>; + qcom,cam-vreg-max-voltage = <1200000 1800000 1420000>; + qcom,cam-vreg-op-mode = <200000 80000 80000>; pinctrl-names = "cam_default", "cam_suspend"; - pinctrl-0 = <&cam_sensor_mclk2_default - &cam_sensor_front1_default>; - pinctrl-1 = <&cam_sensor_mclk2_sleep - &cam_sensor_front1_sleep>; - gpios = <&tlmm 28 0>, - <&tlmm 40 0>, - <&tlmm 39 0>; - qcom,gpio-reset = <1>; - qcom,gpio-standby = <2>; - qcom,gpio-req-tbl-num = <0 1 2>; - qcom,gpio-req-tbl-flags = <1 0 0>; - qcom,gpio-req-tbl-label = "CAMIF_MCLK2", - "CAM_RESET2", - "CAM_STANDBY2"; - qcom,cam-power-seq-type = "sensor_vreg", "sensor_vreg", - "sensor_vreg", - "sensor_gpio", "sensor_gpio" , "sensor_clk"; - qcom,cam-power-seq-val = "cam_vdig", "cam_vana", "cam_vio", - "sensor_gpio_reset", "sensor_gpio_standby", - "sensor_cam_mclk"; - qcom,cam-power-seq-cfg-val = <1 1 1 1 1 24000000>; - qcom,cam-power-seq-delay = <1 1 1 30 30 5>; + pinctrl-0 = <&cam_sensor_mclk1_default + &cam_sensor_front_default>; + pinctrl-1 = <&cam_sensor_mclk1_sleep + &cam_sensor_front_sleep>; + gpios = <&tlmm 27 0>, + <&tlmm 33 0>, + <&tlmm 66 0>, + <&tlmm 38 0>; + qcom,gpio-vana= <1>; + qcom,gpio-vdig= <2>; + qcom,gpio-reset = <3>; + qcom,gpio-req-tbl-num = <0 1 2 3>; + qcom,gpio-req-tbl-flags = <1 0 0 0>; + qcom,gpio-req-tbl-label = "CAMIF_MCLK1", + "CAM_AVDD1", + "CAM_DVDD1", + "CAM_RESET1"; status = "ok"; - clocks = <&clock_gcc clk_mclk2_clk_src>, - <&clock_gcc clk_gcc_camss_mclk2_clk>; + clocks = <&clock_gcc clk_mclk1_clk_src>, + <&clock_gcc clk_gcc_camss_mclk1_clk>; clock-names = "cam_src_clk", "cam_clk"; - qcom,clock-rates = <19200000 0>; + qcom,clock-rates = <24000000 0>; }; qcom,camera@0 { @@ -244,6 +202,8 @@ qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <270>; + qcom,eeprom-src = <&eeprom_spyro1>; + cam_vdig-supply = <&pm660_l3>; cam_vio-supply = <&pm660_l14>; cam_vaf-supply = <&pm660_l19>; @@ -286,7 +246,6 @@ qcom,csiphy-sd-index = <1>; qcom,csid-sd-index = <1>; qcom,mount-angle = <270>; - qcom,eeprom-src = <&eeprom_spyro1>; qcom,actuator-src = <&actuator_spyro1>; cam_vdig-supply = <&pm660_l3>; cam_vana-supply = <&pm660_l7>; diff --git a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi index 4b521b220903..db76a2483f21 100644 --- a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi @@ -55,6 +55,14 @@ <RPM_SMD_REGULATOR_LEVEL_BINNING>; qcom,use-voltage-level; }; + + pm660_cx_cdev: regulator-cx-cdev { + compatible = "qcom,regulator-cooling-device"; + regulator-cdev-supply = <&pm660_s1_floor_level>; + regulator-levels = <RPM_SMD_REGULATOR_LEVEL_NOM_PLUS + RPM_SMD_REGULATOR_LEVEL_RETENTION>; + #cooling-cells = <2>; + }; }; /* PM660 S2 - VDD_MX supply */ diff --git a/arch/arm64/boot/dts/qcom/sdm845-rb3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-rb3.dtsi index 2e16dbdb8249..2db4b60b433f 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-rb3.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-rb3.dtsi @@ -293,6 +293,10 @@ status = "disabled"; }; +&bcl_sensor { + status = "disabled"; +}; + &smb1355_charger_0 { status = "ok"; qcom,disable-ctm; diff --git a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi index 47638e3e57d4..5e1291a54df3 100644 --- a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi +++ b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi @@ -98,10 +98,8 @@ }; &pcie0 { - pinctrl-names = "default", "slot_power_on"; - pinctrl-1 = <&pcie0_3v3_on &pcie0_1v5_on>; - 3v3_gpio = <&tlmm 90 0>; - 1v5_gpio = <&tlmm 90 0>; + vreg-pcie-supply = <&pcie_vcc_eldo>; + qcom,vreg-pcie-voltage-level = <3300000 3300000 24000>; status = "ok"; }; @@ -250,6 +248,16 @@ gpio = <&tlmm 89 0>; enable-active-high; }; + + pcie_vcc_eldo: pcie-gpio-regulator@0 { + compatible = "regulator-fixed"; + regulator-name = "pcie_vcc_eldo"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + gpio = <&tlmm 90 0>; + enable-active-high; + }; + }; &qupv3_se10_i2c { diff --git a/arch/arm64/crypto/sha256-core.S b/arch/arm64/crypto/sha256-core.S deleted file mode 100644 index 3ce82cc860bc..000000000000 --- a/arch/arm64/crypto/sha256-core.S +++ /dev/null @@ -1,2061 +0,0 @@ -// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. -// -// Licensed under the OpenSSL license (the "License"). You may not use -// this file except in compliance with the License. You can obtain a copy -// in the file LICENSE in the source distribution or at -// https://www.openssl.org/source/license.html - -// ==================================================================== -// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL -// project. The module is, however, dual licensed under OpenSSL and -// CRYPTOGAMS licenses depending on where you obtain it. For further -// details see http://www.openssl.org/~appro/cryptogams/. -// -// Permission to use under GPLv2 terms is granted. -// ==================================================================== -// -// SHA256/512 for ARMv8. -// -// Performance in cycles per processed byte and improvement coefficient -// over code generated with "default" compiler: -// -// SHA256-hw SHA256(*) SHA512 -// Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) -// Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) -// Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) -// Denver 2.01 10.5 (+26%) 6.70 (+8%) -// X-Gene 20.0 (+100%) 12.8 (+300%(***)) -// Mongoose 2.36 13.0 (+50%) 8.36 (+33%) -// -// (*) Software SHA256 results are of lesser relevance, presented -// mostly for informational purposes. -// (**) The result is a trade-off: it's possible to improve it by -// 10% (or by 1 cycle per round), but at the cost of 20% loss -// on Cortex-A53 (or by 4 cycles per round). -// (***) Super-impressive coefficients over gcc-generated code are -// indication of some compiler "pathology", most notably code -// generated with -mgeneral-regs-only is significanty faster -// and the gap is only 40-90%. -// -// October 2016. -// -// Originally it was reckoned that it makes no sense to implement NEON -// version of SHA256 for 64-bit processors. This is because performance -// improvement on most wide-spread Cortex-A5x processors was observed -// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was -// observed that 32-bit NEON SHA256 performs significantly better than -// 64-bit scalar version on *some* of the more recent processors. As -// result 64-bit NEON version of SHA256 was added to provide best -// all-round performance. For example it executes ~30% faster on X-Gene -// and Mongoose. [For reference, NEON version of SHA512 is bound to -// deliver much less improvement, likely *negative* on Cortex-A5x. -// Which is why NEON support is limited to SHA256.] - -#ifndef __KERNEL__ -# include "arm_arch.h" -#endif - -.text - -.extern OPENSSL_armcap_P -.globl sha256_block_data_order -.type sha256_block_data_order,%function -.align 6 -sha256_block_data_order: -#ifndef __KERNEL__ -# ifdef __ILP32__ - ldrsw x16,.LOPENSSL_armcap_P -# else - ldr x16,.LOPENSSL_armcap_P -# endif - adr x17,.LOPENSSL_armcap_P - add x16,x16,x17 - ldr w16,[x16] - tst w16,#ARMV8_SHA256 - b.ne .Lv8_entry - tst w16,#ARMV7_NEON - b.ne .Lneon_entry -#endif - stp x29,x30,[sp,#-128]! - add x29,sp,#0 - - stp x19,x20,[sp,#16] - stp x21,x22,[sp,#32] - stp x23,x24,[sp,#48] - stp x25,x26,[sp,#64] - stp x27,x28,[sp,#80] - sub sp,sp,#4*4 - - ldp w20,w21,[x0] // load context - ldp w22,w23,[x0,#2*4] - ldp w24,w25,[x0,#4*4] - add x2,x1,x2,lsl#6 // end of input - ldp w26,w27,[x0,#6*4] - adr x30,.LK256 - stp x0,x2,[x29,#96] - -.Loop: - ldp w3,w4,[x1],#2*4 - ldr w19,[x30],#4 // *K++ - eor w28,w21,w22 // magic seed - str x1,[x29,#112] -#ifndef __AARCH64EB__ - rev w3,w3 // 0 -#endif - ror w16,w24,#6 - add w27,w27,w19 // h+=K[i] - eor w6,w24,w24,ror#14 - and w17,w25,w24 - bic w19,w26,w24 - add w27,w27,w3 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w20,w21 // a^b, b^c in next round - eor w16,w16,w6,ror#11 // Sigma1(e) - ror w6,w20,#2 - add w27,w27,w17 // h+=Ch(e,f,g) - eor w17,w20,w20,ror#9 - add w27,w27,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w23,w23,w27 // d+=h - eor w28,w28,w21 // Maj(a,b,c) - eor w17,w6,w17,ror#13 // Sigma0(a) - add w27,w27,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w27,w27,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w4,w4 // 1 -#endif - ldp w5,w6,[x1],#2*4 - add w27,w27,w17 // h+=Sigma0(a) - ror w16,w23,#6 - add w26,w26,w28 // h+=K[i] - eor w7,w23,w23,ror#14 - and w17,w24,w23 - bic w28,w25,w23 - add w26,w26,w4 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w27,w20 // a^b, b^c in next round - eor w16,w16,w7,ror#11 // Sigma1(e) - ror w7,w27,#2 - add w26,w26,w17 // h+=Ch(e,f,g) - eor w17,w27,w27,ror#9 - add w26,w26,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w22,w22,w26 // d+=h - eor w19,w19,w20 // Maj(a,b,c) - eor w17,w7,w17,ror#13 // Sigma0(a) - add w26,w26,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w26,w26,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w5,w5 // 2 -#endif - add w26,w26,w17 // h+=Sigma0(a) - ror w16,w22,#6 - add w25,w25,w19 // h+=K[i] - eor w8,w22,w22,ror#14 - and w17,w23,w22 - bic w19,w24,w22 - add w25,w25,w5 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w26,w27 // a^b, b^c in next round - eor w16,w16,w8,ror#11 // Sigma1(e) - ror w8,w26,#2 - add w25,w25,w17 // h+=Ch(e,f,g) - eor w17,w26,w26,ror#9 - add w25,w25,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w21,w21,w25 // d+=h - eor w28,w28,w27 // Maj(a,b,c) - eor w17,w8,w17,ror#13 // Sigma0(a) - add w25,w25,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w25,w25,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w6,w6 // 3 -#endif - ldp w7,w8,[x1],#2*4 - add w25,w25,w17 // h+=Sigma0(a) - ror w16,w21,#6 - add w24,w24,w28 // h+=K[i] - eor w9,w21,w21,ror#14 - and w17,w22,w21 - bic w28,w23,w21 - add w24,w24,w6 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w25,w26 // a^b, b^c in next round - eor w16,w16,w9,ror#11 // Sigma1(e) - ror w9,w25,#2 - add w24,w24,w17 // h+=Ch(e,f,g) - eor w17,w25,w25,ror#9 - add w24,w24,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w20,w20,w24 // d+=h - eor w19,w19,w26 // Maj(a,b,c) - eor w17,w9,w17,ror#13 // Sigma0(a) - add w24,w24,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w24,w24,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w7,w7 // 4 -#endif - add w24,w24,w17 // h+=Sigma0(a) - ror w16,w20,#6 - add w23,w23,w19 // h+=K[i] - eor w10,w20,w20,ror#14 - and w17,w21,w20 - bic w19,w22,w20 - add w23,w23,w7 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w24,w25 // a^b, b^c in next round - eor w16,w16,w10,ror#11 // Sigma1(e) - ror w10,w24,#2 - add w23,w23,w17 // h+=Ch(e,f,g) - eor w17,w24,w24,ror#9 - add w23,w23,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w27,w27,w23 // d+=h - eor w28,w28,w25 // Maj(a,b,c) - eor w17,w10,w17,ror#13 // Sigma0(a) - add w23,w23,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w23,w23,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w8,w8 // 5 -#endif - ldp w9,w10,[x1],#2*4 - add w23,w23,w17 // h+=Sigma0(a) - ror w16,w27,#6 - add w22,w22,w28 // h+=K[i] - eor w11,w27,w27,ror#14 - and w17,w20,w27 - bic w28,w21,w27 - add w22,w22,w8 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w23,w24 // a^b, b^c in next round - eor w16,w16,w11,ror#11 // Sigma1(e) - ror w11,w23,#2 - add w22,w22,w17 // h+=Ch(e,f,g) - eor w17,w23,w23,ror#9 - add w22,w22,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w26,w26,w22 // d+=h - eor w19,w19,w24 // Maj(a,b,c) - eor w17,w11,w17,ror#13 // Sigma0(a) - add w22,w22,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w22,w22,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w9,w9 // 6 -#endif - add w22,w22,w17 // h+=Sigma0(a) - ror w16,w26,#6 - add w21,w21,w19 // h+=K[i] - eor w12,w26,w26,ror#14 - and w17,w27,w26 - bic w19,w20,w26 - add w21,w21,w9 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w22,w23 // a^b, b^c in next round - eor w16,w16,w12,ror#11 // Sigma1(e) - ror w12,w22,#2 - add w21,w21,w17 // h+=Ch(e,f,g) - eor w17,w22,w22,ror#9 - add w21,w21,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w25,w25,w21 // d+=h - eor w28,w28,w23 // Maj(a,b,c) - eor w17,w12,w17,ror#13 // Sigma0(a) - add w21,w21,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w21,w21,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w10,w10 // 7 -#endif - ldp w11,w12,[x1],#2*4 - add w21,w21,w17 // h+=Sigma0(a) - ror w16,w25,#6 - add w20,w20,w28 // h+=K[i] - eor w13,w25,w25,ror#14 - and w17,w26,w25 - bic w28,w27,w25 - add w20,w20,w10 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w21,w22 // a^b, b^c in next round - eor w16,w16,w13,ror#11 // Sigma1(e) - ror w13,w21,#2 - add w20,w20,w17 // h+=Ch(e,f,g) - eor w17,w21,w21,ror#9 - add w20,w20,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w24,w24,w20 // d+=h - eor w19,w19,w22 // Maj(a,b,c) - eor w17,w13,w17,ror#13 // Sigma0(a) - add w20,w20,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w20,w20,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w11,w11 // 8 -#endif - add w20,w20,w17 // h+=Sigma0(a) - ror w16,w24,#6 - add w27,w27,w19 // h+=K[i] - eor w14,w24,w24,ror#14 - and w17,w25,w24 - bic w19,w26,w24 - add w27,w27,w11 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w20,w21 // a^b, b^c in next round - eor w16,w16,w14,ror#11 // Sigma1(e) - ror w14,w20,#2 - add w27,w27,w17 // h+=Ch(e,f,g) - eor w17,w20,w20,ror#9 - add w27,w27,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w23,w23,w27 // d+=h - eor w28,w28,w21 // Maj(a,b,c) - eor w17,w14,w17,ror#13 // Sigma0(a) - add w27,w27,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w27,w27,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w12,w12 // 9 -#endif - ldp w13,w14,[x1],#2*4 - add w27,w27,w17 // h+=Sigma0(a) - ror w16,w23,#6 - add w26,w26,w28 // h+=K[i] - eor w15,w23,w23,ror#14 - and w17,w24,w23 - bic w28,w25,w23 - add w26,w26,w12 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w27,w20 // a^b, b^c in next round - eor w16,w16,w15,ror#11 // Sigma1(e) - ror w15,w27,#2 - add w26,w26,w17 // h+=Ch(e,f,g) - eor w17,w27,w27,ror#9 - add w26,w26,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w22,w22,w26 // d+=h - eor w19,w19,w20 // Maj(a,b,c) - eor w17,w15,w17,ror#13 // Sigma0(a) - add w26,w26,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w26,w26,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w13,w13 // 10 -#endif - add w26,w26,w17 // h+=Sigma0(a) - ror w16,w22,#6 - add w25,w25,w19 // h+=K[i] - eor w0,w22,w22,ror#14 - and w17,w23,w22 - bic w19,w24,w22 - add w25,w25,w13 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w26,w27 // a^b, b^c in next round - eor w16,w16,w0,ror#11 // Sigma1(e) - ror w0,w26,#2 - add w25,w25,w17 // h+=Ch(e,f,g) - eor w17,w26,w26,ror#9 - add w25,w25,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w21,w21,w25 // d+=h - eor w28,w28,w27 // Maj(a,b,c) - eor w17,w0,w17,ror#13 // Sigma0(a) - add w25,w25,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w25,w25,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w14,w14 // 11 -#endif - ldp w15,w0,[x1],#2*4 - add w25,w25,w17 // h+=Sigma0(a) - str w6,[sp,#12] - ror w16,w21,#6 - add w24,w24,w28 // h+=K[i] - eor w6,w21,w21,ror#14 - and w17,w22,w21 - bic w28,w23,w21 - add w24,w24,w14 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w25,w26 // a^b, b^c in next round - eor w16,w16,w6,ror#11 // Sigma1(e) - ror w6,w25,#2 - add w24,w24,w17 // h+=Ch(e,f,g) - eor w17,w25,w25,ror#9 - add w24,w24,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w20,w20,w24 // d+=h - eor w19,w19,w26 // Maj(a,b,c) - eor w17,w6,w17,ror#13 // Sigma0(a) - add w24,w24,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w24,w24,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w15,w15 // 12 -#endif - add w24,w24,w17 // h+=Sigma0(a) - str w7,[sp,#0] - ror w16,w20,#6 - add w23,w23,w19 // h+=K[i] - eor w7,w20,w20,ror#14 - and w17,w21,w20 - bic w19,w22,w20 - add w23,w23,w15 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w24,w25 // a^b, b^c in next round - eor w16,w16,w7,ror#11 // Sigma1(e) - ror w7,w24,#2 - add w23,w23,w17 // h+=Ch(e,f,g) - eor w17,w24,w24,ror#9 - add w23,w23,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w27,w27,w23 // d+=h - eor w28,w28,w25 // Maj(a,b,c) - eor w17,w7,w17,ror#13 // Sigma0(a) - add w23,w23,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w23,w23,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w0,w0 // 13 -#endif - ldp w1,w2,[x1] - add w23,w23,w17 // h+=Sigma0(a) - str w8,[sp,#4] - ror w16,w27,#6 - add w22,w22,w28 // h+=K[i] - eor w8,w27,w27,ror#14 - and w17,w20,w27 - bic w28,w21,w27 - add w22,w22,w0 // h+=X[i] - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w23,w24 // a^b, b^c in next round - eor w16,w16,w8,ror#11 // Sigma1(e) - ror w8,w23,#2 - add w22,w22,w17 // h+=Ch(e,f,g) - eor w17,w23,w23,ror#9 - add w22,w22,w16 // h+=Sigma1(e) - and w19,w19,w28 // (b^c)&=(a^b) - add w26,w26,w22 // d+=h - eor w19,w19,w24 // Maj(a,b,c) - eor w17,w8,w17,ror#13 // Sigma0(a) - add w22,w22,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - //add w22,w22,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w1,w1 // 14 -#endif - ldr w6,[sp,#12] - add w22,w22,w17 // h+=Sigma0(a) - str w9,[sp,#8] - ror w16,w26,#6 - add w21,w21,w19 // h+=K[i] - eor w9,w26,w26,ror#14 - and w17,w27,w26 - bic w19,w20,w26 - add w21,w21,w1 // h+=X[i] - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w22,w23 // a^b, b^c in next round - eor w16,w16,w9,ror#11 // Sigma1(e) - ror w9,w22,#2 - add w21,w21,w17 // h+=Ch(e,f,g) - eor w17,w22,w22,ror#9 - add w21,w21,w16 // h+=Sigma1(e) - and w28,w28,w19 // (b^c)&=(a^b) - add w25,w25,w21 // d+=h - eor w28,w28,w23 // Maj(a,b,c) - eor w17,w9,w17,ror#13 // Sigma0(a) - add w21,w21,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - //add w21,w21,w17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev w2,w2 // 15 -#endif - ldr w7,[sp,#0] - add w21,w21,w17 // h+=Sigma0(a) - str w10,[sp,#12] - ror w16,w25,#6 - add w20,w20,w28 // h+=K[i] - ror w9,w4,#7 - and w17,w26,w25 - ror w8,w1,#17 - bic w28,w27,w25 - ror w10,w21,#2 - add w20,w20,w2 // h+=X[i] - eor w16,w16,w25,ror#11 - eor w9,w9,w4,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w21,w22 // a^b, b^c in next round - eor w16,w16,w25,ror#25 // Sigma1(e) - eor w10,w10,w21,ror#13 - add w20,w20,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w8,w8,w1,ror#19 - eor w9,w9,w4,lsr#3 // sigma0(X[i+1]) - add w20,w20,w16 // h+=Sigma1(e) - eor w19,w19,w22 // Maj(a,b,c) - eor w17,w10,w21,ror#22 // Sigma0(a) - eor w8,w8,w1,lsr#10 // sigma1(X[i+14]) - add w3,w3,w12 - add w24,w24,w20 // d+=h - add w20,w20,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w3,w3,w9 - add w20,w20,w17 // h+=Sigma0(a) - add w3,w3,w8 -.Loop_16_xx: - ldr w8,[sp,#4] - str w11,[sp,#0] - ror w16,w24,#6 - add w27,w27,w19 // h+=K[i] - ror w10,w5,#7 - and w17,w25,w24 - ror w9,w2,#17 - bic w19,w26,w24 - ror w11,w20,#2 - add w27,w27,w3 // h+=X[i] - eor w16,w16,w24,ror#11 - eor w10,w10,w5,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w20,w21 // a^b, b^c in next round - eor w16,w16,w24,ror#25 // Sigma1(e) - eor w11,w11,w20,ror#13 - add w27,w27,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w9,w9,w2,ror#19 - eor w10,w10,w5,lsr#3 // sigma0(X[i+1]) - add w27,w27,w16 // h+=Sigma1(e) - eor w28,w28,w21 // Maj(a,b,c) - eor w17,w11,w20,ror#22 // Sigma0(a) - eor w9,w9,w2,lsr#10 // sigma1(X[i+14]) - add w4,w4,w13 - add w23,w23,w27 // d+=h - add w27,w27,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w4,w4,w10 - add w27,w27,w17 // h+=Sigma0(a) - add w4,w4,w9 - ldr w9,[sp,#8] - str w12,[sp,#4] - ror w16,w23,#6 - add w26,w26,w28 // h+=K[i] - ror w11,w6,#7 - and w17,w24,w23 - ror w10,w3,#17 - bic w28,w25,w23 - ror w12,w27,#2 - add w26,w26,w4 // h+=X[i] - eor w16,w16,w23,ror#11 - eor w11,w11,w6,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w27,w20 // a^b, b^c in next round - eor w16,w16,w23,ror#25 // Sigma1(e) - eor w12,w12,w27,ror#13 - add w26,w26,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w10,w10,w3,ror#19 - eor w11,w11,w6,lsr#3 // sigma0(X[i+1]) - add w26,w26,w16 // h+=Sigma1(e) - eor w19,w19,w20 // Maj(a,b,c) - eor w17,w12,w27,ror#22 // Sigma0(a) - eor w10,w10,w3,lsr#10 // sigma1(X[i+14]) - add w5,w5,w14 - add w22,w22,w26 // d+=h - add w26,w26,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w5,w5,w11 - add w26,w26,w17 // h+=Sigma0(a) - add w5,w5,w10 - ldr w10,[sp,#12] - str w13,[sp,#8] - ror w16,w22,#6 - add w25,w25,w19 // h+=K[i] - ror w12,w7,#7 - and w17,w23,w22 - ror w11,w4,#17 - bic w19,w24,w22 - ror w13,w26,#2 - add w25,w25,w5 // h+=X[i] - eor w16,w16,w22,ror#11 - eor w12,w12,w7,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w26,w27 // a^b, b^c in next round - eor w16,w16,w22,ror#25 // Sigma1(e) - eor w13,w13,w26,ror#13 - add w25,w25,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w11,w11,w4,ror#19 - eor w12,w12,w7,lsr#3 // sigma0(X[i+1]) - add w25,w25,w16 // h+=Sigma1(e) - eor w28,w28,w27 // Maj(a,b,c) - eor w17,w13,w26,ror#22 // Sigma0(a) - eor w11,w11,w4,lsr#10 // sigma1(X[i+14]) - add w6,w6,w15 - add w21,w21,w25 // d+=h - add w25,w25,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w6,w6,w12 - add w25,w25,w17 // h+=Sigma0(a) - add w6,w6,w11 - ldr w11,[sp,#0] - str w14,[sp,#12] - ror w16,w21,#6 - add w24,w24,w28 // h+=K[i] - ror w13,w8,#7 - and w17,w22,w21 - ror w12,w5,#17 - bic w28,w23,w21 - ror w14,w25,#2 - add w24,w24,w6 // h+=X[i] - eor w16,w16,w21,ror#11 - eor w13,w13,w8,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w25,w26 // a^b, b^c in next round - eor w16,w16,w21,ror#25 // Sigma1(e) - eor w14,w14,w25,ror#13 - add w24,w24,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w12,w12,w5,ror#19 - eor w13,w13,w8,lsr#3 // sigma0(X[i+1]) - add w24,w24,w16 // h+=Sigma1(e) - eor w19,w19,w26 // Maj(a,b,c) - eor w17,w14,w25,ror#22 // Sigma0(a) - eor w12,w12,w5,lsr#10 // sigma1(X[i+14]) - add w7,w7,w0 - add w20,w20,w24 // d+=h - add w24,w24,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w7,w7,w13 - add w24,w24,w17 // h+=Sigma0(a) - add w7,w7,w12 - ldr w12,[sp,#4] - str w15,[sp,#0] - ror w16,w20,#6 - add w23,w23,w19 // h+=K[i] - ror w14,w9,#7 - and w17,w21,w20 - ror w13,w6,#17 - bic w19,w22,w20 - ror w15,w24,#2 - add w23,w23,w7 // h+=X[i] - eor w16,w16,w20,ror#11 - eor w14,w14,w9,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w24,w25 // a^b, b^c in next round - eor w16,w16,w20,ror#25 // Sigma1(e) - eor w15,w15,w24,ror#13 - add w23,w23,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w13,w13,w6,ror#19 - eor w14,w14,w9,lsr#3 // sigma0(X[i+1]) - add w23,w23,w16 // h+=Sigma1(e) - eor w28,w28,w25 // Maj(a,b,c) - eor w17,w15,w24,ror#22 // Sigma0(a) - eor w13,w13,w6,lsr#10 // sigma1(X[i+14]) - add w8,w8,w1 - add w27,w27,w23 // d+=h - add w23,w23,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w8,w8,w14 - add w23,w23,w17 // h+=Sigma0(a) - add w8,w8,w13 - ldr w13,[sp,#8] - str w0,[sp,#4] - ror w16,w27,#6 - add w22,w22,w28 // h+=K[i] - ror w15,w10,#7 - and w17,w20,w27 - ror w14,w7,#17 - bic w28,w21,w27 - ror w0,w23,#2 - add w22,w22,w8 // h+=X[i] - eor w16,w16,w27,ror#11 - eor w15,w15,w10,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w23,w24 // a^b, b^c in next round - eor w16,w16,w27,ror#25 // Sigma1(e) - eor w0,w0,w23,ror#13 - add w22,w22,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w14,w14,w7,ror#19 - eor w15,w15,w10,lsr#3 // sigma0(X[i+1]) - add w22,w22,w16 // h+=Sigma1(e) - eor w19,w19,w24 // Maj(a,b,c) - eor w17,w0,w23,ror#22 // Sigma0(a) - eor w14,w14,w7,lsr#10 // sigma1(X[i+14]) - add w9,w9,w2 - add w26,w26,w22 // d+=h - add w22,w22,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w9,w9,w15 - add w22,w22,w17 // h+=Sigma0(a) - add w9,w9,w14 - ldr w14,[sp,#12] - str w1,[sp,#8] - ror w16,w26,#6 - add w21,w21,w19 // h+=K[i] - ror w0,w11,#7 - and w17,w27,w26 - ror w15,w8,#17 - bic w19,w20,w26 - ror w1,w22,#2 - add w21,w21,w9 // h+=X[i] - eor w16,w16,w26,ror#11 - eor w0,w0,w11,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w22,w23 // a^b, b^c in next round - eor w16,w16,w26,ror#25 // Sigma1(e) - eor w1,w1,w22,ror#13 - add w21,w21,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w15,w15,w8,ror#19 - eor w0,w0,w11,lsr#3 // sigma0(X[i+1]) - add w21,w21,w16 // h+=Sigma1(e) - eor w28,w28,w23 // Maj(a,b,c) - eor w17,w1,w22,ror#22 // Sigma0(a) - eor w15,w15,w8,lsr#10 // sigma1(X[i+14]) - add w10,w10,w3 - add w25,w25,w21 // d+=h - add w21,w21,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w10,w10,w0 - add w21,w21,w17 // h+=Sigma0(a) - add w10,w10,w15 - ldr w15,[sp,#0] - str w2,[sp,#12] - ror w16,w25,#6 - add w20,w20,w28 // h+=K[i] - ror w1,w12,#7 - and w17,w26,w25 - ror w0,w9,#17 - bic w28,w27,w25 - ror w2,w21,#2 - add w20,w20,w10 // h+=X[i] - eor w16,w16,w25,ror#11 - eor w1,w1,w12,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w21,w22 // a^b, b^c in next round - eor w16,w16,w25,ror#25 // Sigma1(e) - eor w2,w2,w21,ror#13 - add w20,w20,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w0,w0,w9,ror#19 - eor w1,w1,w12,lsr#3 // sigma0(X[i+1]) - add w20,w20,w16 // h+=Sigma1(e) - eor w19,w19,w22 // Maj(a,b,c) - eor w17,w2,w21,ror#22 // Sigma0(a) - eor w0,w0,w9,lsr#10 // sigma1(X[i+14]) - add w11,w11,w4 - add w24,w24,w20 // d+=h - add w20,w20,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w11,w11,w1 - add w20,w20,w17 // h+=Sigma0(a) - add w11,w11,w0 - ldr w0,[sp,#4] - str w3,[sp,#0] - ror w16,w24,#6 - add w27,w27,w19 // h+=K[i] - ror w2,w13,#7 - and w17,w25,w24 - ror w1,w10,#17 - bic w19,w26,w24 - ror w3,w20,#2 - add w27,w27,w11 // h+=X[i] - eor w16,w16,w24,ror#11 - eor w2,w2,w13,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w20,w21 // a^b, b^c in next round - eor w16,w16,w24,ror#25 // Sigma1(e) - eor w3,w3,w20,ror#13 - add w27,w27,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w1,w1,w10,ror#19 - eor w2,w2,w13,lsr#3 // sigma0(X[i+1]) - add w27,w27,w16 // h+=Sigma1(e) - eor w28,w28,w21 // Maj(a,b,c) - eor w17,w3,w20,ror#22 // Sigma0(a) - eor w1,w1,w10,lsr#10 // sigma1(X[i+14]) - add w12,w12,w5 - add w23,w23,w27 // d+=h - add w27,w27,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w12,w12,w2 - add w27,w27,w17 // h+=Sigma0(a) - add w12,w12,w1 - ldr w1,[sp,#8] - str w4,[sp,#4] - ror w16,w23,#6 - add w26,w26,w28 // h+=K[i] - ror w3,w14,#7 - and w17,w24,w23 - ror w2,w11,#17 - bic w28,w25,w23 - ror w4,w27,#2 - add w26,w26,w12 // h+=X[i] - eor w16,w16,w23,ror#11 - eor w3,w3,w14,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w27,w20 // a^b, b^c in next round - eor w16,w16,w23,ror#25 // Sigma1(e) - eor w4,w4,w27,ror#13 - add w26,w26,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w2,w2,w11,ror#19 - eor w3,w3,w14,lsr#3 // sigma0(X[i+1]) - add w26,w26,w16 // h+=Sigma1(e) - eor w19,w19,w20 // Maj(a,b,c) - eor w17,w4,w27,ror#22 // Sigma0(a) - eor w2,w2,w11,lsr#10 // sigma1(X[i+14]) - add w13,w13,w6 - add w22,w22,w26 // d+=h - add w26,w26,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w13,w13,w3 - add w26,w26,w17 // h+=Sigma0(a) - add w13,w13,w2 - ldr w2,[sp,#12] - str w5,[sp,#8] - ror w16,w22,#6 - add w25,w25,w19 // h+=K[i] - ror w4,w15,#7 - and w17,w23,w22 - ror w3,w12,#17 - bic w19,w24,w22 - ror w5,w26,#2 - add w25,w25,w13 // h+=X[i] - eor w16,w16,w22,ror#11 - eor w4,w4,w15,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w26,w27 // a^b, b^c in next round - eor w16,w16,w22,ror#25 // Sigma1(e) - eor w5,w5,w26,ror#13 - add w25,w25,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w3,w3,w12,ror#19 - eor w4,w4,w15,lsr#3 // sigma0(X[i+1]) - add w25,w25,w16 // h+=Sigma1(e) - eor w28,w28,w27 // Maj(a,b,c) - eor w17,w5,w26,ror#22 // Sigma0(a) - eor w3,w3,w12,lsr#10 // sigma1(X[i+14]) - add w14,w14,w7 - add w21,w21,w25 // d+=h - add w25,w25,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w14,w14,w4 - add w25,w25,w17 // h+=Sigma0(a) - add w14,w14,w3 - ldr w3,[sp,#0] - str w6,[sp,#12] - ror w16,w21,#6 - add w24,w24,w28 // h+=K[i] - ror w5,w0,#7 - and w17,w22,w21 - ror w4,w13,#17 - bic w28,w23,w21 - ror w6,w25,#2 - add w24,w24,w14 // h+=X[i] - eor w16,w16,w21,ror#11 - eor w5,w5,w0,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w25,w26 // a^b, b^c in next round - eor w16,w16,w21,ror#25 // Sigma1(e) - eor w6,w6,w25,ror#13 - add w24,w24,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w4,w4,w13,ror#19 - eor w5,w5,w0,lsr#3 // sigma0(X[i+1]) - add w24,w24,w16 // h+=Sigma1(e) - eor w19,w19,w26 // Maj(a,b,c) - eor w17,w6,w25,ror#22 // Sigma0(a) - eor w4,w4,w13,lsr#10 // sigma1(X[i+14]) - add w15,w15,w8 - add w20,w20,w24 // d+=h - add w24,w24,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w15,w15,w5 - add w24,w24,w17 // h+=Sigma0(a) - add w15,w15,w4 - ldr w4,[sp,#4] - str w7,[sp,#0] - ror w16,w20,#6 - add w23,w23,w19 // h+=K[i] - ror w6,w1,#7 - and w17,w21,w20 - ror w5,w14,#17 - bic w19,w22,w20 - ror w7,w24,#2 - add w23,w23,w15 // h+=X[i] - eor w16,w16,w20,ror#11 - eor w6,w6,w1,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w24,w25 // a^b, b^c in next round - eor w16,w16,w20,ror#25 // Sigma1(e) - eor w7,w7,w24,ror#13 - add w23,w23,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w5,w5,w14,ror#19 - eor w6,w6,w1,lsr#3 // sigma0(X[i+1]) - add w23,w23,w16 // h+=Sigma1(e) - eor w28,w28,w25 // Maj(a,b,c) - eor w17,w7,w24,ror#22 // Sigma0(a) - eor w5,w5,w14,lsr#10 // sigma1(X[i+14]) - add w0,w0,w9 - add w27,w27,w23 // d+=h - add w23,w23,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w0,w0,w6 - add w23,w23,w17 // h+=Sigma0(a) - add w0,w0,w5 - ldr w5,[sp,#8] - str w8,[sp,#4] - ror w16,w27,#6 - add w22,w22,w28 // h+=K[i] - ror w7,w2,#7 - and w17,w20,w27 - ror w6,w15,#17 - bic w28,w21,w27 - ror w8,w23,#2 - add w22,w22,w0 // h+=X[i] - eor w16,w16,w27,ror#11 - eor w7,w7,w2,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w23,w24 // a^b, b^c in next round - eor w16,w16,w27,ror#25 // Sigma1(e) - eor w8,w8,w23,ror#13 - add w22,w22,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w6,w6,w15,ror#19 - eor w7,w7,w2,lsr#3 // sigma0(X[i+1]) - add w22,w22,w16 // h+=Sigma1(e) - eor w19,w19,w24 // Maj(a,b,c) - eor w17,w8,w23,ror#22 // Sigma0(a) - eor w6,w6,w15,lsr#10 // sigma1(X[i+14]) - add w1,w1,w10 - add w26,w26,w22 // d+=h - add w22,w22,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w1,w1,w7 - add w22,w22,w17 // h+=Sigma0(a) - add w1,w1,w6 - ldr w6,[sp,#12] - str w9,[sp,#8] - ror w16,w26,#6 - add w21,w21,w19 // h+=K[i] - ror w8,w3,#7 - and w17,w27,w26 - ror w7,w0,#17 - bic w19,w20,w26 - ror w9,w22,#2 - add w21,w21,w1 // h+=X[i] - eor w16,w16,w26,ror#11 - eor w8,w8,w3,ror#18 - orr w17,w17,w19 // Ch(e,f,g) - eor w19,w22,w23 // a^b, b^c in next round - eor w16,w16,w26,ror#25 // Sigma1(e) - eor w9,w9,w22,ror#13 - add w21,w21,w17 // h+=Ch(e,f,g) - and w28,w28,w19 // (b^c)&=(a^b) - eor w7,w7,w0,ror#19 - eor w8,w8,w3,lsr#3 // sigma0(X[i+1]) - add w21,w21,w16 // h+=Sigma1(e) - eor w28,w28,w23 // Maj(a,b,c) - eor w17,w9,w22,ror#22 // Sigma0(a) - eor w7,w7,w0,lsr#10 // sigma1(X[i+14]) - add w2,w2,w11 - add w25,w25,w21 // d+=h - add w21,w21,w28 // h+=Maj(a,b,c) - ldr w28,[x30],#4 // *K++, w19 in next round - add w2,w2,w8 - add w21,w21,w17 // h+=Sigma0(a) - add w2,w2,w7 - ldr w7,[sp,#0] - str w10,[sp,#12] - ror w16,w25,#6 - add w20,w20,w28 // h+=K[i] - ror w9,w4,#7 - and w17,w26,w25 - ror w8,w1,#17 - bic w28,w27,w25 - ror w10,w21,#2 - add w20,w20,w2 // h+=X[i] - eor w16,w16,w25,ror#11 - eor w9,w9,w4,ror#18 - orr w17,w17,w28 // Ch(e,f,g) - eor w28,w21,w22 // a^b, b^c in next round - eor w16,w16,w25,ror#25 // Sigma1(e) - eor w10,w10,w21,ror#13 - add w20,w20,w17 // h+=Ch(e,f,g) - and w19,w19,w28 // (b^c)&=(a^b) - eor w8,w8,w1,ror#19 - eor w9,w9,w4,lsr#3 // sigma0(X[i+1]) - add w20,w20,w16 // h+=Sigma1(e) - eor w19,w19,w22 // Maj(a,b,c) - eor w17,w10,w21,ror#22 // Sigma0(a) - eor w8,w8,w1,lsr#10 // sigma1(X[i+14]) - add w3,w3,w12 - add w24,w24,w20 // d+=h - add w20,w20,w19 // h+=Maj(a,b,c) - ldr w19,[x30],#4 // *K++, w28 in next round - add w3,w3,w9 - add w20,w20,w17 // h+=Sigma0(a) - add w3,w3,w8 - cbnz w19,.Loop_16_xx - - ldp x0,x2,[x29,#96] - ldr x1,[x29,#112] - sub x30,x30,#260 // rewind - - ldp w3,w4,[x0] - ldp w5,w6,[x0,#2*4] - add x1,x1,#14*4 // advance input pointer - ldp w7,w8,[x0,#4*4] - add w20,w20,w3 - ldp w9,w10,[x0,#6*4] - add w21,w21,w4 - add w22,w22,w5 - add w23,w23,w6 - stp w20,w21,[x0] - add w24,w24,w7 - add w25,w25,w8 - stp w22,w23,[x0,#2*4] - add w26,w26,w9 - add w27,w27,w10 - cmp x1,x2 - stp w24,w25,[x0,#4*4] - stp w26,w27,[x0,#6*4] - b.ne .Loop - - ldp x19,x20,[x29,#16] - add sp,sp,#4*4 - ldp x21,x22,[x29,#32] - ldp x23,x24,[x29,#48] - ldp x25,x26,[x29,#64] - ldp x27,x28,[x29,#80] - ldp x29,x30,[sp],#128 - ret -.size sha256_block_data_order,.-sha256_block_data_order - -.align 6 -.type .LK256,%object -.LK256: - .long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 - .long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 - .long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 - .long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 - .long 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc - .long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da - .long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 - .long 0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967 - .long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 - .long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 - .long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 - .long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 - .long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 - .long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 - .long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 - .long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 - .long 0 //terminator -.size .LK256,.-.LK256 -#ifndef __KERNEL__ -.align 3 -.LOPENSSL_armcap_P: -# ifdef __ILP32__ - .long OPENSSL_armcap_P-. -# else - .quad OPENSSL_armcap_P-. -# endif -#endif -.asciz "SHA256 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>" -.align 2 -#ifndef __KERNEL__ -.type sha256_block_armv8,%function -.align 6 -sha256_block_armv8: -.Lv8_entry: - stp x29,x30,[sp,#-16]! - add x29,sp,#0 - - ld1 {v0.4s,v1.4s},[x0] - adr x3,.LK256 - -.Loop_hw: - ld1 {v4.16b-v7.16b},[x1],#64 - sub x2,x2,#1 - ld1 {v16.4s},[x3],#16 - rev32 v4.16b,v4.16b - rev32 v5.16b,v5.16b - rev32 v6.16b,v6.16b - rev32 v7.16b,v7.16b - orr v18.16b,v0.16b,v0.16b // offload - orr v19.16b,v1.16b,v1.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v6.4s - .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v7.4s - .inst 0x5e282887 //sha256su0 v7.16b,v4.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v6.4s - .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v7.4s - .inst 0x5e282887 //sha256su0 v7.16b,v4.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - .inst 0x5e2828a4 //sha256su0 v4.16b,v5.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e0760c4 //sha256su1 v4.16b,v6.16b,v7.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - .inst 0x5e2828c5 //sha256su0 v5.16b,v6.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0460e5 //sha256su1 v5.16b,v7.16b,v4.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v6.4s - .inst 0x5e2828e6 //sha256su0 v6.16b,v7.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - .inst 0x5e056086 //sha256su1 v6.16b,v4.16b,v5.16b - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v7.4s - .inst 0x5e282887 //sha256su0 v7.16b,v4.16b - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - .inst 0x5e0660a7 //sha256su1 v7.16b,v5.16b,v6.16b - ld1 {v17.4s},[x3],#16 - add v16.4s,v16.4s,v4.4s - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - - ld1 {v16.4s},[x3],#16 - add v17.4s,v17.4s,v5.4s - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - - ld1 {v17.4s},[x3] - add v16.4s,v16.4s,v6.4s - sub x3,x3,#64*4-16 // rewind - orr v2.16b,v0.16b,v0.16b - .inst 0x5e104020 //sha256h v0.16b,v1.16b,v16.4s - .inst 0x5e105041 //sha256h2 v1.16b,v2.16b,v16.4s - - add v17.4s,v17.4s,v7.4s - orr v2.16b,v0.16b,v0.16b - .inst 0x5e114020 //sha256h v0.16b,v1.16b,v17.4s - .inst 0x5e115041 //sha256h2 v1.16b,v2.16b,v17.4s - - add v0.4s,v0.4s,v18.4s - add v1.4s,v1.4s,v19.4s - - cbnz x2,.Loop_hw - - st1 {v0.4s,v1.4s},[x0] - - ldr x29,[sp],#16 - ret -.size sha256_block_armv8,.-sha256_block_armv8 -#endif -#ifdef __KERNEL__ -.globl sha256_block_neon -#endif -.type sha256_block_neon,%function -.align 4 -sha256_block_neon: -.Lneon_entry: - stp x29, x30, [sp, #-16]! - mov x29, sp - sub sp,sp,#16*4 - - adr x16,.LK256 - add x2,x1,x2,lsl#6 // len to point at the end of inp - - ld1 {v0.16b},[x1], #16 - ld1 {v1.16b},[x1], #16 - ld1 {v2.16b},[x1], #16 - ld1 {v3.16b},[x1], #16 - ld1 {v4.4s},[x16], #16 - ld1 {v5.4s},[x16], #16 - ld1 {v6.4s},[x16], #16 - ld1 {v7.4s},[x16], #16 - rev32 v0.16b,v0.16b // yes, even on - rev32 v1.16b,v1.16b // big-endian - rev32 v2.16b,v2.16b - rev32 v3.16b,v3.16b - mov x17,sp - add v4.4s,v4.4s,v0.4s - add v5.4s,v5.4s,v1.4s - add v6.4s,v6.4s,v2.4s - st1 {v4.4s-v5.4s},[x17], #32 - add v7.4s,v7.4s,v3.4s - st1 {v6.4s-v7.4s},[x17] - sub x17,x17,#32 - - ldp w3,w4,[x0] - ldp w5,w6,[x0,#8] - ldp w7,w8,[x0,#16] - ldp w9,w10,[x0,#24] - ldr w12,[sp,#0] - mov w13,wzr - eor w14,w4,w5 - mov w15,wzr - b .L_00_48 - -.align 4 -.L_00_48: - ext v4.16b,v0.16b,v1.16b,#4 - add w10,w10,w12 - add w3,w3,w15 - and w12,w8,w7 - bic w15,w9,w7 - ext v7.16b,v2.16b,v3.16b,#4 - eor w11,w7,w7,ror#5 - add w3,w3,w13 - mov d19,v3.d[1] - orr w12,w12,w15 - eor w11,w11,w7,ror#19 - ushr v6.4s,v4.4s,#7 - eor w15,w3,w3,ror#11 - ushr v5.4s,v4.4s,#3 - add w10,w10,w12 - add v0.4s,v0.4s,v7.4s - ror w11,w11,#6 - sli v6.4s,v4.4s,#25 - eor w13,w3,w4 - eor w15,w15,w3,ror#20 - ushr v7.4s,v4.4s,#18 - add w10,w10,w11 - ldr w12,[sp,#4] - and w14,w14,w13 - eor v5.16b,v5.16b,v6.16b - ror w15,w15,#2 - add w6,w6,w10 - sli v7.4s,v4.4s,#14 - eor w14,w14,w4 - ushr v16.4s,v19.4s,#17 - add w9,w9,w12 - add w10,w10,w15 - and w12,w7,w6 - eor v5.16b,v5.16b,v7.16b - bic w15,w8,w6 - eor w11,w6,w6,ror#5 - sli v16.4s,v19.4s,#15 - add w10,w10,w14 - orr w12,w12,w15 - ushr v17.4s,v19.4s,#10 - eor w11,w11,w6,ror#19 - eor w15,w10,w10,ror#11 - ushr v7.4s,v19.4s,#19 - add w9,w9,w12 - ror w11,w11,#6 - add v0.4s,v0.4s,v5.4s - eor w14,w10,w3 - eor w15,w15,w10,ror#20 - sli v7.4s,v19.4s,#13 - add w9,w9,w11 - ldr w12,[sp,#8] - and w13,w13,w14 - eor v17.16b,v17.16b,v16.16b - ror w15,w15,#2 - add w5,w5,w9 - eor w13,w13,w3 - eor v17.16b,v17.16b,v7.16b - add w8,w8,w12 - add w9,w9,w15 - and w12,w6,w5 - add v0.4s,v0.4s,v17.4s - bic w15,w7,w5 - eor w11,w5,w5,ror#5 - add w9,w9,w13 - ushr v18.4s,v0.4s,#17 - orr w12,w12,w15 - ushr v19.4s,v0.4s,#10 - eor w11,w11,w5,ror#19 - eor w15,w9,w9,ror#11 - sli v18.4s,v0.4s,#15 - add w8,w8,w12 - ushr v17.4s,v0.4s,#19 - ror w11,w11,#6 - eor w13,w9,w10 - eor v19.16b,v19.16b,v18.16b - eor w15,w15,w9,ror#20 - add w8,w8,w11 - sli v17.4s,v0.4s,#13 - ldr w12,[sp,#12] - and w14,w14,w13 - ror w15,w15,#2 - ld1 {v4.4s},[x16], #16 - add w4,w4,w8 - eor v19.16b,v19.16b,v17.16b - eor w14,w14,w10 - eor v17.16b,v17.16b,v17.16b - add w7,w7,w12 - add w8,w8,w15 - and w12,w5,w4 - mov v17.d[1],v19.d[0] - bic w15,w6,w4 - eor w11,w4,w4,ror#5 - add w8,w8,w14 - add v0.4s,v0.4s,v17.4s - orr w12,w12,w15 - eor w11,w11,w4,ror#19 - eor w15,w8,w8,ror#11 - add v4.4s,v4.4s,v0.4s - add w7,w7,w12 - ror w11,w11,#6 - eor w14,w8,w9 - eor w15,w15,w8,ror#20 - add w7,w7,w11 - ldr w12,[sp,#16] - and w13,w13,w14 - ror w15,w15,#2 - add w3,w3,w7 - eor w13,w13,w9 - st1 {v4.4s},[x17], #16 - ext v4.16b,v1.16b,v2.16b,#4 - add w6,w6,w12 - add w7,w7,w15 - and w12,w4,w3 - bic w15,w5,w3 - ext v7.16b,v3.16b,v0.16b,#4 - eor w11,w3,w3,ror#5 - add w7,w7,w13 - mov d19,v0.d[1] - orr w12,w12,w15 - eor w11,w11,w3,ror#19 - ushr v6.4s,v4.4s,#7 - eor w15,w7,w7,ror#11 - ushr v5.4s,v4.4s,#3 - add w6,w6,w12 - add v1.4s,v1.4s,v7.4s - ror w11,w11,#6 - sli v6.4s,v4.4s,#25 - eor w13,w7,w8 - eor w15,w15,w7,ror#20 - ushr v7.4s,v4.4s,#18 - add w6,w6,w11 - ldr w12,[sp,#20] - and w14,w14,w13 - eor v5.16b,v5.16b,v6.16b - ror w15,w15,#2 - add w10,w10,w6 - sli v7.4s,v4.4s,#14 - eor w14,w14,w8 - ushr v16.4s,v19.4s,#17 - add w5,w5,w12 - add w6,w6,w15 - and w12,w3,w10 - eor v5.16b,v5.16b,v7.16b - bic w15,w4,w10 - eor w11,w10,w10,ror#5 - sli v16.4s,v19.4s,#15 - add w6,w6,w14 - orr w12,w12,w15 - ushr v17.4s,v19.4s,#10 - eor w11,w11,w10,ror#19 - eor w15,w6,w6,ror#11 - ushr v7.4s,v19.4s,#19 - add w5,w5,w12 - ror w11,w11,#6 - add v1.4s,v1.4s,v5.4s - eor w14,w6,w7 - eor w15,w15,w6,ror#20 - sli v7.4s,v19.4s,#13 - add w5,w5,w11 - ldr w12,[sp,#24] - and w13,w13,w14 - eor v17.16b,v17.16b,v16.16b - ror w15,w15,#2 - add w9,w9,w5 - eor w13,w13,w7 - eor v17.16b,v17.16b,v7.16b - add w4,w4,w12 - add w5,w5,w15 - and w12,w10,w9 - add v1.4s,v1.4s,v17.4s - bic w15,w3,w9 - eor w11,w9,w9,ror#5 - add w5,w5,w13 - ushr v18.4s,v1.4s,#17 - orr w12,w12,w15 - ushr v19.4s,v1.4s,#10 - eor w11,w11,w9,ror#19 - eor w15,w5,w5,ror#11 - sli v18.4s,v1.4s,#15 - add w4,w4,w12 - ushr v17.4s,v1.4s,#19 - ror w11,w11,#6 - eor w13,w5,w6 - eor v19.16b,v19.16b,v18.16b - eor w15,w15,w5,ror#20 - add w4,w4,w11 - sli v17.4s,v1.4s,#13 - ldr w12,[sp,#28] - and w14,w14,w13 - ror w15,w15,#2 - ld1 {v4.4s},[x16], #16 - add w8,w8,w4 - eor v19.16b,v19.16b,v17.16b - eor w14,w14,w6 - eor v17.16b,v17.16b,v17.16b - add w3,w3,w12 - add w4,w4,w15 - and w12,w9,w8 - mov v17.d[1],v19.d[0] - bic w15,w10,w8 - eor w11,w8,w8,ror#5 - add w4,w4,w14 - add v1.4s,v1.4s,v17.4s - orr w12,w12,w15 - eor w11,w11,w8,ror#19 - eor w15,w4,w4,ror#11 - add v4.4s,v4.4s,v1.4s - add w3,w3,w12 - ror w11,w11,#6 - eor w14,w4,w5 - eor w15,w15,w4,ror#20 - add w3,w3,w11 - ldr w12,[sp,#32] - and w13,w13,w14 - ror w15,w15,#2 - add w7,w7,w3 - eor w13,w13,w5 - st1 {v4.4s},[x17], #16 - ext v4.16b,v2.16b,v3.16b,#4 - add w10,w10,w12 - add w3,w3,w15 - and w12,w8,w7 - bic w15,w9,w7 - ext v7.16b,v0.16b,v1.16b,#4 - eor w11,w7,w7,ror#5 - add w3,w3,w13 - mov d19,v1.d[1] - orr w12,w12,w15 - eor w11,w11,w7,ror#19 - ushr v6.4s,v4.4s,#7 - eor w15,w3,w3,ror#11 - ushr v5.4s,v4.4s,#3 - add w10,w10,w12 - add v2.4s,v2.4s,v7.4s - ror w11,w11,#6 - sli v6.4s,v4.4s,#25 - eor w13,w3,w4 - eor w15,w15,w3,ror#20 - ushr v7.4s,v4.4s,#18 - add w10,w10,w11 - ldr w12,[sp,#36] - and w14,w14,w13 - eor v5.16b,v5.16b,v6.16b - ror w15,w15,#2 - add w6,w6,w10 - sli v7.4s,v4.4s,#14 - eor w14,w14,w4 - ushr v16.4s,v19.4s,#17 - add w9,w9,w12 - add w10,w10,w15 - and w12,w7,w6 - eor v5.16b,v5.16b,v7.16b - bic w15,w8,w6 - eor w11,w6,w6,ror#5 - sli v16.4s,v19.4s,#15 - add w10,w10,w14 - orr w12,w12,w15 - ushr v17.4s,v19.4s,#10 - eor w11,w11,w6,ror#19 - eor w15,w10,w10,ror#11 - ushr v7.4s,v19.4s,#19 - add w9,w9,w12 - ror w11,w11,#6 - add v2.4s,v2.4s,v5.4s - eor w14,w10,w3 - eor w15,w15,w10,ror#20 - sli v7.4s,v19.4s,#13 - add w9,w9,w11 - ldr w12,[sp,#40] - and w13,w13,w14 - eor v17.16b,v17.16b,v16.16b - ror w15,w15,#2 - add w5,w5,w9 - eor w13,w13,w3 - eor v17.16b,v17.16b,v7.16b - add w8,w8,w12 - add w9,w9,w15 - and w12,w6,w5 - add v2.4s,v2.4s,v17.4s - bic w15,w7,w5 - eor w11,w5,w5,ror#5 - add w9,w9,w13 - ushr v18.4s,v2.4s,#17 - orr w12,w12,w15 - ushr v19.4s,v2.4s,#10 - eor w11,w11,w5,ror#19 - eor w15,w9,w9,ror#11 - sli v18.4s,v2.4s,#15 - add w8,w8,w12 - ushr v17.4s,v2.4s,#19 - ror w11,w11,#6 - eor w13,w9,w10 - eor v19.16b,v19.16b,v18.16b - eor w15,w15,w9,ror#20 - add w8,w8,w11 - sli v17.4s,v2.4s,#13 - ldr w12,[sp,#44] - and w14,w14,w13 - ror w15,w15,#2 - ld1 {v4.4s},[x16], #16 - add w4,w4,w8 - eor v19.16b,v19.16b,v17.16b - eor w14,w14,w10 - eor v17.16b,v17.16b,v17.16b - add w7,w7,w12 - add w8,w8,w15 - and w12,w5,w4 - mov v17.d[1],v19.d[0] - bic w15,w6,w4 - eor w11,w4,w4,ror#5 - add w8,w8,w14 - add v2.4s,v2.4s,v17.4s - orr w12,w12,w15 - eor w11,w11,w4,ror#19 - eor w15,w8,w8,ror#11 - add v4.4s,v4.4s,v2.4s - add w7,w7,w12 - ror w11,w11,#6 - eor w14,w8,w9 - eor w15,w15,w8,ror#20 - add w7,w7,w11 - ldr w12,[sp,#48] - and w13,w13,w14 - ror w15,w15,#2 - add w3,w3,w7 - eor w13,w13,w9 - st1 {v4.4s},[x17], #16 - ext v4.16b,v3.16b,v0.16b,#4 - add w6,w6,w12 - add w7,w7,w15 - and w12,w4,w3 - bic w15,w5,w3 - ext v7.16b,v1.16b,v2.16b,#4 - eor w11,w3,w3,ror#5 - add w7,w7,w13 - mov d19,v2.d[1] - orr w12,w12,w15 - eor w11,w11,w3,ror#19 - ushr v6.4s,v4.4s,#7 - eor w15,w7,w7,ror#11 - ushr v5.4s,v4.4s,#3 - add w6,w6,w12 - add v3.4s,v3.4s,v7.4s - ror w11,w11,#6 - sli v6.4s,v4.4s,#25 - eor w13,w7,w8 - eor w15,w15,w7,ror#20 - ushr v7.4s,v4.4s,#18 - add w6,w6,w11 - ldr w12,[sp,#52] - and w14,w14,w13 - eor v5.16b,v5.16b,v6.16b - ror w15,w15,#2 - add w10,w10,w6 - sli v7.4s,v4.4s,#14 - eor w14,w14,w8 - ushr v16.4s,v19.4s,#17 - add w5,w5,w12 - add w6,w6,w15 - and w12,w3,w10 - eor v5.16b,v5.16b,v7.16b - bic w15,w4,w10 - eor w11,w10,w10,ror#5 - sli v16.4s,v19.4s,#15 - add w6,w6,w14 - orr w12,w12,w15 - ushr v17.4s,v19.4s,#10 - eor w11,w11,w10,ror#19 - eor w15,w6,w6,ror#11 - ushr v7.4s,v19.4s,#19 - add w5,w5,w12 - ror w11,w11,#6 - add v3.4s,v3.4s,v5.4s - eor w14,w6,w7 - eor w15,w15,w6,ror#20 - sli v7.4s,v19.4s,#13 - add w5,w5,w11 - ldr w12,[sp,#56] - and w13,w13,w14 - eor v17.16b,v17.16b,v16.16b - ror w15,w15,#2 - add w9,w9,w5 - eor w13,w13,w7 - eor v17.16b,v17.16b,v7.16b - add w4,w4,w12 - add w5,w5,w15 - and w12,w10,w9 - add v3.4s,v3.4s,v17.4s - bic w15,w3,w9 - eor w11,w9,w9,ror#5 - add w5,w5,w13 - ushr v18.4s,v3.4s,#17 - orr w12,w12,w15 - ushr v19.4s,v3.4s,#10 - eor w11,w11,w9,ror#19 - eor w15,w5,w5,ror#11 - sli v18.4s,v3.4s,#15 - add w4,w4,w12 - ushr v17.4s,v3.4s,#19 - ror w11,w11,#6 - eor w13,w5,w6 - eor v19.16b,v19.16b,v18.16b - eor w15,w15,w5,ror#20 - add w4,w4,w11 - sli v17.4s,v3.4s,#13 - ldr w12,[sp,#60] - and w14,w14,w13 - ror w15,w15,#2 - ld1 {v4.4s},[x16], #16 - add w8,w8,w4 - eor v19.16b,v19.16b,v17.16b - eor w14,w14,w6 - eor v17.16b,v17.16b,v17.16b - add w3,w3,w12 - add w4,w4,w15 - and w12,w9,w8 - mov v17.d[1],v19.d[0] - bic w15,w10,w8 - eor w11,w8,w8,ror#5 - add w4,w4,w14 - add v3.4s,v3.4s,v17.4s - orr w12,w12,w15 - eor w11,w11,w8,ror#19 - eor w15,w4,w4,ror#11 - add v4.4s,v4.4s,v3.4s - add w3,w3,w12 - ror w11,w11,#6 - eor w14,w4,w5 - eor w15,w15,w4,ror#20 - add w3,w3,w11 - ldr w12,[x16] - and w13,w13,w14 - ror w15,w15,#2 - add w7,w7,w3 - eor w13,w13,w5 - st1 {v4.4s},[x17], #16 - cmp w12,#0 // check for K256 terminator - ldr w12,[sp,#0] - sub x17,x17,#64 - bne .L_00_48 - - sub x16,x16,#256 // rewind x16 - cmp x1,x2 - mov x17, #64 - csel x17, x17, xzr, eq - sub x1,x1,x17 // avoid SEGV - mov x17,sp - add w10,w10,w12 - add w3,w3,w15 - and w12,w8,w7 - ld1 {v0.16b},[x1],#16 - bic w15,w9,w7 - eor w11,w7,w7,ror#5 - ld1 {v4.4s},[x16],#16 - add w3,w3,w13 - orr w12,w12,w15 - eor w11,w11,w7,ror#19 - eor w15,w3,w3,ror#11 - rev32 v0.16b,v0.16b - add w10,w10,w12 - ror w11,w11,#6 - eor w13,w3,w4 - eor w15,w15,w3,ror#20 - add v4.4s,v4.4s,v0.4s - add w10,w10,w11 - ldr w12,[sp,#4] - and w14,w14,w13 - ror w15,w15,#2 - add w6,w6,w10 - eor w14,w14,w4 - add w9,w9,w12 - add w10,w10,w15 - and w12,w7,w6 - bic w15,w8,w6 - eor w11,w6,w6,ror#5 - add w10,w10,w14 - orr w12,w12,w15 - eor w11,w11,w6,ror#19 - eor w15,w10,w10,ror#11 - add w9,w9,w12 - ror w11,w11,#6 - eor w14,w10,w3 - eor w15,w15,w10,ror#20 - add w9,w9,w11 - ldr w12,[sp,#8] - and w13,w13,w14 - ror w15,w15,#2 - add w5,w5,w9 - eor w13,w13,w3 - add w8,w8,w12 - add w9,w9,w15 - and w12,w6,w5 - bic w15,w7,w5 - eor w11,w5,w5,ror#5 - add w9,w9,w13 - orr w12,w12,w15 - eor w11,w11,w5,ror#19 - eor w15,w9,w9,ror#11 - add w8,w8,w12 - ror w11,w11,#6 - eor w13,w9,w10 - eor w15,w15,w9,ror#20 - add w8,w8,w11 - ldr w12,[sp,#12] - and w14,w14,w13 - ror w15,w15,#2 - add w4,w4,w8 - eor w14,w14,w10 - add w7,w7,w12 - add w8,w8,w15 - and w12,w5,w4 - bic w15,w6,w4 - eor w11,w4,w4,ror#5 - add w8,w8,w14 - orr w12,w12,w15 - eor w11,w11,w4,ror#19 - eor w15,w8,w8,ror#11 - add w7,w7,w12 - ror w11,w11,#6 - eor w14,w8,w9 - eor w15,w15,w8,ror#20 - add w7,w7,w11 - ldr w12,[sp,#16] - and w13,w13,w14 - ror w15,w15,#2 - add w3,w3,w7 - eor w13,w13,w9 - st1 {v4.4s},[x17], #16 - add w6,w6,w12 - add w7,w7,w15 - and w12,w4,w3 - ld1 {v1.16b},[x1],#16 - bic w15,w5,w3 - eor w11,w3,w3,ror#5 - ld1 {v4.4s},[x16],#16 - add w7,w7,w13 - orr w12,w12,w15 - eor w11,w11,w3,ror#19 - eor w15,w7,w7,ror#11 - rev32 v1.16b,v1.16b - add w6,w6,w12 - ror w11,w11,#6 - eor w13,w7,w8 - eor w15,w15,w7,ror#20 - add v4.4s,v4.4s,v1.4s - add w6,w6,w11 - ldr w12,[sp,#20] - and w14,w14,w13 - ror w15,w15,#2 - add w10,w10,w6 - eor w14,w14,w8 - add w5,w5,w12 - add w6,w6,w15 - and w12,w3,w10 - bic w15,w4,w10 - eor w11,w10,w10,ror#5 - add w6,w6,w14 - orr w12,w12,w15 - eor w11,w11,w10,ror#19 - eor w15,w6,w6,ror#11 - add w5,w5,w12 - ror w11,w11,#6 - eor w14,w6,w7 - eor w15,w15,w6,ror#20 - add w5,w5,w11 - ldr w12,[sp,#24] - and w13,w13,w14 - ror w15,w15,#2 - add w9,w9,w5 - eor w13,w13,w7 - add w4,w4,w12 - add w5,w5,w15 - and w12,w10,w9 - bic w15,w3,w9 - eor w11,w9,w9,ror#5 - add w5,w5,w13 - orr w12,w12,w15 - eor w11,w11,w9,ror#19 - eor w15,w5,w5,ror#11 - add w4,w4,w12 - ror w11,w11,#6 - eor w13,w5,w6 - eor w15,w15,w5,ror#20 - add w4,w4,w11 - ldr w12,[sp,#28] - and w14,w14,w13 - ror w15,w15,#2 - add w8,w8,w4 - eor w14,w14,w6 - add w3,w3,w12 - add w4,w4,w15 - and w12,w9,w8 - bic w15,w10,w8 - eor w11,w8,w8,ror#5 - add w4,w4,w14 - orr w12,w12,w15 - eor w11,w11,w8,ror#19 - eor w15,w4,w4,ror#11 - add w3,w3,w12 - ror w11,w11,#6 - eor w14,w4,w5 - eor w15,w15,w4,ror#20 - add w3,w3,w11 - ldr w12,[sp,#32] - and w13,w13,w14 - ror w15,w15,#2 - add w7,w7,w3 - eor w13,w13,w5 - st1 {v4.4s},[x17], #16 - add w10,w10,w12 - add w3,w3,w15 - and w12,w8,w7 - ld1 {v2.16b},[x1],#16 - bic w15,w9,w7 - eor w11,w7,w7,ror#5 - ld1 {v4.4s},[x16],#16 - add w3,w3,w13 - orr w12,w12,w15 - eor w11,w11,w7,ror#19 - eor w15,w3,w3,ror#11 - rev32 v2.16b,v2.16b - add w10,w10,w12 - ror w11,w11,#6 - eor w13,w3,w4 - eor w15,w15,w3,ror#20 - add v4.4s,v4.4s,v2.4s - add w10,w10,w11 - ldr w12,[sp,#36] - and w14,w14,w13 - ror w15,w15,#2 - add w6,w6,w10 - eor w14,w14,w4 - add w9,w9,w12 - add w10,w10,w15 - and w12,w7,w6 - bic w15,w8,w6 - eor w11,w6,w6,ror#5 - add w10,w10,w14 - orr w12,w12,w15 - eor w11,w11,w6,ror#19 - eor w15,w10,w10,ror#11 - add w9,w9,w12 - ror w11,w11,#6 - eor w14,w10,w3 - eor w15,w15,w10,ror#20 - add w9,w9,w11 - ldr w12,[sp,#40] - and w13,w13,w14 - ror w15,w15,#2 - add w5,w5,w9 - eor w13,w13,w3 - add w8,w8,w12 - add w9,w9,w15 - and w12,w6,w5 - bic w15,w7,w5 - eor w11,w5,w5,ror#5 - add w9,w9,w13 - orr w12,w12,w15 - eor w11,w11,w5,ror#19 - eor w15,w9,w9,ror#11 - add w8,w8,w12 - ror w11,w11,#6 - eor w13,w9,w10 - eor w15,w15,w9,ror#20 - add w8,w8,w11 - ldr w12,[sp,#44] - and w14,w14,w13 - ror w15,w15,#2 - add w4,w4,w8 - eor w14,w14,w10 - add w7,w7,w12 - add w8,w8,w15 - and w12,w5,w4 - bic w15,w6,w4 - eor w11,w4,w4,ror#5 - add w8,w8,w14 - orr w12,w12,w15 - eor w11,w11,w4,ror#19 - eor w15,w8,w8,ror#11 - add w7,w7,w12 - ror w11,w11,#6 - eor w14,w8,w9 - eor w15,w15,w8,ror#20 - add w7,w7,w11 - ldr w12,[sp,#48] - and w13,w13,w14 - ror w15,w15,#2 - add w3,w3,w7 - eor w13,w13,w9 - st1 {v4.4s},[x17], #16 - add w6,w6,w12 - add w7,w7,w15 - and w12,w4,w3 - ld1 {v3.16b},[x1],#16 - bic w15,w5,w3 - eor w11,w3,w3,ror#5 - ld1 {v4.4s},[x16],#16 - add w7,w7,w13 - orr w12,w12,w15 - eor w11,w11,w3,ror#19 - eor w15,w7,w7,ror#11 - rev32 v3.16b,v3.16b - add w6,w6,w12 - ror w11,w11,#6 - eor w13,w7,w8 - eor w15,w15,w7,ror#20 - add v4.4s,v4.4s,v3.4s - add w6,w6,w11 - ldr w12,[sp,#52] - and w14,w14,w13 - ror w15,w15,#2 - add w10,w10,w6 - eor w14,w14,w8 - add w5,w5,w12 - add w6,w6,w15 - and w12,w3,w10 - bic w15,w4,w10 - eor w11,w10,w10,ror#5 - add w6,w6,w14 - orr w12,w12,w15 - eor w11,w11,w10,ror#19 - eor w15,w6,w6,ror#11 - add w5,w5,w12 - ror w11,w11,#6 - eor w14,w6,w7 - eor w15,w15,w6,ror#20 - add w5,w5,w11 - ldr w12,[sp,#56] - and w13,w13,w14 - ror w15,w15,#2 - add w9,w9,w5 - eor w13,w13,w7 - add w4,w4,w12 - add w5,w5,w15 - and w12,w10,w9 - bic w15,w3,w9 - eor w11,w9,w9,ror#5 - add w5,w5,w13 - orr w12,w12,w15 - eor w11,w11,w9,ror#19 - eor w15,w5,w5,ror#11 - add w4,w4,w12 - ror w11,w11,#6 - eor w13,w5,w6 - eor w15,w15,w5,ror#20 - add w4,w4,w11 - ldr w12,[sp,#60] - and w14,w14,w13 - ror w15,w15,#2 - add w8,w8,w4 - eor w14,w14,w6 - add w3,w3,w12 - add w4,w4,w15 - and w12,w9,w8 - bic w15,w10,w8 - eor w11,w8,w8,ror#5 - add w4,w4,w14 - orr w12,w12,w15 - eor w11,w11,w8,ror#19 - eor w15,w4,w4,ror#11 - add w3,w3,w12 - ror w11,w11,#6 - eor w14,w4,w5 - eor w15,w15,w4,ror#20 - add w3,w3,w11 - and w13,w13,w14 - ror w15,w15,#2 - add w7,w7,w3 - eor w13,w13,w5 - st1 {v4.4s},[x17], #16 - add w3,w3,w15 // h+=Sigma0(a) from the past - ldp w11,w12,[x0,#0] - add w3,w3,w13 // h+=Maj(a,b,c) from the past - ldp w13,w14,[x0,#8] - add w3,w3,w11 // accumulate - add w4,w4,w12 - ldp w11,w12,[x0,#16] - add w5,w5,w13 - add w6,w6,w14 - ldp w13,w14,[x0,#24] - add w7,w7,w11 - add w8,w8,w12 - ldr w12,[sp,#0] - stp w3,w4,[x0,#0] - add w9,w9,w13 - mov w13,wzr - stp w5,w6,[x0,#8] - add w10,w10,w14 - stp w7,w8,[x0,#16] - eor w14,w4,w5 - stp w9,w10,[x0,#24] - mov w15,wzr - mov x17,sp - b.ne .L_00_48 - - ldr x29,[x29] - add sp,sp,#16*4+16 - ret -.size sha256_block_neon,.-sha256_block_neon -#ifndef __KERNEL__ -.comm OPENSSL_armcap_P,4,4 -#endif diff --git a/arch/arm64/crypto/sha512-core.S b/arch/arm64/crypto/sha512-core.S deleted file mode 100644 index bd0f59f06c9d..000000000000 --- a/arch/arm64/crypto/sha512-core.S +++ /dev/null @@ -1,1085 +0,0 @@ -// Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. -// -// Licensed under the OpenSSL license (the "License"). You may not use -// this file except in compliance with the License. You can obtain a copy -// in the file LICENSE in the source distribution or at -// https://www.openssl.org/source/license.html - -// ==================================================================== -// Written by Andy Polyakov <appro@openssl.org> for the OpenSSL -// project. The module is, however, dual licensed under OpenSSL and -// CRYPTOGAMS licenses depending on where you obtain it. For further -// details see http://www.openssl.org/~appro/cryptogams/. -// -// Permission to use under GPLv2 terms is granted. -// ==================================================================== -// -// SHA256/512 for ARMv8. -// -// Performance in cycles per processed byte and improvement coefficient -// over code generated with "default" compiler: -// -// SHA256-hw SHA256(*) SHA512 -// Apple A7 1.97 10.5 (+33%) 6.73 (-1%(**)) -// Cortex-A53 2.38 15.5 (+115%) 10.0 (+150%(***)) -// Cortex-A57 2.31 11.6 (+86%) 7.51 (+260%(***)) -// Denver 2.01 10.5 (+26%) 6.70 (+8%) -// X-Gene 20.0 (+100%) 12.8 (+300%(***)) -// Mongoose 2.36 13.0 (+50%) 8.36 (+33%) -// -// (*) Software SHA256 results are of lesser relevance, presented -// mostly for informational purposes. -// (**) The result is a trade-off: it's possible to improve it by -// 10% (or by 1 cycle per round), but at the cost of 20% loss -// on Cortex-A53 (or by 4 cycles per round). -// (***) Super-impressive coefficients over gcc-generated code are -// indication of some compiler "pathology", most notably code -// generated with -mgeneral-regs-only is significanty faster -// and the gap is only 40-90%. -// -// October 2016. -// -// Originally it was reckoned that it makes no sense to implement NEON -// version of SHA256 for 64-bit processors. This is because performance -// improvement on most wide-spread Cortex-A5x processors was observed -// to be marginal, same on Cortex-A53 and ~10% on A57. But then it was -// observed that 32-bit NEON SHA256 performs significantly better than -// 64-bit scalar version on *some* of the more recent processors. As -// result 64-bit NEON version of SHA256 was added to provide best -// all-round performance. For example it executes ~30% faster on X-Gene -// and Mongoose. [For reference, NEON version of SHA512 is bound to -// deliver much less improvement, likely *negative* on Cortex-A5x. -// Which is why NEON support is limited to SHA256.] - -#ifndef __KERNEL__ -# include "arm_arch.h" -#endif - -.text - -.extern OPENSSL_armcap_P -.globl sha512_block_data_order -.type sha512_block_data_order,%function -.align 6 -sha512_block_data_order: - stp x29,x30,[sp,#-128]! - add x29,sp,#0 - - stp x19,x20,[sp,#16] - stp x21,x22,[sp,#32] - stp x23,x24,[sp,#48] - stp x25,x26,[sp,#64] - stp x27,x28,[sp,#80] - sub sp,sp,#4*8 - - ldp x20,x21,[x0] // load context - ldp x22,x23,[x0,#2*8] - ldp x24,x25,[x0,#4*8] - add x2,x1,x2,lsl#7 // end of input - ldp x26,x27,[x0,#6*8] - adr x30,.LK512 - stp x0,x2,[x29,#96] - -.Loop: - ldp x3,x4,[x1],#2*8 - ldr x19,[x30],#8 // *K++ - eor x28,x21,x22 // magic seed - str x1,[x29,#112] -#ifndef __AARCH64EB__ - rev x3,x3 // 0 -#endif - ror x16,x24,#14 - add x27,x27,x19 // h+=K[i] - eor x6,x24,x24,ror#23 - and x17,x25,x24 - bic x19,x26,x24 - add x27,x27,x3 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x20,x21 // a^b, b^c in next round - eor x16,x16,x6,ror#18 // Sigma1(e) - ror x6,x20,#28 - add x27,x27,x17 // h+=Ch(e,f,g) - eor x17,x20,x20,ror#5 - add x27,x27,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x23,x23,x27 // d+=h - eor x28,x28,x21 // Maj(a,b,c) - eor x17,x6,x17,ror#34 // Sigma0(a) - add x27,x27,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x27,x27,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x4,x4 // 1 -#endif - ldp x5,x6,[x1],#2*8 - add x27,x27,x17 // h+=Sigma0(a) - ror x16,x23,#14 - add x26,x26,x28 // h+=K[i] - eor x7,x23,x23,ror#23 - and x17,x24,x23 - bic x28,x25,x23 - add x26,x26,x4 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x27,x20 // a^b, b^c in next round - eor x16,x16,x7,ror#18 // Sigma1(e) - ror x7,x27,#28 - add x26,x26,x17 // h+=Ch(e,f,g) - eor x17,x27,x27,ror#5 - add x26,x26,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x22,x22,x26 // d+=h - eor x19,x19,x20 // Maj(a,b,c) - eor x17,x7,x17,ror#34 // Sigma0(a) - add x26,x26,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x26,x26,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x5,x5 // 2 -#endif - add x26,x26,x17 // h+=Sigma0(a) - ror x16,x22,#14 - add x25,x25,x19 // h+=K[i] - eor x8,x22,x22,ror#23 - and x17,x23,x22 - bic x19,x24,x22 - add x25,x25,x5 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x26,x27 // a^b, b^c in next round - eor x16,x16,x8,ror#18 // Sigma1(e) - ror x8,x26,#28 - add x25,x25,x17 // h+=Ch(e,f,g) - eor x17,x26,x26,ror#5 - add x25,x25,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x21,x21,x25 // d+=h - eor x28,x28,x27 // Maj(a,b,c) - eor x17,x8,x17,ror#34 // Sigma0(a) - add x25,x25,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x25,x25,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x6,x6 // 3 -#endif - ldp x7,x8,[x1],#2*8 - add x25,x25,x17 // h+=Sigma0(a) - ror x16,x21,#14 - add x24,x24,x28 // h+=K[i] - eor x9,x21,x21,ror#23 - and x17,x22,x21 - bic x28,x23,x21 - add x24,x24,x6 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x25,x26 // a^b, b^c in next round - eor x16,x16,x9,ror#18 // Sigma1(e) - ror x9,x25,#28 - add x24,x24,x17 // h+=Ch(e,f,g) - eor x17,x25,x25,ror#5 - add x24,x24,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x20,x20,x24 // d+=h - eor x19,x19,x26 // Maj(a,b,c) - eor x17,x9,x17,ror#34 // Sigma0(a) - add x24,x24,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x24,x24,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x7,x7 // 4 -#endif - add x24,x24,x17 // h+=Sigma0(a) - ror x16,x20,#14 - add x23,x23,x19 // h+=K[i] - eor x10,x20,x20,ror#23 - and x17,x21,x20 - bic x19,x22,x20 - add x23,x23,x7 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x24,x25 // a^b, b^c in next round - eor x16,x16,x10,ror#18 // Sigma1(e) - ror x10,x24,#28 - add x23,x23,x17 // h+=Ch(e,f,g) - eor x17,x24,x24,ror#5 - add x23,x23,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x27,x27,x23 // d+=h - eor x28,x28,x25 // Maj(a,b,c) - eor x17,x10,x17,ror#34 // Sigma0(a) - add x23,x23,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x23,x23,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x8,x8 // 5 -#endif - ldp x9,x10,[x1],#2*8 - add x23,x23,x17 // h+=Sigma0(a) - ror x16,x27,#14 - add x22,x22,x28 // h+=K[i] - eor x11,x27,x27,ror#23 - and x17,x20,x27 - bic x28,x21,x27 - add x22,x22,x8 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x23,x24 // a^b, b^c in next round - eor x16,x16,x11,ror#18 // Sigma1(e) - ror x11,x23,#28 - add x22,x22,x17 // h+=Ch(e,f,g) - eor x17,x23,x23,ror#5 - add x22,x22,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x26,x26,x22 // d+=h - eor x19,x19,x24 // Maj(a,b,c) - eor x17,x11,x17,ror#34 // Sigma0(a) - add x22,x22,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x22,x22,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x9,x9 // 6 -#endif - add x22,x22,x17 // h+=Sigma0(a) - ror x16,x26,#14 - add x21,x21,x19 // h+=K[i] - eor x12,x26,x26,ror#23 - and x17,x27,x26 - bic x19,x20,x26 - add x21,x21,x9 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x22,x23 // a^b, b^c in next round - eor x16,x16,x12,ror#18 // Sigma1(e) - ror x12,x22,#28 - add x21,x21,x17 // h+=Ch(e,f,g) - eor x17,x22,x22,ror#5 - add x21,x21,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x25,x25,x21 // d+=h - eor x28,x28,x23 // Maj(a,b,c) - eor x17,x12,x17,ror#34 // Sigma0(a) - add x21,x21,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x21,x21,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x10,x10 // 7 -#endif - ldp x11,x12,[x1],#2*8 - add x21,x21,x17 // h+=Sigma0(a) - ror x16,x25,#14 - add x20,x20,x28 // h+=K[i] - eor x13,x25,x25,ror#23 - and x17,x26,x25 - bic x28,x27,x25 - add x20,x20,x10 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x21,x22 // a^b, b^c in next round - eor x16,x16,x13,ror#18 // Sigma1(e) - ror x13,x21,#28 - add x20,x20,x17 // h+=Ch(e,f,g) - eor x17,x21,x21,ror#5 - add x20,x20,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x24,x24,x20 // d+=h - eor x19,x19,x22 // Maj(a,b,c) - eor x17,x13,x17,ror#34 // Sigma0(a) - add x20,x20,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x20,x20,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x11,x11 // 8 -#endif - add x20,x20,x17 // h+=Sigma0(a) - ror x16,x24,#14 - add x27,x27,x19 // h+=K[i] - eor x14,x24,x24,ror#23 - and x17,x25,x24 - bic x19,x26,x24 - add x27,x27,x11 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x20,x21 // a^b, b^c in next round - eor x16,x16,x14,ror#18 // Sigma1(e) - ror x14,x20,#28 - add x27,x27,x17 // h+=Ch(e,f,g) - eor x17,x20,x20,ror#5 - add x27,x27,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x23,x23,x27 // d+=h - eor x28,x28,x21 // Maj(a,b,c) - eor x17,x14,x17,ror#34 // Sigma0(a) - add x27,x27,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x27,x27,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x12,x12 // 9 -#endif - ldp x13,x14,[x1],#2*8 - add x27,x27,x17 // h+=Sigma0(a) - ror x16,x23,#14 - add x26,x26,x28 // h+=K[i] - eor x15,x23,x23,ror#23 - and x17,x24,x23 - bic x28,x25,x23 - add x26,x26,x12 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x27,x20 // a^b, b^c in next round - eor x16,x16,x15,ror#18 // Sigma1(e) - ror x15,x27,#28 - add x26,x26,x17 // h+=Ch(e,f,g) - eor x17,x27,x27,ror#5 - add x26,x26,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x22,x22,x26 // d+=h - eor x19,x19,x20 // Maj(a,b,c) - eor x17,x15,x17,ror#34 // Sigma0(a) - add x26,x26,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x26,x26,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x13,x13 // 10 -#endif - add x26,x26,x17 // h+=Sigma0(a) - ror x16,x22,#14 - add x25,x25,x19 // h+=K[i] - eor x0,x22,x22,ror#23 - and x17,x23,x22 - bic x19,x24,x22 - add x25,x25,x13 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x26,x27 // a^b, b^c in next round - eor x16,x16,x0,ror#18 // Sigma1(e) - ror x0,x26,#28 - add x25,x25,x17 // h+=Ch(e,f,g) - eor x17,x26,x26,ror#5 - add x25,x25,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x21,x21,x25 // d+=h - eor x28,x28,x27 // Maj(a,b,c) - eor x17,x0,x17,ror#34 // Sigma0(a) - add x25,x25,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x25,x25,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x14,x14 // 11 -#endif - ldp x15,x0,[x1],#2*8 - add x25,x25,x17 // h+=Sigma0(a) - str x6,[sp,#24] - ror x16,x21,#14 - add x24,x24,x28 // h+=K[i] - eor x6,x21,x21,ror#23 - and x17,x22,x21 - bic x28,x23,x21 - add x24,x24,x14 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x25,x26 // a^b, b^c in next round - eor x16,x16,x6,ror#18 // Sigma1(e) - ror x6,x25,#28 - add x24,x24,x17 // h+=Ch(e,f,g) - eor x17,x25,x25,ror#5 - add x24,x24,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x20,x20,x24 // d+=h - eor x19,x19,x26 // Maj(a,b,c) - eor x17,x6,x17,ror#34 // Sigma0(a) - add x24,x24,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x24,x24,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x15,x15 // 12 -#endif - add x24,x24,x17 // h+=Sigma0(a) - str x7,[sp,#0] - ror x16,x20,#14 - add x23,x23,x19 // h+=K[i] - eor x7,x20,x20,ror#23 - and x17,x21,x20 - bic x19,x22,x20 - add x23,x23,x15 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x24,x25 // a^b, b^c in next round - eor x16,x16,x7,ror#18 // Sigma1(e) - ror x7,x24,#28 - add x23,x23,x17 // h+=Ch(e,f,g) - eor x17,x24,x24,ror#5 - add x23,x23,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x27,x27,x23 // d+=h - eor x28,x28,x25 // Maj(a,b,c) - eor x17,x7,x17,ror#34 // Sigma0(a) - add x23,x23,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x23,x23,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x0,x0 // 13 -#endif - ldp x1,x2,[x1] - add x23,x23,x17 // h+=Sigma0(a) - str x8,[sp,#8] - ror x16,x27,#14 - add x22,x22,x28 // h+=K[i] - eor x8,x27,x27,ror#23 - and x17,x20,x27 - bic x28,x21,x27 - add x22,x22,x0 // h+=X[i] - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x23,x24 // a^b, b^c in next round - eor x16,x16,x8,ror#18 // Sigma1(e) - ror x8,x23,#28 - add x22,x22,x17 // h+=Ch(e,f,g) - eor x17,x23,x23,ror#5 - add x22,x22,x16 // h+=Sigma1(e) - and x19,x19,x28 // (b^c)&=(a^b) - add x26,x26,x22 // d+=h - eor x19,x19,x24 // Maj(a,b,c) - eor x17,x8,x17,ror#34 // Sigma0(a) - add x22,x22,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - //add x22,x22,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x1,x1 // 14 -#endif - ldr x6,[sp,#24] - add x22,x22,x17 // h+=Sigma0(a) - str x9,[sp,#16] - ror x16,x26,#14 - add x21,x21,x19 // h+=K[i] - eor x9,x26,x26,ror#23 - and x17,x27,x26 - bic x19,x20,x26 - add x21,x21,x1 // h+=X[i] - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x22,x23 // a^b, b^c in next round - eor x16,x16,x9,ror#18 // Sigma1(e) - ror x9,x22,#28 - add x21,x21,x17 // h+=Ch(e,f,g) - eor x17,x22,x22,ror#5 - add x21,x21,x16 // h+=Sigma1(e) - and x28,x28,x19 // (b^c)&=(a^b) - add x25,x25,x21 // d+=h - eor x28,x28,x23 // Maj(a,b,c) - eor x17,x9,x17,ror#34 // Sigma0(a) - add x21,x21,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - //add x21,x21,x17 // h+=Sigma0(a) -#ifndef __AARCH64EB__ - rev x2,x2 // 15 -#endif - ldr x7,[sp,#0] - add x21,x21,x17 // h+=Sigma0(a) - str x10,[sp,#24] - ror x16,x25,#14 - add x20,x20,x28 // h+=K[i] - ror x9,x4,#1 - and x17,x26,x25 - ror x8,x1,#19 - bic x28,x27,x25 - ror x10,x21,#28 - add x20,x20,x2 // h+=X[i] - eor x16,x16,x25,ror#18 - eor x9,x9,x4,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x21,x22 // a^b, b^c in next round - eor x16,x16,x25,ror#41 // Sigma1(e) - eor x10,x10,x21,ror#34 - add x20,x20,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x8,x8,x1,ror#61 - eor x9,x9,x4,lsr#7 // sigma0(X[i+1]) - add x20,x20,x16 // h+=Sigma1(e) - eor x19,x19,x22 // Maj(a,b,c) - eor x17,x10,x21,ror#39 // Sigma0(a) - eor x8,x8,x1,lsr#6 // sigma1(X[i+14]) - add x3,x3,x12 - add x24,x24,x20 // d+=h - add x20,x20,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x3,x3,x9 - add x20,x20,x17 // h+=Sigma0(a) - add x3,x3,x8 -.Loop_16_xx: - ldr x8,[sp,#8] - str x11,[sp,#0] - ror x16,x24,#14 - add x27,x27,x19 // h+=K[i] - ror x10,x5,#1 - and x17,x25,x24 - ror x9,x2,#19 - bic x19,x26,x24 - ror x11,x20,#28 - add x27,x27,x3 // h+=X[i] - eor x16,x16,x24,ror#18 - eor x10,x10,x5,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x20,x21 // a^b, b^c in next round - eor x16,x16,x24,ror#41 // Sigma1(e) - eor x11,x11,x20,ror#34 - add x27,x27,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x9,x9,x2,ror#61 - eor x10,x10,x5,lsr#7 // sigma0(X[i+1]) - add x27,x27,x16 // h+=Sigma1(e) - eor x28,x28,x21 // Maj(a,b,c) - eor x17,x11,x20,ror#39 // Sigma0(a) - eor x9,x9,x2,lsr#6 // sigma1(X[i+14]) - add x4,x4,x13 - add x23,x23,x27 // d+=h - add x27,x27,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x4,x4,x10 - add x27,x27,x17 // h+=Sigma0(a) - add x4,x4,x9 - ldr x9,[sp,#16] - str x12,[sp,#8] - ror x16,x23,#14 - add x26,x26,x28 // h+=K[i] - ror x11,x6,#1 - and x17,x24,x23 - ror x10,x3,#19 - bic x28,x25,x23 - ror x12,x27,#28 - add x26,x26,x4 // h+=X[i] - eor x16,x16,x23,ror#18 - eor x11,x11,x6,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x27,x20 // a^b, b^c in next round - eor x16,x16,x23,ror#41 // Sigma1(e) - eor x12,x12,x27,ror#34 - add x26,x26,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x10,x10,x3,ror#61 - eor x11,x11,x6,lsr#7 // sigma0(X[i+1]) - add x26,x26,x16 // h+=Sigma1(e) - eor x19,x19,x20 // Maj(a,b,c) - eor x17,x12,x27,ror#39 // Sigma0(a) - eor x10,x10,x3,lsr#6 // sigma1(X[i+14]) - add x5,x5,x14 - add x22,x22,x26 // d+=h - add x26,x26,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x5,x5,x11 - add x26,x26,x17 // h+=Sigma0(a) - add x5,x5,x10 - ldr x10,[sp,#24] - str x13,[sp,#16] - ror x16,x22,#14 - add x25,x25,x19 // h+=K[i] - ror x12,x7,#1 - and x17,x23,x22 - ror x11,x4,#19 - bic x19,x24,x22 - ror x13,x26,#28 - add x25,x25,x5 // h+=X[i] - eor x16,x16,x22,ror#18 - eor x12,x12,x7,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x26,x27 // a^b, b^c in next round - eor x16,x16,x22,ror#41 // Sigma1(e) - eor x13,x13,x26,ror#34 - add x25,x25,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x11,x11,x4,ror#61 - eor x12,x12,x7,lsr#7 // sigma0(X[i+1]) - add x25,x25,x16 // h+=Sigma1(e) - eor x28,x28,x27 // Maj(a,b,c) - eor x17,x13,x26,ror#39 // Sigma0(a) - eor x11,x11,x4,lsr#6 // sigma1(X[i+14]) - add x6,x6,x15 - add x21,x21,x25 // d+=h - add x25,x25,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x6,x6,x12 - add x25,x25,x17 // h+=Sigma0(a) - add x6,x6,x11 - ldr x11,[sp,#0] - str x14,[sp,#24] - ror x16,x21,#14 - add x24,x24,x28 // h+=K[i] - ror x13,x8,#1 - and x17,x22,x21 - ror x12,x5,#19 - bic x28,x23,x21 - ror x14,x25,#28 - add x24,x24,x6 // h+=X[i] - eor x16,x16,x21,ror#18 - eor x13,x13,x8,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x25,x26 // a^b, b^c in next round - eor x16,x16,x21,ror#41 // Sigma1(e) - eor x14,x14,x25,ror#34 - add x24,x24,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x12,x12,x5,ror#61 - eor x13,x13,x8,lsr#7 // sigma0(X[i+1]) - add x24,x24,x16 // h+=Sigma1(e) - eor x19,x19,x26 // Maj(a,b,c) - eor x17,x14,x25,ror#39 // Sigma0(a) - eor x12,x12,x5,lsr#6 // sigma1(X[i+14]) - add x7,x7,x0 - add x20,x20,x24 // d+=h - add x24,x24,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x7,x7,x13 - add x24,x24,x17 // h+=Sigma0(a) - add x7,x7,x12 - ldr x12,[sp,#8] - str x15,[sp,#0] - ror x16,x20,#14 - add x23,x23,x19 // h+=K[i] - ror x14,x9,#1 - and x17,x21,x20 - ror x13,x6,#19 - bic x19,x22,x20 - ror x15,x24,#28 - add x23,x23,x7 // h+=X[i] - eor x16,x16,x20,ror#18 - eor x14,x14,x9,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x24,x25 // a^b, b^c in next round - eor x16,x16,x20,ror#41 // Sigma1(e) - eor x15,x15,x24,ror#34 - add x23,x23,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x13,x13,x6,ror#61 - eor x14,x14,x9,lsr#7 // sigma0(X[i+1]) - add x23,x23,x16 // h+=Sigma1(e) - eor x28,x28,x25 // Maj(a,b,c) - eor x17,x15,x24,ror#39 // Sigma0(a) - eor x13,x13,x6,lsr#6 // sigma1(X[i+14]) - add x8,x8,x1 - add x27,x27,x23 // d+=h - add x23,x23,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x8,x8,x14 - add x23,x23,x17 // h+=Sigma0(a) - add x8,x8,x13 - ldr x13,[sp,#16] - str x0,[sp,#8] - ror x16,x27,#14 - add x22,x22,x28 // h+=K[i] - ror x15,x10,#1 - and x17,x20,x27 - ror x14,x7,#19 - bic x28,x21,x27 - ror x0,x23,#28 - add x22,x22,x8 // h+=X[i] - eor x16,x16,x27,ror#18 - eor x15,x15,x10,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x23,x24 // a^b, b^c in next round - eor x16,x16,x27,ror#41 // Sigma1(e) - eor x0,x0,x23,ror#34 - add x22,x22,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x14,x14,x7,ror#61 - eor x15,x15,x10,lsr#7 // sigma0(X[i+1]) - add x22,x22,x16 // h+=Sigma1(e) - eor x19,x19,x24 // Maj(a,b,c) - eor x17,x0,x23,ror#39 // Sigma0(a) - eor x14,x14,x7,lsr#6 // sigma1(X[i+14]) - add x9,x9,x2 - add x26,x26,x22 // d+=h - add x22,x22,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x9,x9,x15 - add x22,x22,x17 // h+=Sigma0(a) - add x9,x9,x14 - ldr x14,[sp,#24] - str x1,[sp,#16] - ror x16,x26,#14 - add x21,x21,x19 // h+=K[i] - ror x0,x11,#1 - and x17,x27,x26 - ror x15,x8,#19 - bic x19,x20,x26 - ror x1,x22,#28 - add x21,x21,x9 // h+=X[i] - eor x16,x16,x26,ror#18 - eor x0,x0,x11,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x22,x23 // a^b, b^c in next round - eor x16,x16,x26,ror#41 // Sigma1(e) - eor x1,x1,x22,ror#34 - add x21,x21,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x15,x15,x8,ror#61 - eor x0,x0,x11,lsr#7 // sigma0(X[i+1]) - add x21,x21,x16 // h+=Sigma1(e) - eor x28,x28,x23 // Maj(a,b,c) - eor x17,x1,x22,ror#39 // Sigma0(a) - eor x15,x15,x8,lsr#6 // sigma1(X[i+14]) - add x10,x10,x3 - add x25,x25,x21 // d+=h - add x21,x21,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x10,x10,x0 - add x21,x21,x17 // h+=Sigma0(a) - add x10,x10,x15 - ldr x15,[sp,#0] - str x2,[sp,#24] - ror x16,x25,#14 - add x20,x20,x28 // h+=K[i] - ror x1,x12,#1 - and x17,x26,x25 - ror x0,x9,#19 - bic x28,x27,x25 - ror x2,x21,#28 - add x20,x20,x10 // h+=X[i] - eor x16,x16,x25,ror#18 - eor x1,x1,x12,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x21,x22 // a^b, b^c in next round - eor x16,x16,x25,ror#41 // Sigma1(e) - eor x2,x2,x21,ror#34 - add x20,x20,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x0,x0,x9,ror#61 - eor x1,x1,x12,lsr#7 // sigma0(X[i+1]) - add x20,x20,x16 // h+=Sigma1(e) - eor x19,x19,x22 // Maj(a,b,c) - eor x17,x2,x21,ror#39 // Sigma0(a) - eor x0,x0,x9,lsr#6 // sigma1(X[i+14]) - add x11,x11,x4 - add x24,x24,x20 // d+=h - add x20,x20,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x11,x11,x1 - add x20,x20,x17 // h+=Sigma0(a) - add x11,x11,x0 - ldr x0,[sp,#8] - str x3,[sp,#0] - ror x16,x24,#14 - add x27,x27,x19 // h+=K[i] - ror x2,x13,#1 - and x17,x25,x24 - ror x1,x10,#19 - bic x19,x26,x24 - ror x3,x20,#28 - add x27,x27,x11 // h+=X[i] - eor x16,x16,x24,ror#18 - eor x2,x2,x13,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x20,x21 // a^b, b^c in next round - eor x16,x16,x24,ror#41 // Sigma1(e) - eor x3,x3,x20,ror#34 - add x27,x27,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x1,x1,x10,ror#61 - eor x2,x2,x13,lsr#7 // sigma0(X[i+1]) - add x27,x27,x16 // h+=Sigma1(e) - eor x28,x28,x21 // Maj(a,b,c) - eor x17,x3,x20,ror#39 // Sigma0(a) - eor x1,x1,x10,lsr#6 // sigma1(X[i+14]) - add x12,x12,x5 - add x23,x23,x27 // d+=h - add x27,x27,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x12,x12,x2 - add x27,x27,x17 // h+=Sigma0(a) - add x12,x12,x1 - ldr x1,[sp,#16] - str x4,[sp,#8] - ror x16,x23,#14 - add x26,x26,x28 // h+=K[i] - ror x3,x14,#1 - and x17,x24,x23 - ror x2,x11,#19 - bic x28,x25,x23 - ror x4,x27,#28 - add x26,x26,x12 // h+=X[i] - eor x16,x16,x23,ror#18 - eor x3,x3,x14,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x27,x20 // a^b, b^c in next round - eor x16,x16,x23,ror#41 // Sigma1(e) - eor x4,x4,x27,ror#34 - add x26,x26,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x2,x2,x11,ror#61 - eor x3,x3,x14,lsr#7 // sigma0(X[i+1]) - add x26,x26,x16 // h+=Sigma1(e) - eor x19,x19,x20 // Maj(a,b,c) - eor x17,x4,x27,ror#39 // Sigma0(a) - eor x2,x2,x11,lsr#6 // sigma1(X[i+14]) - add x13,x13,x6 - add x22,x22,x26 // d+=h - add x26,x26,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x13,x13,x3 - add x26,x26,x17 // h+=Sigma0(a) - add x13,x13,x2 - ldr x2,[sp,#24] - str x5,[sp,#16] - ror x16,x22,#14 - add x25,x25,x19 // h+=K[i] - ror x4,x15,#1 - and x17,x23,x22 - ror x3,x12,#19 - bic x19,x24,x22 - ror x5,x26,#28 - add x25,x25,x13 // h+=X[i] - eor x16,x16,x22,ror#18 - eor x4,x4,x15,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x26,x27 // a^b, b^c in next round - eor x16,x16,x22,ror#41 // Sigma1(e) - eor x5,x5,x26,ror#34 - add x25,x25,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x3,x3,x12,ror#61 - eor x4,x4,x15,lsr#7 // sigma0(X[i+1]) - add x25,x25,x16 // h+=Sigma1(e) - eor x28,x28,x27 // Maj(a,b,c) - eor x17,x5,x26,ror#39 // Sigma0(a) - eor x3,x3,x12,lsr#6 // sigma1(X[i+14]) - add x14,x14,x7 - add x21,x21,x25 // d+=h - add x25,x25,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x14,x14,x4 - add x25,x25,x17 // h+=Sigma0(a) - add x14,x14,x3 - ldr x3,[sp,#0] - str x6,[sp,#24] - ror x16,x21,#14 - add x24,x24,x28 // h+=K[i] - ror x5,x0,#1 - and x17,x22,x21 - ror x4,x13,#19 - bic x28,x23,x21 - ror x6,x25,#28 - add x24,x24,x14 // h+=X[i] - eor x16,x16,x21,ror#18 - eor x5,x5,x0,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x25,x26 // a^b, b^c in next round - eor x16,x16,x21,ror#41 // Sigma1(e) - eor x6,x6,x25,ror#34 - add x24,x24,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x4,x4,x13,ror#61 - eor x5,x5,x0,lsr#7 // sigma0(X[i+1]) - add x24,x24,x16 // h+=Sigma1(e) - eor x19,x19,x26 // Maj(a,b,c) - eor x17,x6,x25,ror#39 // Sigma0(a) - eor x4,x4,x13,lsr#6 // sigma1(X[i+14]) - add x15,x15,x8 - add x20,x20,x24 // d+=h - add x24,x24,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x15,x15,x5 - add x24,x24,x17 // h+=Sigma0(a) - add x15,x15,x4 - ldr x4,[sp,#8] - str x7,[sp,#0] - ror x16,x20,#14 - add x23,x23,x19 // h+=K[i] - ror x6,x1,#1 - and x17,x21,x20 - ror x5,x14,#19 - bic x19,x22,x20 - ror x7,x24,#28 - add x23,x23,x15 // h+=X[i] - eor x16,x16,x20,ror#18 - eor x6,x6,x1,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x24,x25 // a^b, b^c in next round - eor x16,x16,x20,ror#41 // Sigma1(e) - eor x7,x7,x24,ror#34 - add x23,x23,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x5,x5,x14,ror#61 - eor x6,x6,x1,lsr#7 // sigma0(X[i+1]) - add x23,x23,x16 // h+=Sigma1(e) - eor x28,x28,x25 // Maj(a,b,c) - eor x17,x7,x24,ror#39 // Sigma0(a) - eor x5,x5,x14,lsr#6 // sigma1(X[i+14]) - add x0,x0,x9 - add x27,x27,x23 // d+=h - add x23,x23,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x0,x0,x6 - add x23,x23,x17 // h+=Sigma0(a) - add x0,x0,x5 - ldr x5,[sp,#16] - str x8,[sp,#8] - ror x16,x27,#14 - add x22,x22,x28 // h+=K[i] - ror x7,x2,#1 - and x17,x20,x27 - ror x6,x15,#19 - bic x28,x21,x27 - ror x8,x23,#28 - add x22,x22,x0 // h+=X[i] - eor x16,x16,x27,ror#18 - eor x7,x7,x2,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x23,x24 // a^b, b^c in next round - eor x16,x16,x27,ror#41 // Sigma1(e) - eor x8,x8,x23,ror#34 - add x22,x22,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x6,x6,x15,ror#61 - eor x7,x7,x2,lsr#7 // sigma0(X[i+1]) - add x22,x22,x16 // h+=Sigma1(e) - eor x19,x19,x24 // Maj(a,b,c) - eor x17,x8,x23,ror#39 // Sigma0(a) - eor x6,x6,x15,lsr#6 // sigma1(X[i+14]) - add x1,x1,x10 - add x26,x26,x22 // d+=h - add x22,x22,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x1,x1,x7 - add x22,x22,x17 // h+=Sigma0(a) - add x1,x1,x6 - ldr x6,[sp,#24] - str x9,[sp,#16] - ror x16,x26,#14 - add x21,x21,x19 // h+=K[i] - ror x8,x3,#1 - and x17,x27,x26 - ror x7,x0,#19 - bic x19,x20,x26 - ror x9,x22,#28 - add x21,x21,x1 // h+=X[i] - eor x16,x16,x26,ror#18 - eor x8,x8,x3,ror#8 - orr x17,x17,x19 // Ch(e,f,g) - eor x19,x22,x23 // a^b, b^c in next round - eor x16,x16,x26,ror#41 // Sigma1(e) - eor x9,x9,x22,ror#34 - add x21,x21,x17 // h+=Ch(e,f,g) - and x28,x28,x19 // (b^c)&=(a^b) - eor x7,x7,x0,ror#61 - eor x8,x8,x3,lsr#7 // sigma0(X[i+1]) - add x21,x21,x16 // h+=Sigma1(e) - eor x28,x28,x23 // Maj(a,b,c) - eor x17,x9,x22,ror#39 // Sigma0(a) - eor x7,x7,x0,lsr#6 // sigma1(X[i+14]) - add x2,x2,x11 - add x25,x25,x21 // d+=h - add x21,x21,x28 // h+=Maj(a,b,c) - ldr x28,[x30],#8 // *K++, x19 in next round - add x2,x2,x8 - add x21,x21,x17 // h+=Sigma0(a) - add x2,x2,x7 - ldr x7,[sp,#0] - str x10,[sp,#24] - ror x16,x25,#14 - add x20,x20,x28 // h+=K[i] - ror x9,x4,#1 - and x17,x26,x25 - ror x8,x1,#19 - bic x28,x27,x25 - ror x10,x21,#28 - add x20,x20,x2 // h+=X[i] - eor x16,x16,x25,ror#18 - eor x9,x9,x4,ror#8 - orr x17,x17,x28 // Ch(e,f,g) - eor x28,x21,x22 // a^b, b^c in next round - eor x16,x16,x25,ror#41 // Sigma1(e) - eor x10,x10,x21,ror#34 - add x20,x20,x17 // h+=Ch(e,f,g) - and x19,x19,x28 // (b^c)&=(a^b) - eor x8,x8,x1,ror#61 - eor x9,x9,x4,lsr#7 // sigma0(X[i+1]) - add x20,x20,x16 // h+=Sigma1(e) - eor x19,x19,x22 // Maj(a,b,c) - eor x17,x10,x21,ror#39 // Sigma0(a) - eor x8,x8,x1,lsr#6 // sigma1(X[i+14]) - add x3,x3,x12 - add x24,x24,x20 // d+=h - add x20,x20,x19 // h+=Maj(a,b,c) - ldr x19,[x30],#8 // *K++, x28 in next round - add x3,x3,x9 - add x20,x20,x17 // h+=Sigma0(a) - add x3,x3,x8 - cbnz x19,.Loop_16_xx - - ldp x0,x2,[x29,#96] - ldr x1,[x29,#112] - sub x30,x30,#648 // rewind - - ldp x3,x4,[x0] - ldp x5,x6,[x0,#2*8] - add x1,x1,#14*8 // advance input pointer - ldp x7,x8,[x0,#4*8] - add x20,x20,x3 - ldp x9,x10,[x0,#6*8] - add x21,x21,x4 - add x22,x22,x5 - add x23,x23,x6 - stp x20,x21,[x0] - add x24,x24,x7 - add x25,x25,x8 - stp x22,x23,[x0,#2*8] - add x26,x26,x9 - add x27,x27,x10 - cmp x1,x2 - stp x24,x25,[x0,#4*8] - stp x26,x27,[x0,#6*8] - b.ne .Loop - - ldp x19,x20,[x29,#16] - add sp,sp,#4*8 - ldp x21,x22,[x29,#32] - ldp x23,x24,[x29,#48] - ldp x25,x26,[x29,#64] - ldp x27,x28,[x29,#80] - ldp x29,x30,[sp],#128 - ret -.size sha512_block_data_order,.-sha512_block_data_order - -.align 6 -.type .LK512,%object -.LK512: - .quad 0x428a2f98d728ae22,0x7137449123ef65cd - .quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc - .quad 0x3956c25bf348b538,0x59f111f1b605d019 - .quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 - .quad 0xd807aa98a3030242,0x12835b0145706fbe - .quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 - .quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 - .quad 0x9bdc06a725c71235,0xc19bf174cf692694 - .quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 - .quad 0x0fc19dc68b8cd5b5,0x240ca1cc77ac9c65 - .quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 - .quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 - .quad 0x983e5152ee66dfab,0xa831c66d2db43210 - .quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 - .quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 - .quad 0x06ca6351e003826f,0x142929670a0e6e70 - .quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 - .quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df - .quad 0x650a73548baf63de,0x766a0abb3c77b2a8 - .quad 0x81c2c92e47edaee6,0x92722c851482353b - .quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 - .quad 0xc24b8b70d0f89791,0xc76c51a30654be30 - .quad 0xd192e819d6ef5218,0xd69906245565a910 - .quad 0xf40e35855771202a,0x106aa07032bbd1b8 - .quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 - .quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 - .quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb - .quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 - .quad 0x748f82ee5defb2fc,0x78a5636f43172f60 - .quad 0x84c87814a1f0ab72,0x8cc702081a6439ec - .quad 0x90befffa23631e28,0xa4506cebde82bde9 - .quad 0xbef9a3f7b2c67915,0xc67178f2e372532b - .quad 0xca273eceea26619c,0xd186b8c721c0c207 - .quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 - .quad 0x06f067aa72176fba,0x0a637dc5a2c898a6 - .quad 0x113f9804bef90dae,0x1b710b35131c471b - .quad 0x28db77f523047d84,0x32caab7b40c72493 - .quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c - .quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a - .quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 - .quad 0 // terminator -.size .LK512,.-.LK512 -#ifndef __KERNEL__ -.align 3 -.LOPENSSL_armcap_P: -# ifdef __ILP32__ - .long OPENSSL_armcap_P-. -# else - .quad OPENSSL_armcap_P-. -# endif -#endif -.asciz "SHA512 block transform for ARMv8, CRYPTOGAMS by <appro@openssl.org>" -.align 2 -#ifndef __KERNEL__ -.comm OPENSSL_armcap_P,4,4 -#endif diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h index cd63d71551fe..7700bd767ae6 100644 --- a/arch/arm64/include/asm/pgtable.h +++ b/arch/arm64/include/asm/pgtable.h @@ -443,6 +443,8 @@ static inline phys_addr_t pmd_page_paddr(pmd_t pmd) return pmd_val(pmd) & PHYS_MASK & (s32)PAGE_MASK; } +static inline void pte_unmap(pte_t *pte) { } + /* Find an entry in the third-level page table. */ #define pte_index(addr) (((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) @@ -451,7 +453,6 @@ static inline phys_addr_t pmd_page_paddr(pmd_t pmd) #define pte_offset_map(dir,addr) pte_offset_kernel((dir), (addr)) #define pte_offset_map_nested(dir,addr) pte_offset_kernel((dir), (addr)) -#define pte_unmap(pte) do { } while (0) #define pte_unmap_nested(pte) do { } while (0) #define pte_set_fixmap(addr) ((pte_t *)set_fixmap_offset(FIX_PTE, addr)) diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 3b7968201575..af0c14dce54d 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -40,6 +40,7 @@ typedef unsigned long mm_segment_t; */ struct thread_info { unsigned long flags; /* low level flags */ + unsigned long padding[7]; mm_segment_t addr_limit; /* address limit */ #ifdef CONFIG_ARM64_SW_TTBR0_PAN u64 ttbr0; /* saved TTBR0_EL1 */ diff --git a/arch/arm64/include/asm/vdso_datapage.h b/arch/arm64/include/asm/vdso_datapage.h index 2b9a63771eda..f89263c8e11a 100644 --- a/arch/arm64/include/asm/vdso_datapage.h +++ b/arch/arm64/include/asm/vdso_datapage.h @@ -38,6 +38,7 @@ struct vdso_data { __u32 tz_minuteswest; /* Whacky timezone stuff */ __u32 tz_dsttime; __u32 use_syscall; + __u32 hrtimer_res; }; #endif /* !__ASSEMBLY__ */ diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 61ae19ef3c1a..b2debecb51e2 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -94,7 +94,7 @@ int main(void) DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); DEFINE(CLOCK_MONOTONIC_RAW, CLOCK_MONOTONIC_RAW); - DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); + DEFINE(CLOCK_REALTIME_RES, offsetof(struct vdso_data, hrtimer_res)); DEFINE(CLOCK_REALTIME_COARSE, CLOCK_REALTIME_COARSE); DEFINE(CLOCK_MONOTONIC_COARSE,CLOCK_MONOTONIC_COARSE); DEFINE(CLOCK_COARSE_RES, LOW_RES_NSEC); diff --git a/arch/arm64/kernel/cpu_ops.c b/arch/arm64/kernel/cpu_ops.c index e137ceaf5016..82b465207ed0 100644 --- a/arch/arm64/kernel/cpu_ops.c +++ b/arch/arm64/kernel/cpu_ops.c @@ -85,6 +85,7 @@ static const char *__init cpu_read_enable_method(int cpu) pr_err("%s: missing enable-method property\n", dn->full_name); } + of_node_put(dn); } else { enable_method = acpi_get_enable_method(cpu); if (!enable_method) { diff --git a/arch/arm64/kernel/module.c b/arch/arm64/kernel/module.c index f035ff6fb223..22ef48ff2da2 100644..100755 --- a/arch/arm64/kernel/module.c +++ b/arch/arm64/kernel/module.c @@ -34,14 +34,18 @@ void *module_alloc(unsigned long size) { gfp_t gfp_mask = GFP_KERNEL; void *p; + u64 module_alloc_end = module_alloc_base + MODULES_VSIZE; + + if (IS_ENABLED(CONFIG_KASAN)) + /* don't exceed the static module region - see below */ + module_alloc_end = MODULES_END; /* Silence the initial allocation */ if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS)) gfp_mask |= __GFP_NOWARN; p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base, - module_alloc_base + MODULES_VSIZE, - gfp_mask, PAGE_KERNEL_EXEC, 0, + module_alloc_end, gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE, __builtin_return_address(0)); if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) && diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c index e8f759f764f2..56956a1c235d 100644 --- a/arch/arm64/kernel/vdso.c +++ b/arch/arm64/kernel/vdso.c @@ -217,6 +217,9 @@ void update_vsyscall(struct timekeeper *tk) vdso_data->wtm_clock_sec = tk->wall_to_monotonic.tv_sec; vdso_data->wtm_clock_nsec = tk->wall_to_monotonic.tv_nsec; + /* Read without the seqlock held by clock_getres() */ + WRITE_ONCE(vdso_data->hrtimer_res, hrtimer_resolution); + if (!use_syscall) { /* tkr_mono.cycle_last == tkr_raw.cycle_last */ vdso_data->cs_cycle_last = tk->tkr_mono.cycle_last; diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S index 2bd7426ede32..a035df8c79f7 100644 --- a/arch/arm64/kernel/vdso/gettimeofday.S +++ b/arch/arm64/kernel/vdso/gettimeofday.S @@ -310,13 +310,14 @@ ENTRY(__kernel_clock_getres) ccmp w0, #CLOCK_MONOTONIC_RAW, #0x4, ne b.ne 1f - ldr x2, 5f + adr vdso_data, _vdso_data + ldr w2, [vdso_data, #CLOCK_REALTIME_RES] b 2f 1: cmp w0, #CLOCK_REALTIME_COARSE ccmp w0, #CLOCK_MONOTONIC_COARSE, #0x4, ne b.ne 4f - ldr x2, 6f + ldr x2, 5f 2: cbz x1, 3f stp xzr, x2, [x1] @@ -330,8 +331,6 @@ ENTRY(__kernel_clock_getres) svc #0 ret 5: - .quad CLOCK_REALTIME_RES -6: .quad CLOCK_COARSE_RES .cfi_endproc ENDPROC(__kernel_clock_getres) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 04ca1d4ffc3c..b202a2a2819a 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -826,13 +826,18 @@ void *__init fixmap_remap_fdt(phys_addr_t dt_phys) int __init arch_ioremap_pud_supported(void) { - /* only 4k granule supports level 1 block mappings */ - return IS_ENABLED(CONFIG_ARM64_4K_PAGES); + /* + * Only 4k granule supports level 1 block mappings. + * SW table walks can't handle removal of intermediate entries. + */ + return IS_ENABLED(CONFIG_ARM64_4K_PAGES) && + !IS_ENABLED(CONFIG_ARM64_PTDUMP_DEBUGFS); } int __init arch_ioremap_pmd_supported(void) { - return 1; + /* See arch_ioremap_pud_supported() */ + return !IS_ENABLED(CONFIG_ARM64_PTDUMP_DEBUGFS); } int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot) diff --git a/arch/ia64/include/asm/bug.h b/arch/ia64/include/asm/bug.h index 823616b5020b..19067821249f 100644 --- a/arch/ia64/include/asm/bug.h +++ b/arch/ia64/include/asm/bug.h @@ -3,7 +3,11 @@ #ifdef CONFIG_BUG #define ia64_abort() __builtin_trap() -#define BUG() do { printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); ia64_abort(); } while (0) +#define BUG() do { \ + printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + barrier_before_unreachable(); \ + ia64_abort(); \ +} while (0) /* should this BUG be made generic? */ #define HAVE_ARCH_BUG diff --git a/arch/ia64/mm/numa.c b/arch/ia64/mm/numa.c index aa19b7ac8222..476c7b4be378 100644 --- a/arch/ia64/mm/numa.c +++ b/arch/ia64/mm/numa.c @@ -49,6 +49,7 @@ paddr_to_nid(unsigned long paddr) return (i < num_node_memblks) ? node_memblk[i].nid : (num_node_memblks ? -1 : 0); } +EXPORT_SYMBOL(paddr_to_nid); #if defined(CONFIG_SPARSEMEM) && defined(CONFIG_NUMA) /* diff --git a/arch/m68k/include/asm/bug.h b/arch/m68k/include/asm/bug.h index ef9a2e47352f..21ddbf925e22 100644 --- a/arch/m68k/include/asm/bug.h +++ b/arch/m68k/include/asm/bug.h @@ -7,16 +7,19 @@ #ifndef CONFIG_SUN3 #define BUG() do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + barrier_before_unreachable(); \ __builtin_trap(); \ } while (0) #else #define BUG() do { \ printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ + barrier_before_unreachable(); \ panic("BUG!"); \ } while (0) #endif #else #define BUG() do { \ + barrier_before_unreachable(); \ __builtin_trap(); \ } while (0) #endif diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index bb9940c6927e..6cd230434f32 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig @@ -13,6 +13,7 @@ config MIPS select HAVE_OPROFILE select HAVE_PERF_EVENTS select PERF_USE_VMALLOC + select HAVE_ARCH_COMPILER_H select HAVE_ARCH_KGDB select HAVE_ARCH_SECCOMP_FILTER select HAVE_ARCH_TRACEHOOK diff --git a/arch/mips/ath79/setup.c b/arch/mips/ath79/setup.c index c7c31e214813..26a058d58d37 100644 --- a/arch/mips/ath79/setup.c +++ b/arch/mips/ath79/setup.c @@ -183,6 +183,12 @@ const char *get_system_type(void) return ath79_sys_type; } +int get_c0_perfcount_int(void) +{ + return ATH79_MISC_IRQ(5); +} +EXPORT_SYMBOL_GPL(get_c0_perfcount_int); + unsigned int get_c0_compare_int(void) { return CP0_LEGACY_COMPARE_IRQ; diff --git a/arch/mips/include/asm/compiler.h b/arch/mips/include/asm/compiler.h index e081a265f422..cc2eb1b06050 100644 --- a/arch/mips/include/asm/compiler.h +++ b/arch/mips/include/asm/compiler.h @@ -8,6 +8,41 @@ #ifndef _ASM_COMPILER_H #define _ASM_COMPILER_H +/* + * With GCC 4.5 onwards we can use __builtin_unreachable to indicate to the + * compiler that a particular code path will never be hit. This allows it to be + * optimised out of the generated binary. + * + * Unfortunately at least GCC 4.6.3 through 7.3.0 inclusive suffer from a bug + * that can lead to instructions from beyond an unreachable statement being + * incorrectly reordered into earlier delay slots if the unreachable statement + * is the only content of a case in a switch statement. This can lead to + * seemingly random behaviour, such as invalid memory accesses from incorrectly + * reordered loads or stores. See this potential GCC fix for details: + * + * https://gcc.gnu.org/ml/gcc-patches/2015-09/msg00360.html + * + * It is unclear whether GCC 8 onwards suffer from the same issue - nothing + * relevant is mentioned in GCC 8 release notes and nothing obviously relevant + * stands out in GCC commit logs, but these newer GCC versions generate very + * different code for the testcase which doesn't exhibit the bug. + * + * GCC also handles stack allocation suboptimally when calling noreturn + * functions or calling __builtin_unreachable(): + * + * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 + * + * We work around both of these issues by placing a volatile asm statement, + * which GCC is prevented from reordering past, prior to __builtin_unreachable + * calls. + * + * The .insn statement is required to ensure that any branches to the + * statement, which sadly must be kept due to the asm statement, are known to + * be branches to code and satisfy linker requirements for microMIPS kernels. + */ +#undef barrier_before_unreachable +#define barrier_before_unreachable() asm volatile(".insn") + #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) #define GCC_IMM_ASM() "n" #define GCC_REG_ACCUM "$0" diff --git a/arch/mips/include/asm/netlogic/xlr/fmn.h b/arch/mips/include/asm/netlogic/xlr/fmn.h index 5604db3d1836..d79c68fa78d9 100644 --- a/arch/mips/include/asm/netlogic/xlr/fmn.h +++ b/arch/mips/include/asm/netlogic/xlr/fmn.h @@ -301,8 +301,6 @@ static inline int nlm_fmn_send(unsigned int size, unsigned int code, for (i = 0; i < 8; i++) { nlm_msgsnd(dest); status = nlm_read_c2_status0(); - if ((status & 0x2) == 1) - pr_info("Send pending fail!\n"); if ((status & 0x4) == 0) return 0; } diff --git a/arch/mips/include/uapi/asm/sgidefs.h b/arch/mips/include/uapi/asm/sgidefs.h index 876442fcfb32..5be81f8fd479 100644 --- a/arch/mips/include/uapi/asm/sgidefs.h +++ b/arch/mips/include/uapi/asm/sgidefs.h @@ -11,14 +11,6 @@ #define __ASM_SGIDEFS_H /* - * Using a Linux compiler for building Linux seems logic but not to - * everybody. - */ -#ifndef __linux__ -#error Use a Linux compiler or give up. -#endif - -/* * Definitions for the ISA levels * * With the introduction of MIPS32 / MIPS64 instruction sets definitions diff --git a/arch/mips/kernel/uprobes.c b/arch/mips/kernel/uprobes.c index dbb917403131..ec951dde0999 100644 --- a/arch/mips/kernel/uprobes.c +++ b/arch/mips/kernel/uprobes.c @@ -111,9 +111,6 @@ int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs) */ aup->resume_epc = regs->cp0_epc + 4; if (insn_has_delay_slot((union mips_instruction) aup->insn[0])) { - unsigned long epc; - - epc = regs->cp0_epc; __compute_return_epc_for_insn(regs, (union mips_instruction) aup->insn[0]); aup->resume_epc = regs->cp0_epc; diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c index 7f2519cfb5d2..15f788601b64 100644 --- a/arch/mips/math-emu/cp1emu.c +++ b/arch/mips/math-emu/cp1emu.c @@ -828,12 +828,12 @@ do { \ } while (0) #define DIFROMREG(di, x) \ - ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) == 0)], 0)) + ((di) = get_fpr64(&ctx->fpr[(x) & ~(cop1_64bit(xcp) ^ 1)], 0)) #define DITOREG(di, x) \ do { \ unsigned fpr, i; \ - fpr = (x) & ~(cop1_64bit(xcp) == 0); \ + fpr = (x) & ~(cop1_64bit(xcp) ^ 1); \ set_fpr64(&ctx->fpr[fpr], 0, di); \ for (i = 1; i < ARRAY_SIZE(ctx->fpr[x].val64); i++) \ set_fpr64(&ctx->fpr[fpr], i, 0); \ diff --git a/arch/mips/mm/tlbex.c b/arch/mips/mm/tlbex.c index 2da5649fc545..3cc5b2e4263c 100644 --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -386,6 +386,7 @@ static struct work_registers build_get_work_registers(u32 **p) static void build_restore_work_registers(u32 **p) { if (scratch_reg >= 0) { + uasm_i_ehb(p); UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); return; } @@ -674,10 +675,12 @@ static void build_restore_pagemask(u32 **p, struct uasm_reloc **r, uasm_i_mtc0(p, 0, C0_PAGEMASK); uasm_il_b(p, r, lid); } - if (scratch_reg >= 0) + if (scratch_reg >= 0) { + uasm_i_ehb(p); UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); - else + } else { UASM_i_LW(p, 1, scratchpad_offset(0), 0); + } } else { /* Reset default page size */ if (PM_DEFAULT_MASK >> 16) { @@ -935,10 +938,12 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r, uasm_i_jr(p, ptr); if (mode == refill_scratch) { - if (scratch_reg >= 0) + if (scratch_reg >= 0) { + uasm_i_ehb(p); UASM_i_MFC0(p, 1, c0_kscratch(), scratch_reg); - else + } else { UASM_i_LW(p, 1, scratchpad_offset(0), 0); + } } else { uasm_i_nop(p); } @@ -1238,6 +1243,7 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l, UASM_i_MTC0(p, odd, C0_ENTRYLO1); /* load it */ if (c0_scratch_reg >= 0) { + uasm_i_ehb(p); UASM_i_MFC0(p, scratch, c0_kscratch(), c0_scratch_reg); build_tlb_write_entry(p, l, r, tlb_random); uasm_l_leave(l, *p); @@ -1592,15 +1598,17 @@ static void build_setup_pgd(void) uasm_i_dinsm(&p, a0, 0, 29, 64 - 29); uasm_l_tlbl_goaround1(&l, p); UASM_i_SLL(&p, a0, a0, 11); - uasm_i_jr(&p, 31); UASM_i_MTC0(&p, a0, C0_CONTEXT); + uasm_i_jr(&p, 31); + uasm_i_ehb(&p); } else { /* PGD in c0_KScratch */ - uasm_i_jr(&p, 31); if (cpu_has_ldpte) UASM_i_MTC0(&p, a0, C0_PWBASE); else UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); + uasm_i_jr(&p, 31); + uasm_i_ehb(&p); } #else #ifdef CONFIG_SMP @@ -1614,13 +1622,16 @@ static void build_setup_pgd(void) UASM_i_LA_mostly(&p, a2, pgdc); UASM_i_SW(&p, a0, uasm_rel_lo(pgdc), a2); #endif /* SMP */ - uasm_i_jr(&p, 31); /* if pgd_reg is allocated, save PGD also to scratch register */ - if (pgd_reg != -1) + if (pgd_reg != -1) { UASM_i_MTC0(&p, a0, c0_kscratch(), pgd_reg); - else + uasm_i_jr(&p, 31); + uasm_i_ehb(&p); + } else { + uasm_i_jr(&p, 31); uasm_i_nop(&p); + } #endif if (p >= tlbmiss_handler_setup_pgd_end) panic("tlbmiss_handler_setup_pgd space exceeded"); diff --git a/arch/mips/pistachio/Platform b/arch/mips/pistachio/Platform index d80cd612df1f..c3592b374ad2 100644 --- a/arch/mips/pistachio/Platform +++ b/arch/mips/pistachio/Platform @@ -6,3 +6,4 @@ cflags-$(CONFIG_MACH_PISTACHIO) += \ -I$(srctree)/arch/mips/include/asm/mach-pistachio load-$(CONFIG_MACH_PISTACHIO) += 0xffffffff80400000 zload-$(CONFIG_MACH_PISTACHIO) += 0xffffffff81000000 +all-$(CONFIG_MACH_PISTACHIO) := uImage.gz diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h index 933423fa5144..b0db61188a61 100644 --- a/arch/parisc/math-emu/cnv_float.h +++ b/arch/parisc/math-emu/cnv_float.h @@ -60,19 +60,19 @@ ((exponent < (SGL_P - 1)) ? \ (Sall(sgl_value) << (SGL_EXP_LENGTH + 1 + exponent)) : FALSE) -#define Int_isinexact_to_sgl(int_value) (int_value << 33 - SGL_EXP_LENGTH) +#define Int_isinexact_to_sgl(int_value) ((int_value << 33 - SGL_EXP_LENGTH) != 0) #define Sgl_roundnearest_from_int(int_value,sgl_value) \ if (int_value & 1<<(SGL_EXP_LENGTH - 2)) /* round bit */ \ - if ((int_value << 34 - SGL_EXP_LENGTH) || Slow(sgl_value)) \ + if (((int_value << 34 - SGL_EXP_LENGTH) != 0) || Slow(sgl_value)) \ Sall(sgl_value)++ #define Dint_isinexact_to_sgl(dint_valueA,dint_valueB) \ - ((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) || Dintp2(dint_valueB)) + (((Dintp1(dint_valueA) << 33 - SGL_EXP_LENGTH) != 0) || Dintp2(dint_valueB)) #define Sgl_roundnearest_from_dint(dint_valueA,dint_valueB,sgl_value) \ if (Dintp1(dint_valueA) & 1<<(SGL_EXP_LENGTH - 2)) \ - if ((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) || \ + if (((Dintp1(dint_valueA) << 34 - SGL_EXP_LENGTH) != 0) || \ Dintp2(dint_valueB) || Slow(sgl_value)) Sall(sgl_value)++ #define Dint_isinexact_to_dbl(dint_value) \ diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c index 9d9f6f334d3c..3da3e2b1b51b 100644 --- a/arch/powerpc/boot/addnote.c +++ b/arch/powerpc/boot/addnote.c @@ -223,7 +223,11 @@ main(int ac, char **av) PUT_16(E_PHNUM, np + 2); /* write back */ - lseek(fd, (long) 0, SEEK_SET); + i = lseek(fd, (long) 0, SEEK_SET); + if (i < 0) { + perror("lseek"); + exit(1); + } i = write(fd, buf, n); if (i < 0) { perror("write"); diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 5e12e19940e2..defa553fe823 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h @@ -271,6 +271,7 @@ struct kvm_arch { #ifdef CONFIG_PPC_BOOK3S_64 struct list_head spapr_tce_tables; struct list_head rtas_tokens; + struct mutex rtas_token_lock; DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); #endif #ifdef CONFIG_KVM_MPIC diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 48e8f1f14872..b7067590f15c 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -261,6 +261,7 @@ #define PPC_INST_MULLI 0x1c000000 #define PPC_INST_DIVWU 0x7c000396 #define PPC_INST_DIVD 0x7c0003d2 +#define PPC_INST_DIVDU 0x7c000392 #define PPC_INST_RLWINM 0x54000000 #define PPC_INST_RLWIMI 0x50000000 #define PPC_INST_RLDICL 0x78000000 diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index b6952dd23152..73c3c127d858 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c @@ -811,6 +811,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) #ifdef CONFIG_PPC64 INIT_LIST_HEAD_RCU(&kvm->arch.spapr_tce_tables); INIT_LIST_HEAD(&kvm->arch.rtas_tokens); + mutex_init(&kvm->arch.rtas_token_lock); #endif return kvm->arch.kvm_ops->init_vm(kvm); diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 0a2b247dbc6b..e840f943cd2c 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c @@ -374,12 +374,7 @@ static void kvmppc_dump_regs(struct kvm_vcpu *vcpu) static struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id) { - struct kvm_vcpu *ret; - - mutex_lock(&kvm->lock); - ret = kvm_get_vcpu_by_id(kvm, id); - mutex_unlock(&kvm->lock); - return ret; + return kvm_get_vcpu_by_id(kvm, id); } static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa) @@ -1098,7 +1093,6 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, struct kvmppc_vcore *vc = vcpu->arch.vcore; u64 mask; - mutex_lock(&kvm->lock); spin_lock(&vc->lock); /* * If ILE (interrupt little-endian) has changed, update the @@ -1132,7 +1126,6 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, mask &= 0xFFFFFFFF; vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); spin_unlock(&vc->lock); - mutex_unlock(&kvm->lock); } static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, diff --git a/arch/powerpc/kvm/book3s_rtas.c b/arch/powerpc/kvm/book3s_rtas.c index ef27fbd5d9c5..b1b2273d1f6d 100644 --- a/arch/powerpc/kvm/book3s_rtas.c +++ b/arch/powerpc/kvm/book3s_rtas.c @@ -133,7 +133,7 @@ static int rtas_token_undefine(struct kvm *kvm, char *name) { struct rtas_token_definition *d, *tmp; - lockdep_assert_held(&kvm->lock); + lockdep_assert_held(&kvm->arch.rtas_token_lock); list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) { if (rtas_name_matches(d->handler->name, name)) { @@ -154,7 +154,7 @@ static int rtas_token_define(struct kvm *kvm, char *name, u64 token) bool found; int i; - lockdep_assert_held(&kvm->lock); + lockdep_assert_held(&kvm->arch.rtas_token_lock); list_for_each_entry(d, &kvm->arch.rtas_tokens, list) { if (d->token == token) @@ -193,14 +193,14 @@ int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp) if (copy_from_user(&args, argp, sizeof(args))) return -EFAULT; - mutex_lock(&kvm->lock); + mutex_lock(&kvm->arch.rtas_token_lock); if (args.token) rc = rtas_token_define(kvm, args.name, args.token); else rc = rtas_token_undefine(kvm, args.name); - mutex_unlock(&kvm->lock); + mutex_unlock(&kvm->arch.rtas_token_lock); return rc; } @@ -232,7 +232,7 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu) orig_rets = args.rets; args.rets = &args.args[be32_to_cpu(args.nargs)]; - mutex_lock(&vcpu->kvm->lock); + mutex_lock(&vcpu->kvm->arch.rtas_token_lock); rc = -ENOENT; list_for_each_entry(d, &vcpu->kvm->arch.rtas_tokens, list) { @@ -243,7 +243,7 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu) } } - mutex_unlock(&vcpu->kvm->lock); + mutex_unlock(&vcpu->kvm->arch.rtas_token_lock); if (rc == 0) { args.rets = orig_rets; @@ -269,8 +269,6 @@ void kvmppc_rtas_tokens_free(struct kvm *kvm) { struct rtas_token_definition *d, *tmp; - lockdep_assert_held(&kvm->lock); - list_for_each_entry_safe(d, tmp, &kvm->arch.rtas_tokens, list) { list_del(&d->list); kfree(d); diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 9cad2ed812ab..31e9064ba628 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c @@ -1574,6 +1574,9 @@ int start_topology_update(void) { int rc = 0; + if (!topology_updates_enabled) + return 0; + if (firmware_has_feature(FW_FEATURE_PRRN)) { if (!prrn_enabled) { prrn_enabled = 1; @@ -1603,6 +1606,9 @@ int stop_topology_update(void) { int rc = 0; + if (!topology_updates_enabled) + return 0; + if (prrn_enabled) { prrn_enabled = 0; #ifdef CONFIG_SMP @@ -1648,11 +1654,13 @@ static ssize_t topology_write(struct file *file, const char __user *buf, kbuf[read_len] = '\0'; - if (!strncmp(kbuf, "on", 2)) + if (!strncmp(kbuf, "on", 2)) { + topology_updates_enabled = true; start_topology_update(); - else if (!strncmp(kbuf, "off", 3)) + } else if (!strncmp(kbuf, "off", 3)) { stop_topology_update(); - else + topology_updates_enabled = false; + } else return -EINVAL; return count; @@ -1667,9 +1675,7 @@ static const struct file_operations topology_ops = { static int topology_update_init(void) { - /* Do not poll for changes if disabled at boot */ - if (topology_updates_enabled) - start_topology_update(); + start_topology_update(); if (!proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops)) return -ENOMEM; diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 7b1d1721a26a..83e5b255d142 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -116,7 +116,7 @@ ___PPC_RA(a) | IMM_L(i)) #define PPC_DIVWU(d, a, b) EMIT(PPC_INST_DIVWU | ___PPC_RT(d) | \ ___PPC_RA(a) | ___PPC_RB(b)) -#define PPC_DIVD(d, a, b) EMIT(PPC_INST_DIVD | ___PPC_RT(d) | \ +#define PPC_DIVDU(d, a, b) EMIT(PPC_INST_DIVDU | ___PPC_RT(d) | \ ___PPC_RA(a) | ___PPC_RB(b)) #define PPC_AND(d, a, b) EMIT(PPC_INST_AND | ___PPC_RA(d) | \ ___PPC_RS(a) | ___PPC_RB(b)) diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index e7d78f9156ce..9f0810cfe5f3 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -419,12 +419,12 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, PPC_LI(b2p[BPF_REG_0], 0); PPC_JMP(exit_addr); if (BPF_OP(code) == BPF_MOD) { - PPC_DIVD(b2p[TMP_REG_1], dst_reg, src_reg); + PPC_DIVDU(b2p[TMP_REG_1], dst_reg, src_reg); PPC_MULD(b2p[TMP_REG_1], src_reg, b2p[TMP_REG_1]); PPC_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]); } else - PPC_DIVD(dst_reg, dst_reg, src_reg); + PPC_DIVDU(dst_reg, dst_reg, src_reg); break; case BPF_ALU | BPF_MOD | BPF_K: /* (u32) dst %= (u32) imm */ case BPF_ALU | BPF_DIV | BPF_K: /* (u32) dst /= (u32) imm */ @@ -452,7 +452,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, break; case BPF_ALU64: if (BPF_OP(code) == BPF_MOD) { - PPC_DIVD(b2p[TMP_REG_2], dst_reg, + PPC_DIVDU(b2p[TMP_REG_2], dst_reg, b2p[TMP_REG_1]); PPC_MULD(b2p[TMP_REG_1], b2p[TMP_REG_1], @@ -460,7 +460,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, PPC_SUB(dst_reg, dst_reg, b2p[TMP_REG_1]); } else - PPC_DIVD(dst_reg, dst_reg, + PPC_DIVDU(dst_reg, dst_reg, b2p[TMP_REG_1]); break; } diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index 771edffa2d40..ba49ae6625f1 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c @@ -1800,6 +1800,7 @@ static int power_pmu_event_init(struct perf_event *event) int n; int err; struct cpu_hw_events *cpuhw; + u64 bhrb_filter; if (!ppmu) return -ENOENT; @@ -1896,13 +1897,14 @@ static int power_pmu_event_init(struct perf_event *event) err = power_check_constraints(cpuhw, events, cflags, n + 1); if (has_branch_stack(event)) { - cpuhw->bhrb_filter = ppmu->bhrb_filter_map( + bhrb_filter = ppmu->bhrb_filter_map( event->attr.branch_sample_type); - if (cpuhw->bhrb_filter == -1) { + if (bhrb_filter == -1) { put_cpu_var(cpu_hw_events); return -EOPNOTSUPP; } + cpuhw->bhrb_filter = bhrb_filter; } put_cpu_var(cpu_hw_events); diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index ab830d106ec5..5fbd9bdefa4e 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c @@ -29,6 +29,7 @@ enum { #define POWER8_MMCRA_IFM1 0x0000000040000000UL #define POWER8_MMCRA_IFM2 0x0000000080000000UL #define POWER8_MMCRA_IFM3 0x00000000C0000000UL +#define POWER8_MMCRA_BHRB_MASK 0x00000000C0000000UL /* Table of alternatives, sorted by column 0 */ static const unsigned int event_alternatives[][MAX_ALT] = { @@ -262,6 +263,8 @@ static u64 power8_bhrb_filter_map(u64 branch_sample_type) static void power8_config_bhrb(u64 pmu_bhrb_filter) { + pmu_bhrb_filter &= POWER8_MMCRA_BHRB_MASK; + /* Enable BHRB filter in PMU */ mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter)); } diff --git a/arch/powerpc/perf/power9-pmu.c b/arch/powerpc/perf/power9-pmu.c index 9abcd8f65504..c396d5e5098c 100644 --- a/arch/powerpc/perf/power9-pmu.c +++ b/arch/powerpc/perf/power9-pmu.c @@ -30,6 +30,7 @@ enum { #define POWER9_MMCRA_IFM1 0x0000000040000000UL #define POWER9_MMCRA_IFM2 0x0000000080000000UL #define POWER9_MMCRA_IFM3 0x00000000C0000000UL +#define POWER9_MMCRA_BHRB_MASK 0x00000000C0000000UL GENERIC_EVENT_ATTR(cpu-cycles, PM_CYC); GENERIC_EVENT_ATTR(stalled-cycles-frontend, PM_ICT_NOSLOT_CYC); @@ -177,6 +178,8 @@ static u64 power9_bhrb_filter_map(u64 branch_sample_type) static void power9_config_bhrb(u64 pmu_bhrb_filter) { + pmu_bhrb_filter &= POWER9_MMCRA_BHRB_MASK; + /* Enable BHRB filter in PMU */ mtspr(SPRN_MMCRA, (mfspr(SPRN_MMCRA) | pmu_bhrb_filter)); } diff --git a/arch/s390/include/asm/facility.h b/arch/s390/include/asm/facility.h index 5811e7849a2e..1df70a73dc5c 100644 --- a/arch/s390/include/asm/facility.h +++ b/arch/s390/include/asm/facility.h @@ -61,6 +61,18 @@ static inline int test_facility(unsigned long nr) return __test_facility(nr, &S390_lowcore.stfle_fac_list); } +static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) +{ + register unsigned long reg0 asm("0") = size - 1; + + asm volatile( + ".insn s,0xb2b00000,0(%1)" /* stfle */ + : "+d" (reg0) + : "a" (stfle_fac_list) + : "memory", "cc"); + return reg0; +} + /** * stfle - Store facility list extended * @stfle_fac_list: array where facility list can be stored @@ -78,13 +90,8 @@ static inline void stfle(u64 *stfle_fac_list, int size) memcpy(stfle_fac_list, &S390_lowcore.stfl_fac_list, 4); if (S390_lowcore.stfl_fac_list & 0x01000000) { /* More facility bits available with stfle */ - register unsigned long reg0 asm("0") = size - 1; - - asm volatile(".insn s,0xb2b00000,0(%1)" /* stfle */ - : "+d" (reg0) - : "a" (stfle_fac_list) - : "memory", "cc"); - nr = (reg0 + 1) * 8; /* # bytes stored by stfle */ + nr = __stfle_asm(stfle_fac_list, size); + nr = min_t(unsigned long, (nr + 1) * 8, size * 8); } memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); preempt_enable(); diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 2032ab81b2d7..07f571900676 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -3288,21 +3288,28 @@ void kvm_arch_commit_memory_region(struct kvm *kvm, const struct kvm_memory_slot *new, enum kvm_mr_change change) { - int rc; - - /* If the basics of the memslot do not change, we do not want - * to update the gmap. Every update causes several unnecessary - * segment translation exceptions. This is usually handled just - * fine by the normal fault handler + gmap, but it will also - * cause faults on the prefix page of running guest CPUs. - */ - if (old->userspace_addr == mem->userspace_addr && - old->base_gfn * PAGE_SIZE == mem->guest_phys_addr && - old->npages * PAGE_SIZE == mem->memory_size) - return; + int rc = 0; - rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr, - mem->guest_phys_addr, mem->memory_size); + switch (change) { + case KVM_MR_DELETE: + rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE, + old->npages * PAGE_SIZE); + break; + case KVM_MR_MOVE: + rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE, + old->npages * PAGE_SIZE); + if (rc) + break; + /* FALLTHROUGH */ + case KVM_MR_CREATE: + rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr, + mem->guest_phys_addr, mem->memory_size); + break; + case KVM_MR_FLAGS_ONLY: + break; + default: + WARN(1, "Unknown KVM MR CHANGE: %d\n", change); + } if (rc) pr_warn("failed to commit memory region\n"); return; diff --git a/arch/sparc/include/asm/bug.h b/arch/sparc/include/asm/bug.h index eaa8f8d38125..fa85cac0285c 100644 --- a/arch/sparc/include/asm/bug.h +++ b/arch/sparc/include/asm/bug.h @@ -8,10 +8,14 @@ void do_BUG(const char *file, int line); #define BUG() do { \ do_BUG(__FILE__, __LINE__); \ + barrier_before_unreachable(); \ __builtin_trap(); \ } while (0) #else -#define BUG() __builtin_trap() +#define BUG() do { \ + barrier_before_unreachable(); \ + __builtin_trap(); \ +} while (0) #endif #define HAVE_ARCH_BUG diff --git a/arch/sparc/kernel/perf_event.c b/arch/sparc/kernel/perf_event.c index 71e7f77f6776..84a80cd004eb 100644 --- a/arch/sparc/kernel/perf_event.c +++ b/arch/sparc/kernel/perf_event.c @@ -889,6 +889,10 @@ static int sparc_perf_event_set_period(struct perf_event *event, s64 period = hwc->sample_period; int ret = 0; + /* The period may have been changed by PERF_EVENT_IOC_PERIOD */ + if (unlikely(period != hwc->last_period)) + left = period - (hwc->last_period - left); + if (unlikely(left <= -period)) { left = period; local64_set(&hwc->period_left, left); diff --git a/arch/sparc/mm/ultra.S b/arch/sparc/mm/ultra.S index fcf4d27a38fb..e09f7b440b8c 100644 --- a/arch/sparc/mm/ultra.S +++ b/arch/sparc/mm/ultra.S @@ -586,7 +586,7 @@ xcall_flush_tlb_kernel_range: /* 44 insns */ sub %g7, %g1, %g3 srlx %g3, 18, %g2 brnz,pn %g2, 2f - add %g2, 1, %g2 + sethi %hi(PAGE_SIZE), %g2 sub %g3, %g2, %g3 or %g1, 0x20, %g1 ! Nucleus 1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP @@ -750,7 +750,7 @@ __cheetah_xcall_flush_tlb_kernel_range: /* 44 insns */ sub %g7, %g1, %g3 srlx %g3, 18, %g2 brnz,pn %g2, 2f - add %g2, 1, %g2 + sethi %hi(PAGE_SIZE), %g2 sub %g3, %g2, %g3 or %g1, 0x20, %g1 ! Nucleus 1: stxa %g0, [%g1 + %g3] ASI_DMMU_DEMAP diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 25c23666d592..040e3efdc9a6 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -56,7 +56,7 @@ static int itimer_one_shot(struct clock_event_device *evt) static struct clock_event_device timer_clockevent = { .name = "posix-timer", .rating = 250, - .cpumask = cpu_all_mask, + .cpumask = cpu_possible_mask, .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, .set_state_shutdown = itimer_shutdown, diff --git a/arch/x86/Makefile b/arch/x86/Makefile index 93b170ea2480..f20c83a6393d 100644 --- a/arch/x86/Makefile +++ b/arch/x86/Makefile @@ -47,7 +47,7 @@ export REALMODE_CFLAGS export BITS ifdef CONFIG_X86_NEED_RELOCS - LDFLAGS_vmlinux := --emit-relocs + LDFLAGS_vmlinux := --emit-relocs --discard-none endif # diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c index cb8178a2783a..e98e238d3775 100644 --- a/arch/x86/events/intel/core.c +++ b/arch/x86/events/intel/core.c @@ -2867,7 +2867,7 @@ static int intel_pmu_hw_config(struct perf_event *event) return ret; if (event->attr.precise_ip) { - if (!(event->attr.freq || event->attr.wakeup_events)) { + if (!(event->attr.freq || (event->attr.wakeup_events && !event->attr.watermark))) { event->hw.flags |= PERF_X86_EVENT_AUTO_RELOAD; if (!(event->attr.sample_type & ~intel_pmu_free_running_flags(event))) diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c index f26e26e4d84f..ad31c01f810f 100644 --- a/arch/x86/events/intel/ds.c +++ b/arch/x86/events/intel/ds.c @@ -655,7 +655,7 @@ struct event_constraint intel_core2_pebs_event_constraints[] = { INTEL_FLAGS_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */ INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x01), EVENT_CONSTRAINT_END }; @@ -664,7 +664,7 @@ struct event_constraint intel_atom_pebs_event_constraints[] = { INTEL_FLAGS_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */ INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0x1), /* MEM_LOAD_RETIRED.* */ /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x01), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x01), /* Allow all events as PEBS with no flags */ INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), EVENT_CONSTRAINT_END @@ -672,7 +672,7 @@ struct event_constraint intel_atom_pebs_event_constraints[] = { struct event_constraint intel_slm_pebs_event_constraints[] = { /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x1), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x1), /* Allow all events as PEBS with no flags */ INTEL_ALL_EVENT_CONSTRAINT(0, 0x1), EVENT_CONSTRAINT_END @@ -697,7 +697,7 @@ struct event_constraint intel_nehalem_pebs_event_constraints[] = { INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */ INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */ /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x0f), EVENT_CONSTRAINT_END }; @@ -714,7 +714,7 @@ struct event_constraint intel_westmere_pebs_event_constraints[] = { INTEL_FLAGS_EVENT_CONSTRAINT(0xcb, 0xf), /* MEM_LOAD_RETIRED.* */ INTEL_FLAGS_EVENT_CONSTRAINT(0xf7, 0xf), /* FP_ASSIST.* */ /* INST_RETIRED.ANY_P, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x0f), EVENT_CONSTRAINT_END }; @@ -723,7 +723,7 @@ struct event_constraint intel_snb_pebs_event_constraints[] = { INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ @@ -738,9 +738,9 @@ struct event_constraint intel_ivb_pebs_event_constraints[] = { INTEL_PLD_CONSTRAINT(0x01cd, 0x8), /* MEM_TRANS_RETIRED.LAT_ABOVE_THR */ INTEL_PST_CONSTRAINT(0x02cd, 0x8), /* MEM_TRANS_RETIRED.PRECISE_STORES */ /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), INTEL_EXCLEVT_CONSTRAINT(0xd0, 0xf), /* MEM_UOP_RETIRED.* */ INTEL_EXCLEVT_CONSTRAINT(0xd1, 0xf), /* MEM_LOAD_UOPS_RETIRED.* */ INTEL_EXCLEVT_CONSTRAINT(0xd2, 0xf), /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */ @@ -754,9 +754,9 @@ struct event_constraint intel_hsw_pebs_event_constraints[] = { INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */ /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_XLD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ @@ -777,9 +777,9 @@ struct event_constraint intel_bdw_pebs_event_constraints[] = { INTEL_FLAGS_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */ INTEL_PLD_CONSTRAINT(0x01cd, 0xf), /* MEM_TRANS_RETIRED.* */ /* UOPS_RETIRED.ALL, inv=1, cmask=16 (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c2, 0xf), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c2, 0xf), /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_NA(0x01c2, 0xf), /* UOPS_RETIRED.ALL */ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_UOPS_RETIRED.STLB_MISS_LOADS */ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x21d0, 0xf), /* MEM_UOPS_RETIRED.LOCK_LOADS */ @@ -800,9 +800,9 @@ struct event_constraint intel_bdw_pebs_event_constraints[] = { struct event_constraint intel_skl_pebs_event_constraints[] = { INTEL_FLAGS_UEVENT_CONSTRAINT(0x1c0, 0x2), /* INST_RETIRED.PREC_DIST */ /* INST_RETIRED.PREC_DIST, inv=1, cmask=16 (cycles:ppp). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108001c0, 0x2), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108001c0, 0x2), /* INST_RETIRED.TOTAL_CYCLES_PS (inv=1, cmask=16) (cycles:p). */ - INTEL_FLAGS_EVENT_CONSTRAINT(0x108000c0, 0x0f), + INTEL_FLAGS_UEVENT_CONSTRAINT(0x108000c0, 0x0f), INTEL_PLD_CONSTRAINT(0x1cd, 0xf), /* MEM_TRANS_RETIRED.* */ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_LD(0x11d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_LOADS */ INTEL_FLAGS_UEVENT_CONSTRAINT_DATALA_ST(0x12d0, 0xf), /* MEM_INST_RETIRED.STLB_MISS_STORES */ diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c index cb13c0564ea7..9978ea4382bf 100644 --- a/arch/x86/ia32/ia32_signal.c +++ b/arch/x86/ia32/ia32_signal.c @@ -60,9 +60,8 @@ } while (0) #define RELOAD_SEG(seg) { \ - unsigned int pre = GET_SEG(seg); \ + unsigned int pre = (seg) | 3; \ unsigned int cur = get_user_seg(seg); \ - pre |= 3; \ if (pre != cur) \ set_user_seg(seg, pre); \ } @@ -71,6 +70,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_32 __user *sc) { unsigned int tmpflags, err = 0; + u16 gs, fs, es, ds; void __user *buf; u32 tmp; @@ -78,16 +78,10 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, current->restart_block.fn = do_no_restart_syscall; get_user_try { - /* - * Reload fs and gs if they have changed in the signal - * handler. This does not handle long fs/gs base changes in - * the handler, but does not clobber them at least in the - * normal case. - */ - RELOAD_SEG(gs); - RELOAD_SEG(fs); - RELOAD_SEG(ds); - RELOAD_SEG(es); + gs = GET_SEG(gs); + fs = GET_SEG(fs); + ds = GET_SEG(ds); + es = GET_SEG(es); COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx); COPY(dx); COPY(cx); COPY(ip); COPY(ax); @@ -105,6 +99,17 @@ static int ia32_restore_sigcontext(struct pt_regs *regs, buf = compat_ptr(tmp); } get_user_catch(err); + /* + * Reload fs and gs if they have changed in the signal + * handler. This does not handle long fs/gs base changes in + * the handler, but does not clobber them at least in the + * normal case. + */ + RELOAD_SEG(gs); + RELOAD_SEG(fs); + RELOAD_SEG(ds); + RELOAD_SEG(es); + err |= fpu__restore_sig(buf, 1); force_iret(); diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c index be6d0543e626..52a65f14db06 100644 --- a/arch/x86/kernel/cpu/amd.c +++ b/arch/x86/kernel/cpu/amd.c @@ -766,8 +766,11 @@ static void init_amd_zn(struct cpuinfo_x86 *c) { set_cpu_cap(c, X86_FEATURE_ZEN); - /* Fix erratum 1076: CPB feature bit not being set in CPUID. */ - if (!cpu_has(c, X86_FEATURE_CPB)) + /* + * Fix erratum 1076: CPB feature bit not being set in CPUID. + * Always set it, except when running under a hypervisor. + */ + if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_CPB)) set_cpu_cap(c, X86_FEATURE_CPB); } diff --git a/arch/x86/kernel/cpu/bugs.c b/arch/x86/kernel/cpu/bugs.c index 16970c39baea..07a6c1fa173b 100644 --- a/arch/x86/kernel/cpu/bugs.c +++ b/arch/x86/kernel/cpu/bugs.c @@ -829,6 +829,16 @@ static enum ssb_mitigation __init __ssb_select_mitigation(void) } /* + * If SSBD is controlled by the SPEC_CTRL MSR, then set the proper + * bit in the mask to allow guests to use the mitigation even in the + * case where the host does not enable it. + */ + if (static_cpu_has(X86_FEATURE_SPEC_CTRL_SSBD) || + static_cpu_has(X86_FEATURE_AMD_SSBD)) { + x86_spec_ctrl_mask |= SPEC_CTRL_SSBD; + } + + /* * We have three CPU feature flags that are in play here: * - X86_BUG_SPEC_STORE_BYPASS - CPU is susceptible. * - X86_FEATURE_SSBD - CPU is able to turn off speculative store bypass @@ -845,7 +855,6 @@ static enum ssb_mitigation __init __ssb_select_mitigation(void) x86_amd_ssb_disable(); } else { x86_spec_ctrl_base |= SPEC_CTRL_SSBD; - x86_spec_ctrl_mask |= SPEC_CTRL_SSBD; wrmsrl(MSR_IA32_SPEC_CTRL, x86_spec_ctrl_base); } } diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d9ad49ca3cbe..e348bee411e3 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -673,20 +673,50 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t *b) barrier(); m.status = mce_rdmsrl(msr_ops.status(i)); + + /* If this entry is not valid, ignore it */ if (!(m.status & MCI_STATUS_VAL)) continue; /* - * Uncorrected or signalled events are handled by the exception - * handler when it is enabled, so don't process those here. - * - * TBD do the same check for MCI_STATUS_EN here? + * If we are logging everything (at CPU online) or this + * is a corrected error, then we must log it. */ - if (!(flags & MCP_UC) && - (m.status & (mca_cfg.ser ? MCI_STATUS_S : MCI_STATUS_UC))) - continue; + if ((flags & MCP_UC) || !(m.status & MCI_STATUS_UC)) + goto log_it; + + /* + * Newer Intel systems that support software error + * recovery need to make additional checks. Other + * CPUs should skip over uncorrected errors, but log + * everything else. + */ + if (!mca_cfg.ser) { + if (m.status & MCI_STATUS_UC) + continue; + goto log_it; + } + + /* Log "not enabled" (speculative) errors */ + if (!(m.status & MCI_STATUS_EN)) + goto log_it; + + /* + * Log UCNA (SDM: 15.6.3 "UCR Error Classification") + * UC == 1 && PCC == 0 && S == 0 + */ + if (!(m.status & MCI_STATUS_PCC) && !(m.status & MCI_STATUS_S)) + goto log_it; + + /* + * Skip anything else. Presumption is that our read of this + * bank is racing with a machine check. Leave the log alone + * for do_machine_check() to deal with it. + */ + continue; +log_it: error_seen = true; mce_read_aux(&m, i); diff --git a/arch/x86/kernel/irq_64.c b/arch/x86/kernel/irq_64.c index bcd1b82c86e8..005e9a77a664 100644 --- a/arch/x86/kernel/irq_64.c +++ b/arch/x86/kernel/irq_64.c @@ -25,9 +25,18 @@ int sysctl_panic_on_stackoverflow; /* * Probabilistic stack overflow check: * - * Only check the stack in process context, because everything else - * runs on the big interrupt stacks. Checking reliably is too expensive, - * so we just check from interrupts. + * Regular device interrupts can enter on the following stacks: + * + * - User stack + * + * - Kernel task stack + * + * - Interrupt stack if a device driver reenables interrupts + * which should only happen in really old drivers. + * + * - Debug IST stack + * + * All other contexts are invalid. */ static inline void stack_overflow_check(struct pt_regs *regs) { @@ -52,8 +61,8 @@ static inline void stack_overflow_check(struct pt_regs *regs) return; oist = this_cpu_ptr(&orig_ist); - estack_top = (u64)oist->ist[0] - EXCEPTION_STKSZ + STACK_TOP_MARGIN; - estack_bottom = (u64)oist->ist[N_EXCEPTION_STACKS - 1]; + estack_bottom = (u64)oist->ist[DEBUG_STACK]; + estack_top = estack_bottom - DEBUG_STKSZ + STACK_TOP_MARGIN; if (regs->sp >= estack_top && regs->sp <= estack_bottom) return; diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index e497d374412a..8d20fb09722c 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -23,6 +23,7 @@ #include <linux/rcupdate.h> #include <linux/export.h> #include <linux/context_tracking.h> +#include <linux/nospec.h> #include <asm/uaccess.h> #include <asm/pgtable.h> @@ -650,9 +651,11 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) { struct thread_struct *thread = &tsk->thread; unsigned long val = 0; + int index = n; if (n < HBP_NUM) { - struct perf_event *bp = thread->ptrace_bps[n]; + struct perf_event *bp = thread->ptrace_bps[index]; + index = array_index_nospec(index, HBP_NUM); if (bp) val = bp->hw.info.address; diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index b1a5d252d482..ca010dfb9682 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c @@ -129,16 +129,6 @@ static int restore_sigcontext(struct pt_regs *regs, COPY_SEG_CPL3(cs); COPY_SEG_CPL3(ss); -#ifdef CONFIG_X86_64 - /* - * Fix up SS if needed for the benefit of old DOSEMU and - * CRIU. - */ - if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && - user_64bit_mode(regs))) - force_valid_ss(regs); -#endif - get_user_ex(tmpflags, &sc->flags); regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS); regs->orig_ax = -1; /* disable syscall checks */ @@ -147,6 +137,15 @@ static int restore_sigcontext(struct pt_regs *regs, buf = (void __user *)buf_val; } get_user_catch(err); +#ifdef CONFIG_X86_64 + /* + * Fix up SS if needed for the benefit of old DOSEMU and + * CRIU. + */ + if (unlikely(!(uc_flags & UC_STRICT_RESTORE_SS) && user_64bit_mode(regs))) + force_valid_ss(regs); +#endif + err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32)); force_iret(); @@ -458,6 +457,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, { struct rt_sigframe __user *frame; void __user *fp = NULL; + unsigned long uc_flags; int err = 0; frame = get_sigframe(&ksig->ka, regs, sizeof(struct rt_sigframe), &fp); @@ -470,9 +470,11 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig, return -EFAULT; } + uc_flags = frame_uc_flags(regs); + put_user_try { /* Create the ucontext. */ - put_user_ex(frame_uc_flags(regs), &frame->uc.uc_flags); + put_user_ex(uc_flags, &frame->uc.uc_flags); put_user_ex(0, &frame->uc.uc_link); save_altstack_ex(&frame->uc.uc_stack, regs->sp); @@ -538,6 +540,7 @@ static int x32_setup_rt_frame(struct ksignal *ksig, { #ifdef CONFIG_X86_X32_ABI struct rt_sigframe_x32 __user *frame; + unsigned long uc_flags; void __user *restorer; int err = 0; void __user *fpstate = NULL; @@ -552,9 +555,11 @@ static int x32_setup_rt_frame(struct ksignal *ksig, return -EFAULT; } + uc_flags = frame_uc_flags(regs); + put_user_try { /* Create the ucontext. */ - put_user_ex(frame_uc_flags(regs), &frame->uc.uc_flags); + put_user_ex(uc_flags, &frame->uc.uc_flags); put_user_ex(0, &frame->uc.uc_link); compat_save_altstack_ex(&frame->uc.uc_stack, regs->sp); put_user_ex(0, &frame->uc.uc__pad0); diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index 9692a5e9fdab..b95693a73f12 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c @@ -4,6 +4,7 @@ #include <linux/user.h> #include <linux/regset.h> #include <linux/syscalls.h> +#include <linux/nospec.h> #include <asm/uaccess.h> #include <asm/desc.h> @@ -219,6 +220,7 @@ int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *u_info) { struct user_desc info; + int index; if (idx == -1 && get_user(idx, &u_info->entry_number)) return -EFAULT; @@ -226,8 +228,11 @@ int do_get_thread_area(struct task_struct *p, int idx, if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) return -EINVAL; - fill_user_desc(&info, idx, - &p->thread.tls_array[idx - GDT_ENTRY_TLS_MIN]); + index = idx - GDT_ENTRY_TLS_MIN; + index = array_index_nospec(index, + GDT_ENTRY_TLS_MAX - GDT_ENTRY_TLS_MIN + 1); + + fill_user_desc(&info, idx, &p->thread.tls_array[index]); if (copy_to_user(u_info, &info, sizeof(info))) return -EFAULT; diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c index c8630569e392..cf32533225bb 100644 --- a/arch/x86/kvm/lapic.c +++ b/arch/x86/kvm/lapic.c @@ -1992,7 +1992,7 @@ int kvm_apic_has_interrupt(struct kvm_vcpu *vcpu) struct kvm_lapic *apic = vcpu->arch.apic; int highest_irr; - if (!apic_enabled(apic)) + if (!kvm_apic_hw_enabled(apic)) return -1; apic_update_ppr(apic); diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c index 5ab4a364348e..2729131fe9bf 100644 --- a/arch/x86/kvm/pmu_intel.c +++ b/arch/x86/kvm/pmu_intel.c @@ -235,11 +235,14 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) } break; default: - if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0)) || - (pmc = get_fixed_pmc(pmu, msr))) { - if (!msr_info->host_initiated) - data = (s64)(s32)data; - pmc->counter += data - pmc_read_counter(pmc); + if ((pmc = get_gp_pmc(pmu, msr, MSR_IA32_PERFCTR0))) { + if (msr_info->host_initiated) + pmc->counter = data; + else + pmc->counter = (s32)data; + return 0; + } else if ((pmc = get_fixed_pmc(pmu, msr))) { + pmc->counter = data; return 0; } else if ((pmc = get_gp_pmc(pmu, msr, MSR_P6_EVNTSEL0))) { if (data == pmc->eventsel) diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 9338136a6a23..f7a7b98b3271 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c @@ -1518,7 +1518,11 @@ static void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (!kvm_vcpu_apicv_active(vcpu)) return; - if (WARN_ON(h_physical_id >= AVIC_MAX_PHYSICAL_ID_COUNT)) + /* + * Since the host physical APIC id is 8 bits, + * we can support host APIC ID upto 255. + */ + if (WARN_ON(h_physical_id > AVIC_PHYSICAL_ID_ENTRY_HOST_PHYSICAL_ID_MASK)) return; entry = READ_ONCE(*(svm->avic_physical_id_cache)); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 1f32c4e32a00..8b06700d1676 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -1109,7 +1109,7 @@ static int set_efer(struct kvm_vcpu *vcpu, struct msr_data *msr_info) u64 efer = msr_info->data; if (efer & efer_reserved_bits) - return false; + return 1; if (!msr_info->host_initiated) { if (!__kvm_valid_efer(vcpu, efer)) @@ -1365,7 +1365,7 @@ static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale) vcpu->arch.tsc_always_catchup = 1; return 0; } else { - WARN(1, "user requested TSC rate below hardware speed\n"); + pr_warn_ratelimited("user requested TSC rate below hardware speed\n"); return -1; } } @@ -1375,8 +1375,8 @@ static int set_tsc_khz(struct kvm_vcpu *vcpu, u32 user_tsc_khz, bool scale) user_tsc_khz, tsc_khz); if (ratio == 0 || ratio >= kvm_max_tsc_scaling_ratio) { - WARN_ONCE(1, "Invalid TSC scaling ratio - virtual-tsc-khz=%u\n", - user_tsc_khz); + pr_warn_ratelimited("Invalid TSC scaling ratio - virtual-tsc-khz=%u\n", + user_tsc_khz); return -1; } diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index f7f8aa648c2e..bc33d54d1f63 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -430,8 +430,6 @@ static noinline int vmalloc_fault(unsigned long address) if (!(address >= VMALLOC_START && address < VMALLOC_END)) return -1; - WARN_ON_ONCE(in_nmi()); - /* * Copy kernel mappings over when needed. This can also * happen within a race in page table update. In the later diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 9bd115484745..5f0e596b0519 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1117,6 +1117,8 @@ static struct dmi_system_id __initdata pciirq_dmi_table[] = { void __init pcibios_irq_init(void) { + struct irq_routing_table *rtable = NULL; + DBG(KERN_DEBUG "PCI: IRQ init\n"); if (raw_pci_ops == NULL) @@ -1127,8 +1129,10 @@ void __init pcibios_irq_init(void) pirq_table = pirq_find_routing_table(); #ifdef CONFIG_PCI_BIOS - if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) + if (!pirq_table && (pci_probe & PCI_BIOS_IRQ_SCAN)) { pirq_table = pcibios_get_irq_routing_table(); + rtable = pirq_table; + } #endif if (pirq_table) { pirq_peer_trick(); @@ -1143,8 +1147,10 @@ void __init pcibios_irq_init(void) * If we're using the I/O APIC, avoid using the PCI IRQ * routing table */ - if (io_apic_assign_pci_irqs) + if (io_apic_assign_pci_irqs) { + kfree(rtable); pirq_table = NULL; + } } x86_init.pci.fixup_irqs(); diff --git a/arch/x86/power/cpu.c b/arch/x86/power/cpu.c index 054e27671df9..29dc59baf0c2 100644 --- a/arch/x86/power/cpu.c +++ b/arch/x86/power/cpu.c @@ -292,7 +292,17 @@ int hibernate_resume_nonboot_cpu_disable(void) * address in its instruction pointer may not be possible to resolve * any more at that point (the page tables used by it previously may * have been overwritten by hibernate image data). + * + * First, make sure that we wake up all the potentially disabled SMT + * threads which have been initially brought up and then put into + * mwait/cpuidle sleep. + * Those will be put to proper (not interfering with hibernation + * resume) sleep afterwards, and the resumed kernel will decide itself + * what to do with them. */ + ret = cpuhp_smt_enable(); + if (ret) + return ret; smp_ops.play_dead = resume_play_dead; ret = disable_nonboot_cpus(); smp_ops.play_dead = play_dead; diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index fef485b789ca..6120046bb7dd 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c @@ -11,6 +11,7 @@ #include <linux/gfp.h> #include <linux/smp.h> #include <linux/suspend.h> +#include <linux/cpu.h> #include <asm/init.h> #include <asm/proto.h> @@ -218,3 +219,35 @@ int arch_hibernation_header_restore(void *addr) restore_cr3 = rdr->cr3; return (rdr->magic == RESTORE_MAGIC) ? 0 : -EINVAL; } + +int arch_resume_nosmt(void) +{ + int ret = 0; + /* + * We reached this while coming out of hibernation. This means + * that SMT siblings are sleeping in hlt, as mwait is not safe + * against control transition during resume (see comment in + * hibernate_resume_nonboot_cpu_disable()). + * + * If the resumed kernel has SMT disabled, we have to take all the + * SMT siblings out of hlt, and offline them again so that they + * end up in mwait proper. + * + * Called with hotplug disabled. + */ + cpu_hotplug_enable(); + if (cpu_smt_control == CPU_SMT_DISABLED || + cpu_smt_control == CPU_SMT_FORCE_DISABLED) { + enum cpuhp_smt_control old = cpu_smt_control; + + ret = cpuhp_smt_enable(); + if (ret) + goto out; + ret = cpuhp_smt_disable(old); + if (ret) + goto out; + } +out: + cpu_hotplug_disable(); + return ret; +} diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c index 1c5705481c69..c90a1727cd2c 100644 --- a/crypto/crypto_user.c +++ b/crypto/crypto_user.c @@ -55,6 +55,9 @@ static struct crypto_alg *crypto_alg_match(struct crypto_user_alg *p, int exact) list_for_each_entry(q, &crypto_alg_list, cra_list) { int match = 0; + if (crypto_is_larval(q)) + continue; + if ((q->cra_flags ^ p->cru_type) & p->cru_mask) continue; diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 6107c03f78da..edb108a66478 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -3227,6 +3227,7 @@ static void binder_transaction(struct binder_proc *proc, if (target_node && target_node->txn_security_ctx) { u32 secid; + size_t added_size; security_task_getsecid(proc->tsk, &secid); ret = security_secid_to_secctx(secid, &secctx, &secctx_sz); @@ -3236,7 +3237,15 @@ static void binder_transaction(struct binder_proc *proc, return_error_line = __LINE__; goto err_get_secctx_failed; } - extra_buffers_size += ALIGN(secctx_sz, sizeof(u64)); + added_size = ALIGN(secctx_sz, sizeof(u64)); + extra_buffers_size += added_size; + if (extra_buffers_size < added_size) { + /* integer overflow of extra_buffers_size */ + return_error = BR_FAILED_REPLY; + return_error_param = EINVAL; + return_error_line = __LINE__; + goto err_bad_extra_size; + } } trace_binder_transaction(reply, t, target_node); @@ -3585,6 +3594,7 @@ err_copy_data_failed: t->buffer->transaction = NULL; binder_alloc_free_buf(&target_proc->alloc, t->buffer); err_binder_alloc_buf_failed: +err_bad_extra_size: if (secctx) security_release_secctx(secctx, secctx_sz); err_get_secctx_failed: diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 34454b073b82..ce006afaf4ed 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -891,14 +891,13 @@ enum lru_status binder_alloc_free_page(struct list_head *item, index = page - alloc->pages; page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; + + mm = alloc->vma_vm_mm; + if (!mmget_not_zero(mm)) + goto err_mmget; + if (!down_write_trylock(&mm->mmap_sem)) + goto err_down_write_mmap_sem_failed; vma = alloc->vma; - if (vma) { - if (!mmget_not_zero(alloc->vma_vm_mm)) - goto err_mmget; - mm = alloc->vma_vm_mm; - if (!down_write_trylock(&mm->mmap_sem)) - goto err_down_write_mmap_sem_failed; - } list_lru_isolate(lru, item); spin_unlock(lock); @@ -909,10 +908,9 @@ enum lru_status binder_alloc_free_page(struct list_head *item, zap_page_range(vma, page_addr, PAGE_SIZE, NULL); trace_binder_unmap_user_end(alloc, index); - - up_write(&mm->mmap_sem); - mmput(mm); } + up_write(&mm->mmap_sem); + mmput(mm); trace_binder_unmap_kernel_start(alloc, index); diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 35be49f5791d..da1a987c622a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4355,9 +4355,12 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { { "ST3320[68]13AS", "SD1[5-9]", ATA_HORKAGE_NONCQ | ATA_HORKAGE_FIRMWARE_WARN }, - /* drives which fail FPDMA_AA activation (some may freeze afterwards) */ - { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA }, - { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA }, + /* drives which fail FPDMA_AA activation (some may freeze afterwards) + the ST disks also have LPM issues */ + { "ST1000LM024 HN-M101MBB", "2AR10001", ATA_HORKAGE_BROKEN_FPDMA_AA | + ATA_HORKAGE_NOLPM, }, + { "ST1000LM024 HN-M101MBB", "2BA30001", ATA_HORKAGE_BROKEN_FPDMA_AA | + ATA_HORKAGE_NOLPM, }, { "VB0250EAVER", "HPG7", ATA_HORKAGE_BROKEN_FPDMA_AA }, /* Blacklist entries taken from Silicon Image 3124/3132 diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 574d08f1673e..76373148385c 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1388,6 +1388,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) if (dev->power.syscore) goto Complete; + /* Avoid direct_complete to let wakeup_path propagate. */ + if (device_may_wakeup(dev) || dev->power.wakeup_path) + dev->power.direct_complete = false; + if (dev->power.direct_complete) { if (pm_runtime_status_suspended(dev)) { pm_runtime_disable(dev); diff --git a/drivers/bluetooth/bluetooth-power.c b/drivers/bluetooth/bluetooth-power.c index 650585c2ea44..272a83dc2cfd 100644 --- a/drivers/bluetooth/bluetooth-power.c +++ b/drivers/bluetooth/bluetooth-power.c @@ -676,8 +676,8 @@ static int bt_power_probe(struct platform_device *pdev) btpdev = pdev; if (of_id) { - if ((get_bt_reset_gpio_value() == BT_RESET_GPIO_HIGH_VAL) - && (strcmp(of_id->compatible, "qca,qca6174") == 0)) { + if ((strcmp(of_id->compatible, "qca,qca6174") == 0) && + (get_bt_reset_gpio_value() == BT_RESET_GPIO_HIGH_VAL)) { bluetooth_toggle_radio(pdev->dev.platform_data, 0); bluetooth_toggle_radio(pdev->dev.platform_data, 1); } diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index dea48e16f193..f62d96dcf636 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -240,6 +240,8 @@ struct smq_invoke_ctx { unsigned int *attrs; uint32_t *crc; uint64_t ctxid; + void *handle; + const void *ptr; }; struct fastrpc_ctx_lst { @@ -742,15 +744,14 @@ 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) { - unsigned long dma_attrs = 0; if (me->dev == NULL) { pr_err("failed to free remote heap allocation\n"); return; } if (map->phys) { - dma_attrs |= - DMA_ATTR_SKIP_ZEROING | DMA_ATTR_NO_KERNEL_MAPPING; + unsigned long dma_attrs = DMA_ATTR_SKIP_ZEROING | + DMA_ATTR_NO_KERNEL_MAPPING; dma_free_attrs(me->dev, map->size, (void *)map->va, (dma_addr_t)map->phys, dma_attrs); } @@ -2044,7 +2045,8 @@ static int fastrpc_internal_invoke(struct fastrpc_file *fl, uint32_t mode, if (err) goto bail; } - + if (ctx->handle) + glink_rx_done(ctx->handle, ctx->ptr, true); PERF(fl->profile, GET_COUNTER(perf_counter, PERF_INVARGS), if (!fl->sctx->smmu.coherent) inv_args(ctx); @@ -2448,29 +2450,34 @@ static int fastrpc_munmap_on_dsp_rh(struct fastrpc_file *fl, uint64_t phys, { int err = 0; struct fastrpc_apps *me = &gfa; + int tgid = 0; int destVM[1] = {VMID_HLOS}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; if (flags == ADSP_MMAP_HEAP_ADDR) { struct fastrpc_ioctl_invoke_crc ioctl; struct scm_desc desc = {0}; - remote_arg_t ra[1]; - int err = 0; + remote_arg_t ra[2]; + struct { uint8_t skey; } routargs; - ra[0].buf.pv = (void *)&routargs; - ra[0].buf.len = sizeof(routargs); + if (fl == NULL) + goto bail; + tgid = fl->tgid; + ra[0].buf.pv = (void *)&tgid; + ra[0].buf.len = sizeof(tgid); + ra[1].buf.pv = (void *)&routargs; + ra[1].buf.len = sizeof(routargs); ioctl.inv.handle = FASTRPC_STATIC_HANDLE_KERNEL; - ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1); + ioctl.inv.sc = REMOTE_SCALARS_MAKE(9, 1, 1); ioctl.inv.pra = ra; ioctl.fds = NULL; ioctl.attrs = NULL; ioctl.crc = NULL; - if (fl == NULL) - goto bail; + VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl, FASTRPC_MODE_PARALLEL, 1, &ioctl))); @@ -2883,11 +2890,13 @@ static void fastrpc_glink_notify_rx(void *handle, const void *priv, if (err) goto bail; + me->ctxtable[index]->handle = handle; + me->ctxtable[index]->ptr = ptr; + context_notify_user(me->ctxtable[index], rsp->retval); bail: if (err) pr_err("adsprpc: invalid response or context\n"); - glink_rx_done(handle, ptr, true); } static void fastrpc_glink_notify_state(void *handle, const void *priv, diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index 12bc3ac5032b..12c8bd91f239 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -2082,6 +2082,11 @@ static int diag_process_dci_pkt_rsp(unsigned char *buf, int len) if ((ret == DIAG_DCI_NO_ERROR && !common_cmd) || ret < 0) return ret; + reg_entry.cmd_code = 0; + reg_entry.subsys_id = 0; + reg_entry.cmd_code_hi = 0; + reg_entry.cmd_code_lo = 0; + if (header_len >= (sizeof(uint8_t))) reg_entry.cmd_code = header->cmd_code; if (header_len >= (2 * sizeof(uint8_t))) diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c index 560f0df41839..d99f984208b7 100644 --- a/drivers/char/diag/diagfwd_peripheral.c +++ b/drivers/char/diag/diagfwd_peripheral.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2019, 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 @@ -1436,9 +1436,6 @@ int diagfwd_channel_close(struct diagfwd_info *fwd_info) if (!fwd_info) return -EIO; - if (fwd_info->type == TYPE_CNTL) - flush_workqueue(driver->cntl_wq); - mutex_lock(&driver->diagfwd_channel_mutex[fwd_info->peripheral]); fwd_info->ch_open = 0; if (fwd_info && fwd_info->c_ops && fwd_info->c_ops->close) diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c index d7d73668b7b8..3451aba1784f 100644 --- a/drivers/char/diag/diagfwd_socket.c +++ b/drivers/char/diag/diagfwd_socket.c @@ -496,7 +496,7 @@ static void __socket_close_channel(struct diag_socket_info *info) if (!atomic_read(&info->opened)) return; - if ((bootup_req[info->peripheral] == PEPIPHERAL_SSR_UP) && + if ((bootup_req[info->peripheral] == PERIPHERAL_SSR_UP) && (info->port_type == PORT_TYPE_SERVER)) { DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: %s is up, stopping cleanup: bootup_req = %d\n", @@ -504,9 +504,10 @@ static void __socket_close_channel(struct diag_socket_info *info) return; } - memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc)); - diagfwd_channel_close(info->fwd_ctxt); - + if (info->type != TYPE_CNTL) { + memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc)); + diagfwd_channel_close(info->fwd_ctxt); + } atomic_set(&info->opened, 0); /* Don't close the server. Server should always remain open */ @@ -955,6 +956,7 @@ static int restart_notifier_cb(struct notifier_block *this, unsigned long code, void *_cmd) { struct restart_notifier_block *notifier; + struct diag_socket_info *info = NULL; notifier = container_of(this, struct restart_notifier_block, nb); @@ -964,22 +966,31 @@ static int restart_notifier_cb(struct notifier_block *this, unsigned long code, return NOTIFY_DONE; } - mutex_lock(&driver->diag_notifier_mutex); DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "%s: ssr for processor %d ('%s')\n", __func__, notifier->processor, notifier->name); + info = &socket_cntl[notifier->processor]; switch (code) { case SUBSYS_BEFORE_SHUTDOWN: DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: %s: SUBSYS_BEFORE_SHUTDOWN\n", __func__); - bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN; + mutex_lock(&driver->diag_notifier_mutex); + bootup_req[notifier->processor] = PERIPHERAL_SSR_DOWN; + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag: bootup_req[%s] = %d\n", + notifier->name, (int)bootup_req[notifier->processor]); + mutex_unlock(&driver->diag_notifier_mutex); break; case SUBSYS_AFTER_SHUTDOWN: DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: %s: SUBSYS_AFTER_SHUTDOWN\n", __func__); + mutex_lock(&driver->diag_notifier_mutex); + memset(&info->remote_addr, 0, sizeof(struct sockaddr_msm_ipc)); + diagfwd_channel_close(info->fwd_ctxt); + mutex_unlock(&driver->diag_notifier_mutex); break; case SUBSYS_BEFORE_POWERUP: @@ -990,11 +1001,20 @@ static int restart_notifier_cb(struct notifier_block *this, unsigned long code, case SUBSYS_AFTER_POWERUP: DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "diag: %s: SUBSYS_AFTER_POWERUP\n", __func__); + mutex_lock(&driver->diag_notifier_mutex); if (!bootup_req[notifier->processor]) { - bootup_req[notifier->processor] = PEPIPHERAL_SSR_DOWN; + bootup_req[notifier->processor] = PERIPHERAL_SSR_DOWN; + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag: bootup_req[%s] = %d\n", + notifier->name, (int)bootup_req[notifier->processor]); + mutex_unlock(&driver->diag_notifier_mutex); break; } - bootup_req[notifier->processor] = PEPIPHERAL_SSR_UP; + bootup_req[notifier->processor] = PERIPHERAL_SSR_UP; + DIAG_LOG(DIAG_DEBUG_PERIPHERALS, + "diag: bootup_req[%s] = %d\n", + notifier->name, (int)bootup_req[notifier->processor]); + mutex_unlock(&driver->diag_notifier_mutex); break; default: @@ -1002,10 +1022,6 @@ static int restart_notifier_cb(struct notifier_block *this, unsigned long code, "diag: code: %lu\n", code); break; } - mutex_unlock(&driver->diag_notifier_mutex); - DIAG_LOG(DIAG_DEBUG_PERIPHERALS, - "diag: bootup_req[%s] = %d\n", - notifier->name, (int)bootup_req[notifier->processor]); return NOTIFY_DONE; } @@ -1165,8 +1181,12 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len, if (read_len <= 0) goto fail; - if (!atomic_read(&info->opened) && - info->port_type == PORT_TYPE_SERVER) { + if (info->type == TYPE_CNTL) { + memcpy(&info->remote_addr, &src_addr, sizeof(src_addr)); + if (!atomic_read(&info->opened)) + __socket_open_channel(info); + } else if (!atomic_read(&info->opened) && + info->port_type == PORT_TYPE_SERVER) { /* * This is the first packet from the client. Copy its * address to the connection object. Consider this diff --git a/drivers/char/diag/diagfwd_socket.h b/drivers/char/diag/diagfwd_socket.h index c42be06aa976..128c2be4e9fd 100644 --- a/drivers/char/diag/diagfwd_socket.h +++ b/drivers/char/diag/diagfwd_socket.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 2019, 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 @@ -24,9 +24,9 @@ #define PORT_TYPE_SERVER 0 #define PORT_TYPE_CLIENT 1 -#define PEPIPHERAL_AFTER_BOOT 0 -#define PEPIPHERAL_SSR_DOWN 1 -#define PEPIPHERAL_SSR_UP 2 +#define PERIPHERAL_AFTER_BOOT 0 +#define PERIPHERAL_SSR_DOWN 1 +#define PERIPHERAL_SSR_UP 2 #define CNTL_CMD_NEW_SERVER 4 #define CNTL_CMD_REMOVE_SERVER 5 diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 8c0017d48571..800ced0a5a24 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -75,7 +75,7 @@ struct ports_driver_data { /* All the console devices handled by this driver */ struct list_head consoles; }; -static struct ports_driver_data pdrvdata; +static struct ports_driver_data pdrvdata = { .next_vtermno = 1}; static DEFINE_SPINLOCK(pdrvdata_lock); static DECLARE_COMPLETION(early_console_added); @@ -1425,6 +1425,7 @@ static int add_port(struct ports_device *portdev, u32 id) port->async_queue = NULL; port->cons.ws.ws_row = port->cons.ws.ws_col = 0; + port->cons.vtermno = 0; port->host_connected = port->guest_connected = false; port->stats = (struct port_stats) { 0 }; diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 39af05a589b3..32b130c53ff9 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -826,6 +826,9 @@ static const int rk3288_saved_cru_reg_ids[] = { RK3288_CLKSEL_CON(10), RK3288_CLKSEL_CON(33), RK3288_CLKSEL_CON(37), + + /* We turn aclk_dmac1 on for suspend; this will restore it */ + RK3288_CLKGATE_CON(10), }; static u32 rk3288_saved_cru_regs[ARRAY_SIZE(rk3288_saved_cru_reg_ids)]; @@ -842,6 +845,14 @@ static int rk3288_clk_suspend(void) } /* + * Going into deep sleep (specifically setting PMU_CLR_DMA in + * RK3288_PMU_PWRMODE_CON1) appears to fail unless + * "aclk_dmac1" is on. + */ + writel_relaxed(1 << (12 + 16), + rk3288_cru_base + RK3288_CLKGATE_CON(10)); + + /* * Switch PLLs other than DPLL (for SDRAM) to slow mode to * avoid crashes on resume. The Mask ROM on the system will * put APLL, CPLL, and GPLL into slow mode at resume time diff --git a/drivers/clk/sunxi/clk-sun8i-bus-gates.c b/drivers/clk/sunxi/clk-sun8i-bus-gates.c index 63fdb790df29..bee305bdddbe 100644 --- a/drivers/clk/sunxi/clk-sun8i-bus-gates.c +++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c @@ -78,6 +78,10 @@ static void __init sun8i_h3_bus_gates_init(struct device_node *node) clk_parent = APB1; else if (index >= 96 && index <= 127) clk_parent = APB2; + else { + WARN_ON(true); + continue; + } clk_reg = reg + 4 * (index / 32); clk_bit = index % 32; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 91cf85785782..863be4358a58 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -334,7 +334,7 @@ config ARM_ARCH_TIMER_VCT_ACCESS config MSM_TIMER_LEAP bool "ARCH TIMER counter rollover" default n - depends on ARM_ARCH_TIMER && ARM64 + depends on ARM_ARCH_TIMER help This option enables a check for least significant 32 bits of counter rollover. On every counter read if least significant diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 08e8d50d2cc9..fd33dddab64b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1185,6 +1185,7 @@ static struct cpufreq_policy *cpufreq_policy_alloc(unsigned int cpu) cpufreq_global_kobject, "policy%u", cpu); if (ret) { pr_err("%s: failed to init policy->kobj: %d\n", __func__, ret); + kobject_put(&policy->kobj); goto err_free_real_cpus; } diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 38d1a8216084..32c9524a6ec5 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -449,6 +449,8 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy) /* Failure, so roll back. */ pr_err("initialization failed (dbs_data kobject init error %d)\n", ret); + kobject_put(&dbs_data->attr_set.kobj); + policy->governor_data = NULL; if (!have_governor_per_policy()) diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index 35dd4d7ffee0..58c933f48300 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -146,6 +146,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) cpu = of_get_cpu_node(policy->cpu, NULL); + of_node_put(cpu); if (!cpu) goto out; diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index ff44016ea031..641f8021855a 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -551,6 +551,7 @@ static int pmac_cpufreq_init_7447A(struct device_node *cpunode) volt_gpio_np = of_find_node_by_name(NULL, "cpu-vcore-select"); if (volt_gpio_np) voltage_gpio = read_gpio(volt_gpio_np); + of_node_put(volt_gpio_np); if (!voltage_gpio){ pr_err("missing cpu-vcore-select gpio\n"); return 1; @@ -587,6 +588,7 @@ static int pmac_cpufreq_init_750FX(struct device_node *cpunode) if (volt_gpio_np) voltage_gpio = read_gpio(volt_gpio_np); + of_node_put(volt_gpio_np); pvr = mfspr(SPRN_PVR); has_cpu_l2lve = !((pvr & 0xf00) == 0x100); diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 5a4c5a639f61..2eaeebcc93af 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -86,6 +86,7 @@ static int cbe_cpufreq_cpu_init(struct cpufreq_policy *policy) if (!cbe_get_cpu_pmd_regs(policy->cpu) || !cbe_get_cpu_mic_tm_regs(policy->cpu)) { pr_info("invalid CBE regs pointers for cpufreq\n"); + of_node_put(cpu); return -EINVAL; } diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c index 0de2f62d51ff..ec16ec2e284d 100644 --- a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c +++ b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c @@ -250,7 +250,10 @@ static int sun4i_hash(struct ahash_request *areq) } } else { /* Since we have the flag final, we can go up to modulo 4 */ - end = ((areq->nbytes + op->len) / 4) * 4 - op->len; + if (areq->nbytes < 4) + end = 0; + else + end = ((areq->nbytes + op->len) / 4) * 4 - op->len; } /* TODO if SGlen % 4 and op->len == 0 then DMA */ diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 463033b4db1d..5a24a484ecc7 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c @@ -2185,7 +2185,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(sha1),cbc(aes))", .cra_driver_name = "authenc-hmac-sha1-" - "cbc-aes-talitos", + "cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2229,7 +2229,7 @@ static struct talitos_alg_template driver_algs[] = { .cra_name = "authenc(hmac(sha1)," "cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha1-" - "cbc-3des-talitos", + "cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2271,7 +2271,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(sha224),cbc(aes))", .cra_driver_name = "authenc-hmac-sha224-" - "cbc-aes-talitos", + "cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2315,7 +2315,7 @@ static struct talitos_alg_template driver_algs[] = { .cra_name = "authenc(hmac(sha224)," "cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha224-" - "cbc-3des-talitos", + "cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2357,7 +2357,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(sha256),cbc(aes))", .cra_driver_name = "authenc-hmac-sha256-" - "cbc-aes-talitos", + "cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2401,7 +2401,7 @@ static struct talitos_alg_template driver_algs[] = { .cra_name = "authenc(hmac(sha256)," "cbc(des3_ede))", .cra_driver_name = "authenc-hmac-sha256-" - "cbc-3des-talitos", + "cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2527,7 +2527,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(md5),cbc(aes))", .cra_driver_name = "authenc-hmac-md5-" - "cbc-aes-talitos", + "cbc-aes-talitos-hsna", .cra_blocksize = AES_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, @@ -2569,7 +2569,7 @@ static struct talitos_alg_template driver_algs[] = { .base = { .cra_name = "authenc(hmac(md5),cbc(des3_ede))", .cra_driver_name = "authenc-hmac-md5-" - "cbc-3des-talitos", + "cbc-3des-talitos-hsna", .cra_blocksize = DES3_EDE_BLOCK_SIZE, .cra_flags = CRYPTO_ALG_ASYNC, }, diff --git a/drivers/crypto/vmx/aesp8-ppc.pl b/drivers/crypto/vmx/aesp8-ppc.pl index d9281a28818d..930a3f1e3ec0 100644 --- a/drivers/crypto/vmx/aesp8-ppc.pl +++ b/drivers/crypto/vmx/aesp8-ppc.pl @@ -1318,7 +1318,7 @@ Loop_ctr32_enc: addi $idx,$idx,16 bdnz Loop_ctr32_enc - vadduwm $ivec,$ivec,$one + vadduqm $ivec,$ivec,$one vmr $dat,$inptail lvx $inptail,0,$inp addi $inp,$inp,16 diff --git a/drivers/crypto/vmx/ghash.c b/drivers/crypto/vmx/ghash.c index 1c4b5b889fba..1bfe867c0b7b 100644 --- a/drivers/crypto/vmx/ghash.c +++ b/drivers/crypto/vmx/ghash.c @@ -1,22 +1,14 @@ +// SPDX-License-Identifier: GPL-2.0 /** * GHASH routines supporting VMX instructions on the Power 8 * - * Copyright (C) 2015 International Business Machines Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 only. - * - * 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. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Copyright (C) 2015, 2019 International Business Machines Inc. * * Author: Marcelo Henrique Cerri <mhcerri@br.ibm.com> + * + * Extended by Daniel Axtens <dja@axtens.net> to replace the fallback + * mechanism. The new approach is based on arm64 code, which is: + * Copyright (C) 2014 - 2018 Linaro Ltd. <ard.biesheuvel@linaro.org> */ #include <linux/types.h> @@ -39,71 +31,25 @@ void gcm_ghash_p8(u64 Xi[2], const u128 htable[16], const u8 *in, size_t len); struct p8_ghash_ctx { + /* key used by vector asm */ u128 htable[16]; - struct crypto_shash *fallback; + /* key used by software fallback */ + be128 key; }; struct p8_ghash_desc_ctx { u64 shash[2]; u8 buffer[GHASH_DIGEST_SIZE]; int bytes; - struct shash_desc fallback_desc; }; -static int p8_ghash_init_tfm(struct crypto_tfm *tfm) -{ - const char *alg = "ghash-generic"; - struct crypto_shash *fallback; - struct crypto_shash *shash_tfm = __crypto_shash_cast(tfm); - struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm); - - fallback = crypto_alloc_shash(alg, 0, CRYPTO_ALG_NEED_FALLBACK); - if (IS_ERR(fallback)) { - printk(KERN_ERR - "Failed to allocate transformation for '%s': %ld\n", - alg, PTR_ERR(fallback)); - return PTR_ERR(fallback); - } - - crypto_shash_set_flags(fallback, - crypto_shash_get_flags((struct crypto_shash - *) tfm)); - - /* Check if the descsize defined in the algorithm is still enough. */ - if (shash_tfm->descsize < sizeof(struct p8_ghash_desc_ctx) - + crypto_shash_descsize(fallback)) { - printk(KERN_ERR - "Desc size of the fallback implementation (%s) does not match the expected value: %lu vs %u\n", - alg, - shash_tfm->descsize - sizeof(struct p8_ghash_desc_ctx), - crypto_shash_descsize(fallback)); - return -EINVAL; - } - ctx->fallback = fallback; - - return 0; -} - -static void p8_ghash_exit_tfm(struct crypto_tfm *tfm) -{ - struct p8_ghash_ctx *ctx = crypto_tfm_ctx(tfm); - - if (ctx->fallback) { - crypto_free_shash(ctx->fallback); - ctx->fallback = NULL; - } -} - static int p8_ghash_init(struct shash_desc *desc) { - struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm)); struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc); dctx->bytes = 0; memset(dctx->shash, 0, GHASH_DIGEST_SIZE); - dctx->fallback_desc.tfm = ctx->fallback; - dctx->fallback_desc.flags = desc->flags; - return crypto_shash_init(&dctx->fallback_desc); + return 0; } static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key, @@ -121,7 +67,51 @@ static int p8_ghash_setkey(struct crypto_shash *tfm, const u8 *key, disable_kernel_vsx(); pagefault_enable(); preempt_enable(); - return crypto_shash_setkey(ctx->fallback, key, keylen); + + memcpy(&ctx->key, key, GHASH_BLOCK_SIZE); + + return 0; +} + +static inline void __ghash_block(struct p8_ghash_ctx *ctx, + struct p8_ghash_desc_ctx *dctx) +{ + if (!IN_INTERRUPT) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); + gcm_ghash_p8(dctx->shash, ctx->htable, + dctx->buffer, GHASH_DIGEST_SIZE); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + } else { + crypto_xor((u8 *)dctx->shash, dctx->buffer, GHASH_BLOCK_SIZE); + gf128mul_lle((be128 *)dctx->shash, &ctx->key); + } +} + +static inline void __ghash_blocks(struct p8_ghash_ctx *ctx, + struct p8_ghash_desc_ctx *dctx, + const u8 *src, unsigned int srclen) +{ + if (!IN_INTERRUPT) { + preempt_disable(); + pagefault_disable(); + enable_kernel_vsx(); + gcm_ghash_p8(dctx->shash, ctx->htable, + src, srclen); + disable_kernel_vsx(); + pagefault_enable(); + preempt_enable(); + } else { + while (srclen >= GHASH_BLOCK_SIZE) { + crypto_xor((u8 *)dctx->shash, src, GHASH_BLOCK_SIZE); + gf128mul_lle((be128 *)dctx->shash, &ctx->key); + srclen -= GHASH_BLOCK_SIZE; + src += GHASH_BLOCK_SIZE; + } + } } static int p8_ghash_update(struct shash_desc *desc, @@ -131,49 +121,33 @@ static int p8_ghash_update(struct shash_desc *desc, struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm)); struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc); - if (IN_INTERRUPT) { - return crypto_shash_update(&dctx->fallback_desc, src, - srclen); - } else { - if (dctx->bytes) { - if (dctx->bytes + srclen < GHASH_DIGEST_SIZE) { - memcpy(dctx->buffer + dctx->bytes, src, - srclen); - dctx->bytes += srclen; - return 0; - } + if (dctx->bytes) { + if (dctx->bytes + srclen < GHASH_DIGEST_SIZE) { memcpy(dctx->buffer + dctx->bytes, src, - GHASH_DIGEST_SIZE - dctx->bytes); - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - gcm_ghash_p8(dctx->shash, ctx->htable, - dctx->buffer, GHASH_DIGEST_SIZE); - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); - src += GHASH_DIGEST_SIZE - dctx->bytes; - srclen -= GHASH_DIGEST_SIZE - dctx->bytes; - dctx->bytes = 0; - } - len = srclen & ~(GHASH_DIGEST_SIZE - 1); - if (len) { - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - gcm_ghash_p8(dctx->shash, ctx->htable, src, len); - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); - src += len; - srclen -= len; - } - if (srclen) { - memcpy(dctx->buffer, src, srclen); - dctx->bytes = srclen; + srclen); + dctx->bytes += srclen; + return 0; } - return 0; + memcpy(dctx->buffer + dctx->bytes, src, + GHASH_DIGEST_SIZE - dctx->bytes); + + __ghash_block(ctx, dctx); + + src += GHASH_DIGEST_SIZE - dctx->bytes; + srclen -= GHASH_DIGEST_SIZE - dctx->bytes; + dctx->bytes = 0; + } + len = srclen & ~(GHASH_DIGEST_SIZE - 1); + if (len) { + __ghash_blocks(ctx, dctx, src, len); + src += len; + srclen -= len; } + if (srclen) { + memcpy(dctx->buffer, src, srclen); + dctx->bytes = srclen; + } + return 0; } static int p8_ghash_final(struct shash_desc *desc, u8 *out) @@ -182,25 +156,14 @@ static int p8_ghash_final(struct shash_desc *desc, u8 *out) struct p8_ghash_ctx *ctx = crypto_tfm_ctx(crypto_shash_tfm(desc->tfm)); struct p8_ghash_desc_ctx *dctx = shash_desc_ctx(desc); - if (IN_INTERRUPT) { - return crypto_shash_final(&dctx->fallback_desc, out); - } else { - if (dctx->bytes) { - for (i = dctx->bytes; i < GHASH_DIGEST_SIZE; i++) - dctx->buffer[i] = 0; - preempt_disable(); - pagefault_disable(); - enable_kernel_vsx(); - gcm_ghash_p8(dctx->shash, ctx->htable, - dctx->buffer, GHASH_DIGEST_SIZE); - disable_kernel_vsx(); - pagefault_enable(); - preempt_enable(); - dctx->bytes = 0; - } - memcpy(out, dctx->shash, GHASH_DIGEST_SIZE); - return 0; + if (dctx->bytes) { + for (i = dctx->bytes; i < GHASH_DIGEST_SIZE; i++) + dctx->buffer[i] = 0; + __ghash_block(ctx, dctx); + dctx->bytes = 0; } + memcpy(out, dctx->shash, GHASH_DIGEST_SIZE); + return 0; } struct shash_alg p8_ghash_alg = { @@ -215,11 +178,9 @@ struct shash_alg p8_ghash_alg = { .cra_name = "ghash", .cra_driver_name = "p8_ghash", .cra_priority = 1000, - .cra_flags = CRYPTO_ALG_TYPE_SHASH | CRYPTO_ALG_NEED_FALLBACK, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, .cra_blocksize = GHASH_BLOCK_SIZE, .cra_ctxsize = sizeof(struct p8_ghash_ctx), .cra_module = THIS_MODULE, - .cra_init = p8_ghash_init_tfm, - .cra_exit = p8_ghash_exit_tfm, }, }; diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index b222dd7afe8e..12d904829324 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -1608,7 +1608,11 @@ static void at_xdmac_tasklet(unsigned long data) struct at_xdmac_desc, xfer_node); dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); - BUG_ON(!desc->active_xfer); + if (!desc->active_xfer) { + dev_err(chan2dev(&atchan->chan), "Xfer not active: exiting"); + spin_unlock_bh(&atchan->lock); + return; + } txd = &desc->tx_dma_desc; diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 1953e57505f4..f17a4c7a1781 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -589,7 +589,7 @@ static int idma64_probe(struct idma64_chip *chip) idma64->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV); idma64->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; - idma64->dma.dev = chip->dev; + idma64->dma.dev = chip->sysdev; dma_set_max_seg_size(idma64->dma.dev, IDMA64C_CTLH_BLOCK_TS_MASK); @@ -629,6 +629,7 @@ static int idma64_platform_probe(struct platform_device *pdev) { struct idma64_chip *chip; struct device *dev = &pdev->dev; + struct device *sysdev = dev->parent; struct resource *mem; int ret; @@ -645,11 +646,12 @@ static int idma64_platform_probe(struct platform_device *pdev) if (IS_ERR(chip->regs)) return PTR_ERR(chip->regs); - ret = dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + ret = dma_coerce_mask_and_coherent(sysdev, DMA_BIT_MASK(64)); if (ret) return ret; chip->dev = dev; + chip->sysdev = sysdev; ret = idma64_probe(chip); if (ret) diff --git a/drivers/dma/idma64.h b/drivers/dma/idma64.h index 6b816878e5e7..baa32e1425de 100644 --- a/drivers/dma/idma64.h +++ b/drivers/dma/idma64.h @@ -216,12 +216,14 @@ static inline void idma64_writel(struct idma64 *idma64, int offset, u32 value) /** * struct idma64_chip - representation of iDMA 64-bit controller hardware * @dev: struct device of the DMA controller + * @sysdev: struct device of the physical device that does DMA * @irq: irq line * @regs: memory mapped I/O space * @idma64: struct idma64 that is filed by idma64_probe() */ struct idma64_chip { struct device *dev; + struct device *sysdev; int irq; void __iomem *regs; struct idma64 *idma64; diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index b9c29720aeb1..84856ac75a09 100644 --- a/drivers/dma/imx-sdma.c +++ b/drivers/dma/imx-sdma.c @@ -632,7 +632,7 @@ static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size, spin_lock_irqsave(&sdma->channel_0_lock, flags); bd0->mode.command = C0_SETPM; - bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; + bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD; bd0->mode.count = size / 2; bd0->buffer_addr = buf_phys; bd0->ext_buffer_addr = address; @@ -909,7 +909,7 @@ static int sdma_load_context(struct sdma_channel *sdmac) context->gReg[7] = sdmac->watermark_level; bd0->mode.command = C0_SETDM; - bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD; + bd0->mode.status = BD_DONE | BD_WRAP | BD_EXTD; bd0->mode.count = sizeof(*context) / 4; bd0->buffer_addr = sdma->context_phys; bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * channel; diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 6d7e3cd4aba4..57b375d0de29 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -1020,6 +1020,7 @@ static void _stop(struct pl330_thread *thrd) { void __iomem *regs = thrd->dmac->base; u8 insn[6] = {0, 0, 0, 0, 0, 0}; + u32 inten = readl(regs + INTEN); if (_state(thrd) == PL330_STATE_FAULT_COMPLETING) UNTIL(thrd, PL330_STATE_FAULTING | PL330_STATE_KILLING); @@ -1032,10 +1033,13 @@ static void _stop(struct pl330_thread *thrd) _emit_KILL(0, insn); - /* Stop generating interrupts for SEV */ - writel(readl(regs + INTEN) & ~(1 << thrd->ev), regs + INTEN); - _execute_DBGINSN(thrd, insn, is_manager(thrd)); + + /* clear the event */ + if (inten & (1 << thrd->ev)) + writel(1 << thrd->ev, regs + INTCLR); + /* Stop generating interrupts for SEV */ + writel(inten & ~(1 << thrd->ev), regs + INTEN); } /* Start doing req 'idx' of thread 'thrd' */ diff --git a/drivers/dma/tegra210-adma.c b/drivers/dma/tegra210-adma.c index b10cbaa82ff5..e9e46a520745 100644 --- a/drivers/dma/tegra210-adma.c +++ b/drivers/dma/tegra210-adma.c @@ -22,7 +22,6 @@ #include <linux/of_device.h> #include <linux/of_dma.h> #include <linux/of_irq.h> -#include <linux/pm_clock.h> #include <linux/pm_runtime.h> #include <linux/slab.h> @@ -141,6 +140,7 @@ struct tegra_adma { struct dma_device dma_dev; struct device *dev; void __iomem *base_addr; + struct clk *ahub_clk; unsigned int nr_channels; unsigned long rx_requests_reserved; unsigned long tx_requests_reserved; @@ -637,8 +637,9 @@ static int tegra_adma_runtime_suspend(struct device *dev) struct tegra_adma *tdma = dev_get_drvdata(dev); tdma->global_cmd = tdma_read(tdma, ADMA_GLOBAL_CMD); + clk_disable_unprepare(tdma->ahub_clk); - return pm_clk_suspend(dev); + return 0; } static int tegra_adma_runtime_resume(struct device *dev) @@ -646,10 +647,11 @@ static int tegra_adma_runtime_resume(struct device *dev) struct tegra_adma *tdma = dev_get_drvdata(dev); int ret; - ret = pm_clk_resume(dev); - if (ret) + ret = clk_prepare_enable(tdma->ahub_clk); + if (ret) { + dev_err(dev, "ahub clk_enable failed: %d\n", ret); return ret; - + } tdma_write(tdma, ADMA_GLOBAL_CMD, tdma->global_cmd); return 0; @@ -692,13 +694,11 @@ static int tegra_adma_probe(struct platform_device *pdev) if (IS_ERR(tdma->base_addr)) return PTR_ERR(tdma->base_addr); - ret = pm_clk_create(&pdev->dev); - if (ret) - return ret; - - ret = of_pm_clk_add_clk(&pdev->dev, "d_audio"); - if (ret) - goto clk_destroy; + tdma->ahub_clk = devm_clk_get(&pdev->dev, "d_audio"); + if (IS_ERR(tdma->ahub_clk)) { + dev_err(&pdev->dev, "Error: Missing ahub controller clock\n"); + return PTR_ERR(tdma->ahub_clk); + } pm_runtime_enable(&pdev->dev); @@ -775,8 +775,6 @@ rpm_put: pm_runtime_put_sync(&pdev->dev); rpm_disable: pm_runtime_disable(&pdev->dev); -clk_destroy: - pm_clk_destroy(&pdev->dev); return ret; } @@ -786,6 +784,7 @@ static int tegra_adma_remove(struct platform_device *pdev) struct tegra_adma *tdma = platform_get_drvdata(pdev); int i; + of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&tdma->dma_dev); for (i = 0; i < tdma->nr_channels; ++i) @@ -793,7 +792,6 @@ static int tegra_adma_remove(struct platform_device *pdev) pm_runtime_put_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); - pm_clk_destroy(&pdev->dev); return 0; } diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 56e6c4c7c60d..4c0b6df8b5dd 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1684,6 +1684,16 @@ static int arizona_extcon_remove(struct platform_device *pdev) struct arizona_extcon_info *info = platform_get_drvdata(pdev); struct arizona *arizona = info->arizona; int jack_irq_rise, jack_irq_fall; + bool change; + + regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, + ARIZONA_MICD_ENA, 0, + &change); + + if (change) { + regulator_disable(info->micvdd); + pm_runtime_put(info->dev); + } gpiod_put(info->micd_pol_gpio); diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 7ec09ea81b94..726d1467b778 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -18,6 +18,7 @@ #include "efistub.h" + static int efi_get_secureboot(efi_system_table_t *sys_table_arg) { static efi_char16_t const sb_var_name[] = { diff --git a/drivers/firmware/efi/libstub/efi-stub-helper.c b/drivers/firmware/efi/libstub/efi-stub-helper.c index d9843329e9b2..1c963c4d1bde 100644..100755 --- a/drivers/firmware/efi/libstub/efi-stub-helper.c +++ b/drivers/firmware/efi/libstub/efi-stub-helper.c @@ -32,6 +32,13 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; +static int __section(.data) __nokaslr; + +int __pure nokaslr(void) +{ + return __nokaslr; +} + /* * Allow the platform to override the allocation granularity: this allows * systems that have the capability to run with a larger page size to deal @@ -41,13 +48,6 @@ static unsigned long __chunk_size = EFI_READ_CHUNK_SIZE; #define EFI_ALLOC_ALIGN EFI_PAGE_SIZE #endif -static int __section(.data) __nokaslr; - -int __pure nokaslr(void) -{ - return __nokaslr; -} - #define EFI_MMAP_NR_SLACK_SLOTS 8 struct file_info { @@ -367,14 +367,6 @@ efi_status_t efi_parse_options(char const *cmdline) __nokaslr = 1; /* - * Currently, the only efi= option we look for is 'nochunk', which - * is intended to work around known issues on certain x86 UEFI - * versions. So ignore for now on other architectures. - */ - if (!IS_ENABLED(CONFIG_X86)) - return EFI_SUCCESS; - - /* * If no EFI parameters were specified on the cmdline we've got * nothing to do. */ diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 642fa03f9292..768be774aad6 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -689,6 +689,7 @@ config GPIO_ADP5588 config GPIO_ADP5588_IRQ bool "Interrupt controller support for ADP5588" depends on GPIO_ADP5588=y + select GPIOLIB_IRQCHIP help Say yes here to enable the adp5588 to be used as an interrupt controller. It requires the driver to be built in the kernel. diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index 75f30a0c418a..038882183bdf 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -296,6 +296,22 @@ static void omap_clear_gpio_debounce(struct gpio_bank *bank, unsigned offset) } } +/* + * Off mode wake-up capable GPIOs in bank(s) that are in the wakeup domain. + * See TRM section for GPIO for "Wake-Up Generation" for the list of GPIOs + * in wakeup domain. If bank->non_wakeup_gpios is not configured, assume none + * are capable waking up the system from off mode. + */ +static bool omap_gpio_is_off_wakeup_capable(struct gpio_bank *bank, u32 gpio_mask) +{ + u32 no_wake = bank->non_wakeup_gpios; + + if (no_wake) + return !!(~no_wake & gpio_mask); + + return false; +} + static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, unsigned trigger) { @@ -327,13 +343,7 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, } /* This part needs to be executed always for OMAP{34xx, 44xx} */ - if (!bank->regs->irqctrl) { - /* On omap24xx proceed only when valid GPIO bit is set */ - if (bank->non_wakeup_gpios) { - if (!(bank->non_wakeup_gpios & gpio_bit)) - goto exit; - } - + if (!bank->regs->irqctrl && !omap_gpio_is_off_wakeup_capable(bank, gpio)) { /* * Log the edge gpio and manually trigger the IRQ * after resume if the input level changes @@ -346,7 +356,6 @@ static inline void omap_set_gpio_trigger(struct gpio_bank *bank, int gpio, bank->enabled_non_wakeup_gpios &= ~gpio_bit; } -exit: bank->level_mask = readl_relaxed(bank->base + bank->regs->leveldetect0) | readl_relaxed(bank->base + bank->regs->leveldetect1); diff --git a/drivers/gpu/drm/arm/hdlcd_crtc.c b/drivers/gpu/drm/arm/hdlcd_crtc.c index 28341b32067f..84dea276175b 100644 --- a/drivers/gpu/drm/arm/hdlcd_crtc.c +++ b/drivers/gpu/drm/arm/hdlcd_crtc.c @@ -170,7 +170,8 @@ static int hdlcd_crtc_atomic_check(struct drm_crtc *crtc, long rate, clk_rate = mode->clock * 1000; rate = clk_round_rate(hdlcd->clk, clk_rate); - if (rate != clk_rate) { + /* 0.1% seems a close enough tolerance for the TDA19988 on Juno */ + if (abs(rate - clk_rate) * 1000 > clk_rate) { /* clock required by mode not supported by hardware */ return -EINVAL; } diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 32ab5c32834b..1b2fae915ecc 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -735,11 +735,11 @@ static void adv7511_mode_set(struct adv7511 *adv7511, vsync_polarity = 1; } - if (mode->vrefresh <= 24000) + if (drm_mode_vrefresh(mode) <= 24) low_refresh_rate = ADV7511_LOW_REFRESH_RATE_24HZ; - else if (mode->vrefresh <= 25000) + else if (drm_mode_vrefresh(mode) <= 25) low_refresh_rate = ADV7511_LOW_REFRESH_RATE_25HZ; - else if (mode->vrefresh <= 30000) + else if (drm_mode_vrefresh(mode) <= 30) low_refresh_rate = ADV7511_LOW_REFRESH_RATE_30HZ; else low_refresh_rate = ADV7511_LOW_REFRESH_RATE_NONE; diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 847ba40e1f26..246f818d0885 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -522,6 +522,7 @@ put_back_event: file_priv->event_space -= length; list_add(&e->link, &file_priv->event_list); spin_unlock_irq(&dev->event_lock); + wake_up_interruptible(&file_priv->event_wait); break; } diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index ea733ab5b1e0..d83be4623c7f 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -609,6 +609,9 @@ void cdv_intel_lvds_init(struct drm_device *dev, int pipe; u8 pin; + if (!dev_priv->lvds_enabled_in_vbt) + return; + pin = GMBUS_PORT_PANEL; if (!lvds_is_present_in_vbt(dev, &pin)) { DRM_DEBUG_KMS("LVDS is not present in VBT\n"); diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c index 63bde4e86c6a..e019ea271ffc 100644 --- a/drivers/gpu/drm/gma500/intel_bios.c +++ b/drivers/gpu/drm/gma500/intel_bios.c @@ -436,6 +436,9 @@ parse_driver_features(struct drm_psb_private *dev_priv, if (driver->lvds_config == BDB_DRIVER_FEATURE_EDP) dev_priv->edp.support = 1; + dev_priv->lvds_enabled_in_vbt = driver->lvds_config != 0; + DRM_DEBUG_KMS("LVDS VBT config bits: 0x%x\n", driver->lvds_config); + /* This bit means to use 96Mhz for DPLL_A or not */ if (driver->primary_lfp_id) dev_priv->dplla_96mhz = true; diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index b74372760d7f..d18e11d61312 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -538,6 +538,7 @@ struct drm_psb_private { int lvds_ssc_freq; bool is_lvds_on; bool is_mipi_on; + bool lvds_enabled_in_vbt; u32 mipi_ctrl_display; unsigned int core_freq; diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 1ea0e1f43397..54d878cb458f 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -280,10 +280,17 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, uint32_t i; uint32_t *dmc_payload; uint32_t required_version; + size_t fsize; if (!fw) return NULL; + fsize = sizeof(struct intel_css_header) + + sizeof(struct intel_package_header) + + sizeof(struct intel_dmc_header); + if (fsize > fw->size) + goto error_truncated; + /* Extract CSS Header information*/ css_header = (struct intel_css_header *)fw->data; if (sizeof(struct intel_css_header) != @@ -349,6 +356,9 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, return NULL; } readcount += dmc_offset; + fsize += dmc_offset; + if (fsize > fw->size) + goto error_truncated; /* Extract dmc_header information. */ dmc_header = (struct intel_dmc_header *)&fw->data[readcount]; @@ -379,6 +389,10 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */ nbytes = dmc_header->fw_size * 4; + fsize += nbytes; + if (fsize > fw->size) + goto error_truncated; + if (nbytes > CSR_MAX_FW_SIZE) { DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes); return NULL; @@ -392,6 +406,10 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, } return memcpy(dmc_payload, &fw->data[readcount], nbytes); + +error_truncated: + DRM_ERROR("Truncated DMC firmware, rejecting.\n"); + return NULL; } static void csr_load_work_fn(struct work_struct *work) diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index 8dbba61a2708..82114fe2a42a 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -76,14 +76,14 @@ static void ipu_crtc_atomic_disable(struct drm_crtc *crtc, drm_atomic_helper_disable_planes_on_crtc(old_crtc_state, false); ipu_dc_disable(ipu); + drm_crtc_vblank_off(crtc); + spin_lock_irq(&crtc->dev->event_lock); - if (crtc->state->event) { + if (crtc->state->event && !crtc->state->active) { drm_crtc_send_vblank_event(crtc, crtc->state->event); crtc->state->event = NULL; } spin_unlock_irq(&crtc->dev->event_lock); - - drm_crtc_vblank_off(crtc); } static void imx_drm_crtc_reset(struct drm_crtc *crtc) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index eaa5a2240c0c..bdbf358697cd 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -720,6 +720,8 @@ static void mtk_dsi_destroy_conn_enc(struct mtk_dsi *dsi) /* Skip connector cleanup if creation was delegated to the bridge */ if (dsi->conn.dev) drm_connector_cleanup(&dsi->conn); + if (dsi->panel) + drm_panel_detach(dsi->panel); } static void mtk_dsi_ddp_start(struct mtk_ddp_comp *comp) diff --git a/drivers/gpu/drm/msm/dp/dp_debug.c b/drivers/gpu/drm/msm/dp/dp_debug.c index 92fc9bc1bb3a..d023f64178e5 100644 --- a/drivers/gpu/drm/msm/dp/dp_debug.c +++ b/drivers/gpu/drm/msm/dp/dp_debug.c @@ -192,6 +192,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file, goto bail; size = min_t(size_t, count, SZ_2K); + if (size < 4) + goto bail; buf = kzalloc(size, GFP_KERNEL); if (ZERO_OR_NULL_PTR(buf)) { @@ -220,6 +222,8 @@ static ssize_t dp_debug_write_dpcd(struct file *file, } size -= 4; + if (size == 0) + goto bail; dpcd_size = size / char_to_nib; buf_t = buf + 4; @@ -271,6 +275,7 @@ static ssize_t dp_debug_read_dpcd(struct file *file, len += snprintf(buf, SZ_8, "0x%x\n", debug->aux->reg); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; @@ -428,7 +433,7 @@ static ssize_t dp_debug_write_exe_mode(struct file *file, const char __user *user_buff, size_t count, loff_t *ppos) { struct dp_debug_private *debug = file->private_data; - char *buf; + char buf[SZ_32]; size_t len = 0; if (!debug) @@ -437,8 +442,11 @@ static ssize_t dp_debug_write_exe_mode(struct file *file, if (*ppos) return 0; + /* Leave room for termination char */ len = min_t(size_t, count, SZ_32 - 1); - buf = memdup_user(user_buff, len); + if (copy_from_user(buf, user_buff, len)) + goto end; + buf[len] = '\0'; if (sscanf(buf, "%3s", debug->exe_mode) != 1) @@ -469,6 +477,7 @@ static ssize_t dp_debug_read_connected(struct file *file, len += snprintf(buf, SZ_8, "%d\n", debug->usbpd->hpd_high); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; @@ -532,6 +541,7 @@ static ssize_t dp_debug_read_edid_modes(struct file *file, } mutex_unlock(&connector->dev->mode_config.mutex); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) { kfree(buf); rc = -EFAULT; @@ -621,6 +631,7 @@ static ssize_t dp_debug_read_info(struct file *file, char __user *user_buff, if (dp_debug_check_buffer_overflow(rc, &max_size, &len)) goto error; + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) goto error; @@ -653,6 +664,7 @@ static ssize_t dp_debug_bw_code_read(struct file *file, len += snprintf(buf + len, (SZ_4K - len), "max_bw_code = %d\n", debug->panel->max_bw_code); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) { kfree(buf); return -EFAULT; @@ -678,6 +690,7 @@ static ssize_t dp_debug_tpg_read(struct file *file, len += snprintf(buf, SZ_8, "%d\n", debug->dp_debug.tpg_state); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; @@ -868,6 +881,7 @@ static ssize_t dp_debug_read_hdr(struct file *file, goto error; } + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) { kfree(buf); rc = -EFAULT; @@ -1027,6 +1041,7 @@ static ssize_t dp_debug_read_dump(struct file *file, print_hex_dump(KERN_DEBUG, prefix, DUMP_PREFIX_NONE, 16, 4, buf, len, false); + len = min_t(size_t, count, len); if (copy_to_user(user_buff, buf, len)) return -EFAULT; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h index a63c5ac69f66..23b8f25402d0 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h @@ -37,6 +37,7 @@ struct nvkm_i2c_bus { struct mutex mutex; struct list_head head; struct i2c_adapter i2c; + u8 enabled; }; int nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *); @@ -56,6 +57,7 @@ struct nvkm_i2c_aux { struct mutex mutex; struct list_head head; struct i2c_adapter i2c; + u8 enabled; u32 intr; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c index f0851d57df2f..f89692cb2bc7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.c @@ -105,9 +105,15 @@ nvkm_i2c_aux_acquire(struct nvkm_i2c_aux *aux) { struct nvkm_i2c_pad *pad = aux->pad; int ret; + AUX_TRACE(aux, "acquire"); mutex_lock(&aux->mutex); - ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_AUX); + + if (aux->enabled) + ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_AUX); + else + ret = -EIO; + if (ret) mutex_unlock(&aux->mutex); return ret; @@ -141,6 +147,24 @@ nvkm_i2c_aux_del(struct nvkm_i2c_aux **paux) } } +void +nvkm_i2c_aux_init(struct nvkm_i2c_aux *aux) +{ + AUX_TRACE(aux, "init"); + mutex_lock(&aux->mutex); + aux->enabled = true; + mutex_unlock(&aux->mutex); +} + +void +nvkm_i2c_aux_fini(struct nvkm_i2c_aux *aux) +{ + AUX_TRACE(aux, "fini"); + mutex_lock(&aux->mutex); + aux->enabled = false; + mutex_unlock(&aux->mutex); +} + int nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *func, struct nvkm_i2c_pad *pad, int id, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h index fc6b162fa0b1..1be175a8fb02 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/aux.h @@ -14,6 +14,8 @@ int nvkm_i2c_aux_ctor(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *, int nvkm_i2c_aux_new_(const struct nvkm_i2c_aux_func *, struct nvkm_i2c_pad *, int id, struct nvkm_i2c_aux **); void nvkm_i2c_aux_del(struct nvkm_i2c_aux **); +void nvkm_i2c_aux_init(struct nvkm_i2c_aux *); +void nvkm_i2c_aux_fini(struct nvkm_i2c_aux *); int nvkm_i2c_aux_xfer(struct nvkm_i2c_aux *, bool retry, u8 type, u32 addr, u8 *data, u8 size); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c index 4f197b15acf6..ecacb22834d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c @@ -160,8 +160,18 @@ nvkm_i2c_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_i2c *i2c = nvkm_i2c(subdev); struct nvkm_i2c_pad *pad; + struct nvkm_i2c_bus *bus; + struct nvkm_i2c_aux *aux; u32 mask; + list_for_each_entry(aux, &i2c->aux, head) { + nvkm_i2c_aux_fini(aux); + } + + list_for_each_entry(bus, &i2c->bus, head) { + nvkm_i2c_bus_fini(bus); + } + if ((mask = (1 << i2c->func->aux) - 1), i2c->func->aux_stat) { i2c->func->aux_mask(i2c, NVKM_I2C_ANY, mask, 0); i2c->func->aux_stat(i2c, &mask, &mask, &mask, &mask); @@ -180,6 +190,7 @@ nvkm_i2c_init(struct nvkm_subdev *subdev) struct nvkm_i2c *i2c = nvkm_i2c(subdev); struct nvkm_i2c_bus *bus; struct nvkm_i2c_pad *pad; + struct nvkm_i2c_aux *aux; list_for_each_entry(pad, &i2c->pad, head) { nvkm_i2c_pad_init(pad); @@ -189,6 +200,10 @@ nvkm_i2c_init(struct nvkm_subdev *subdev) nvkm_i2c_bus_init(bus); } + list_for_each_entry(aux, &i2c->aux, head) { + nvkm_i2c_aux_init(aux); + } + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c index 807a2b67bd64..ed50cc3736b9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.c @@ -110,6 +110,19 @@ nvkm_i2c_bus_init(struct nvkm_i2c_bus *bus) BUS_TRACE(bus, "init"); if (bus->func->init) bus->func->init(bus); + + mutex_lock(&bus->mutex); + bus->enabled = true; + mutex_unlock(&bus->mutex); +} + +void +nvkm_i2c_bus_fini(struct nvkm_i2c_bus *bus) +{ + BUS_TRACE(bus, "fini"); + mutex_lock(&bus->mutex); + bus->enabled = false; + mutex_unlock(&bus->mutex); } void @@ -126,9 +139,15 @@ nvkm_i2c_bus_acquire(struct nvkm_i2c_bus *bus) { struct nvkm_i2c_pad *pad = bus->pad; int ret; + BUS_TRACE(bus, "acquire"); mutex_lock(&bus->mutex); - ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_I2C); + + if (bus->enabled) + ret = nvkm_i2c_pad_acquire(pad, NVKM_I2C_PAD_I2C); + else + ret = -EIO; + if (ret) mutex_unlock(&bus->mutex); return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h index e1be14c23e54..2fdb1b8e7164 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/i2c/bus.h @@ -17,6 +17,7 @@ int nvkm_i2c_bus_new_(const struct nvkm_i2c_bus_func *, struct nvkm_i2c_pad *, int id, struct nvkm_i2c_bus **); void nvkm_i2c_bus_del(struct nvkm_i2c_bus **); void nvkm_i2c_bus_init(struct nvkm_i2c_bus *); +void nvkm_i2c_bus_fini(struct nvkm_i2c_bus *); int nvkm_i2c_bit_xfer(struct nvkm_i2c_bus *, struct i2c_msg *, int); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index ca1caf405832..8b6f8aa23806 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -935,12 +935,12 @@ static void avivo_get_fb_ref_div(unsigned nom, unsigned den, unsigned post_div, ref_div_max = max(min(100 / post_div, ref_div_max), 1u); /* get matching reference and feedback divider */ - *ref_div = min(max(DIV_ROUND_CLOSEST(den, post_div), 1u), ref_div_max); + *ref_div = min(max(den/post_div, 1u), ref_div_max); *fb_div = DIV_ROUND_CLOSEST(nom * *ref_div * post_div, den); /* limit fb divider to its maximum */ if (*fb_div > fb_div_max) { - *ref_div = DIV_ROUND_CLOSEST(*ref_div * fb_div_max, *fb_div); + *ref_div = (*ref_div * fb_div_max)/(*fb_div); *fb_div = fb_div_max; } } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 4b556e698f13..6c30c24c779f 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1245,7 +1245,13 @@ static int vmw_master_set(struct drm_device *dev, } dev_priv->active_master = vmaster; - drm_sysfs_hotplug_event(dev); + + /* + * Inform a new master that the layout may have changed while + * it was gone. + */ + if (!from_open) + drm_sysfs_hotplug_event(dev); return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 9fe8eda7c859..40c1e89ed361 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -2493,7 +2493,8 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, cmd = container_of(header, typeof(*cmd), header); - if (cmd->body.type >= SVGA3D_SHADERTYPE_DX10_MAX) { + if (cmd->body.type >= SVGA3D_SHADERTYPE_DX10_MAX || + cmd->body.type < SVGA3D_SHADERTYPE_MIN) { DRM_ERROR("Illegal shader type %u.\n", (unsigned) cmd->body.type); return -EINVAL; @@ -2732,6 +2733,10 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv, if (view_type == vmw_view_max) return -EINVAL; cmd = container_of(header, typeof(*cmd), header); + if (unlikely(cmd->sid == SVGA3D_INVALID_ID)) { + DRM_ERROR("Invalid surface id.\n"); + return -EINVAL; + } ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, &cmd->sid, &srf_node); diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 81efba580279..d030731d2a51 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -200,13 +200,14 @@ static unsigned hid_lookup_collection(struct hid_parser *parser, unsigned type) * Add a usage to the temporary parser table. */ -static int hid_add_usage(struct hid_parser *parser, unsigned usage) +static int hid_add_usage(struct hid_parser *parser, unsigned usage, u8 size) { if (parser->local.usage_index >= HID_MAX_USAGES) { hid_err(parser->device, "usage index exceeded\n"); return -1; } parser->local.usage[parser->local.usage_index] = usage; + parser->local.usage_size[parser->local.usage_index] = size; parser->local.collection_index[parser->local.usage_index] = parser->collection_stack_ptr ? parser->collection_stack[parser->collection_stack_ptr - 1] : 0; @@ -463,10 +464,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - - return hid_add_usage(parser, data); + return hid_add_usage(parser, data, item->size); case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: @@ -475,9 +473,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - parser->local.usage_minimum = data; return 0; @@ -488,9 +483,6 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) return 0; } - if (item->size <= 2) - data = (parser->global.usage_page << 16) + data; - count = data - parser->local.usage_minimum; if (count + parser->local.usage_index >= HID_MAX_USAGES) { /* @@ -510,7 +502,7 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) } for (n = parser->local.usage_minimum; n <= data; n++) - if (hid_add_usage(parser, n)) { + if (hid_add_usage(parser, n, item->size)) { dbg_hid("hid_add_usage failed\n"); return -1; } @@ -525,6 +517,22 @@ static int hid_parser_local(struct hid_parser *parser, struct hid_item *item) } /* + * Concatenate Usage Pages into Usages where relevant: + * As per specification, 6.2.2.8: "When the parser encounters a main item it + * concatenates the last declared Usage Page with a Usage to form a complete + * usage value." + */ + +static void hid_concatenate_usage_page(struct hid_parser *parser) +{ + int i; + + for (i = 0; i < parser->local.usage_index; i++) + if (parser->local.usage_size[i] <= 2) + parser->local.usage[i] += parser->global.usage_page << 16; +} + +/* * Process a main item. */ @@ -533,6 +541,8 @@ static int hid_parser_main(struct hid_parser *parser, struct hid_item *item) __u32 data; int ret; + hid_concatenate_usage_page(parser); + data = item_udata(item); switch (item->tag) { @@ -746,6 +756,8 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) __u32 data; int i; + hid_concatenate_usage_page(parser); + data = item_udata(item); switch (item->tag) { diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 3198faf5cff4..38d9deb03d16 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -449,13 +449,16 @@ static int hidpp_root_get_feature(struct hidpp_device *hidpp, u16 feature, static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) { + const u8 ping_byte = 0x5a; + u8 ping_data[3] = { 0, 0, ping_byte }; struct hidpp_report response; int ret; - ret = hidpp_send_fap_command_sync(hidpp, + ret = hidpp_send_rap_command_sync(hidpp, + REPORT_ID_HIDPP_SHORT, HIDPP_PAGE_ROOT_IDX, CMD_ROOT_GET_PROTOCOL_VERSION, - NULL, 0, &response); + ping_data, sizeof(ping_data), &response); if (ret == HIDPP_ERROR_INVALID_SUBID) { hidpp->protocol_major = 1; @@ -475,8 +478,14 @@ static int hidpp_root_get_protocol_version(struct hidpp_device *hidpp) if (ret) return ret; - hidpp->protocol_major = response.fap.params[0]; - hidpp->protocol_minor = response.fap.params[1]; + if (response.rap.params[2] != ping_byte) { + hid_err(hidpp->hid_dev, "%s: ping mismatch 0x%02x != 0x%02x\n", + __func__, response.rap.params[2], ping_byte); + return -EPROTO; + } + + hidpp->protocol_major = response.rap.params[0]; + hidpp->protocol_minor = response.rap.params[1]; return ret; } diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c index facd05cda26d..e8c089886427 100644 --- a/drivers/hwmon/f71805f.c +++ b/drivers/hwmon/f71805f.c @@ -96,17 +96,23 @@ superio_select(int base, int ld) outb(ld, base + 1); } -static inline void +static inline int superio_enter(int base) { + if (!request_muxed_region(base, 2, DRVNAME)) + return -EBUSY; + outb(0x87, base); outb(0x87, base); + + return 0; } static inline void superio_exit(int base) { outb(0xaa, base); + release_region(base, 2); } /* @@ -1561,7 +1567,7 @@ exit: static int __init f71805f_find(int sioaddr, unsigned short *address, struct f71805f_sio_data *sio_data) { - int err = -ENODEV; + int err; u16 devid; static const char * const names[] = { @@ -1569,8 +1575,11 @@ static int __init f71805f_find(int sioaddr, unsigned short *address, "F71872F/FG or F71806F/FG", }; - superio_enter(sioaddr); + err = superio_enter(sioaddr); + if (err) + return err; + err = -ENODEV; devid = superio_inw(sioaddr, SIO_REG_MANID); if (devid != SIO_FINTEK_ID) goto exit; diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c index cb9fdd37bd0d..2b5b8c3de8fc 100644 --- a/drivers/hwmon/pc87427.c +++ b/drivers/hwmon/pc87427.c @@ -106,6 +106,13 @@ static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" }; #define LD_IN 1 #define LD_TEMP 1 +static inline int superio_enter(int sioaddr) +{ + if (!request_muxed_region(sioaddr, 2, DRVNAME)) + return -EBUSY; + return 0; +} + static inline void superio_outb(int sioaddr, int reg, int val) { outb(reg, sioaddr); @@ -122,6 +129,7 @@ static inline void superio_exit(int sioaddr) { outb(0x02, sioaddr); outb(0x02, sioaddr + 1); + release_region(sioaddr, 2); } /* @@ -1220,7 +1228,11 @@ static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) { u16 val; u8 cfg, cfg_b; - int i, err = 0; + int i, err; + + err = superio_enter(sioaddr); + if (err) + return err; /* Identify device */ val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID); diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index c00bad02761a..0d75bc7b5065 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c @@ -1028,14 +1028,15 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, const struct pmbus_driver_info *info, const char *name, int index, int page, - const struct pmbus_sensor_attr *attr) + const struct pmbus_sensor_attr *attr, + bool paged) { struct pmbus_sensor *base; int ret; if (attr->label) { ret = pmbus_add_label(data, name, index, attr->label, - attr->paged ? page + 1 : 0); + paged ? page + 1 : 0); if (ret) return ret; } @@ -1067,6 +1068,30 @@ static int pmbus_add_sensor_attrs_one(struct i2c_client *client, return 0; } +static bool pmbus_sensor_is_paged(const struct pmbus_driver_info *info, + const struct pmbus_sensor_attr *attr) +{ + int p; + + if (attr->paged) + return true; + + /* + * Some attributes may be present on more than one page despite + * not being marked with the paged attribute. If that is the case, + * then treat the sensor as being paged and add the page suffix to the + * attribute name. + * We don't just add the paged attribute to all such attributes, in + * order to maintain the un-suffixed labels in the case where the + * attribute is only on page 0. + */ + for (p = 1; p < info->pages; p++) { + if (info->func[p] & attr->func) + return true; + } + return false; +} + static int pmbus_add_sensor_attrs(struct i2c_client *client, struct pmbus_data *data, const char *name, @@ -1080,14 +1105,15 @@ static int pmbus_add_sensor_attrs(struct i2c_client *client, index = 1; for (i = 0; i < nattrs; i++) { int page, pages; + bool paged = pmbus_sensor_is_paged(info, attrs); - pages = attrs->paged ? info->pages : 1; + pages = paged ? info->pages : 1; for (page = 0; page < pages; page++) { if (!(info->func[page] & attrs->func)) continue; ret = pmbus_add_sensor_attrs_one(client, data, info, name, index, page, - attrs); + attrs, paged); if (ret) return ret; index++; diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c index 086e706a242e..772aac1e9ebd 100644 --- a/drivers/hwmon/qpnp-adc-voltage.c +++ b/drivers/hwmon/qpnp-adc-voltage.c @@ -749,7 +749,7 @@ int32_t qpnp_vadc_hc_read(struct qpnp_vadc_chip *vadc, QPNP_VADC_CAL_DELAY_CTL_1, &val, 1); if (rc < 0) { pr_err("qpnp adc write cal_delay failed with %d\n", rc); - return rc; + goto fail_unlock; } } diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c index 6bd200756560..cbdb5c4991ae 100644 --- a/drivers/hwmon/smsc47b397.c +++ b/drivers/hwmon/smsc47b397.c @@ -72,14 +72,19 @@ static inline void superio_select(int ld) superio_outb(0x07, ld); } -static inline void superio_enter(void) +static inline int superio_enter(void) { + if (!request_muxed_region(REG, 2, DRVNAME)) + return -EBUSY; + outb(0x55, REG); + return 0; } static inline void superio_exit(void) { outb(0xAA, REG); + release_region(REG, 2); } #define SUPERIO_REG_DEVID 0x20 @@ -300,8 +305,12 @@ static int __init smsc47b397_find(void) u8 id, rev; char *name; unsigned short addr; + int err; + + err = superio_enter(); + if (err) + return err; - superio_enter(); id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); switch (id) { diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 5d323186d2c1..d24df0c50bea 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -73,16 +73,21 @@ superio_inb(int reg) /* logical device for fans is 0x0A */ #define superio_select() superio_outb(0x07, 0x0A) -static inline void +static inline int superio_enter(void) { + if (!request_muxed_region(REG, 2, DRVNAME)) + return -EBUSY; + outb(0x55, REG); + return 0; } static inline void superio_exit(void) { outb(0xAA, REG); + release_region(REG, 2); } #define SUPERIO_REG_ACT 0x30 @@ -531,8 +536,12 @@ static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data) { u8 val; unsigned short addr; + int err; + + err = superio_enter(); + if (err) + return err; - superio_enter(); val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); /* @@ -608,13 +617,14 @@ static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data) static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data) { if ((sio_data->activate & 0x01) == 0) { - superio_enter(); - superio_select(); - - pr_info("Disabling device\n"); - superio_outb(SUPERIO_REG_ACT, sio_data->activate); - - superio_exit(); + if (!superio_enter()) { + superio_select(); + pr_info("Disabling device\n"); + superio_outb(SUPERIO_REG_ACT, sio_data->activate); + superio_exit(); + } else { + pr_warn("Failed to disable device\n"); + } } } diff --git a/drivers/hwmon/vt1211.c b/drivers/hwmon/vt1211.c index 3a6bfa51cb94..95d5e8ec8b7f 100644 --- a/drivers/hwmon/vt1211.c +++ b/drivers/hwmon/vt1211.c @@ -226,15 +226,21 @@ static inline void superio_select(int sio_cip, int ldn) outb(ldn, sio_cip + 1); } -static inline void superio_enter(int sio_cip) +static inline int superio_enter(int sio_cip) { + if (!request_muxed_region(sio_cip, 2, DRVNAME)) + return -EBUSY; + outb(0x87, sio_cip); outb(0x87, sio_cip); + + return 0; } static inline void superio_exit(int sio_cip) { outb(0xaa, sio_cip); + release_region(sio_cip, 2); } /* --------------------------------------------------------------------- @@ -1282,11 +1288,14 @@ EXIT: static int __init vt1211_find(int sio_cip, unsigned short *address) { - int err = -ENODEV; + int err; int devid; - superio_enter(sio_cip); + err = superio_enter(sio_cip); + if (err) + return err; + err = -ENODEV; devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID); if (devid != SIO_VT1211_ID) goto EXIT; diff --git a/drivers/i2c/busses/i2c-acorn.c b/drivers/i2c/busses/i2c-acorn.c index 9d7be5af2bf2..6618db75fa25 100644 --- a/drivers/i2c/busses/i2c-acorn.c +++ b/drivers/i2c/busses/i2c-acorn.c @@ -83,6 +83,7 @@ static struct i2c_algo_bit_data ioc_data = { static struct i2c_adapter ioc_ops = { .nr = 0, + .name = "ioc", .algo_data = &ioc_data, }; diff --git a/drivers/i2c/busses/i2c-msm-v2.c b/drivers/i2c/busses/i2c-msm-v2.c index 631169b4081d..ad999a27c92a 100644 --- a/drivers/i2c/busses/i2c-msm-v2.c +++ b/drivers/i2c/busses/i2c-msm-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2019, 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 @@ -2144,8 +2144,12 @@ static bool i2c_msm_xfer_next_buf(struct i2c_msm_ctrl *ctrl) { struct i2c_msm_xfer_buf *cur_buf = &ctrl->xfer.cur_buf; struct i2c_msg *cur_msg = ctrl->xfer.msgs + cur_buf->msg_idx; - int bc_rem = cur_msg->len - cur_buf->end_idx; + int bc_rem = 0; + if (!cur_msg) + return false; + + bc_rem = cur_msg->len - cur_buf->end_idx; if (cur_buf->is_init && cur_buf->end_idx && bc_rem) { /* not the first buffer in a message */ @@ -2321,17 +2325,12 @@ i2c_msm_frmwrk_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) struct i2c_msm_ctrl *ctrl = i2c_get_adapdata(adap); struct i2c_msm_xfer *xfer = &ctrl->xfer; - if (num < 1) { + if (IS_ERR_OR_NULL(msgs) || num < 1) { dev_err(ctrl->dev, - "error on number of msgs(%d) received\n", num); + "Error on msgs Accessing invalid message pointer or message buffer\n"); return -EINVAL; } - if (IS_ERR_OR_NULL(msgs)) { - dev_err(ctrl->dev, " error on msgs Accessing invalid pointer location\n"); - return PTR_ERR(msgs); - } - /* if system is suspended just bail out */ if (ctrl->pwr_state == I2C_MSM_PM_SYS_SUSPENDED) { dev_err(ctrl->dev, diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 00e8e675cbeb..eaa312bc3a3c 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -297,6 +297,7 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, rdwr_pa[i].buf[0] < 1 || rdwr_pa[i].len < rdwr_pa[i].buf[0] + I2C_SMBUS_BLOCK_MAX) { + i++; res = -EINVAL; break; } diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index a1d072ecb717..30f200ad6b97 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -62,7 +62,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg, struct spi_transfer t = { .tx_buf = data, .len = size + 1, - .cs_change = sigma_delta->bus_locked, + .cs_change = sigma_delta->keep_cs_asserted, }; struct spi_message m; int ret; @@ -217,6 +217,7 @@ static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, spi_bus_lock(sigma_delta->spi->master); sigma_delta->bus_locked = true; + sigma_delta->keep_cs_asserted = true; reinit_completion(&sigma_delta->completion); ret = ad_sigma_delta_set_mode(sigma_delta, mode); @@ -234,9 +235,10 @@ static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, ret = 0; } out: + sigma_delta->keep_cs_asserted = false; + ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); sigma_delta->bus_locked = false; spi_bus_unlock(sigma_delta->spi->master); - ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); return ret; } @@ -288,6 +290,7 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, spi_bus_lock(sigma_delta->spi->master); sigma_delta->bus_locked = true; + sigma_delta->keep_cs_asserted = true; reinit_completion(&sigma_delta->completion); ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_SINGLE); @@ -297,9 +300,6 @@ int ad_sigma_delta_single_conversion(struct iio_dev *indio_dev, ret = wait_for_completion_interruptible_timeout( &sigma_delta->completion, HZ); - sigma_delta->bus_locked = false; - spi_bus_unlock(sigma_delta->spi->master); - if (ret == 0) ret = -EIO; if (ret < 0) @@ -315,7 +315,10 @@ out: sigma_delta->irq_dis = true; } + sigma_delta->keep_cs_asserted = false; ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); + sigma_delta->bus_locked = false; + spi_bus_unlock(sigma_delta->spi->master); mutex_unlock(&indio_dev->mlock); if (ret) @@ -352,6 +355,8 @@ static int ad_sd_buffer_postenable(struct iio_dev *indio_dev) spi_bus_lock(sigma_delta->spi->master); sigma_delta->bus_locked = true; + sigma_delta->keep_cs_asserted = true; + ret = ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_CONTINUOUS); if (ret) goto err_unlock; @@ -380,6 +385,7 @@ static int ad_sd_buffer_postdisable(struct iio_dev *indio_dev) sigma_delta->irq_dis = true; } + sigma_delta->keep_cs_asserted = false; ad_sigma_delta_set_mode(sigma_delta, AD_SD_MODE_IDLE); sigma_delta->bus_locked = false; diff --git a/drivers/iio/common/ssp_sensors/ssp_iio.c b/drivers/iio/common/ssp_sensors/ssp_iio.c index a3ae165f8d9f..16180e6321bd 100644 --- a/drivers/iio/common/ssp_sensors/ssp_iio.c +++ b/drivers/iio/common/ssp_sensors/ssp_iio.c @@ -80,7 +80,7 @@ int ssp_common_process_data(struct iio_dev *indio_dev, void *buf, unsigned int len, int64_t timestamp) { __le32 time; - int64_t calculated_time; + int64_t calculated_time = 0; struct ssp_sensor_data *spd = iio_priv(indio_dev); if (indio_dev->scan_bytes == 0) diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c index 3de7f4426ac4..86abba5827a2 100644 --- a/drivers/iio/magnetometer/hmc5843_i2c.c +++ b/drivers/iio/magnetometer/hmc5843_i2c.c @@ -58,8 +58,13 @@ static const struct regmap_config hmc5843_i2c_regmap_config = { static int hmc5843_i2c_probe(struct i2c_client *cli, const struct i2c_device_id *id) { + struct regmap *regmap = devm_regmap_init_i2c(cli, + &hmc5843_i2c_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + return hmc5843_common_probe(&cli->dev, - devm_regmap_init_i2c(cli, &hmc5843_i2c_regmap_config), + regmap, id->driver_data, id->name); } diff --git a/drivers/iio/magnetometer/hmc5843_spi.c b/drivers/iio/magnetometer/hmc5843_spi.c index 535f03a70d63..79b2b707f90e 100644 --- a/drivers/iio/magnetometer/hmc5843_spi.c +++ b/drivers/iio/magnetometer/hmc5843_spi.c @@ -58,6 +58,7 @@ static const struct regmap_config hmc5843_spi_regmap_config = { static int hmc5843_spi_probe(struct spi_device *spi) { int ret; + struct regmap *regmap; const struct spi_device_id *id = spi_get_device_id(spi); spi->mode = SPI_MODE_3; @@ -67,8 +68,12 @@ static int hmc5843_spi_probe(struct spi_device *spi) if (ret) return ret; + regmap = devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + return hmc5843_common_probe(&spi->dev, - devm_regmap_init_spi(spi, &hmc5843_spi_regmap_config), + regmap, id->driver_data, id->name); } diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index a2322b2dbd82..e5752352e0fb 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -455,6 +455,8 @@ static struct sk_buff *get_skb(struct sk_buff *skb, int len, gfp_t gfp) skb_reset_transport_header(skb); } else { skb = alloc_skb(len, gfp); + if (!skb) + return NULL; } t4_set_arp_err_handler(skb, NULL, NULL); return skb; diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index d30b3b908621..85db856047a9 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -9620,6 +9620,7 @@ void hfi1_quiet_serdes(struct hfi1_pportdata *ppd) /* disable the port */ clear_rcvctrl(dd, RCV_CTRL_RCV_PORT_ENABLE_SMASK); + cancel_work_sync(&ppd->freeze_work); } static inline int init_cpu_counters(struct hfi1_devdata *dd) diff --git a/drivers/infiniband/hw/hfi1/sdma.c b/drivers/infiniband/hw/hfi1/sdma.c index 9cbe52d21077..76e63c88a87a 100644 --- a/drivers/infiniband/hw/hfi1/sdma.c +++ b/drivers/infiniband/hw/hfi1/sdma.c @@ -410,10 +410,7 @@ static void sdma_flush(struct sdma_engine *sde) sdma_flush_descq(sde); spin_lock_irqsave(&sde->flushlist_lock, flags); /* copy flush list */ - list_for_each_entry_safe(txp, txp_next, &sde->flushlist, list) { - list_del_init(&txp->list); - list_add_tail(&txp->list, &flushlist); - } + list_splice_init(&sde->flushlist, &flushlist); spin_unlock_irqrestore(&sde->flushlist_lock, flags); /* flush from flush list */ list_for_each_entry_safe(txp, txp_next, &flushlist, list) @@ -2406,7 +2403,7 @@ unlock_noconn: wait->tx_count++; wait->count += tx->num_desc; } - schedule_work(&sde->flush_worker); + queue_work_on(sde->cpu, system_highpri_wq, &sde->flush_worker); ret = -ECOMM; goto unlock; nodesc: @@ -2504,7 +2501,7 @@ unlock_noconn: } } spin_unlock(&sde->flushlist_lock); - schedule_work(&sde->flush_worker); + queue_work_on(sde->cpu, system_highpri_wq, &sde->flush_worker); ret = -ECOMM; goto update_tail; nodesc: diff --git a/drivers/infiniband/hw/hfi1/user_sdma.c b/drivers/infiniband/hw/hfi1/user_sdma.c index 4c111162d552..098296aaa225 100644 --- a/drivers/infiniband/hw/hfi1/user_sdma.c +++ b/drivers/infiniband/hw/hfi1/user_sdma.c @@ -260,7 +260,6 @@ struct user_sdma_txreq { struct list_head list; struct user_sdma_request *req; u16 flags; - unsigned busycount; u64 seqnum; }; @@ -323,25 +322,22 @@ static int defer_packet_queue( struct hfi1_user_sdma_pkt_q *pq = container_of(wait, struct hfi1_user_sdma_pkt_q, busy); struct hfi1_ibdev *dev = &pq->dd->verbs_dev; - struct user_sdma_txreq *tx = - container_of(txreq, struct user_sdma_txreq, txreq); - if (sdma_progress(sde, seq, txreq)) { - if (tx->busycount++ < MAX_DEFER_RETRY_COUNT) - goto eagain; - } + write_seqlock(&dev->iowait_lock); + if (sdma_progress(sde, seq, txreq)) + goto eagain; /* * We are assuming that if the list is enqueued somewhere, it * is to the dmawait list since that is the only place where * it is supposed to be enqueued. */ xchg(&pq->state, SDMA_PKT_Q_DEFERRED); - write_seqlock(&dev->iowait_lock); if (list_empty(&pq->busy.list)) list_add_tail(&pq->busy.list, &sde->dmawait); write_sequnlock(&dev->iowait_lock); return -EBUSY; eagain: + write_sequnlock(&dev->iowait_lock); return -EAGAIN; } @@ -925,7 +921,6 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts) tx->flags = 0; tx->req = req; - tx->busycount = 0; INIT_LIST_HEAD(&tx->list); if (req->seqnum == req->info.npkts - 1) diff --git a/drivers/infiniband/hw/hfi1/verbs.c b/drivers/infiniband/hw/hfi1/verbs.c index d9c71750e22d..15054a0cbf6d 100644 --- a/drivers/infiniband/hw/hfi1/verbs.c +++ b/drivers/infiniband/hw/hfi1/verbs.c @@ -1344,8 +1344,6 @@ static void hfi1_fill_device_attr(struct hfi1_devdata *dd) rdi->dparms.props.max_cq = hfi1_max_cqs; rdi->dparms.props.max_ah = hfi1_max_ahs; rdi->dparms.props.max_cqe = hfi1_max_cqes; - rdi->dparms.props.max_mr = rdi->lkey_table.max; - rdi->dparms.props.max_fmr = rdi->lkey_table.max; rdi->dparms.props.max_map_per_fmr = 32767; rdi->dparms.props.max_pd = hfi1_max_pds; rdi->dparms.props.max_qp_rd_atom = HFI1_MAX_RDMA_ATOMIC; diff --git a/drivers/infiniband/hw/hfi1/verbs_txreq.c b/drivers/infiniband/hw/hfi1/verbs_txreq.c index d8a5bad49680..837729d0be46 100644 --- a/drivers/infiniband/hw/hfi1/verbs_txreq.c +++ b/drivers/infiniband/hw/hfi1/verbs_txreq.c @@ -100,7 +100,7 @@ struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev, if (ib_rvt_state_ops[qp->state] & RVT_PROCESS_RECV_OK) { struct hfi1_qp_priv *priv; - tx = kmem_cache_alloc(dev->verbs_txreq_cache, GFP_ATOMIC); + tx = kmem_cache_alloc(dev->verbs_txreq_cache, VERBS_TXREQ_GFP); if (tx) goto out; priv = qp->priv; diff --git a/drivers/infiniband/hw/hfi1/verbs_txreq.h b/drivers/infiniband/hw/hfi1/verbs_txreq.h index 31ded57592ee..0bd58a0772e2 100644 --- a/drivers/infiniband/hw/hfi1/verbs_txreq.h +++ b/drivers/infiniband/hw/hfi1/verbs_txreq.h @@ -71,6 +71,7 @@ struct hfi1_ibdev; struct verbs_txreq *__get_txreq(struct hfi1_ibdev *dev, struct rvt_qp *qp); +#define VERBS_TXREQ_GFP (GFP_ATOMIC | __GFP_NOWARN) static inline struct verbs_txreq *get_txreq(struct hfi1_ibdev *dev, struct rvt_qp *qp) __must_hold(&qp->slock) @@ -78,7 +79,7 @@ static inline struct verbs_txreq *get_txreq(struct hfi1_ibdev *dev, struct verbs_txreq *tx; struct hfi1_qp_priv *priv = qp->priv; - tx = kmem_cache_alloc(dev->verbs_txreq_cache, GFP_ATOMIC); + tx = kmem_cache_alloc(dev->verbs_txreq_cache, VERBS_TXREQ_GFP); if (unlikely(!tx)) { /* call slow path to get the lock */ tx = __get_txreq(dev, qp); diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index 954f15064514..d6e183775e24 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c @@ -1568,8 +1568,6 @@ static void qib_fill_device_attr(struct qib_devdata *dd) rdi->dparms.props.max_cq = ib_qib_max_cqs; rdi->dparms.props.max_cqe = ib_qib_max_cqes; rdi->dparms.props.max_ah = ib_qib_max_ahs; - rdi->dparms.props.max_mr = rdi->lkey_table.max; - rdi->dparms.props.max_fmr = rdi->lkey_table.max; rdi->dparms.props.max_map_per_fmr = 32767; rdi->dparms.props.max_qp_rd_atom = QIB_MAX_RDMA_ATOMIC; rdi->dparms.props.max_qp_init_rd_atom = 255; diff --git a/drivers/infiniband/sw/rdmavt/mr.c b/drivers/infiniband/sw/rdmavt/mr.c index 49d55a0322f6..dbd4c0d268e9 100644 --- a/drivers/infiniband/sw/rdmavt/mr.c +++ b/drivers/infiniband/sw/rdmavt/mr.c @@ -94,6 +94,8 @@ int rvt_driver_mr_init(struct rvt_dev_info *rdi) for (i = 0; i < rdi->lkey_table.max; i++) RCU_INIT_POINTER(rdi->lkey_table.table[i], NULL); + rdi->dparms.props.max_mr = rdi->lkey_table.max; + rdi->dparms.props.max_fmr = rdi->lkey_table.max; return 0; } diff --git a/drivers/infiniband/sw/rdmavt/qp.c b/drivers/infiniband/sw/rdmavt/qp.c index 6500c3b5a89c..8b330b53d636 100644 --- a/drivers/infiniband/sw/rdmavt/qp.c +++ b/drivers/infiniband/sw/rdmavt/qp.c @@ -370,7 +370,8 @@ static int alloc_qpn(struct rvt_dev_info *rdi, struct rvt_qpn_table *qpt, offset = qpt->incr | ((offset & 1) ^ 1); } /* there can be no set bits in low-order QoS bits */ - WARN_ON(offset & (BIT(rdi->dparms.qos_shift) - 1)); + WARN_ON(rdi->dparms.qos_shift > 1 && + offset & ((BIT(rdi->dparms.qos_shift - 1) - 1) << 1)); qpn = mk_qpn(qpt, map, offset); } diff --git a/drivers/input/keyboard/imx_keypad.c b/drivers/input/keyboard/imx_keypad.c index 2165f3dd328b..842c0235471d 100644 --- a/drivers/input/keyboard/imx_keypad.c +++ b/drivers/input/keyboard/imx_keypad.c @@ -530,11 +530,12 @@ static int imx_keypad_probe(struct platform_device *pdev) return 0; } -static int __maybe_unused imx_kbd_suspend(struct device *dev) +static int __maybe_unused imx_kbd_noirq_suspend(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); struct input_dev *input_dev = kbd->input_dev; + unsigned short reg_val = readw(kbd->mmio_base + KPSR); /* imx kbd can wake up system even clock is disabled */ mutex_lock(&input_dev->mutex); @@ -544,13 +545,20 @@ static int __maybe_unused imx_kbd_suspend(struct device *dev) mutex_unlock(&input_dev->mutex); - if (device_may_wakeup(&pdev->dev)) + if (device_may_wakeup(&pdev->dev)) { + if (reg_val & KBD_STAT_KPKD) + reg_val |= KBD_STAT_KRIE; + if (reg_val & KBD_STAT_KPKR) + reg_val |= KBD_STAT_KDIE; + writew(reg_val, kbd->mmio_base + KPSR); + enable_irq_wake(kbd->irq); + } return 0; } -static int __maybe_unused imx_kbd_resume(struct device *dev) +static int __maybe_unused imx_kbd_noirq_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct imx_keypad *kbd = platform_get_drvdata(pdev); @@ -574,7 +582,9 @@ err_clk: return ret; } -static SIMPLE_DEV_PM_OPS(imx_kbd_pm_ops, imx_kbd_suspend, imx_kbd_resume); +static const struct dev_pm_ops imx_kbd_pm_ops = { + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(imx_kbd_noirq_suspend, imx_kbd_noirq_resume) +}; static struct platform_driver imx_keypad_driver = { .driver = { diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index a306453d40d2..89d37d0d45ed 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -991,13 +991,31 @@ static long uinput_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_COMPAT -#define UI_SET_PHYS_COMPAT _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t) +/* + * These IOCTLs change their size and thus their numbers between + * 32 and 64 bits. + */ +#define UI_SET_PHYS_COMPAT \ + _IOW(UINPUT_IOCTL_BASE, 108, compat_uptr_t) +#define UI_BEGIN_FF_UPLOAD_COMPAT \ + _IOWR(UINPUT_IOCTL_BASE, 200, struct uinput_ff_upload_compat) +#define UI_END_FF_UPLOAD_COMPAT \ + _IOW(UINPUT_IOCTL_BASE, 201, struct uinput_ff_upload_compat) static long uinput_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - if (cmd == UI_SET_PHYS_COMPAT) + switch (cmd) { + case UI_SET_PHYS_COMPAT: cmd = UI_SET_PHYS; + break; + case UI_BEGIN_FF_UPLOAD_COMPAT: + cmd = UI_BEGIN_FF_UPLOAD; + break; + case UI_END_FF_UPLOAD_COMPAT: + cmd = UI_END_FF_UPLOAD; + break; + } return uinput_ioctl_handler(file, cmd, arg, compat_ptr(arg)); } diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index 38edf8f5bf8a..15be3ee6cc50 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c @@ -1187,6 +1187,8 @@ static const char * const middle_button_pnp_ids[] = { "LEN2132", /* ThinkPad P52 */ "LEN2133", /* ThinkPad P72 w/ NFC */ "LEN2134", /* ThinkPad P72 */ + "LEN0407", + "LEN0408", NULL }; diff --git a/drivers/input/sensors/smi130/smi130_acc.c b/drivers/input/sensors/smi130/smi130_acc.c index c36c31dab67b..a63e08e521c3 100644 --- a/drivers/input/sensors/smi130/smi130_acc.c +++ b/drivers/input/sensors/smi130/smi130_acc.c @@ -1604,6 +1604,7 @@ struct smi130_acc_data { bool read_acc_boot_sample; int acc_bufsample_cnt; bool acc_buffer_smi130_samples; + bool acc_enable; struct kmem_cache *smi_acc_cachepool; struct smi_acc_sample *smi130_acc_samplist[SMI_ACC_MAXSAMPLE]; int max_buffer_time; @@ -4073,12 +4074,25 @@ static inline int smi130_check_acc_early_buff_enable_flag( else return 0; } +static void smi130_check_acc_enable_flag(struct smi130_acc_data *client_data, + unsigned long data) +{ + if (data == SMI_ACC2X2_MODE_NORMAL) + client_data->acc_enable = true; + else + client_data->acc_enable = false; +} #else static inline int smi130_check_acc_early_buff_enable_flag( struct smi130_acc_data *client_data) { return 0; } +static void smi130_check_acc_enable_flag(struct smi130_acc_data *client_data, + unsigned long data) +{ + +} #endif static ssize_t smi130_acc_enable_int_store(struct device *dev, @@ -5481,13 +5495,17 @@ static ssize_t smi130_acc_mode_store(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct smi130_acc_data *smi130_acc = i2c_get_clientdata(client); - error = smi130_check_acc_early_buff_enable_flag(smi130_acc); - if (error) - return count; error = kstrtoul(buf, 10, &data); if (error) return error; + + smi130_check_acc_enable_flag(smi130_acc, data); + + error = smi130_check_acc_early_buff_enable_flag(smi130_acc); + if (error) + return count; + if (smi130_acc_set_mode(smi130_acc->smi130_acc_client, (unsigned char) data, SMI_ACC_ENABLED_BSX) < 0) return -EINVAL; @@ -6915,6 +6933,9 @@ static void store_acc_boot_sample(struct smi130_acc_data *client_data, PINFO("End of ACC buffering %d\n", client_data->acc_bufsample_cnt); client_data->acc_buffer_smi130_samples = false; + if (client_data->acc_enable == false) + smi130_acc_set_mode(client_data->smi130_acc_client, + SMI_ACC2X2_MODE_SUSPEND, 1); } } #else @@ -6982,6 +7003,7 @@ static int smi130_acc_early_buff_init(struct i2c_client *client, } client_data->acc_buffer_smi130_samples = true; + client_data->acc_enable = false; smi130_acc_set_mode(client, SMI_ACC2X2_MODE_NORMAL, 1); smi130_acc_set_bandwidth(client, SMI_ACC2X2_BW_62_50HZ); diff --git a/drivers/input/sensors/smi130/smi130_gyro_driver.c b/drivers/input/sensors/smi130/smi130_gyro_driver.c index 552d39cf25fc..fd9e87d2e5b3 100644 --- a/drivers/input/sensors/smi130/smi130_gyro_driver.c +++ b/drivers/input/sensors/smi130/smi130_gyro_driver.c @@ -295,6 +295,7 @@ struct smi_gyro_client_data { bool read_gyro_boot_sample; int gyro_bufsample_cnt; bool gyro_buffer_smi130_samples; + bool gyro_enable; struct kmem_cache *smi_gyro_cachepool; struct smi_gyro_sample *smi130_gyro_samplist[SMI_GYRO_MAXSAMPLE]; int max_buffer_time; @@ -860,12 +861,24 @@ static inline int smi130_check_gyro_early_buff_enable_flag( else return 0; } +static void smi130_check_gyro_enable_flag( + struct smi_gyro_client_data *client_data, unsigned long data) +{ + if (data == SMI130_GYRO_MODE_NORMAL) + client_data->gyro_enable = true; + else + client_data->gyro_enable = false; +} #else static inline int smi130_check_gyro_early_buff_enable_flag( struct smi_gyro_client_data *client_data) { return 0; } +static void smi130_check_gyro_enable_flag( + struct smi_gyro_client_data *client_data, unsigned long data) +{ +} #endif static ssize_t smi_gyro_show_op_mode(struct device *dev, @@ -895,13 +908,17 @@ static ssize_t smi_gyro_store_op_mode(struct device *dev, long op_mode; - err = smi130_check_gyro_early_buff_enable_flag(client_data); - if (err) - return count; err = kstrtoul(buf, 10, &op_mode); if (err) return err; + + smi130_check_gyro_enable_flag(client_data, op_mode); + + err = smi130_check_gyro_early_buff_enable_flag(client_data); + if (err) + return count; + mutex_lock(&client_data->mutex_op_mode); err = SMI_GYRO_CALL_API(set_mode)(op_mode); @@ -1742,6 +1759,10 @@ static void store_gyro_boot_sample(struct smi_gyro_client_data *client_data, PINFO("End of GYRO buffering %d", client_data->gyro_bufsample_cnt); client_data->gyro_buffer_smi130_samples = false; + if (client_data->gyro_enable == false) { + smi130_gyro_set_mode(SMI130_GYRO_MODE_SUSPEND); + smi130_gyro_delay(5); + } } } #else @@ -1810,6 +1831,7 @@ static int smi130_gyro_early_buff_init(struct smi_gyro_client_data *client_data) } client_data->gyro_buffer_smi130_samples = true; + client_data->gyro_enable = false; smi130_gyro_set_mode(SMI130_GYRO_MODE_NORMAL); smi130_gyro_delay(5); diff --git a/drivers/input/touchscreen/cyttsp5/cyttsp5_core.c b/drivers/input/touchscreen/cyttsp5/cyttsp5_core.c index 44bb9ba6507e..f2b2bce3e138 100644 --- a/drivers/input/touchscreen/cyttsp5/cyttsp5_core.c +++ b/drivers/input/touchscreen/cyttsp5/cyttsp5_core.c @@ -3765,6 +3765,7 @@ static int cyttsp5_core_sleep_(struct cyttsp5_core_data *cd) /* Ensure watchdog and startup works stopped */ cyttsp5_stop_wd_timer(cd); cancel_work_sync(&cd->startup_work); + cancel_work_sync(&cd->resume_work); cyttsp5_stop_wd_timer(cd); if (cd->cpdata->flags & CY_CORE_FLAG_POWEROFF_ON_SLEEP) @@ -5965,6 +5966,19 @@ void *cyttsp5_get_module_data(struct device *dev, struct cyttsp5_module *module) } EXPORT_SYMBOL(cyttsp5_get_module_data); +static void cyttsp5_resume_work(struct work_struct *work) +{ + struct cyttsp5_core_data *cd = container_of(work, + struct cyttsp5_core_data, resume_work); + + #ifdef USE_FB_SUSPEND_RESUME + cyttsp5_core_resume(cd->dev); + cd->wake_initiated_by_device = 0; + #endif + call_atten_cb(cd, CY_ATTEN_RESUME, 0); + cd->fb_state = FB_ON; +} + #ifdef CONFIG_HAS_EARLYSUSPEND static void cyttsp5_early_suspend(struct early_suspend *h) { @@ -6008,12 +6022,7 @@ static int fb_notifier_callback(struct notifier_block *self, case FB_BLANK_UNBLANK: dev_dbg(cd->dev, "%s: UNBLANK!\n", __func__); if (cd->fb_state != FB_ON) { - #ifdef USE_FB_SUSPEND_RESUME - cyttsp5_core_resume(cd->dev); - cd->wake_initiated_by_device = 0; - #endif - call_atten_cb(cd, CY_ATTEN_RESUME, 0); - cd->fb_state = FB_ON; + schedule_work(&cd->resume_work); } break; @@ -6305,6 +6314,7 @@ int cyttsp5_probe(const struct cyttsp5_bus_ops *ops, struct device *dev, /* Initialize works */ INIT_WORK(&cd->startup_work, cyttsp5_startup_work_function); + INIT_WORK(&cd->resume_work, cyttsp5_resume_work); INIT_WORK(&cd->watchdog_work, cyttsp5_watchdog_work); /* Initialize HID specific data */ @@ -6448,6 +6458,7 @@ error_startup: pm_runtime_disable(dev); device_init_wakeup(dev, 0); cancel_work_sync(&cd->startup_work); + cancel_work_sync(&cd->resume_work); cyttsp5_stop_wd_timer(cd); remove_sysfs_interfaces(dev); error_attr_create: @@ -6498,6 +6509,7 @@ int cyttsp5_release(struct cyttsp5_core_data *cd) pm_runtime_disable(dev); cancel_work_sync(&cd->startup_work); + cancel_work_sync(&cd->resume_work); cyttsp5_stop_wd_timer(cd); diff --git a/drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c b/drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c index 9f3f586467cc..c7dbafa5e31a 100644 --- a/drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c +++ b/drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c @@ -751,7 +751,7 @@ static int upgrade_firmware_from_class(struct device *dev) parade_debug(dev, DEBUG_LEVEL_2, "%s: Enabling firmware class loader\n", __func__); - retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG, + retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, CY_FW_MANUAL_UPGRADE_FILE_NAME, dev, GFP_KERNEL, dev, _cyttsp5_firmware_cont); if (retval < 0) { diff --git a/drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h b/drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h index e7b16db91b1f..9502c7a08f9a 100644 --- a/drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h +++ b/drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h @@ -168,7 +168,7 @@ enum PARADE_DEBUG_LEVEL { #else #define CY_HID_OUTPUT_TIMEOUT 200 #endif -#define CY_HID_OUTPUT_START_BOOTLOADER_TIMEOUT 2000 +#define CY_HID_OUTPUT_START_BOOTLOADER_TIMEOUT 200 #define CY_HID_OUTPUT_USER_TIMEOUT 8000 #define CY_HID_OUTPUT_GET_SYSINFO_TIMEOUT 3000 #define CY_HID_OUTPUT_CALIBRATE_IDAC_TIMEOUT 5000 @@ -991,6 +991,7 @@ struct cyttsp5_core_data { struct notifier_block pm_notifier; #endif struct work_struct startup_work; + struct work_struct resume_work; struct cyttsp5_sysinfo sysinfo; void *exclusive_dev; int exclusive_waits; diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 28feb1744710..25cc6ae87039 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -4119,9 +4119,7 @@ static void __init init_no_remapping_devices(void) /* This IOMMU has *only* gfx devices. Either bypass it or set the gfx_mapped flag, as appropriate */ - if (dmar_map_gfx) { - intel_iommu_gfx_mapped = 1; - } else { + if (!dmar_map_gfx) { drhd->ignored = 1; for_each_active_dev_scope(drhd->devices, drhd->devices_cnt, i, dev) @@ -4870,6 +4868,9 @@ int __init intel_iommu_init(void) goto out_free_reserved_range; } + if (dmar_map_gfx) + intel_iommu_gfx_mapped = 1; + init_no_remapping_devices(); ret = init_dmars(); diff --git a/drivers/irqchip/irq-ath79-misc.c b/drivers/irqchip/irq-ath79-misc.c index 0390603170b4..aa7290784636 100644 --- a/drivers/irqchip/irq-ath79-misc.c +++ b/drivers/irqchip/irq-ath79-misc.c @@ -22,15 +22,6 @@ #define AR71XX_RESET_REG_MISC_INT_ENABLE 4 #define ATH79_MISC_IRQ_COUNT 32 -#define ATH79_MISC_PERF_IRQ 5 - -static int ath79_perfcount_irq; - -int get_c0_perfcount_int(void) -{ - return ath79_perfcount_irq; -} -EXPORT_SYMBOL_GPL(get_c0_perfcount_int); static void ath79_misc_irq_handler(struct irq_desc *desc) { @@ -122,8 +113,6 @@ static void __init ath79_misc_intc_domain_init( { void __iomem *base = domain->host_data; - ath79_perfcount_irq = irq_create_mapping(domain, ATH79_MISC_PERF_IRQ); - /* Disable and clear all interrupts */ __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_ENABLE); __raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS); diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c index f96b8f2bdf74..d7c986fb0b3b 100644 --- a/drivers/isdn/mISDN/socket.c +++ b/drivers/isdn/mISDN/socket.c @@ -394,7 +394,7 @@ data_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) memcpy(di.channelmap, dev->channelmap, sizeof(di.channelmap)); di.nrbchan = dev->nrbchan; - strcpy(di.name, dev_name(&dev->dev)); + strscpy(di.name, dev_name(&dev->dev), sizeof(di.name)); if (copy_to_user((void __user *)arg, &di, sizeof(di))) err = -EFAULT; } else @@ -678,7 +678,7 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) memcpy(di.channelmap, dev->channelmap, sizeof(di.channelmap)); di.nrbchan = dev->nrbchan; - strcpy(di.name, dev_name(&dev->dev)); + strscpy(di.name, dev_name(&dev->dev), sizeof(di.name)); if (copy_to_user((void __user *)arg, &di, sizeof(di))) err = -EFAULT; } else @@ -692,6 +692,7 @@ base_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) err = -EFAULT; break; } + dn.name[sizeof(dn.name) - 1] = '\0'; dev = get_mdevice(dn.id); if (dev) err = device_rename(&dev->dev, dn.name); diff --git a/drivers/md/bcache/alloc.c b/drivers/md/bcache/alloc.c index dd344ee9e62b..ebacd21714ef 100644 --- a/drivers/md/bcache/alloc.c +++ b/drivers/md/bcache/alloc.c @@ -322,10 +322,11 @@ static int bch_allocator_thread(void *arg) * possibly issue discards to them, then we add the bucket to * the free list: */ - while (!fifo_empty(&ca->free_inc)) { + while (1) { long bucket; - fifo_pop(&ca->free_inc, bucket); + if (!fifo_pop(&ca->free_inc, bucket)) + break; if (ca->discard) { mutex_unlock(&ca->set->bucket_lock); diff --git a/drivers/md/bcache/bset.c b/drivers/md/bcache/bset.c index 646fe85261c1..158eae17031c 100644 --- a/drivers/md/bcache/bset.c +++ b/drivers/md/bcache/bset.c @@ -823,12 +823,22 @@ unsigned bch_btree_insert_key(struct btree_keys *b, struct bkey *k, struct bset *i = bset_tree_last(b)->data; struct bkey *m, *prev = NULL; struct btree_iter iter; + struct bkey preceding_key_on_stack = ZERO_KEY; + struct bkey *preceding_key_p = &preceding_key_on_stack; BUG_ON(b->ops->is_extents && !KEY_SIZE(k)); - m = bch_btree_iter_init(b, &iter, b->ops->is_extents - ? PRECEDING_KEY(&START_KEY(k)) - : PRECEDING_KEY(k)); + /* + * If k has preceding key, preceding_key_p will be set to address + * of k's preceding key; otherwise preceding_key_p will be set + * to NULL inside preceding_key(). + */ + if (b->ops->is_extents) + preceding_key(&START_KEY(k), &preceding_key_p); + else + preceding_key(k, &preceding_key_p); + + m = bch_btree_iter_init(b, &iter, preceding_key_p); if (b->ops->insert_fixup(b, k, &iter, replace_key)) return status; diff --git a/drivers/md/bcache/bset.h b/drivers/md/bcache/bset.h index ae964624efb2..b935839ab79c 100644 --- a/drivers/md/bcache/bset.h +++ b/drivers/md/bcache/bset.h @@ -417,20 +417,26 @@ static inline bool bch_cut_back(const struct bkey *where, struct bkey *k) return __bch_cut_back(where, k); } -#define PRECEDING_KEY(_k) \ -({ \ - struct bkey *_ret = NULL; \ - \ - if (KEY_INODE(_k) || KEY_OFFSET(_k)) { \ - _ret = &KEY(KEY_INODE(_k), KEY_OFFSET(_k), 0); \ - \ - if (!_ret->low) \ - _ret->high--; \ - _ret->low--; \ - } \ - \ - _ret; \ -}) +/* + * Pointer '*preceding_key_p' points to a memory object to store preceding + * key of k. If the preceding key does not exist, set '*preceding_key_p' to + * NULL. So the caller of preceding_key() needs to take care of memory + * which '*preceding_key_p' pointed to before calling preceding_key(). + * Currently the only caller of preceding_key() is bch_btree_insert_key(), + * and it points to an on-stack variable, so the memory release is handled + * by stackframe itself. + */ +static inline void preceding_key(struct bkey *k, struct bkey **preceding_key_p) +{ + if (KEY_INODE(k) || KEY_OFFSET(k)) { + (**preceding_key_p) = KEY(KEY_INODE(k), KEY_OFFSET(k), 0); + if (!(*preceding_key_p)->low) + (*preceding_key_p)->high--; + (*preceding_key_p)->low--; + } else { + (*preceding_key_p) = NULL; + } +} static inline bool bch_ptr_invalid(struct btree_keys *b, const struct bkey *k) { diff --git a/drivers/md/bcache/journal.c b/drivers/md/bcache/journal.c index c76a0176b5c6..6ee5370eb916 100644 --- a/drivers/md/bcache/journal.c +++ b/drivers/md/bcache/journal.c @@ -309,6 +309,18 @@ void bch_journal_mark(struct cache_set *c, struct list_head *list) } } +bool is_discard_enabled(struct cache_set *s) +{ + struct cache *ca; + unsigned int i; + + for_each_cache(ca, s, i) + if (ca->discard) + return true; + + return false; +} + int bch_journal_replay(struct cache_set *s, struct list_head *list) { int ret = 0, keys = 0, entries = 0; @@ -322,9 +334,17 @@ int bch_journal_replay(struct cache_set *s, struct list_head *list) list_for_each_entry(i, list, list) { BUG_ON(i->pin && atomic_read(i->pin) != 1); - cache_set_err_on(n != i->j.seq, s, -"bcache: journal entries %llu-%llu missing! (replaying %llu-%llu)", - n, i->j.seq - 1, start, end); + if (n != i->j.seq) { + if (n == start && is_discard_enabled(s)) + pr_info("bcache: journal entries %llu-%llu may be discarded! (replaying %llu-%llu)", + n, i->j.seq - 1, start, end); + else { + pr_err("bcache: journal entries %llu-%llu missing! (replaying %llu-%llu)", + n, i->j.seq - 1, start, end); + ret = -EIO; + goto err; + } + } for (k = i->j.start; k < bset_bkey_last(&i->j); diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c index 8031bb2f2d4e..298e45d9212e 100644 --- a/drivers/md/bcache/super.c +++ b/drivers/md/bcache/super.c @@ -1561,7 +1561,7 @@ err: return NULL; } -static void run_cache_set(struct cache_set *c) +static int run_cache_set(struct cache_set *c) { const char *err = "cannot allocate memory"; struct cached_dev *dc, *t; @@ -1653,7 +1653,9 @@ static void run_cache_set(struct cache_set *c) if (j->version < BCACHE_JSET_VERSION_UUID) __uuid_write(c); - bch_journal_replay(c, &journal); + err = "bcache: replay journal failed"; + if (bch_journal_replay(c, &journal)) + goto err; } else { pr_notice("invalidating existing data"); @@ -1721,11 +1723,13 @@ static void run_cache_set(struct cache_set *c) flash_devs_run(c); set_bit(CACHE_SET_RUNNING, &c->flags); - return; + return 0; err: closure_sync(&cl); /* XXX: test this, it's broken */ bch_cache_set_error(c, "%s", err); + + return -EIO; } static bool can_attach_cache(struct cache *ca, struct cache_set *c) @@ -1789,8 +1793,11 @@ found: ca->set->cache[ca->sb.nr_this_dev] = ca; c->cache_by_alloc[c->caches_loaded++] = ca; - if (c->caches_loaded == c->sb.nr_in_set) - run_cache_set(c); + if (c->caches_loaded == c->sb.nr_in_set) { + err = "failed to run cache set"; + if (run_cache_set(c) < 0) + goto err; + } return NULL; err: diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 46b3227eff20..f15f21928f7e 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -224,8 +224,8 @@ static int verity_handle_err(struct dm_verity *v, enum verity_block_type type, BUG(); } - DMERR("%s: %s block %llu is corrupted", v->data_dev->name, type_str, - block); + DMERR_LIMIT("%s: %s block %llu is corrupted", v->data_dev->name, + type_str, block); if (v->corrupted_errs == DM_VERITY_MAX_CORRUPTED_ERRS) DMERR("%s: reached maximum errors", v->data_dev->name); diff --git a/drivers/md/md.c b/drivers/md/md.c index 527ba287275d..bb65392c9aa5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -7296,9 +7296,9 @@ static void status_unused(struct seq_file *seq) static int status_resync(struct seq_file *seq, struct mddev *mddev) { sector_t max_sectors, resync, res; - unsigned long dt, db; - sector_t rt; - int scale; + unsigned long dt, db = 0; + sector_t rt, curr_mark_cnt, resync_mark_cnt; + int scale, recovery_active; unsigned int per_milli; if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) || @@ -7368,22 +7368,30 @@ static int status_resync(struct seq_file *seq, struct mddev *mddev) * db: blocks written from mark until now * rt: remaining time * - * rt is a sector_t, so could be 32bit or 64bit. - * So we divide before multiply in case it is 32bit and close - * to the limit. - * We scale the divisor (db) by 32 to avoid losing precision - * near the end of resync when the number of remaining sectors - * is close to 'db'. - * We then divide rt by 32 after multiplying by db to compensate. - * The '+1' avoids division by zero if db is very small. + * rt is a sector_t, which is always 64bit now. We are keeping + * the original algorithm, but it is not really necessary. + * + * Original algorithm: + * So we divide before multiply in case it is 32bit and close + * to the limit. + * We scale the divisor (db) by 32 to avoid losing precision + * near the end of resync when the number of remaining sectors + * is close to 'db'. + * We then divide rt by 32 after multiplying by db to compensate. + * The '+1' avoids division by zero if db is very small. */ dt = ((jiffies - mddev->resync_mark) / HZ); if (!dt) dt++; - db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active)) - - mddev->resync_mark_cnt; + + curr_mark_cnt = mddev->curr_mark_cnt; + recovery_active = atomic_read(&mddev->recovery_active); + resync_mark_cnt = mddev->resync_mark_cnt; + + if (curr_mark_cnt >= (recovery_active + resync_mark_cnt)) + db = curr_mark_cnt - (recovery_active + resync_mark_cnt); rt = max_sectors - resync; /* number of remaining sectors */ - sector_div(rt, db/32+1); + rt = div64_u64(rt, db/32+1); rt *= dt; rt >>= 5; diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c index 31f16105184c..59a4563c0466 100644 --- a/drivers/media/dvb-frontends/m88ds3103.c +++ b/drivers/media/dvb-frontends/m88ds3103.c @@ -309,6 +309,9 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) u16 u16tmp; u32 tuner_frequency_khz, target_mclk; s32 s32tmp; + static const struct reg_sequence reset_buf[] = { + {0x07, 0x80}, {0x07, 0x00} + }; dev_dbg(&client->dev, "delivery_system=%d modulation=%d frequency=%u symbol_rate=%d inversion=%d pilot=%d rolloff=%d\n", @@ -321,11 +324,7 @@ static int m88ds3103_set_frontend(struct dvb_frontend *fe) } /* reset */ - ret = regmap_write(dev->regmap, 0x07, 0x80); - if (ret) - goto err; - - ret = regmap_write(dev->regmap, 0x07, 0x00); + ret = regmap_multi_reg_write(dev->regmap, reset_buf, 2); if (ret) goto err; diff --git a/drivers/media/i2c/ov2659.c b/drivers/media/i2c/ov2659.c index 1f999e9c0118..3554eea77e04 100644 --- a/drivers/media/i2c/ov2659.c +++ b/drivers/media/i2c/ov2659.c @@ -1117,8 +1117,10 @@ static int ov2659_set_fmt(struct v4l2_subdev *sd, if (ov2659_formats[index].code == mf->code) break; - if (index < 0) - return -EINVAL; + if (index < 0) { + index = 0; + mf->code = ov2659_formats[index].code; + } mf->colorspace = V4L2_COLORSPACE_SRGB; mf->code = ov2659_formats[index].code; diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c index e21b7e1c2ee1..fc187c5aeb1e 100644 --- a/drivers/media/i2c/soc_camera/ov6650.c +++ b/drivers/media/i2c/soc_camera/ov6650.c @@ -840,9 +840,16 @@ static int ov6650_video_probe(struct i2c_client *client) u8 pidh, pidl, midh, midl; int ret; + priv->clk = v4l2_clk_get(&client->dev, NULL); + if (IS_ERR(priv->clk)) { + ret = PTR_ERR(priv->clk); + dev_err(&client->dev, "v4l2_clk request err: %d\n", ret); + return ret; + } + ret = ov6650_s_power(&priv->subdev, 1); if (ret < 0) - return ret; + goto eclkput; msleep(20); @@ -879,6 +886,11 @@ static int ov6650_video_probe(struct i2c_client *client) done: ov6650_s_power(&priv->subdev, 0); + if (!ret) + return 0; +eclkput: + v4l2_clk_put(priv->clk); + return ret; } @@ -1035,18 +1047,9 @@ static int ov6650_probe(struct i2c_client *client, priv->code = MEDIA_BUS_FMT_YUYV8_2X8; priv->colorspace = V4L2_COLORSPACE_JPEG; - priv->clk = v4l2_clk_get(&client->dev, NULL); - if (IS_ERR(priv->clk)) { - ret = PTR_ERR(priv->clk); - goto eclkget; - } - ret = ov6650_video_probe(client); - if (ret) { - v4l2_clk_put(priv->clk); -eclkget: + if (ret) v4l2_ctrl_handler_free(&priv->hdl); - } return ret; } diff --git a/drivers/media/pci/saa7146/hexium_gemini.c b/drivers/media/pci/saa7146/hexium_gemini.c index c889ec9f8a5a..f5fc8bcbd14b 100644 --- a/drivers/media/pci/saa7146/hexium_gemini.c +++ b/drivers/media/pci/saa7146/hexium_gemini.c @@ -270,9 +270,8 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d /* enable i2c-port pins */ saa7146_write(dev, MC1, (MASK_08 | MASK_24 | MASK_10 | MASK_26)); - hexium->i2c_adapter = (struct i2c_adapter) { - .name = "hexium gemini", - }; + strscpy(hexium->i2c_adapter.name, "hexium gemini", + sizeof(hexium->i2c_adapter.name)); saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S("cannot register i2c-device. skipping.\n"); diff --git a/drivers/media/pci/saa7146/hexium_orion.c b/drivers/media/pci/saa7146/hexium_orion.c index c306a92e8909..dc07ca37ebd0 100644 --- a/drivers/media/pci/saa7146/hexium_orion.c +++ b/drivers/media/pci/saa7146/hexium_orion.c @@ -232,9 +232,8 @@ static int hexium_probe(struct saa7146_dev *dev) saa7146_write(dev, DD1_STREAM_B, 0x00000000); saa7146_write(dev, MC2, (MASK_09 | MASK_25 | MASK_10 | MASK_26)); - hexium->i2c_adapter = (struct i2c_adapter) { - .name = "hexium orion", - }; + strscpy(hexium->i2c_adapter.name, "hexium orion", + sizeof(hexium->i2c_adapter.name)); saa7146_i2c_adapter_prepare(dev, &hexium->i2c_adapter, SAA7146_I2C_BUS_BIT_RATE_480); if (i2c_add_adapter(&hexium->i2c_adapter) < 0) { DEB_S("cannot register i2c-device. skipping.\n"); diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index b6625047250d..717ee9a6a80e 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -1829,6 +1829,9 @@ static int coda_prepare_decode(struct coda_ctx *ctx) /* Clear decode success flag */ coda_write(dev, 0, CODA_RET_DEC_PIC_SUCCESS); + /* Clear error return value */ + coda_write(dev, 0, CODA_RET_DEC_PIC_ERR_MB); + trace_coda_dec_pic_run(ctx, meta); coda_command_async(ctx, CODA_COMMAND_PIC_RUN); diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c index 8c2853b5cc62..927e00bb54e6 100644 --- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2017-2019, 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 @@ -51,6 +51,10 @@ int cam_cci_init(struct v4l2_subdev *sd, CAM_DBG(CAM_CCI, "master %d", master); if (master < MASTER_MAX && master >= 0) { mutex_lock(&cci_dev->cci_master_info[master].mutex); + mutex_lock(&cci_dev-> + cci_master_info[master].mutex_q[QUEUE_0]); + mutex_lock(&cci_dev-> + cci_master_info[master].mutex_q[QUEUE_1]); flush_workqueue(cci_dev->write_wq[master]); /* Re-initialize the completion */ reinit_completion( @@ -73,6 +77,10 @@ int cam_cci_init(struct v4l2_subdev *sd, CCI_TIMEOUT); if (rc <= 0) CAM_ERR(CAM_CCI, "wait failed %d", rc); + mutex_unlock(&cci_dev-> + cci_master_info[master].mutex_q[QUEUE_1]); + mutex_unlock(&cci_dev-> + cci_master_info[master].mutex_q[QUEUE_0]); mutex_unlock(&cci_dev->cci_master_info[master].mutex); } return 0; diff --git a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c index 576d5d6742dd..e63c79abcdbb 100644 --- a/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c +++ b/drivers/media/platform/msm/camera_v2/pproc/cpp/msm_cpp.c @@ -1571,12 +1571,6 @@ static int cpp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) pr_debug("DEBUG_R1: 0x%x\n", msm_camera_io_r(cpp_dev->cpp_hw_base + 0x8C)); - /* Update bandwidth usage to enable AXI/ABH clock, - * which will help to reset CPP AXI.Bandwidth will be - * made zero at cpp_release_hardware. - */ - msm_cpp_update_bandwidth(cpp_dev, 0x1000, 0x1000); - /* mask IRQ status */ msm_camera_io_w(0xB, cpp_dev->cpp_hw_base + 0xC); @@ -3657,6 +3651,8 @@ STREAM_BUFF_END: } else { ioctl_cmd = VIDIOC_MSM_BUF_MNGR_IOCTL_CMD; idx = MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX; + buff_mgr_info.index = + frame_info.output_buffer_info[0].index; } rc = msm_cpp_buffer_ops(cpp_dev, ioctl_cmd, idx, &buff_mgr_info); @@ -4370,6 +4366,8 @@ static long msm_cpp_subdev_fops_compat_ioctl(struct file *file, memset(&k64_frame_info, 0, sizeof(k64_frame_info)); k64_frame_info.identity = k32_frame_info.identity; k64_frame_info.frame_id = k32_frame_info.frame_id; + k64_frame_info.output_buffer_info[0].index = + k32_frame_info.output_buffer_info[0].index; kp_ioctl.ioctl_ptr = (__force void __user *)&k64_frame_info; diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h index 6b7a9007cff9..2afdafb03184 100644 --- a/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_hw_mgr_intf.h @@ -262,6 +262,16 @@ struct cam_hw_dump_pf_args { bool *mem_found; }; +/** + * struct cam_hw_reset_args -hw reset arguments + * + * @ctxt_to_hw_map: HW context from the acquire + * + */ +struct cam_hw_reset_args { + void *ctxt_to_hw_map; +}; + /* enum cam_hw_mgr_command - Hardware manager command type */ enum cam_hw_mgr_command { CAM_HW_MGR_CMD_INTERNAL, @@ -313,6 +323,7 @@ struct cam_hw_cmd_args { * @hw_open: Function pointer for HW init * @hw_close: Function pointer for HW deinit * @hw_flush: Function pointer for HW flush + * @hw_reset: Function pointer for HW reset * */ struct cam_hw_mgr_intf { @@ -333,6 +344,7 @@ struct cam_hw_mgr_intf { int (*hw_open)(void *hw_priv, void *fw_download_args); int (*hw_close)(void *hw_priv, void *hw_close_args); int (*hw_flush)(void *hw_priv, void *hw_flush_args); + int (*hw_reset)(void *hw_priv, void *hw_reset_args); }; #endif /* _CAM_HW_MGR_INTF_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c index a68032cf6c19..a68e20745b1a 100644 --- a/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c +++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cam_cpas_hw.c @@ -980,8 +980,10 @@ static int cam_cpas_hw_start(void *hw_priv, void *start_args, return -EINVAL; } - if (!CAM_CPAS_CLIENT_VALID(client_indx)) + if (!CAM_CPAS_CLIENT_VALID(client_indx)) { + CAM_ERR(CAM_CPAS, "Client index invalid %d", client_indx); return -EINVAL; + } mutex_lock(&cpas_hw->hw_mutex); mutex_lock(&cpas_core->client_mutex[client_indx]); @@ -1099,8 +1101,10 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, cmd_hw_stop = (struct cam_cpas_hw_cmd_stop *)stop_args; client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_stop->client_handle); - if (!CAM_CPAS_CLIENT_VALID(client_indx)) + if (!CAM_CPAS_CLIENT_VALID(client_indx)) { + CAM_ERR(CAM_CPAS, "Client index invalid %d", client_indx); return -EINVAL; + } mutex_lock(&cpas_hw->hw_mutex); mutex_lock(&cpas_core->client_mutex[client_indx]); @@ -1162,14 +1166,20 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, ahb_vote.vote.level = CAM_SUSPEND_VOTE; rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client, &ahb_vote, NULL); - if (rc) + if (rc) { + CAM_ERR(CAM_CPAS, "ahb vote failed for %s rc %d", + cpas_client->data.identifier, rc); goto done; + } axi_vote.uncompressed_bw = 0; axi_vote.compressed_bw = 0; axi_vote.compressed_bw_ab = 0; rc = cam_cpas_util_apply_client_axi_vote(cpas_hw, cpas_client, &axi_vote); + if (rc) + CAM_ERR(CAM_CPAS, "axi vote failed for %s rc %d", + cpas_client->data.identifier, rc); done: mutex_unlock(&cpas_core->client_mutex[client_indx]); diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c index 719fb12d7353..aaa435d34f4c 100644 --- a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c +++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cam_cpastop_hw.c @@ -21,6 +21,7 @@ #include "cam_cpas_soc.h" #include "cpastop100.h" #include "cpastop_v150_100.h" +#include "cpastop_v150_110.h" #include "cpastop_v170_110.h" #include "cpastop_v175_100.h" #include "cpastop_v175_101.h" @@ -117,6 +118,10 @@ static int cam_cpastop_get_hw_info(struct cam_hw_info *cpas_hw, (hw_caps->cpas_version.minor == 0) && (hw_caps->cpas_version.incr == 0)) soc_info->hw_version = CAM_CPAS_TITAN_150_V100; + else if ((hw_caps->cpas_version.major == 1) && + (hw_caps->cpas_version.minor == 1) && + (hw_caps->cpas_version.incr == 0)) + soc_info->hw_version = CAM_CPAS_TITAN_150_V110; } CAM_DBG(CAM_CPAS, "CPAS HW VERSION %x", soc_info->hw_version); @@ -668,6 +673,9 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, case CAM_CPAS_TITAN_150_V100: camnoc_info = &cam150_cpas100_camnoc_info; break; + case CAM_CPAS_TITAN_150_V110: + camnoc_info = &cam150_cpas110_camnoc_info; + break; default: CAM_ERR(CAM_CPAS, "Camera Version not supported %d.%d.%d", hw_caps->camera_version.major, diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_110.h b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_110.h new file mode 100644 index 000000000000..734f3784ef6c --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_cpas/cpas_top/cpastop_v150_110.h @@ -0,0 +1,537 @@ +/* Copyright (c) 2019, 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. + */ + +#ifndef _CPASTOP_V150_110_H_ +#define _CPASTOP_V150_110_H_ + +#define TEST_IRQ_ENABLE 0 + +static struct cam_camnoc_irq_sbm cam_cpas_v150_110_irq_sbm = { + .sbm_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2040, /* SBM_FAULTINEN0_LOW */ + .value = 0x1 | /* SBM_FAULTINEN0_LOW_PORT0_MASK*/ + 0x2 | /* SBM_FAULTINEN0_LOW_PORT1_MASK */ + 0x4 | /* SBM_FAULTINEN0_LOW_PORT2_MASK */ + 0x8 | /* SBM_FAULTINEN0_LOW_PORT3_MASK */ + 0x10 | /* SBM_FAULTINEN0_LOW_PORT4_MASK */ + 0x20 | /* SBM_FAULTINEN0_LOW_PORT5_MASK */ + (TEST_IRQ_ENABLE ? + 0x100 : /* SBM_FAULTINEN0_LOW_PORT8_MASK */ + 0x0), + }, + .sbm_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2048, /* SBM_FAULTINSTATUS0_LOW */ + }, + .sbm_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2080, /* SBM_FLAGOUTCLR0_LOW */ + .value = TEST_IRQ_ENABLE ? 0x6 : 0x2, + } +}; + +static struct cam_camnoc_irq_err + cam_cpas_v150_110_irq_err[] = { + { + .irq_type = CAM_CAMNOC_HW_IRQ_SLAVE_ERROR, + .enable = true, + .sbm_port = 0x1, /* SBM_FAULTINSTATUS0_LOW_PORT0_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2708, /* ERRLOGGER_MAINCTL_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2710, /* ERRLOGGER_ERRVLD_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x2718, /* ERRLOGGER_ERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE02_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x2, /* SBM_FAULTINSTATUS0_LOW_PORT1_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x5a0, /* SPECIFIC_IFE02_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x590, /* SPECIFIC_IFE02_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x598, /* SPECIFIC_IFE02_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IFE13_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x4, /* SBM_FAULTINSTATUS0_LOW_PORT2_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x9a0, /* SPECIFIC_IFE13_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x990, /* SPECIFIC_IFE13_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x998, /* SPECIFIC_IFE13_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_DECODE_ERROR, + .enable = true, + .sbm_port = 0x8, /* SBM_FAULTINSTATUS0_LOW_PORT3_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0xd20, /* SPECIFIC_IBL_RD_DECERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0xd10, /* SPECIFIC_IBL_RD_DECERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0xd18, /* SPECIFIC_IBL_RD_DECERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_IPE_BPS_UBWC_ENCODE_ERROR, + .enable = true, + .sbm_port = 0x10, /* SBM_FAULTINSTATUS0_LOW_PORT4_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x11a0, /* SPECIFIC_IBL_WR_ENCERREN_LOW */ + .value = 1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x1190, + /* SPECIFIC_IBL_WR_ENCERRSTATUS_LOW */ + }, + .err_clear = { + .access_type = CAM_REG_TYPE_WRITE, + .enable = true, + .offset = 0x1198, /* SPECIFIC_IBL_WR_ENCERRCLR_LOW */ + .value = 1, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_AHB_TIMEOUT, + .enable = true, + .sbm_port = 0x20, /* SBM_FAULTINSTATUS0_LOW_PORT5_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x1, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED1, + .enable = false, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_RESERVED2, + .enable = false, + }, + { + .irq_type = CAM_CAMNOC_HW_IRQ_CAMNOC_TEST, + .enable = TEST_IRQ_ENABLE ? true : false, + .sbm_port = 0x100, /* SBM_FAULTINSTATUS0_LOW_PORT8_MASK */ + .err_enable = { + .access_type = CAM_REG_TYPE_READ_WRITE, + .enable = true, + .offset = 0x2088, /* SBM_FLAGOUTSET0_LOW */ + .value = 0x5, + }, + .err_status = { + .access_type = CAM_REG_TYPE_READ, + .enable = true, + .offset = 0x2090, /* SBM_FLAGOUTSTATUS0_LOW */ + }, + .err_clear = { + .enable = false, + }, + }, +}; + +static struct cam_camnoc_specific + cam_cpas_v150_110_camnoc_specific[] = { + { + .port_type = CAM_CAMNOC_CDM, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x30, /* SPECIFIC_CDM_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x34, /* SPECIFIC_CDM_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x38, /* SPECIFIC_CDM_URGENCY_LOW */ + .mask = 0x7, /* SPECIFIC_CDM_URGENCY_LOW_READ_MASK */ + .shift = 0x0, /* SPECIFIC_CDM_URGENCY_LOW_READ_SHIFT */ + .value = 0x2, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x40, /* SPECIFIC_CDM_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x48, /* SPECIFIC_CDM_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE02, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x430, /* SPECIFIC_IFE02_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x438, /* SPECIFIC_IFE02_URGENCY_LOW */ + /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* SPECIFIC_IFE02_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x440, /* SPECIFIC_IFE02_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x448, /* SPECIFIC_IFE02_SAFELUT_LOW */ + .value = 0x1, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IFE13, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x830, /* SPECIFIC_IFE13_PRIORITYLUT_LOW */ + .value = 0x66665433, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */ + .value = 0x66666666, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x838, /* SPECIFIC_IFE13_URGENCY_LOW */ + /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* SPECIFIC_IFE13_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x840, /* SPECIFIC_IFE13_DANGERLUT_LOW */ + .value = 0xFFFFFF00, + }, + .safe_lut = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .offset = 0x848, /* SPECIFIC_IFE13_SAFELUT_LOW */ + .value = 0x1, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_LRME_READ, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc30, /* SPECIFIC_IBL_RD_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc34, /* SPECIFIC_IBL_RD_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0xc38, /* SPECIFIC_IBL_RD_URGENCY_LOW */ + /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_MASK */ + .mask = 0x7, + /* SPECIFIC_IBL_RD_URGENCY_LOW_READ_SHIFT */ + .shift = 0x0, + .value = 3, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc40, /* SPECIFIC_IBL_RD_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xc48, /* SPECIFIC_IBL_RD_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0xd08, /* SPECIFIC_IBL_RD_DECCTL_LOW */ + .value = 1, + }, + }, + { + .port_type = CAM_CAMNOC_IPE_BPS_LRME_WRITE, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1030, /* SPECIFIC_IBL_WR_PRIORITYLUT_LOW */ + .value = 0x33333333, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1034, /* SPECIFIC_IBL_WR_PRIORITYLUT_HIGH */ + .value = 0x33333333, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 1, + .offset = 0x1038, /* SPECIFIC_IBL_WR_URGENCY_LOW */ + /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_MASK */ + .mask = 0x70, + /* SPECIFIC_IBL_WR_URGENCY_LOW_WRITE_SHIFT */ + .shift = 0x4, + .value = 0x30, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1040, /* SPECIFIC_IBL_WR_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1048, /* SPECIFIC_IBL_WR_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1188, /* SPECIFIC_IBL_WR_ENCCTL_LOW */ + .value = 0x5, + }, + }, + { + .port_type = CAM_CAMNOC_JPEG, + .enable = true, + .priority_lut_low = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1430, /* SPECIFIC_JPEG_PRIORITYLUT_LOW */ + .value = 0x22222222, + }, + .priority_lut_high = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1434, /* SPECIFIC_JPEG_PRIORITYLUT_HIGH */ + .value = 0x22222222, + }, + .urgency = { + .enable = true, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1438, /* SPECIFIC_JPEG_URGENCY_LOW */ + .value = 0x22, + }, + .danger_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1440, /* SPECIFIC_JPEG_DANGERLUT_LOW */ + .value = 0x0, + }, + .safe_lut = { + .enable = false, + .access_type = CAM_REG_TYPE_READ_WRITE, + .masked_value = 0, + .offset = 0x1448, /* SPECIFIC_JPEG_SAFELUT_LOW */ + .value = 0x0, + }, + .ubwc_ctl = { + .enable = false, + }, + }, + { + .port_type = CAM_CAMNOC_FD, + .enable = false, + }, + { + .port_type = CAM_CAMNOC_ICP, + .enable = true, + .flag_out_set0_low = { + .enable = true, + .access_type = CAM_REG_TYPE_WRITE, + .masked_value = 0, + .offset = 0x2088, + .value = 0x100000, + }, + }, +}; + +static struct cam_camnoc_err_logger_info cam150_cpas110_err_logger_offsets = { + .mainctrl = 0x2708, /* ERRLOGGER_MAINCTL_LOW */ + .errvld = 0x2710, /* ERRLOGGER_ERRVLD_LOW */ + .errlog0_low = 0x2720, /* ERRLOGGER_ERRLOG0_LOW */ + .errlog0_high = 0x2724, /* ERRLOGGER_ERRLOG0_HIGH */ + .errlog1_low = 0x2728, /* ERRLOGGER_ERRLOG1_LOW */ + .errlog1_high = 0x272c, /* ERRLOGGER_ERRLOG1_HIGH */ + .errlog2_low = 0x2730, /* ERRLOGGER_ERRLOG2_LOW */ + .errlog2_high = 0x2734, /* ERRLOGGER_ERRLOG2_HIGH */ + .errlog3_low = 0x2738, /* ERRLOGGER_ERRLOG3_LOW */ + .errlog3_high = 0x273c, /* ERRLOGGER_ERRLOG3_HIGH */ +}; + +static struct cam_cpas_hw_errata_wa_list cam150_cpas110_errata_wa_list = { + .camnoc_flush_slave_pending_trans = { + .enable = false, + .data.reg_info = { + .access_type = CAM_REG_TYPE_READ, + .offset = 0x2100, /* SidebandManager_SenseIn0_Low */ + .mask = 0xE0000, /* Bits 17, 18, 19 */ + .value = 0, /* expected to be 0 */ + }, + }, +}; + +static struct cam_camnoc_info cam150_cpas110_camnoc_info = { + .specific = &cam_cpas_v150_110_camnoc_specific[0], + .specific_size = sizeof(cam_cpas_v150_110_camnoc_specific) / + sizeof(cam_cpas_v150_110_camnoc_specific[0]), + .irq_sbm = &cam_cpas_v150_110_irq_sbm, + .irq_err = &cam_cpas_v150_110_irq_err[0], + .irq_err_size = sizeof(cam_cpas_v150_110_irq_err) / + sizeof(cam_cpas_v150_110_irq_err[0]), + .err_logger = &cam150_cpas110_err_logger_offsets, + .errata_wa_list = &cam150_cpas110_errata_wa_list, +}; + +#endif /* _CPASTOP_V150_110_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_cpas/include/cam_cpas_api.h b/drivers/media/platform/msm/camera_v3/cam_cpas/include/cam_cpas_api.h index 7b534a93c71d..f2858631ce29 100644 --- a/drivers/media/platform/msm/camera_v3/cam_cpas/include/cam_cpas_api.h +++ b/drivers/media/platform/msm/camera_v3/cam_cpas/include/cam_cpas_api.h @@ -43,6 +43,7 @@ enum cam_cpas_reg_base { enum cam_cpas_hw_version { CAM_CPAS_TITAN_NONE = 0, CAM_CPAS_TITAN_150_V100 = 0x150100, + CAM_CPAS_TITAN_150_V110 = 0x150110, CAM_CPAS_TITAN_170_V100 = 0x170100, CAM_CPAS_TITAN_170_V110 = 0x170110, CAM_CPAS_TITAN_170_V120 = 0x170120, diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/a5_hw/a5_core.c index e13d7f2edcee..4dbc8f1bd991 100644 --- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/a5_hw/a5_core.c @@ -464,7 +464,11 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_A5_CMD_CPAS_STOP: if (core_info->cpas_start) { - cam_cpas_stop(core_info->cpas_handle); + rc = cam_cpas_stop(core_info->cpas_handle); + if (rc) { + CAM_ERR(CAM_ICP, "cpas stop failed %d", rc); + return rc; + } core_info->cpas_start = false; } break; diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c index c94276ce8778..f522f7138765 100644 --- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/bps_hw/bps_core.c @@ -347,7 +347,11 @@ int cam_bps_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_BPS_CMD_CPAS_STOP: if (core_info->cpas_start) { - cam_cpas_stop(core_info->cpas_handle); + rc = cam_cpas_stop(core_info->cpas_handle); + if (rc) { + CAM_ERR(CAM_ICP, "cpas stop failed %d", rc); + return rc; + } core_info->cpas_start = false; } break; diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index cfc474afc633..03b93acbd847 100644 --- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -4077,8 +4077,13 @@ static void cam_icp_mgr_print_io_bufs(struct cam_packet *packet, for (i = 0; i < packet->num_io_configs; i++) { for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { - if (!io_cfg[i].mem_handle[j]) + if (!io_cfg[i].mem_handle[j]) { + CAM_ERR(CAM_ICP, + "Mem Handle %d is NULL for %d io config", + j, i); break; + } + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == GET_FD_FROM_HANDLE(pf_buf_info)) { diff --git a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c index ae3d1343c1c4..ae58b34062d6 100644 --- a/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_icp/icp_hw/ipe_hw/ipe_core.c @@ -342,7 +342,11 @@ int cam_ipe_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_IPE_CMD_CPAS_STOP: if (core_info->cpas_start) { - cam_cpas_stop(core_info->cpas_handle); + rc = cam_cpas_stop(core_info->cpas_handle); + if (rc) { + CAM_ERR(CAM_ICP, "CPAS stop failed %d", rc); + return rc; + } core_info->cpas_start = false; } break; diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c index 1eb7389b2516..53c1c0fd54a9 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.c @@ -452,6 +452,14 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( trace_cam_buf_done("ISP", ctx, req); req_isp = (struct cam_isp_ctx_req *) req->req_priv; + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = done->irq_mono_boot_time; + else if (ctx_isp->fps && ((done->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = done->irq_mono_boot_time; + for (i = 0; i < done->num_handles; i++) { for (j = 0; j < req_isp->num_fence_map_out; j++) { if (done->resource_handle[i] == @@ -565,27 +573,50 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state( ctx_isp->substate_activated); } + if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) { + CAM_ERR(CAM_ISP, "isp req[%lld] IRQ buf done got delayed", + req->request_id); + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + + for (j = 0; j < req_isp->num_fence_map_out; j++) { + rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id, + CAM_SYNC_STATE_SIGNALED_ERROR); + if (rc) + CAM_DBG(CAM_ISP, "Sync failed with rc = %d", + rc); + req_isp->fence_map_out[j].sync_id = -1; + } + list_del_init(&req->list); + list_add_tail(&req->list, &ctx->free_req_list); + ctx_isp->active_req_cnt--; + } + ctx_isp->irq_delay_detect = false; end: return rc; } static void __cam_isp_ctx_send_sof_boot_timestamp( struct cam_isp_context *ctx_isp, uint64_t request_id, - uint32_t sof_event_status) + uint32_t sof_event_status, uint64_t delta_ts) { struct cam_req_mgr_message req_msg; req_msg.session_hdl = ctx_isp->base->session_hdl; req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; req_msg.u.frame_msg.request_id = request_id; - req_msg.u.frame_msg.timestamp = ctx_isp->boot_timestamp; req_msg.u.frame_msg.link_hdl = ctx_isp->base->link_hdl; req_msg.u.frame_msg.sof_status = sof_event_status; + req_msg.u.frame_msg.timestamp = ctx_isp->prev_boot_timestamp + delta_ts; + CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld boot time stamp:0x%llx", - request_id, ctx_isp->frame_id, - ctx_isp->boot_timestamp); + "req id:%lld frame num:%lld bt_ts:0x%llx pre_bt_ts:0x%llx diff:0x%llx", + request_id, ctx_isp->frame_id, + ctx_isp->boot_timestamp, ctx_isp->prev_boot_timestamp, + delta_ts); + if (cam_req_mgr_notify_message(&req_msg, V4L_EVENT_CAM_REQ_MGR_SOF_BOOT_TS, @@ -593,6 +624,8 @@ static void __cam_isp_ctx_send_sof_boot_timestamp( CAM_ERR(CAM_ISP, "Error in notifying the boot time for req id:%lld", request_id); + + ctx_isp->prev_boot_timestamp = req_msg.u.frame_msg.timestamp; } @@ -601,6 +634,7 @@ static void __cam_isp_ctx_send_sof_timestamp( uint32_t sof_event_status) { struct cam_req_mgr_message req_msg; + uint64_t delta_ts; req_msg.session_hdl = ctx_isp->base->session_hdl; req_msg.u.frame_msg.frame_id = ctx_isp->frame_id; @@ -610,9 +644,9 @@ static void __cam_isp_ctx_send_sof_timestamp( req_msg.u.frame_msg.sof_status = sof_event_status; CAM_DBG(CAM_ISP, - "request id:%lld frame number:%lld SOF time stamp:0x%llx", + "request id:%lld frame number:%lld SOF time stamp:0x%llx, Prev SOF time:0x%llx", request_id, ctx_isp->frame_id, - ctx_isp->sof_timestamp_val); + ctx_isp->sof_timestamp_val, ctx_isp->prev_sof_timestamp_val); CAM_DBG(CAM_ISP, "sof status:%d", sof_event_status); if (cam_req_mgr_notify_message(&req_msg, @@ -620,21 +654,64 @@ static void __cam_isp_ctx_send_sof_timestamp( CAM_ERR(CAM_ISP, "Error in notifying the sof time for req id:%lld", request_id); + delta_ts = ctx_isp->sof_timestamp_val - + ctx_isp->prev_sof_timestamp_val; __cam_isp_ctx_send_sof_boot_timestamp(ctx_isp, - request_id, sof_event_status); + request_id, sof_event_status, + (ctx_isp->prev_sof_timestamp_val == 0) ? + ctx_isp->boot_timestamp : + delta_ts); + + ctx_isp->prev_sof_timestamp_val = + ctx_isp->sof_timestamp_val; } static int __cam_isp_ctx_reg_upd_in_epoch_state( struct cam_isp_context *ctx_isp, void *evt_data) { - if (ctx_isp->frame_id == 1) + struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data; + + struct cam_context *ctx = ctx_isp->base; + struct cam_ctx_request *req = NULL; + struct cam_isp_ctx_req *req_isp = NULL; + + if (ctx_isp->frame_id == 1) { CAM_DBG(CAM_ISP, "Reg update for early PCR"); - else + if (!list_empty(&ctx->active_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + } else if (!list_empty(&ctx->wait_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + } + } else { + if (!list_empty(&ctx->wait_req_list)) { + req = list_first_entry(&ctx->active_req_list, + struct cam_ctx_request, list); + req_isp = (struct cam_isp_ctx_req *) req->req_priv; + } CAM_WARN(CAM_ISP, "Unexpected reg update in activated substate:%d for frame_id:%lld", ctx_isp->substate_activated, ctx_isp->frame_id); + } + + if (req_isp && req_isp->hw_update_data.fps) { + ctx_isp->fps = req_isp->hw_update_data.fps; + CAM_DBG(CAM_ISP, "req_isp %pK, Upadting ctx_isp->fps %d", + req_isp, ctx_isp->fps); + } + + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; return 0; } @@ -644,7 +721,8 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( int rc = 0; struct cam_ctx_request *req; struct cam_context *ctx = ctx_isp->base; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; + struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data; if (list_empty(&ctx->wait_req_list)) { CAM_ERR(CAM_ISP, "Reg upd ack with no waiting request"); @@ -669,13 +747,22 @@ static int __cam_isp_ctx_reg_upd_in_activated_state( req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + /* * This function only called directly from applied and bubble applied * state so change substate here. */ ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_EPOCH; CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; end: return rc; } @@ -703,6 +790,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld ctx %u", @@ -802,6 +890,14 @@ static int __cam_isp_ctx_sof_in_activated_state( ctx_isp->sof_timestamp_val = sof_event_data->timestamp; ctx_isp->boot_timestamp = sof_event_data->boot_time; + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((sof_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx, ctx %u", ctx_isp->frame_id, ctx_isp->sof_timestamp_val, ctx->ctx_id); @@ -813,8 +909,9 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp, { int rc = 0; struct cam_ctx_request *req = NULL; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_context *ctx = ctx_isp->base; + struct cam_isp_hw_reg_update_event_data *rup_event_data = evt_data; if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) { CAM_DBG(CAM_ISP, "invalid RUP"); @@ -837,6 +934,16 @@ static int __cam_isp_ctx_reg_upd_in_sof(struct cam_isp_context *ctx_isp, "receive rup in unexpected state"); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((rup_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = rup_event_data->irq_mono_boot_time; end: return rc; } @@ -845,9 +952,10 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, void *evt_data) { struct cam_ctx_request *req; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_context *ctx = ctx_isp->base; uint64_t request_id = 0; + struct cam_isp_hw_epoch_event_data *epoch_hw_event_data = evt_data; if (list_empty(&ctx->wait_req_list)) { /* @@ -913,6 +1021,15 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp, ctx_isp->substate_activated); end: + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = + epoch_hw_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((epoch_hw_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = epoch_hw_event_data->irq_mono_boot_time; + return 0; } @@ -945,6 +1062,14 @@ static int __cam_isp_ctx_sof_in_epoch(struct cam_isp_context *ctx_isp, ctx_isp->sof_timestamp_val = sof_event_data->timestamp; ctx_isp->boot_timestamp = sof_event_data->boot_time; + if (ctx_isp->frame_id == 1) + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + else if (ctx_isp->fps && ((sof_event_data->irq_mono_boot_time - + ctx_isp->irq_timestamps) > ((1000*1000)/ctx_isp->fps))) + ctx_isp->irq_delay_detect = true; + + ctx_isp->irq_timestamps = sof_event_data->irq_mono_boot_time; + if (list_empty(&ctx->active_req_list)) ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; else @@ -1335,6 +1460,7 @@ static int __cam_isp_ctx_fs2_sof_in_sof_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -1426,7 +1552,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp, { int rc = 0; struct cam_ctx_request *req = NULL; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_context *ctx = ctx_isp->base; if (ctx->state != CAM_CTX_ACTIVATED && ctx_isp->frame_id > 1) { @@ -1450,6 +1576,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_sof(struct cam_isp_context *ctx_isp, "receive rup in unexpected state"); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + end: return rc; } @@ -1460,7 +1589,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( int rc = 0; struct cam_ctx_request *req = NULL; struct cam_context *ctx = ctx_isp->base; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_req_mgr_trigger_notify notify; uint64_t request_id = 0; @@ -1483,6 +1612,9 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( list_add_tail(&req->list, &ctx->free_req_list); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + /* * This function only called directly from applied and bubble applied * state so change substate here. @@ -1512,6 +1644,7 @@ static int __cam_isp_ctx_fs2_reg_upd_in_applied_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -1905,16 +2038,19 @@ static int __cam_isp_ctx_flush_req_in_top_state( struct cam_req_mgr_flush_request *flush_req) { int rc = 0; - struct cam_isp_context *ctx_isp; - - ctx_isp = (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_context *ctx_isp = + (struct cam_isp_context *) ctx->ctx_priv; + struct cam_isp_stop_args stop_isp; + struct cam_hw_stop_args stop_args; + struct cam_isp_start_args start_isp; + struct cam_hw_reset_args reset_args; if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { - CAM_INFO(CAM_ISP, "Last request id to flush is %lld", - flush_req->req_id); + CAM_INFO(CAM_ISP, "ctx id:%d Last request id to flush is %lld", + ctx->ctx_id, flush_req->req_id); ctx->last_flush_req = flush_req->req_id; } - CAM_DBG(CAM_ISP, "try to flush pending list"); + CAM_DBG(CAM_ISP, "ctx id:%d try to flush pending list", ctx->ctx_id); spin_lock_bh(&ctx->lock); rc = __cam_isp_ctx_flush_req(ctx, &ctx->pending_req_list, flush_req); @@ -1937,6 +2073,57 @@ static int __cam_isp_ctx_flush_req_in_top_state( spin_unlock_bh(&ctx->lock); atomic_set(&ctx_isp->process_bubble, 0); + if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_ALL) { + /* if active and wait list are empty, return */ + spin_lock_bh(&ctx->lock); + if ((list_empty(&ctx->wait_req_list)) && + (list_empty(&ctx->active_req_list))) { + spin_unlock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "ctx id:%d active,wait list are empty", + ctx->ctx_id); + goto end; + } + spin_unlock_bh(&ctx->lock); + + /* Stop hw first before active list flush */ + CAM_DBG(CAM_ISP, "ctx id:%d try to stop hw", ctx->ctx_id); + stop_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + stop_isp.hw_stop_cmd = CAM_ISP_HW_STOP_AT_FRAME_BOUNDARY; + stop_isp.stop_only = true; + stop_args.args = (void *)&stop_isp; + ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv, + &stop_args); + + spin_lock_bh(&ctx->lock); + CAM_DBG(CAM_ISP, "try to flush wait list"); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->wait_req_list, + flush_req); + CAM_DBG(CAM_ISP, "try to flush active list"); + rc = __cam_isp_ctx_flush_req(ctx, &ctx->active_req_list, + flush_req); + ctx_isp->active_req_cnt = 0; + spin_unlock_bh(&ctx->lock); + + CAM_DBG(CAM_ISP, "try to reset hw"); + /* Reset hw */ + reset_args.ctxt_to_hw_map = ctx_isp->hw_ctx; + rc = ctx->hw_mgr_intf->hw_reset(ctx->hw_mgr_intf->hw_mgr_priv, + &reset_args); + if (rc) + goto end; + + CAM_DBG(CAM_ISP, "ctx id%d try to start hw", ctx->ctx_id); + /* Start hw */ + start_isp.hw_config.ctxt_to_hw_map = ctx_isp->hw_ctx; + start_isp.start_only = true; + start_isp.hw_config.priv = NULL; + + rc = ctx->hw_mgr_intf->hw_start(ctx->hw_mgr_intf->hw_mgr_priv, + &start_isp); + } + +end: + ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF; return rc; } @@ -2100,6 +2287,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_top_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -2291,6 +2479,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -2320,7 +2509,7 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( { struct cam_ctx_request *req; struct cam_context *ctx = ctx_isp->base; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; struct cam_req_mgr_trigger_notify notify; uint64_t request_id = 0; @@ -2361,6 +2550,7 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( notify.dev_hdl = ctx->dev_hdl; notify.frame_id = ctx_isp->frame_id; notify.trigger = CAM_TRIGGER_POINT_SOF; + notify.sof_timestamp_val = ctx_isp->sof_timestamp_val; ctx->ctx_crm_intf->notify_trigger(¬ify); CAM_DBG(CAM_ISP, "Notify CRM SOF frame %lld", @@ -2374,6 +2564,9 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state( jiffies_to_msecs(jiffies); } + if (req_isp && req_isp->hw_update_data.fps) + ctx_isp->fps = req_isp->hw_update_data.fps; + __cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id, CAM_REQ_MGR_SOF_EVENT_SUCCESS); CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated); @@ -2649,7 +2842,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( { int rc = 0, i; struct cam_ctx_request *req = NULL; - struct cam_isp_ctx_req *req_isp; + struct cam_isp_ctx_req *req_isp = NULL; uintptr_t packet_addr; struct cam_packet *packet; size_t len = 0; @@ -2738,6 +2931,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( rc = -EFAULT; goto free_cpu_buf; } + req_isp->num_cfg = cfg.num_hw_update_entries; req_isp->num_fence_map_out = cfg.num_out_map_entries; req_isp->num_fence_map_in = cfg.num_in_map_entries; @@ -2794,6 +2988,7 @@ static int __cam_isp_ctx_config_dev_in_top_state( CAM_ERR(CAM_ISP, "Recevied Update in wrong state"); } } + if (rc) goto put_ref; @@ -3383,6 +3578,8 @@ static int __cam_isp_ctx_stop_dev_in_activated_unlock( ctx_isp->req_info.last_applied_time_stamp = 0; ctx_isp->req_info.last_bufdone_time_stamp = 0; ctx_isp->req_info.last_reported_id_time_stamp = 0; + ctx_isp->prev_sof_timestamp_val = 0; + ctx_isp->prev_boot_timestamp = 0; atomic_set(&ctx_isp->process_bubble, 0); @@ -3573,8 +3770,6 @@ static int __cam_isp_ctx_apply_req(struct cam_context *ctx, return rc; } - - static int __cam_isp_ctx_handle_irq_in_activated(void *context, uint32_t evt_id, void *evt_data) { diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h index bec84a85391c..cb73252363db 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/cam_isp_context.h @@ -35,6 +35,11 @@ #define CAM_ISP_CTX_CFG_MAX 22 /* + * Defalut fps value set to 30 + */ +#define CAM_ISP_CTX_DEFAULT_FPS 30 + +/* * Maximum entries in state monitoring array for error logging */ #define CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES 20 @@ -165,7 +170,9 @@ struct cam_isp_context_req_id_info { * @req_isp: ISP private request object storage * @hw_ctx: HW object returned by the acquire device command * @sof_timestamp_val: Captured time stamp value at sof hw event + * @prev_sof_timestamp_val Holds last notified sof time stamp * @boot_timestamp: Boot time stamp for a given req_id + * @prev_boot_timestamp Holds last notified boot time stamp * @active_req_cnt: Counter for the active request * @subscribe_event: The irq event mask that CRM subscribes to, IFE * will invoke CRM cb at those event. @@ -178,6 +185,9 @@ struct cam_isp_context_req_id_info { * @hw_acquired: Indicate whether HW resources are acquired * @init_received: Indicate whether init config packet is received * @split_acquire: Indicate whether a separate acquire is expected + * @irq_delay_detect: Indicate whether a irq delay has detected or not + * @irq_timestamps: Timestamp from last handled IRQ + * @fps: Current FPS for the activated state. * */ struct cam_isp_context { @@ -194,7 +204,9 @@ struct cam_isp_context { void *hw_ctx; uint64_t sof_timestamp_val; + uint64_t prev_sof_timestamp_val; uint64_t boot_timestamp; + uint64_t prev_boot_timestamp; int32_t active_req_cnt; uint32_t subscribe_event; atomic64_t state_monitor_head; @@ -205,6 +217,9 @@ struct cam_isp_context { bool hw_acquired; bool init_received; bool split_acquire; + bool irq_delay_detect; + uint64_t irq_timestamps; + uint32_t fps; }; /** diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c index 9b4839261c3e..91e1e74f7360 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c @@ -146,6 +146,74 @@ static int cam_ife_hw_mgr_is_rdi_res(uint32_t res_id) return rc; } +static const char *cam_ife_hw_mgr_get_res_id( + enum cam_ife_pix_path_res_id csid_res_id) +{ + char *res_name = NULL; + + switch (csid_res_id) { + case CAM_IFE_PIX_PATH_RES_RDI_0: + res_name = "RDI_0"; + break; + case CAM_IFE_PIX_PATH_RES_RDI_1: + res_name = "RDI_1"; + break; + case CAM_IFE_PIX_PATH_RES_RDI_2: + res_name = "RDI_2"; + break; + case CAM_IFE_PIX_PATH_RES_RDI_3: + res_name = "RDI_3"; + break; + case CAM_IFE_PIX_PATH_RES_IPP: + res_name = "IPP"; + break; + case CAM_IFE_PIX_PATH_RES_PPP: + res_name = "PPP"; + break; + case CAM_IFE_PIX_PATH_RES_MAX: + res_name = "Invalid Max res"; + break; + default: + res_name = "Invalid"; + break; + } + return res_name; +} + +static const char *cam_ife_hw_mgr_get_res_type( + enum cam_isp_resource_type csid_res_type) +{ + char *res_type = NULL; + + switch (csid_res_type) { + case CAM_ISP_RESOURCE_UNINT: + res_type = "Unint"; + break; + case CAM_ISP_RESOURCE_SRC: + res_type = "Src"; + break; + case CAM_ISP_RESOURCE_CID: + res_type = "Cid"; + break; + case CAM_ISP_RESOURCE_PIX_PATH: + res_type = "Pix Path"; + break; + case CAM_ISP_RESOURCE_VFE_IN: + res_type = "Vfe In"; + break; + case CAM_ISP_RESOURCE_VFE_OUT: + res_type = "Vfe Out"; + break; + case CAM_ISP_RESOURCE_MAX: + res_type = "Invalid Max res"; + break; + default: + res_type = "Invalid"; + break; + } + return res_type; +} + static int cam_ife_hw_mgr_reset_csid_res( struct cam_ife_hw_mgr_res *isp_hw_res) { @@ -599,6 +667,61 @@ static int cam_ife_hw_mgr_get_ctx( return rc; } +static void cam_ife_hw_mgr_dump_all_ctx( + struct cam_ife_hw_mgr_ctx *ife_ctx) +{ + uint32_t i; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr; + + mutex_lock(&g_ife_hw_mgr.ctx_mutex); + list_for_each_entry(ctx, &g_ife_hw_mgr.used_ctx_list, list) { + CAM_ERR_RATE_LIMIT(CAM_ISP, + "ctx id:%d dual:%d in src:%d num_base:%d rdi only:%d", + ctx->ctx_index, + ctx->res_list_ife_in.is_dual_vfe, + ctx->res_list_ife_in.res_id, + ctx->num_base, ctx->is_rdi_only_context); + list_for_each_entry(hw_mgr, &ctx->res_list_ife_csid, + list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr->hw_res[i]) + continue; + CAM_ERR_RATE_LIMIT(CAM_ISP, + "csid:%d res_type:%s id:%s state:%d", + hw_mgr->hw_res[i]->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_type( + hw_mgr->hw_res[i]->res_type), + cam_ife_hw_mgr_get_res_id( + hw_mgr->hw_res[i]->res_id), + hw_mgr->hw_res[i]->res_state); + } + } + list_for_each_entry(hw_mgr, &ctx->res_list_ife_src, + list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr->hw_res[i]) + continue; + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Src IFE:%d res_type:%s id:%s state:%d", + hw_mgr->hw_res[i]->hw_intf->hw_idx, + cam_ife_hw_mgr_get_res_type( + hw_mgr->hw_res[i]->res_type), + cam_ife_hw_mgr_get_res_id( + hw_mgr->hw_res[i]->res_id), + hw_mgr->hw_res[i]->res_state); + } + } + } + CAM_ERR_RATE_LIMIT(CAM_ISP, + "Current ctx id:%d dual:%d in src:%d num_base:%d rdi only:%d", + ife_ctx->ctx_index, + ife_ctx->res_list_ife_in.is_dual_vfe, + ife_ctx->res_list_ife_in.res_id, + ife_ctx->num_base, ife_ctx->is_rdi_only_context); + mutex_unlock(&g_ife_hw_mgr.ctx_mutex); +} + static void cam_ife_mgr_add_base_info( struct cam_ife_hw_mgr_ctx *ctx, enum cam_isp_hw_split_id split_id, @@ -1509,8 +1632,9 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_pxl( &csid_acquire, sizeof(csid_acquire)); if (rc) { CAM_ERR(CAM_ISP, - "Cannot acquire ife csid pxl path rsrc %s", - (is_ipp) ? "IPP" : "PPP"); + "Cannot acquire ife csid pxl path rsrc %s, hw=%d rc=%d", + (is_ipp) ? "IPP" : "PPP", + hw_intf->hw_idx, rc); goto put_res; } @@ -1622,7 +1746,6 @@ static int cam_ife_hw_mgr_acquire_res_ife_csid_rdi( "CSID Path reserve failed hw=%d rc=%d cid=%d", hw_intf->hw_idx, rc, cid_res->hw_res[0]->res_id); - goto put_res; } @@ -2018,6 +2141,8 @@ static int cam_ife_mgr_acquire_hw(void *hw_mgr_priv, void *acquire_hw_args) return 0; free_res: + /*Dump all the current acquired resources */ + cam_ife_hw_mgr_dump_all_ctx(ife_ctx); cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); free_cdm: cam_cdm_release(ife_ctx->cdm_handle); @@ -2172,11 +2297,13 @@ static int cam_ife_mgr_acquire_dev(void *hw_mgr_priv, void *acquire_hw_args) ife_ctx->ctx_in_use = 1; cam_ife_hw_mgr_put_ctx(&ife_hw_mgr->used_ctx_list, &ife_ctx); - CAM_DBG(CAM_ISP, "Exit...(success)"); return 0; + free_res: + /*Dump all the current acquired resources */ + cam_ife_hw_mgr_dump_all_ctx(ife_ctx); cam_ife_hw_mgr_release_hw_for_ctx(ife_ctx); cam_cdm_release(ife_ctx->cdm_handle); free_ctx: @@ -2572,6 +2699,11 @@ static int cam_ife_mgr_pause_hw(struct cam_ife_hw_mgr_ctx *ctx) return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_EXCLUDE); } +static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) +{ + return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); +} + /* entry function: stop_hw */ static int cam_ife_mgr_stop_hw(void *hw_mgr_priv, void *stop_hw_args) { @@ -2925,6 +3057,9 @@ start_only: CAM_DBG(CAM_ISP, "START IFE OUT ... in ctx id:%d", ctx->ctx_index); + if (start_isp->start_only) + cam_ife_mgr_resume_hw(ctx); + /* start the IFE out devices */ for (i = 0; i < CAM_IFE_HW_OUT_RES_MAX; i++) { rc = cam_ife_hw_mgr_start_hw_res( @@ -3025,6 +3160,44 @@ static int cam_ife_mgr_write(void *hw_mgr_priv, void *write_args) return -EPERM; } +static int cam_ife_mgr_reset(void *hw_mgr_priv, void *hw_reset_args) +{ + struct cam_ife_hw_mgr *hw_mgr = hw_mgr_priv; + struct cam_hw_reset_args *reset_args = hw_reset_args; + struct cam_ife_hw_mgr_ctx *ctx; + struct cam_ife_hw_mgr_res *hw_mgr_res; + uint32_t i; + int rc = 0; + + if (!hw_mgr_priv || !hw_reset_args) { + CAM_ERR(CAM_ISP, "Invalid arguments"); + return -EINVAL; + } + + ctx = (struct cam_ife_hw_mgr_ctx *)reset_args->ctxt_to_hw_map; + if (!ctx || !ctx->ctx_in_use) { + CAM_ERR(CAM_ISP, "Invalid context is used"); + return -EPERM; + } + + CAM_DBG(CAM_ISP, "reset csid and vfe hw"); + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, + list) { + rc = cam_ife_hw_mgr_reset_csid_res(hw_mgr_res); + if (rc) { + CAM_ERR(CAM_ISP, "Failed RESET (%d) rc:%d", + hw_mgr_res->res_id, rc); + goto end; + } + } + + for (i = 0; i < ctx->num_base; i++) + rc = cam_ife_mgr_reset_vfe_hw(hw_mgr, ctx->base[i].idx); + +end: + return rc; +} + static int cam_ife_mgr_release_hw(void *hw_mgr_priv, void *release_hw_args) { @@ -3152,6 +3325,54 @@ static int cam_isp_blob_fe_update( return rc; } +static int cam_isp_blob_fps_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_fps_config *fps_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_vfe_fps_config_args fps_config_args; + int rc = -EINVAL; + uint32_t i; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + if (hw_mgr_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF) { + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + fps_config_args.fps = + fps_config->fps; + fps_config_args.node_res = + hw_mgr_res->hw_res[i]; + + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_ISP_HW_CMD_FPS_CONFIG, + &fps_config_args, + sizeof( + struct cam_vfe_fps_config_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Failed fps config:%d", + fps_config->fps); + } else + CAM_WARN(CAM_ISP, "NULL hw_intf!"); + } + } + } + + return rc; +} + static int cam_isp_blob_ubwc_update( uint32_t blob_type, struct cam_isp_generic_blob_info *blob_info, @@ -3528,6 +3749,75 @@ static int cam_isp_blob_clock_update( return rc; } +static int cam_isp_blob_sensor_config( + uint32_t blob_type, + struct cam_isp_generic_blob_info *blob_info, + struct cam_isp_sensor_config *dim_config, + struct cam_hw_prepare_update_args *prepare) +{ + struct cam_ife_hw_mgr_ctx *ctx = NULL; + struct cam_ife_hw_mgr_res *hw_mgr_res; + struct cam_hw_intf *hw_intf; + struct cam_ife_sensor_dimension_update_args update_args; + int rc = -EINVAL, found = 0; + uint32_t i, j; + struct cam_isp_sensor_dimension *path_config; + + ctx = prepare->ctxt_to_hw_map; + + list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_csid, list) { + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + found = 1; + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf && hw_intf->hw_ops.process_cmd) { + path_config = &(dim_config->ipp_path); + update_args.ipp_path.width = + path_config->width; + update_args.ipp_path.height = + path_config->height; + update_args.ipp_path.measure_enabled = + path_config->measure_enabled; + path_config = &(dim_config->ppp_path); + update_args.ppp_path.width = + path_config->width; + update_args.ppp_path.height = + path_config->height; + update_args.ppp_path.measure_enabled = + path_config->measure_enabled; + for (j = 0; j < CAM_IFE_RDI_NUM_MAX; j++) { + path_config = + &(dim_config->rdi_path[j]); + update_args.rdi_path[j].width = + path_config->width; + update_args.rdi_path[j].height = + path_config->height; + update_args.rdi_path[j].measure_enabled = + path_config->measure_enabled; + } + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, + &update_args, + sizeof( + struct + cam_ife_sensor_dimension_update_args) + ); + if (rc) + CAM_ERR(CAM_ISP, + "Dimension Update failed"); + } else + CAM_ERR(CAM_ISP, "hw_intf is NULL"); + } + if (found) + break; + } + + return rc; +} + + void fill_res_bitmap(uint32_t resource_type, unsigned long *res_bitmap) { @@ -3620,12 +3910,6 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, return -EINVAL; } - if (blob_type >= CAM_ISP_GENERIC_BLOB_TYPE_MAX) { - CAM_WARN(CAM_ISP, "Invalid Blob Type %d Max %d", blob_type, - CAM_ISP_GENERIC_BLOB_TYPE_MAX); - return 0; - } - prepare = blob_info->prepare; if (!prepare) { CAM_ERR(CAM_ISP, "Failed. prepare is NULL, blob_type %d", @@ -3633,7 +3917,6 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, return -EINVAL; } - CAM_DBG(CAM_ISP, "FS2: BLOB Type: %d", blob_type); switch (blob_type) { case CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG: { struct cam_isp_resource_hfr_config *hfr_config; @@ -3868,6 +4151,50 @@ static int cam_isp_packet_generic_blob_handler(void *user_data, CAM_ERR(CAM_ISP, "Init Frame drop Update Failed"); } break; + case CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG: { + struct cam_isp_sensor_config *csid_dim_config; + + if (blob_size < sizeof(struct cam_isp_sensor_config)) { + CAM_ERR(CAM_ISP, "Invalid blob size %u expected %lu", + blob_size, + sizeof(struct cam_isp_sensor_config)); + return -EINVAL; + } + + csid_dim_config = + (struct cam_isp_sensor_config *)blob_data; + + rc = cam_isp_blob_sensor_config(blob_type, blob_info, + csid_dim_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, + "Sensor Dimension Update Failed rc: %d", rc); + } + break; + case CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG: { + struct cam_fps_config *fps_config; + struct cam_isp_prepare_hw_update_data *prepare_hw_data; + + if (blob_size < sizeof(struct cam_fps_config)) { + CAM_ERR(CAM_ISP, + "Invalid fps blob size %u expected %lu", + blob_size, sizeof(struct cam_fps_config)); + return -EINVAL; + } + + fps_config = (struct cam_fps_config *)blob_data; + prepare_hw_data = (struct cam_isp_prepare_hw_update_data *) + prepare->priv; + + prepare_hw_data->fps = fps_config->fps; + + rc = cam_isp_blob_fps_config(blob_type, blob_info, + fps_config, prepare); + if (rc) + CAM_ERR(CAM_ISP, "FPS Update Failed rc: %d", rc); + + } + break; default: CAM_WARN(CAM_ISP, "Invalid blob type %d", blob_type); break; @@ -4025,10 +4352,6 @@ end: return rc; } -static int cam_ife_mgr_resume_hw(struct cam_ife_hw_mgr_ctx *ctx) -{ - return cam_ife_mgr_bw_control(ctx, CAM_VFE_BW_CONTROL_INCLUDE); -} static int cam_ife_mgr_sof_irq_debug( struct cam_ife_hw_mgr_ctx *ctx, @@ -4097,8 +4420,12 @@ static void cam_ife_mgr_print_io_bufs(struct cam_packet *packet, for (i = 0; i < packet->num_io_configs; i++) { for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { - if (!io_cfg[i].mem_handle[j]) + if (!io_cfg[i].mem_handle[j]) { + CAM_ERR(CAM_ISP, + "Mem Handle %d is NULL for %d io config", + j, i); break; + } if (pf_buf_info && GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == @@ -4261,45 +4588,44 @@ static int cam_ife_mgr_cmd_get_sof_timestamp( struct cam_hw_intf *hw_intf; struct cam_csid_get_time_stamp_args csid_get_time; - list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) { - for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { - if (!hw_mgr_res->hw_res[i]) - continue; + hw_mgr_res = list_first_entry(&ife_ctx->res_list_ife_csid, + struct cam_ife_hw_mgr_res, list); + for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) { + if (!hw_mgr_res->hw_res[i]) + continue; + + /* + * Get the SOF time stamp from left resource only. + * Left resource is master for dual vfe case and + * Rdi only context case left resource only hold + * the RDI resource + */ + hw_intf = hw_mgr_res->hw_res[i]->hw_intf; + if (hw_intf->hw_ops.process_cmd) { /* - * Get the SOF time stamp from left resource only. - * Left resource is master for dual vfe case and - * Rdi only context case left resource only hold - * the RDI resource + * Single VFE case, Get the time stamp from + * available one csid hw in the context + * Dual VFE case, get the time stamp from + * master(left) would be sufficient */ - hw_intf = hw_mgr_res->hw_res[i]->hw_intf; - if (hw_intf->hw_ops.process_cmd) { - /* - * Single VFE case, Get the time stamp from - * available one csid hw in the context - * Dual VFE case, get the time stamp from - * master(left) would be sufficient - */ - - csid_get_time.node_res = - hw_mgr_res->hw_res[i]; - rc = hw_intf->hw_ops.process_cmd( - hw_intf->hw_priv, - CAM_IFE_CSID_CMD_GET_TIME_STAMP, - &csid_get_time, - sizeof( - struct cam_csid_get_time_stamp_args)); - if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { - *time_stamp = - csid_get_time.time_stamp_val; - *boot_time_stamp = - csid_get_time.boot_timestamp; - } + csid_get_time.node_res = + hw_mgr_res->hw_res[i]; + rc = hw_intf->hw_ops.process_cmd( + hw_intf->hw_priv, + CAM_IFE_CSID_CMD_GET_TIME_STAMP, + &csid_get_time, + sizeof( + struct cam_csid_get_time_stamp_args)); + if (!rc && (i == CAM_ISP_HW_SPLIT_LEFT)) { + *time_stamp = + csid_get_time.time_stamp_val; + *boot_time_stamp = + csid_get_time.boot_timestamp; } } } - if (rc) CAM_ERR(CAM_ISP, "Getting sof time stamp failed"); @@ -4763,6 +5089,8 @@ static int cam_ife_hw_mgr_handle_reg_update( break; if (!rup_status) { + rup_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hwr_irq_rup_cb( ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_REG_UPDATE, @@ -4792,6 +5120,8 @@ static int cam_ife_hw_mgr_handle_reg_update( if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) break; if (!rup_status) { + rup_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; /* Send the Reg update hw event */ ife_hwr_irq_rup_cb( ife_hwr_mgr_ctx->common.cb_priv, @@ -5151,6 +5481,8 @@ static int cam_ife_hw_mgr_handle_sof( ife_hw_mgr_ctx, &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); + sof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hw_irq_sof_cb( ife_hw_mgr_ctx->common.cb_priv, @@ -5174,6 +5506,8 @@ static int cam_ife_hw_mgr_handle_sof( ife_hw_mgr_ctx, &sof_done_event_data.timestamp, &sof_done_event_data.boot_time); + sof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hw_irq_sof_cb( ife_hw_mgr_ctx->common.cb_priv, @@ -5259,13 +5593,15 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res( if (atomic_read( &ife_hwr_mgr_ctx->overflow_pending)) break; - if (!eof_status) + if (!eof_status) { + eof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hwr_irq_eof_cb( ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + } } - break; /* Handling dual VFE Scenario */ case 1: @@ -5306,11 +5642,14 @@ static int cam_ife_hw_mgr_handle_eof_for_camif_hw_res( if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) break; - if (!rc) + if (!rc) { + eof_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; ife_hwr_irq_eof_cb( ife_hwr_mgr_ctx->common.cb_priv, CAM_ISP_HW_EVENT_EOF, &eof_done_event_data); + } break; @@ -5410,6 +5749,8 @@ static int cam_ife_hw_mgr_handle_buf_done_for_hw_res( if (atomic_read(&ife_hwr_mgr_ctx->overflow_pending)) break; + buf_done_event_data.irq_mono_boot_time = + evt_payload->ts.time_usecs; /* Report for Successful buf_done event if any */ if (buf_done_event_data.num_handles > 0 && ife_hwr_irq_wm_done_cb) { @@ -5849,6 +6190,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl) hw_mgr_intf->hw_prepare_update = cam_ife_mgr_prepare_hw_update; hw_mgr_intf->hw_config = cam_ife_mgr_config_hw; hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd; + hw_mgr_intf->hw_reset = cam_ife_mgr_reset; if (iommu_hdl) *iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl; diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c index 5efab9f289dd..21f67bac9efe 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/hw_utils/cam_isp_packet_parser.c @@ -491,7 +491,7 @@ int cam_isp_add_io_buffers( CAM_DBG(CAM_ISP, "======= io config idx %d ============", i); CAM_DBG(CAM_REQ, "i %d req_id %llu resource_type:%d fence:%d direction %d", - i, prepare->packet->header.request_id, + i, req_id, io_cfg[i].resource_type, io_cfg[i].fence, io_cfg[i].direction); CAM_DBG(CAM_ISP, "format: %d", io_cfg[i].format); @@ -618,8 +618,16 @@ int cam_isp_add_io_buffers( mmu_hdl, &io_addr[plane_id], &size); if (rc) { CAM_ERR(CAM_ISP, - "no io addr for plane%d", - plane_id); + "no io addr for plane%d Bufhdl:%d, Size =%d", + plane_id, + io_cfg[i].mem_handle[plane_id], + (int)size); + CAM_ERR(CAM_ISP, + "Port i %d Reqid %llu res_type:%d fence:%d dir %d", + i, req_id, + io_cfg[i].resource_type, + io_cfg[i].fence, + io_cfg[i].direction); rc = -ENOMEM; return rc; } diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h index 096e0f186bbf..1ab9361af1d1 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/include/cam_isp_hw_mgr_intf.h @@ -130,6 +130,7 @@ struct cam_isp_bw_config_internal { * @bw_config: BW config information * @bw_config_valid: Flag indicating whether the bw_config at the index * is valid or not + * @fps: fps vaue which has been updated in hw * */ struct cam_isp_prepare_hw_update_data { @@ -137,40 +138,47 @@ struct cam_isp_prepare_hw_update_data { struct cam_isp_bw_config_internal bw_config[CAM_IFE_HW_NUM_MAX]; struct cam_isp_bw_config_internal_ab bw_config_ab[CAM_IFE_HW_NUM_MAX]; bool bw_config_valid[CAM_IFE_HW_NUM_MAX]; + uint32_t fps; }; /** * struct cam_isp_hw_sof_event_data - Event payload for CAM_HW_EVENT_SOF * - * @timestamp: Time stamp for the sof event - * @boot_time: Boot time stamp for the sof event + * @timestamp: Time stamp for the sof event + * @boot_time: Boot time stamp for the sof event + * @irq_mono_boot_time: Time stamp till the execution of IRQ wrt event started * */ struct cam_isp_hw_sof_event_data { uint64_t timestamp; uint64_t boot_time; + uint64_t irq_mono_boot_time; }; /** * struct cam_isp_hw_reg_update_event_data - Event payload for * CAM_HW_EVENT_REG_UPDATE * - * @timestamp: Time stamp for the reg update event + * @timestamp: Time stamp for the reg update event + * @irq_mono_boot_time: Time stamp till the execution of IRQ wrt event started * */ struct cam_isp_hw_reg_update_event_data { uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** * struct cam_isp_hw_epoch_event_data - Event payload for CAM_HW_EVENT_EPOCH * - * @timestamp: Time stamp for the epoch event + * @timestamp: Time stamp for the epoch event + * @irq_mono_boot_time: Time stamp till the execution of this event started * */ struct cam_isp_hw_epoch_event_data { uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** @@ -179,6 +187,7 @@ struct cam_isp_hw_epoch_event_data { * @num_handles: Number of resource handeles * @resource_handle: Resource handle array * @timestamp: Timestamp for the buf done event + * @irq_mono_boot_time: Time stamp till the execution of this event started * */ struct cam_isp_hw_done_event_data { @@ -186,16 +195,19 @@ struct cam_isp_hw_done_event_data { uint32_t resource_handle[ CAM_NUM_OUT_PER_COMP_IRQ_MAX]; uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** * struct cam_isp_hw_eof_event_data - Event payload for CAM_HW_EVENT_EOF * * @timestamp: Timestamp for the eof event + * @irq_mono_boot_time: Time stamp till the execution of this event started * */ struct cam_isp_hw_eof_event_data { uint64_t timestamp; + uint64_t irq_mono_boot_time; }; /** diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile index 25bdc51d369f..719bbe7aa941 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/Makefile @@ -8,5 +8,6 @@ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/in ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_smmu/ ccflags-y += -Idrivers/media/platform/msm/camera_v3/cam_req_mgr/ +obj-$(CONFIG_SPECTRA_CAMERA) += cam_csid_ppi_dev.o cam_csid_ppi_core.o cam_csid_ppi170.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_ife_csid_dev.o cam_ife_csid_soc.o cam_ife_csid_core.o obj-$(CONFIG_SPECTRA_CAMERA) += cam_ife_csid17x.o cam_ife_csid_lite17x.o diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.c new file mode 100644 index 000000000000..2051292be5be --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.c @@ -0,0 +1,58 @@ +/* Copyright (c) 2019, 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. + */ + +#include <linux/module.h> +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi170.h" +#include "cam_csid_ppi_dev.h" + +#define CAM_PPI_DRV_NAME "ppi_170" +#define CAM_PPI_VERSION_V170 0x10070000 + +static struct cam_csid_ppi_hw_info cam_csid_ppi170_hw_info = { + .ppi_reg = &cam_csid_ppi_170_reg_offset, +}; + +static const struct of_device_id cam_csid_ppi170_dt_match[] = { + { + .compatible = "qcom,ppi170", + .data = &cam_csid_ppi170_hw_info, + }, + {} +}; + +MODULE_DEVICE_TABLE(of, cam_csid_ppi170_dt_match); + +static struct platform_driver cam_csid_ppi170_driver = { + .probe = cam_csid_ppi_probe, + .remove = cam_csid_ppi_remove, + .driver = { + .name = CAM_PPI_DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = cam_csid_ppi170_dt_match, + .suppress_bind_attrs = true, + }, +}; + +static int __init cam_csid_ppi170_init_module(void) +{ + return platform_driver_register(&cam_csid_ppi170_driver); +} + +static void __exit cam_csid_ppi170_exit_module(void) +{ + platform_driver_unregister(&cam_csid_ppi170_driver); +} + +module_init(cam_csid_ppi170_init_module); +MODULE_DESCRIPTION("CAM CSID_PPI170 driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.h new file mode 100644 index 000000000000..0ec767204914 --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi170.h @@ -0,0 +1,32 @@ +/* Copyright (c) 2019, 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. + */ + +#ifndef _CAM_CSID_PPI_170_H_ +#define _CAM_CSID_PPI_170_H_ + +#include "cam_csid_ppi_core.h" + +static struct cam_csid_ppi_reg_offset cam_csid_ppi_170_reg_offset = { + .ppi_hw_version_addr = 0, + .ppi_module_cfg_addr = 0x60, + .ppi_irq_status_addr = 0x68, + .ppi_irq_mask_addr = 0x6c, + .ppi_irq_set_addr = 0x70, + .ppi_irq_clear_addr = 0x74, + .ppi_irq_cmd_addr = 0x78, + .ppi_rst_cmd_addr = 0x7c, + .ppi_test_bus_ctrl_addr = 0x1f4, + .ppi_debug_addr = 0x1f8, + .ppi_spare_addr = 0x1fc, +}; + +#endif /*_CAM_CSID_PPI_170_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.c new file mode 100644 index 000000000000..058a4e955b38 --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.c @@ -0,0 +1,404 @@ +/* Copyright (c) 2019, 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. + */ +#include <linux/iopoll.h> +#include <linux/slab.h> +#include <uapi/media/cam_defs.h> + +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_soc_util.h" +#include "cam_debug_util.h" +#include "cam_io_util.h" + +static int cam_csid_ppi_reset(struct cam_csid_ppi_hw *ppi_hw) +{ + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + int rc = 0; + + uint32_t val = 0; + uint32_t clear_mask; + uint32_t status; + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "PPI:%d reset", ppi_hw->hw_intf->hw_idx); + + /* Mask all interrupts */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + + /* clear all interrupts */ + clear_mask = PPI_IRQ_FIFO0_OVERFLOW | PPI_IRQ_FIFO1_OVERFLOW | + PPI_IRQ_FIFO2_OVERFLOW; + cam_io_w_mb(clear_mask, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(PPI_IRQ_CMD_CLEAR, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + /* perform the top PPI HW registers reset */ + cam_io_w_mb(PPI_RST_CONTROL, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_rst_cmd_addr); + + rc = readl_poll_timeout(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr, status, + (status & 0x1) == 0x1, 1000, 100000); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d ppi_reset fail rc = %d", + ppi_hw->hw_intf->hw_idx, rc); + rc = -ETIMEDOUT; + } + CAM_DBG(CAM_ISP, "PPI: reset status %d", status); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + if (val != 0) + CAM_ERR(CAM_ISP, "PPI:%d IRQ value after reset rc = %d", + ppi_hw->hw_intf->hw_idx, val); + + return rc; +} + +static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + uint32_t i; + uint64_t val; + + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + CAM_DBG(CAM_ISP, "PPI:%d init PPI HW", ppi_hw->hw_intf->hw_idx); + + for (i = 0; i < soc_info->num_clk; i++) { + /* Passing zero in clk_rate results in setting no clk_rate */ + rc = cam_soc_util_clk_enable(soc_info->clk[i], + soc_info->clk_name[i], 0); + if (rc) + goto clk_disable; + } + + rc = cam_soc_util_irq_enable(soc_info); + if (rc) + goto clk_disable; + + /* Reset PPI */ + rc = cam_csid_ppi_reset(ppi_hw); + if (rc) + goto irq_disable; + + /* Clear the RST done IRQ */ + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_hw_version_addr); + CAM_DBG(CAM_ISP, "PPI:%d PPI HW version: 0x%x", + ppi_hw->hw_intf->hw_idx, val); + + ppi_hw->device_enabled = 1; + return 0; +irq_disable: + cam_soc_util_irq_disable(soc_info); +clk_disable: + for (i--; i >= 0; i--) { + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + } + return rc; +} + +static int cam_csid_ppi_disable_hw(struct cam_csid_ppi_hw *ppi_hw) +{ + int rc = 0; + int i; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + uint64_t ppi_cfg_val = 0; + + CAM_DBG(CAM_ISP, "PPI:%d De-init PPI HW", + ppi_hw->hw_intf->hw_idx); + + soc_info = &ppi_hw->hw_info->soc_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + + CAM_DBG(CAM_ISP, "%s:Calling PPI Reset\n", __func__); + cam_csid_ppi_reset(ppi_hw); + CAM_DBG(CAM_ISP, "%s:PPI Reset Done\n", __func__); + + /* disable the clocks */ + for (i = 0; i < soc_info->num_clk; i++) { + cam_soc_util_clk_disable(soc_info->clk[i], + soc_info->clk_name[i]); + } + + /* disable the interrupt */ + cam_io_w_mb(0, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_mask_addr); + cam_soc_util_irq_disable(soc_info); + + /* disable lanes */ + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + + ppi_hw->device_enabled = 0; + + return rc; +} + +static int cam_csid_ppi_init_hw(void *hw_priv, void *init_args, + uint32_t arg_size) +{ + int i, rc = 0; + uint32_t num_lanes; + uint32_t lanes[CAM_CSID_PPI_HW_MAX] = {0, 0, 0, 0}; + uint32_t cphy; + bool dl0, dl1; + uint32_t ppi_cfg_val = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + struct cam_hw_soc_info *soc_info; + struct cam_csid_ppi_cfg ppi_cfg; + + if (!hw_priv || !init_args || + (arg_size != sizeof(struct cam_csid_ppi_cfg))) { + CAM_ERR(CAM_ISP, "PPI: Invalid args"); + rc = -EINVAL; + goto end; + } + + dl0 = dl1 = false; + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + ppi_reg = ppi_hw->ppi_info->ppi_reg; + ppi_cfg = *((struct cam_csid_ppi_cfg *)init_args); + + /* Initialize the ppi hardware */ + rc = cam_csid_ppi_enable_hw(ppi_hw); + if (rc) + goto end; + + /* Do lane configuration here*/ + num_lanes = ppi_cfg.lane_num; + /* lane_type = 1 refers to cphy */ + cphy = ppi_cfg.lane_type; + CAM_DBG(CAM_ISP, "lane_cfg 0x%x | num_lanes 0x%x | lane_type 0x%x", + ppi_cfg.lane_cfg, num_lanes, cphy); + + for (i = 0; i < num_lanes; i++) { + lanes[i] = ppi_cfg.lane_cfg & (0x3 << (4 * i)); + (lanes[i] < 2) ? (dl0 = true) : (dl1 = true); + CAM_DBG(CAM_ISP, "lanes[%d] %d", i, lanes[i]); + } + + if (num_lanes) { + if (cphy) { + for (i = 0; i < num_lanes; i++) { + /* Select Cphy */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_SEL(lanes[i]); + /* Enable lane Cphy */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(lanes[i]); + } + } else { + if (dl0) + /* Enable lane 0 */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(0); + if (dl1) + /* Enable lane 1 */ + ppi_cfg_val |= PPI_CFG_CPHY_DLX_EN(1); + } + } else { + CAM_ERR(CAM_ISP, + "Number of lanes to enable is cannot be zero"); + rc = -1; + goto end; + } + + CAM_DBG(CAM_ISP, "ppi_cfg_val 0x%x", ppi_cfg_val); + soc_info = &ppi_hw->hw_info->soc_info; + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); +end: + return rc; +} + +static int cam_csid_ppi_deinit_hw(void *hw_priv, void *deinit_args, + uint32_t arg_size) +{ + int rc = 0; + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_info *ppi_hw_info; + + CAM_DBG(CAM_ISP, "Enter"); + + if (!hw_priv) { + CAM_ERR(CAM_ISP, "PPI:Invalid arguments"); + rc = -EINVAL; + goto end; + } + + ppi_hw_info = (struct cam_hw_info *)hw_priv; + ppi_hw = (struct cam_csid_ppi_hw *)ppi_hw_info->core_info; + + CAM_DBG(CAM_ISP, "Disabling PPI Hw\n"); + rc = cam_csid_ppi_disable_hw(ppi_hw); + if (rc < 0) + CAM_DBG(CAM_ISP, "%s: Exit with %d\n", __func__, rc); +end: + return rc; +} + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx) +{ + int rc = -EINVAL; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *csid_ppi_hw = NULL; + + if (ppi_idx >= CAM_CSID_PPI_HW_MAX) { + CAM_ERR(CAM_ISP, "Invalid ppi index:%d", ppi_idx); + goto err; + } + + ppi_hw_info = (struct cam_hw_info *) ppi_hw_intf->hw_priv; + csid_ppi_hw = (struct cam_csid_ppi_hw *) ppi_hw_info->core_info; + + csid_ppi_hw->hw_intf = ppi_hw_intf; + csid_ppi_hw->hw_info = ppi_hw_info; + + CAM_DBG(CAM_ISP, "type %d index %d", + csid_ppi_hw->hw_intf->hw_type, ppi_idx); + + rc = cam_csid_ppi_init_soc_resources(&csid_ppi_hw->hw_info->soc_info, + cam_csid_ppi_irq, csid_ppi_hw); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Failed to init_soc", ppi_idx); + goto err; + } + + csid_ppi_hw->hw_intf->hw_ops.init = cam_csid_ppi_init_hw; + csid_ppi_hw->hw_intf->hw_ops.deinit = cam_csid_ppi_deinit_hw; + return 0; +err: + return rc; +} + +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data) +{ + int rc = 0; + + rc = cam_soc_util_get_dt_properties(soc_info); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Failed to get dt properties"); + goto end; + } + + rc = cam_soc_util_request_platform_resource(soc_info, ppi_irq_handler, + irq_data); + if (rc) { + CAM_ERR(CAM_ISP, + "PPI: Error Request platform resources failed rc=%d", + rc); + goto err; + } +end: + return rc; +err: + cam_soc_util_release_platform_resource(soc_info); + return rc; +} + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data) +{ + uint32_t irq_status = 0; + uint32_t i, ppi_cfg_val = 0; + bool fatal_err_detected = false; + + struct cam_csid_ppi_hw *ppi_hw; + struct cam_hw_soc_info *soc_info; + const struct cam_csid_ppi_reg_offset *ppi_reg; + + if (!data) { + CAM_ERR(CAM_ISP, "PPI: Invalid arguments"); + return IRQ_HANDLED; + } + + ppi_hw = (struct cam_csid_ppi_hw *)data; + CAM_DBG(CAM_ISP, "PPI %d IRQ Handling", ppi_hw->hw_intf->hw_idx); + ppi_reg = ppi_hw->ppi_info->ppi_reg; + soc_info = &ppi_hw->hw_info->soc_info; + + /* read */ + irq_status = cam_io_r_mb(soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_status_addr); + + /* clear */ + cam_io_w_mb(irq_status, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_clear_addr); + + cam_io_w_mb(1, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_irq_cmd_addr); + + CAM_DBG(CAM_ISP, "PPI %d irq status 0x%x", ppi_hw->hw_intf->hw_idx, + irq_status); + + if (ppi_hw->device_enabled == 1) { + if (irq_status & PPI_IRQ_RST_DONE) { + CAM_DBG(CAM_ISP, "PPI Reset Done"); + goto ret; + } + if ((irq_status & PPI_IRQ_FIFO0_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO1_OVERFLOW) || + (irq_status & PPI_IRQ_FIFO2_OVERFLOW)) { + fatal_err_detected = true; + goto handle_fatal_error; + } + } + +handle_fatal_error: + if (fatal_err_detected) { + CAM_ERR(CAM_ISP, "PPI: %d irq_status:0x%x", + ppi_hw->hw_intf->hw_idx, irq_status); + /* disable lanes */ + for (i = 0; i < CAM_CSID_PPI_LANES_MAX; i++) + ppi_cfg_val &= ~PPI_CFG_CPHY_DLX_EN(i); + + cam_io_w_mb(ppi_cfg_val, soc_info->reg_map[0].mem_base + + ppi_reg->ppi_module_cfg_addr); + } +ret: + CAM_DBG(CAM_ISP, "IRQ Handling exit"); + return IRQ_HANDLED; +} + +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw) +{ + if (!csid_ppi_hw) { + CAM_ERR(CAM_ISP, "Invalid param"); + return -EINVAL; + } + /* release the privdate data memory from resources */ + return cam_soc_util_release_platform_resource( + &csid_ppi_hw->hw_info->soc_info); +} + diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.h new file mode 100644 index 000000000000..058c2421b6da --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_core.h @@ -0,0 +1,103 @@ +/* Copyright (c) 2019, 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. + */ + +#ifndef _CAM_CSID_PPI_HW_H_ +#define _CAM_CSID_PPI_HW_H_ + +#include "cam_hw.h" +#include "cam_hw_intf.h" + +#define CAM_CSID_PPI_HW_MAX 4 +#define CAM_CSID_PPI_LANES_MAX 3 + +#define PPI_IRQ_RST_DONE BIT(0) +#define PPI_IRQ_FIFO0_OVERFLOW BIT(1) +#define PPI_IRQ_FIFO1_OVERFLOW BIT(2) +#define PPI_IRQ_FIFO2_OVERFLOW BIT(3) + +#define PPI_IRQ_CMD_SET BIT(0) + +#define PPI_IRQ_CMD_CLEAR BIT(0) + +#define PPI_RST_CONTROL BIT(0) +/* + * Select the PHY (CPHY set '1' or DPHY set '0') + */ +#define PPI_CFG_CPHY_DLX_SEL(X) ((X < 2) ? BIT(X) : 0) + +#define PPI_CFG_CPHY_DLX_EN(X) BIT(4+X) + +struct cam_csid_ppi_reg_offset { + uint32_t ppi_hw_version_addr; + uint32_t ppi_module_cfg_addr; + + uint32_t ppi_irq_status_addr; + uint32_t ppi_irq_mask_addr; + uint32_t ppi_irq_set_addr; + uint32_t ppi_irq_clear_addr; + uint32_t ppi_irq_cmd_addr; + uint32_t ppi_rst_cmd_addr; + uint32_t ppi_test_bus_ctrl_addr; + uint32_t ppi_debug_addr; + uint32_t ppi_spare_addr; +}; + +/** + * struct cam_csid_ppi_hw_info- ppi HW info + * + * @ppi_reg: ppi register offsets + * + */ +struct cam_csid_ppi_hw_info { + const struct cam_csid_ppi_reg_offset *ppi_reg; +}; + +/** + * struct cam_csid_ppi_hw- ppi hw device resources data + * + * @hw_intf: contain the ppi hw interface information + * @hw_info: ppi hw device information + * @ppi_info: ppi hw specific information + * @device_enabled Device enabled will set once ppi powered on and + * initial configuration are done. + * @lock_state ppi spin lock + * + */ +struct cam_csid_ppi_hw { + struct cam_hw_intf *hw_intf; + struct cam_hw_info *hw_info; + struct cam_csid_ppi_hw_info *ppi_info; + uint32_t device_enabled; +}; + +/** + * struct cam_csid_ppi_cfg - ppi lane configuration data + * @lane_type: lane type: c-phy or d-phy + * @lane_num : active lane number + * @lane_cfg: lane configurations: 4 bits per lane + * + */ +struct cam_csid_ppi_cfg { + uint32_t lane_type; + uint32_t lane_num; + uint32_t lane_cfg; +}; + +int cam_csid_ppi_hw_probe_init(struct cam_hw_intf *ppi_hw_intf, + uint32_t ppi_idx); +int cam_csid_ppi_hw_deinit(struct cam_csid_ppi_hw *csid_ppi_hw); +int cam_csid_ppi_init_soc_resources(struct cam_hw_soc_info *soc_info, + irq_handler_t ppi_irq_handler, void *irq_data); +int cam_csid_ppi_deinit_soc_resources(struct cam_hw_soc_info *soc_info); +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx); +#endif /* _CAM_CSID_PPI_HW_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c new file mode 100644 index 000000000000..1a4e14525bc3 --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.c @@ -0,0 +1,147 @@ +/* Copyright (c) 2019, 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. + */ + +#include <linux/slab.h> +#include <linux/mod_devicetable.h> +#include <linux/of_device.h> + +#include "cam_isp_hw.h" +#include "cam_hw_intf.h" +#include "cam_csid_ppi_core.h" +#include "cam_csid_ppi_dev.h" +#include "cam_debug_util.h" + +static struct cam_hw_intf *cam_csid_ppi_hw_list[CAM_CSID_PPI_HW_MAX] = { + 0, 0, 0, 0}; +static char ppi_dev_name[8]; + +int cam_csid_ppi_probe(struct platform_device *pdev) +{ + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + struct cam_csid_ppi_hw *ppi_dev = NULL; + const struct of_device_id *match_dev = NULL; + struct cam_csid_ppi_hw_info *ppi_hw_data = NULL; + uint32_t ppi_dev_idx; + int rc = 0; + + CAM_DBG(CAM_ISP, "PPI probe called"); + + ppi_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL); + if (!ppi_hw_intf) { + rc = -ENOMEM; + goto err; + } + + ppi_hw_info = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL); + if (!ppi_hw_info) { + rc = -ENOMEM; + goto free_hw_intf; + } + + ppi_dev = kzalloc(sizeof(struct cam_csid_ppi_hw), GFP_KERNEL); + if (!ppi_dev) { + rc = -ENOMEM; + goto free_hw_info; + } + + /* get csid ppi hw index */ + of_property_read_u32(pdev->dev.of_node, "cell-index", &ppi_dev_idx); + + /* get csid ppi hw information */ + match_dev = of_match_device(pdev->dev.driver->of_match_table, + &pdev->dev); + if (!match_dev) { + CAM_ERR(CAM_ISP, "No matching table for the CSID PPI HW!"); + rc = -EINVAL; + goto free_dev; + } + + memset(ppi_dev_name, 0, sizeof(ppi_dev_name)); + snprintf(ppi_dev_name, sizeof(ppi_dev_name), "ppi%1u", ppi_dev_idx); + + ppi_hw_intf->hw_idx = ppi_dev_idx; + ppi_hw_intf->hw_priv = ppi_hw_info; + + ppi_hw_info->core_info = ppi_dev; + ppi_hw_info->soc_info.pdev = pdev; + ppi_hw_info->soc_info.dev = &pdev->dev; + ppi_hw_info->soc_info.dev_name = ppi_dev_name; + ppi_hw_info->soc_info.index = ppi_dev_idx; + + ppi_hw_data = (struct cam_csid_ppi_hw_info *)match_dev->data; + /* need to setup the pdev before call the csid ppi hw probe init */ + ppi_dev->ppi_info = ppi_hw_data; + + rc = cam_csid_ppi_hw_probe_init(ppi_hw_intf, ppi_dev_idx); + if (rc) { + CAM_ERR(CAM_ISP, "PPI: Probe init failed!"); + goto free_dev; + } + + platform_set_drvdata(pdev, ppi_dev); + CAM_DBG(CAM_ISP, "PPI:%d probe successful", + ppi_hw_intf->hw_idx); + + if (ppi_hw_intf->hw_idx < CAM_CSID_PPI_HW_MAX) + cam_csid_ppi_hw_list[ppi_hw_intf->hw_idx] = ppi_hw_intf; + else + goto free_dev; + + return 0; +free_dev: + kfree(ppi_dev); +free_hw_info: + kfree(ppi_hw_info); +free_hw_intf: + kfree(ppi_hw_intf); +err: + return rc; +} + +int cam_csid_ppi_remove(struct platform_device *pdev) +{ + struct cam_csid_ppi_hw *ppi_dev = NULL; + struct cam_hw_intf *ppi_hw_intf; + struct cam_hw_info *ppi_hw_info; + + ppi_dev = (struct cam_csid_ppi_hw *)platform_get_drvdata(pdev); + ppi_hw_intf = ppi_dev->hw_intf; + ppi_hw_info = ppi_dev->hw_info; + + CAM_DBG(CAM_ISP, "PPI:%d remove", ppi_dev->hw_intf->hw_idx); + + cam_csid_ppi_hw_deinit(ppi_dev); + + /* release the ppi device memory */ + kfree(ppi_dev); + kfree(ppi_hw_info); + kfree(ppi_hw_intf); + return 0; +} + +int cam_csid_ppi_hw_init(struct cam_hw_intf **csid_ppi_hw, + uint32_t hw_idx) +{ + int rc = 0; + + if (cam_csid_ppi_hw_list[hw_idx]) { + *csid_ppi_hw = cam_csid_ppi_hw_list[hw_idx]; + } else { + *csid_ppi_hw = NULL; + rc = -1; + } + + return rc; +} +EXPORT_SYMBOL(cam_csid_ppi_hw_init); + diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.h new file mode 100644 index 000000000000..b2ebeaf92947 --- /dev/null +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_csid_ppi_dev.h @@ -0,0 +1,22 @@ +/* Copyright (c) 2019, 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. + */ + +#ifndef _CAM_CSID_PPI_DEV_H_ +#define _CAM_CSID_PPI_DEV_H_ + +#include "cam_isp_hw.h" + +irqreturn_t cam_csid_ppi_irq(int irq_num, void *data); +int cam_csid_ppi_probe(struct platform_device *pdev); +int cam_csid_ppi_remove(struct platform_device *pdev); + +#endif /*_CAM_CSID_PPI_DEV_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h index 576e8cb8d3b8..6254b97c436a 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid170.h @@ -293,6 +293,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0x0, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_170_reg_offset = { diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h index 42f0f290a166..ed2857bd78ed 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175.h @@ -334,6 +334,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_175_reg_offset = { diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h index 8a78fe0b9b0d..d430ceef3360 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid175_200.h @@ -350,6 +350,10 @@ static struct cam_ife_csid_common_reg_offset .ppp_irq_mask_all = 0xFFFF, .measure_en_hbi_vbi_cnt_mask = 0xC, .format_measure_en_val = 1, + .format_measure_height_mask_val = 0xFFFF, + .format_measure_height_shift_val = 0x10, + .format_measure_width_mask_val = 0xFFFF, + .format_measure_width_shift_val = 0x0, }; static struct cam_ife_csid_reg_offset cam_ife_csid_175_200_reg_offset = { diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c index 5610f6d267ff..7541d06e7ede 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c @@ -16,6 +16,7 @@ #include <uapi/media/cam_defs.h> #include "cam_ife_csid_core.h" +#include "cam_csid_ppi_core.h" #include "cam_isp_hw.h" #include "cam_soc_util.h" #include "cam_io_util.h" @@ -78,7 +79,7 @@ static int cam_ife_csid_is_ipp_ppp_format_supported( static int cam_ife_csid_get_format_rdi( uint32_t in_format, uint32_t out_format, - uint32_t *decode_fmt, uint32_t *plain_fmt) + uint32_t *decode_fmt, uint32_t *plain_fmt, uint32_t *in_bpp) { int rc = 0; @@ -96,6 +97,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 6; break; case CAM_FORMAT_MIPI_RAW_8: switch (out_format) { @@ -111,6 +113,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 8; break; case CAM_FORMAT_MIPI_RAW_10: switch (out_format) { @@ -126,6 +129,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 10; break; case CAM_FORMAT_MIPI_RAW_12: switch (out_format) { @@ -140,6 +144,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 12; break; case CAM_FORMAT_MIPI_RAW_14: switch (out_format) { @@ -154,6 +159,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 14; break; case CAM_FORMAT_MIPI_RAW_16: switch (out_format) { @@ -168,6 +174,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 16; break; case CAM_FORMAT_MIPI_RAW_20: switch (out_format) { @@ -182,6 +189,7 @@ static int cam_ife_csid_get_format_rdi( rc = -EINVAL; break; } + *in_bpp = 20; break; case CAM_FORMAT_DPCM_10_6_10: *decode_fmt = 0x7; @@ -467,6 +475,7 @@ static int cam_ife_csid_global_reset(struct cam_ife_csid_hw *csid_hw) CAM_ERR(CAM_ISP, "CSID:%d IRQ value after reset rc = %d", csid_hw->hw_intf->hw_idx, val); csid_hw->error_irq_count = 0; + csid_hw->first_sof_ts = 0; for (i = 0 ; i < CAM_IFE_PIX_PATH_RES_MAX; i++) csid_hw->res_sof_cnt[i] = 0; @@ -565,10 +574,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, init_completion(complete); reset_strb_val = csid_reg->cmn_reg->path_rst_stb_all; - /* Enable the Test gen before reset */ - cam_io_w_mb(1, csid_hw->hw_info->soc_info.reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - /* Reset the corresponding ife csid path */ cam_io_w_mb(reset_strb_val, soc_info->reg_map[0].mem_base + reset_strb_addr); @@ -583,10 +588,6 @@ static int cam_ife_csid_path_reset(struct cam_ife_csid_hw *csid_hw, rc = -ETIMEDOUT; } - /* Disable Test Gen after reset*/ - cam_io_w_mb(0, soc_info->reg_map[0].mem_base + - csid_reg->tpg_reg->csid_tpg_ctrl_addr); - end: return rc; @@ -1165,8 +1166,14 @@ static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw) for (i = 0; i < CAM_IFE_PIX_PATH_RES_MAX; i++) csid_hw->res_sof_cnt[i] = 0; + csid_hw->ipp_path_config.measure_enabled = 0; + csid_hw->ppp_path_config.measure_enabled = 0; + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) + csid_hw->rdi_path_config[i].measure_enabled = 0; + csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; csid_hw->error_irq_count = 0; + csid_hw->first_sof_ts = 0; return rc; } @@ -1420,10 +1427,12 @@ static int cam_ife_csid_enable_csi2( struct cam_isp_resource_node *res) { int rc = 0; - const struct cam_ife_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; - struct cam_ife_csid_cid_data *cid_data; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + struct cam_ife_csid_cid_data *cid_data; + struct cam_csid_ppi_cfg ppi_lane_cfg; uint32_t val = 0; + uint32_t ppi_index = 0; csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; @@ -1514,6 +1523,24 @@ static int cam_ife_csid_enable_csi2( cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->csi2_reg->csid_csi2_rx_irq_mask_addr); + ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + ppi_lane_cfg.lane_type = csid_hw->csi2_rx_cfg.lane_type; + ppi_lane_cfg.lane_num = csid_hw->csi2_rx_cfg.lane_num; + ppi_lane_cfg.lane_cfg = csid_hw->csi2_rx_cfg.lane_cfg; + + CAM_DBG(CAM_ISP, "ppi_index to init %d", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.init( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + &ppi_lane_cfg, + sizeof(struct cam_csid_ppi_cfg)); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d Init Failed", + ppi_index); + return rc; + } + } + return 0; } @@ -1521,8 +1548,10 @@ static int cam_ife_csid_disable_csi2( struct cam_ife_csid_hw *csid_hw, struct cam_isp_resource_node *res) { - const struct cam_ife_csid_reg_offset *csid_reg; - struct cam_hw_soc_info *soc_info; + int rc = 0; + const struct cam_ife_csid_reg_offset *csid_reg; + struct cam_hw_soc_info *soc_info; + uint32_t ppi_index = 0; if (res->res_id >= CAM_IFE_CSID_CID_MAX) { CAM_ERR(CAM_ISP, "CSID:%d Invalid res id :%d", @@ -1553,6 +1582,19 @@ static int cam_ife_csid_disable_csi2( res->res_state = CAM_ISP_RESOURCE_STATE_RESERVED; + ppi_index = csid_hw->csi2_rx_cfg.phy_sel; + if (csid_hw->ppi_hw_intf[ppi_index] && csid_hw->ppi_enable) { + /* De-Initialize the PPI bridge */ + CAM_DBG(CAM_ISP, "ppi_index to de-init %d\n", ppi_index); + rc = csid_hw->ppi_hw_intf[ppi_index]->hw_ops.deinit( + csid_hw->ppi_hw_intf[ppi_index]->hw_priv, + NULL, 0); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI:%d De-Init Failed", ppi_index); + return rc; + } + } + return 0; } @@ -1587,6 +1629,7 @@ static int cam_ife_csid_init_config_pxl_path( const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; bool is_ipp; uint32_t decode_format = 0, plain_format = 0, val = 0; + struct cam_isp_sensor_dimension *path_config; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -1595,9 +1638,11 @@ static int cam_ife_csid_init_config_pxl_path( if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { is_ipp = true; pxl_reg = csid_reg->ipp_reg; + path_config = &(csid_hw->ipp_path_config); } else { is_ipp = false; pxl_reg = csid_reg->ppp_reg; + path_config = &(csid_hw->ppp_path_config); } if (!pxl_reg) { @@ -1666,6 +1711,24 @@ static int cam_ife_csid_init_config_pxl_path( } } + /* configure pixel format measure */ + if (path_config->measure_enabled) { + val = (((path_config->height & + csid_reg->cmn_reg->format_measure_height_mask_val) << + csid_reg->cmn_reg->format_measure_height_shift_val) | + (path_config->width & + csid_reg->cmn_reg->format_measure_width_mask_val)); + CAM_DBG(CAM_ISP, "CSID:%d format measure cfg1 value : 0x%x", + csid_hw->hw_intf->hw_idx, val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg1_addr); + + /* enable pixel and line counter */ + cam_io_w_mb(3, soc_info->reg_map[0].mem_base + + pxl_reg->csid_pxl_format_measure_cfg0_addr); + } + /* set frame drop pattern to 0 and period to 1 */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_frm_drop_period_addr); @@ -1811,6 +1874,7 @@ static int cam_ife_csid_enable_pxl_path( const struct cam_ife_csid_pxl_reg_offset *pxl_reg = NULL; bool is_ipp; uint32_t val = 0, path_status; + struct cam_isp_sensor_dimension *path_config; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; csid_reg = csid_hw->csid_info->csid_reg; @@ -1819,9 +1883,11 @@ static int cam_ife_csid_enable_pxl_path( if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) { is_ipp = true; pxl_reg = csid_reg->ipp_reg; + path_config = &(csid_hw->ipp_path_config); } else { is_ipp = false; pxl_reg = csid_reg->ppp_reg; + path_config = &(csid_hw->ppp_path_config); } if (res->res_state != CAM_ISP_RESOURCE_STATE_INIT_HW) { @@ -1882,6 +1948,10 @@ static int cam_ife_csid_enable_pxl_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; + if (path_config->measure_enabled) + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + pxl_reg->csid_pxl_irq_mask_addr); @@ -1982,7 +2052,7 @@ static int cam_ife_csid_init_config_rdi_path( struct cam_ife_csid_path_cfg *path_data; const struct cam_ife_csid_reg_offset *csid_reg; struct cam_hw_soc_info *soc_info; - uint32_t path_format = 0, plain_fmt = 0, val = 0, id; + uint32_t path_format = 0, plain_fmt = 0, val = 0, id, in_bpp = 0; uint32_t format_measure_addr; path_data = (struct cam_ife_csid_path_cfg *) res->res_priv; @@ -1997,7 +2067,7 @@ static int cam_ife_csid_init_config_rdi_path( } rc = cam_ife_csid_get_format_rdi(path_data->in_format, - path_data->out_format, &path_format, &plain_fmt); + path_data->out_format, &path_format, &plain_fmt, &in_bpp); if (rc) return rc; @@ -2046,6 +2116,32 @@ static int cam_ife_csid_init_config_rdi_path( CAM_DBG(CAM_ISP, "CSID:%d Vertical Crop config val: 0x%x", csid_hw->hw_intf->hw_idx, val); } + + /* configure pixel format measure */ + if (csid_hw->rdi_path_config[id].measure_enabled) { + val = ((csid_hw->rdi_path_config[id].height & + csid_reg->cmn_reg->format_measure_height_mask_val) << + csid_reg->cmn_reg->format_measure_height_shift_val); + + if (path_format == 0xF) + val |= (((csid_hw->rdi_path_config[id].width * + in_bpp) / 8) & + csid_reg->cmn_reg->format_measure_width_mask_val); + else + val |= (csid_hw->rdi_path_config[id].width & + csid_reg->cmn_reg->format_measure_width_mask_val); + + CAM_DBG(CAM_ISP, "CSID:%d format measure cfg1 value : 0x%x", + csid_hw->hw_intf->hw_idx, val); + + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg1_addr); + + /* enable pixel and line counter */ + cam_io_w_mb(3, soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[id]->csid_rdi_format_measure_cfg0_addr); + } + /* set frame drop pattern to 0 and period to 1 */ cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_frm_drop_period_addr); @@ -2218,6 +2314,10 @@ static int cam_ife_csid_enable_rdi_path( if (csid_hw->csid_debug & CSID_DEBUG_ENABLE_EOF_IRQ) val |= CSID_PATH_INFO_INPUT_EOF; + if (csid_hw->rdi_path_config[id].measure_enabled) + val |= (CSID_PATH_ERROR_PIX_COUNT | + CSID_PATH_ERROR_LINE_COUNT); + cam_io_w_mb(val, soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[id]->csid_rdi_irq_mask_addr); @@ -2454,9 +2554,16 @@ static int cam_ife_csid_get_time_stamp( CAM_IFE_CSID_QTIMER_MUL_FACTOR, CAM_IFE_CSID_QTIMER_DIV_FACTOR); - get_monotonic_boottime64(&ts); - time_stamp->boot_timestamp = (uint64_t)((ts.tv_sec * 1000000000) + - ts.tv_nsec); + if (!csid_hw->first_sof_ts) { + get_monotonic_boottime64(&ts); + time_stamp->boot_timestamp = + (uint64_t)((ts.tv_sec * 1000000000) + + ts.tv_nsec); + CAM_DBG(CAM_ISP, "timestamp:%lld", + time_stamp->boot_timestamp); + csid_hw->first_sof_ts = 1; + } else + time_stamp->boot_timestamp = 0; return 0; } @@ -2664,6 +2771,13 @@ static int cam_ife_csid_release(void *hw_priv, case CAM_ISP_RESOURCE_PIX_PATH: res->res_state = CAM_ISP_RESOURCE_STATE_AVAILABLE; cam_ife_csid_reset_init_frame_drop(csid_hw); + if (res->res_id == CAM_IFE_PIX_PATH_RES_IPP) + csid_hw->ipp_path_config.measure_enabled = 0; + else if (res->res_id == CAM_IFE_PIX_PATH_RES_PPP) + csid_hw->ppp_path_config.measure_enabled = 0; + else + csid_hw->rdi_path_config[res->res_id].measure_enabled + = 0; break; default: CAM_ERR(CAM_ISP, "CSID:%d Invalid res type:%d res id%d", @@ -3094,6 +3208,57 @@ static int cam_ife_csid_set_csid_clock( return 0; } +static int cam_ife_csid_set_sensor_dimension( + struct cam_ife_csid_hw *csid_hw, void *cmd_args) +{ + struct cam_ife_sensor_dimension_update_args *dimension_update = NULL; + uint32_t i; + + if (!csid_hw) + return -EINVAL; + + dimension_update = + (struct cam_ife_sensor_dimension_update_args *)cmd_args; + csid_hw->ipp_path_config.measure_enabled = + dimension_update->ipp_path.measure_enabled; + if (dimension_update->ipp_path.measure_enabled) { + csid_hw->ipp_path_config.width = + dimension_update->ipp_path.width; + csid_hw->ipp_path_config.height = + dimension_update->ipp_path.height; + CAM_DBG(CAM_ISP, "CSID ipp path width %d height %d", + csid_hw->ipp_path_config.width, + csid_hw->ipp_path_config.height); + } + csid_hw->ppp_path_config.measure_enabled = + dimension_update->ppp_path.measure_enabled; + if (dimension_update->ppp_path.measure_enabled) { + csid_hw->ppp_path_config.width = + dimension_update->ppp_path.width; + csid_hw->ppp_path_config.height = + dimension_update->ppp_path.height; + CAM_DBG(CAM_ISP, "CSID ppp path width %d height %d", + csid_hw->ppp_path_config.width, + csid_hw->ppp_path_config.height); + } + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) { + csid_hw->rdi_path_config[i].measure_enabled + = dimension_update->rdi_path[i].measure_enabled; + if (csid_hw->rdi_path_config[i].measure_enabled) { + csid_hw->rdi_path_config[i].width = + dimension_update->rdi_path[i].width; + csid_hw->rdi_path_config[i].height = + dimension_update->rdi_path[i].height; + CAM_DBG(CAM_ISP, + "CSID rdi path[%d] width %d height %d", + i, csid_hw->rdi_path_config[i].width, + csid_hw->rdi_path_config[i].height); + } + } + + return 0; +} + static int cam_ife_csid_process_cmd(void *hw_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { @@ -3131,6 +3296,9 @@ static int cam_ife_csid_process_cmd(void *hw_priv, case CAM_IFE_CSID_SET_INIT_FRAME_DROP: rc = cam_ife_csid_set_init_frame_drop(csid_hw, cmd_args); break; + case CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG: + rc = cam_ife_csid_set_sensor_dimension(csid_hw, cmd_args); + break; default: CAM_ERR(CAM_ISP, "CSID:%d unsupported cmd:%d", csid_hw->hw_intf->hw_idx, cmd_type); @@ -3153,20 +3321,19 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) const struct cam_ife_csid_rdi_reg_offset *rdi_reg; uint32_t i, irq_status_top, irq_status_rx, irq_status_ipp = 0; uint32_t irq_status_rdi[4] = {0, 0, 0, 0}; - uint32_t val, irq_status_ppp = 0; + uint32_t val, val2, irq_status_ppp = 0; bool fatal_err_detected = false; uint32_t sof_irq_debug_en = 0; unsigned long flags; - csid_hw = (struct cam_ife_csid_hw *)data; - - CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); - if (!data) { CAM_ERR(CAM_ISP, "CSID: Invalid arguments"); return IRQ_HANDLED; } + csid_hw = (struct cam_ife_csid_hw *)data; + CAM_DBG(CAM_ISP, "CSID %d IRQ Handling", csid_hw->hw_intf->hw_idx); + csid_reg = csid_hw->csid_info->csid_reg; soc_info = &csid_hw->hw_info->soc_info; csi2_reg = csid_reg->csi2_reg; @@ -3209,7 +3376,7 @@ irqreturn_t cam_ife_csid_irq(int irq_num, void *data) cam_io_w_mb(1, soc_info->reg_map[0].mem_base + csid_reg->cmn_reg->csid_irq_cmd_addr); - CAM_DBG(CAM_ISP, + CAM_ERR_RATE_LIMIT(CAM_ISP, "CSID %d irq status 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", csid_hw->hw_intf->hw_idx, irq_status_top, irq_status_rx, irq_status_ipp, irq_status_ppp, @@ -3446,6 +3613,25 @@ handle_fatal_error: csid_reg->ipp_reg->csid_pxl_ctrl_addr); } } + + if ((irq_status_ipp & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_ipp & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ipp_reg->csid_pxl_format_measure0_addr); + + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_ipp:0x%x", + csid_hw->hw_intf->hw_idx, irq_status_ipp); + CAM_ERR(CAM_ISP, + "Expected sz 0x%x*0x%x actual sz 0x%x*0x%x", + csid_hw->ipp_path_config.height, + csid_hw->ipp_path_config.width, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } /*read PPP errors */ @@ -3527,6 +3713,25 @@ handle_fatal_error: csid_reg->ppp_reg->csid_pxl_ctrl_addr); } } + + if ((irq_status_ppp & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_ppp & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->ppp_reg->csid_pxl_format_measure0_addr); + + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_ppp:0x%x", + csid_hw->hw_intf->hw_idx, irq_status_ppp); + CAM_ERR(CAM_ISP, + "Expected sz 0x%x*0x%x actual sz 0x%x*0x%x", + csid_hw->ppp_path_config.height, + csid_hw->ppp_path_config.width, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } for (i = 0; i < csid_reg->cmn_reg->num_rdis; i++) { @@ -3593,6 +3798,31 @@ handle_fatal_error: soc_info->reg_map[0].mem_base + csid_reg->rdi_reg[i]->csid_rdi_ctrl_addr); } + + if ((irq_status_rdi[i] & CSID_PATH_ERROR_PIX_COUNT) || + (irq_status_rdi[i] & CSID_PATH_ERROR_LINE_COUNT)) { + val = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_format_measure0_addr); + val2 = cam_io_r_mb(soc_info->reg_map[0].mem_base + + csid_reg->rdi_reg[i]->csid_rdi_format_measure_cfg1_addr + ); + CAM_ERR(CAM_ISP, + "CSID:%d irq_status_rdi[%d]:0x%x", + csid_hw->hw_intf->hw_idx, i, + irq_status_rdi[i]); + CAM_ERR(CAM_ISP, + "Expected sz 0x%x*0x%x actual sz 0x%x*0x%x", + ((val2 >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val2 & + csid_reg->cmn_reg->format_measure_width_mask_val, + ((val >> + csid_reg->cmn_reg->format_measure_height_shift_val) & + csid_reg->cmn_reg->format_measure_height_mask_val), + val & + csid_reg->cmn_reg->format_measure_width_mask_val); + } } if (csid_hw->irq_debug_cnt >= CAM_CSID_IRQ_SOF_DEBUG_CNT_MAX) { @@ -3629,7 +3859,6 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, CAM_DBG(CAM_ISP, "type %d index %d", ife_csid_hw->hw_intf->hw_type, csid_idx); - ife_csid_hw->device_enabled = 0; ife_csid_hw->hw_info->hw_state = CAM_HW_STATE_POWER_DOWN; mutex_init(&ife_csid_hw->hw_info->hw_mutex); @@ -3644,7 +3873,6 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, for (i = 0; i < CAM_IFE_CSID_RDI_MAX; i++) init_completion(&ife_csid_hw->csid_rdin_complete[i]); - rc = cam_ife_csid_init_soc_resources(&ife_csid_hw->hw_info->soc_info, cam_ife_csid_irq, ife_csid_hw); if (rc < 0) { @@ -3737,8 +3965,28 @@ int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, ife_csid_hw->csid_debug = 0; ife_csid_hw->error_irq_count = 0; + ife_csid_hw->first_sof_ts = 0; + ife_csid_hw->ipp_path_config.measure_enabled = 0; + ife_csid_hw->ppp_path_config.measure_enabled = 0; + for (i = 0; i <= CAM_IFE_PIX_PATH_RES_RDI_3; i++) + ife_csid_hw->rdi_path_config[i].measure_enabled = 0; + + /* Check if ppi bridge is present or not? */ + ife_csid_hw->ppi_enable = of_property_read_bool( + csid_hw_info->soc_info.pdev->dev.of_node, + "ppi-enable"); + + if (!ife_csid_hw->ppi_enable) + return 0; - return 0; + /* Initialize the PPI bridge */ + for (i = 0; i < CAM_CSID_PPI_HW_MAX; i++) { + rc = cam_csid_ppi_hw_init(&ife_csid_hw->ppi_hw_intf[i], i); + if (rc < 0) { + CAM_ERR(CAM_ISP, "PPI init failed for PPI %d", i); + break; + } + } err: if (rc) { kfree(ife_csid_hw->ipp_res.res_priv); diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h index 600deb245f32..f2173f13f0c4 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.h @@ -16,6 +16,7 @@ #include "cam_hw.h" #include "cam_ife_csid_hw_intf.h" #include "cam_ife_csid_soc.h" +#include "cam_csid_ppi_core.h" #define CAM_IFE_CSID_HW_RES_MAX 4 #define CAM_IFE_CSID_CID_RES_MAX 4 @@ -309,6 +310,10 @@ struct cam_ife_csid_common_reg_offset { uint32_t ppp_irq_mask_all; uint32_t measure_en_hbi_vbi_cnt_mask; uint32_t format_measure_en_val; + uint32_t format_measure_width_shift_val; + uint32_t format_measure_width_mask_val; + uint32_t format_measure_height_shift_val; + uint32_t format_measure_height_mask_val; }; /** @@ -468,6 +473,11 @@ struct cam_ife_csid_path_cfg { * @csid_debug: csid debug information to enable the SOT, EOT, * SOF, EOF, measure etc in the csid hw * @clk_rate Clock rate + * @ipp_path ipp path configuration + * @ppp_path ppp path configuration + * @rdi_path RDI path configuration + * @hbi Horizontal blanking + * @vbi Vertical blanking * @sof_irq_triggered: Flag is set on receiving event to enable sof irq * incase of SOF freeze. * @irq_debug_cnt: Counter to track sof irq's when above flag is set. @@ -480,7 +490,10 @@ struct cam_ife_csid_path_cfg { * @init_frame_drop Initial frame drop number * @res_sof_cnt path resource sof count value. it used for initial * frame drop - * + * @first_sof_ts flag to mark the first sof has been registered + * @ppi_hw_intf interface to ppi hardware + * @ppi_enabled flag to specify if the hardware has ppi bridge + * or not */ struct cam_ife_csid_hw { struct cam_hw_intf *hw_intf; @@ -503,6 +516,11 @@ struct cam_ife_csid_hw { struct completion csid_rdin_complete[CAM_IFE_CSID_RDI_MAX]; uint64_t csid_debug; uint64_t clk_rate; + struct cam_isp_sensor_dimension ipp_path_config; + struct cam_isp_sensor_dimension ppp_path_config; + struct cam_isp_sensor_dimension rdi_path_config[4]; + uint32_t hbi; + uint32_t vbi; bool sof_irq_triggered; uint32_t irq_debug_cnt; uint32_t error_irq_count; @@ -511,6 +529,9 @@ struct cam_ife_csid_hw { uint32_t dual_usage; uint32_t init_frame_drop; uint32_t res_sof_cnt[CAM_IFE_PIX_PATH_RES_MAX]; + uint32_t first_sof_ts; + struct cam_hw_intf *ppi_hw_intf[CAM_CSID_PPI_HW_MAX]; + bool ppi_enable; }; int cam_ife_csid_hw_probe_init(struct cam_hw_intf *csid_hw_intf, diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h index 0c45bd1268b9..8d340207a0a1 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_ife_csid_hw_intf.h @@ -158,6 +158,7 @@ enum cam_ife_csid_cmd_type { CAM_IFE_CSID_SET_CSID_DEBUG, CAM_IFE_CSID_SOF_IRQ_DEBUG, CAM_IFE_CSID_SET_INIT_FRAME_DROP, + CAM_IFE_CSID_SET_SENSOR_DIMENSION_CFG, CAM_IFE_CSID_CMD_MAX, }; @@ -181,5 +182,17 @@ struct cam_ife_csid_clock_update_args { uint64_t clk_rate; }; +/* + * struct cam_ife_sensor_dim_update_args: + * + * @ppp_path: expected ppp path configuration + * @ipp_path: expected ipp path configuration + * @rdi_path: expected rdi path configuration + */ +struct cam_ife_sensor_dimension_update_args { + struct cam_isp_sensor_dimension ppp_path; + struct cam_isp_sensor_dimension ipp_path; + struct cam_isp_sensor_dimension rdi_path[4]; +}; #endif /* _CAM_CSID_HW_INTF_H_ */ diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h index b23014773022..d90030d9ed16 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h @@ -20,17 +20,21 @@ #include "cam_irq_controller.h" #include <uapi/media/cam_isp.h> +#define CAM_ISP_FPS_60 60 + /* * struct cam_isp_timestamp: * * @mono_time: Monotonic boot time * @vt_time: AV Timer time * @ticks: Qtimer ticks + * @time_usecs: time in micro seconds */ struct cam_isp_timestamp { struct timeval mono_time; struct timeval vt_time; uint64_t ticks; + uint64_t time_usecs; }; /* @@ -105,6 +109,7 @@ enum cam_isp_hw_cmd_type { CAM_ISP_HW_CMD_FE_UPDATE_IN_RD, CAM_ISP_HW_CMD_FE_UPDATE_BUS_RD, CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, + CAM_ISP_HW_CMD_FPS_CONFIG, CAM_ISP_HW_CMD_MAX, }; diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h index 9d6bcb71bb69..3bcedc948a18 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/include/cam_vfe_hw_intf.h @@ -178,6 +178,17 @@ struct cam_vfe_clock_update_args { }; /* + * struct cam_vfe_fps_config_args: + * + * @node_res: Resource to get the fps value + * @fps: FPS value to configure EPOCH + */ +struct cam_vfe_fps_config_args { + struct cam_isp_resource_node *node_res; + uint32_t fps; +}; + +/* * struct cam_vfe_bw_update_args: * * @node_res: Resource to get the BW diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c index a26c11264d2c..162ddadd744f 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c @@ -444,6 +444,8 @@ void cam_isp_hw_get_timestamp(struct cam_isp_timestamp *time_stamp) get_monotonic_boottime(&ts); time_stamp->mono_time.tv_sec = ts.tv_sec; time_stamp->mono_time.tv_usec = ts.tv_nsec/1000; + time_stamp->time_usecs = ts.tv_sec * 1000000 + + time_stamp->mono_time.tv_usec; } static int cam_vfe_irq_top_half(uint32_t evt_id, @@ -761,6 +763,7 @@ int cam_vfe_process_cmd(void *hw_priv, uint32_t cmd_type, case CAM_ISP_HW_CMD_BW_UPDATE: case CAM_ISP_HW_CMD_BW_CONTROL: case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP: + case CAM_ISP_HW_CMD_FPS_CONFIG: rc = core_info->vfe_top->hw_ops.process_cmd( core_info->vfe_top->top_priv, cmd_type, cmd_args, arg_size); diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c index 4e9a97501749..a70f0bbd1340 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c @@ -44,6 +44,7 @@ struct cam_vfe_mux_camif_data { bool enable_sof_irq_debug; uint32_t irq_debug_cnt; uint32_t camif_debug; + uint32_t fps; }; static int cam_vfe_camif_validate_pix_pattern(uint32_t pattern) @@ -265,9 +266,15 @@ static int cam_vfe_camif_resource_start( case CAM_CPAS_TITAN_170_V110: case CAM_CPAS_TITAN_170_V120: default: - epoch0_irq_mask = (((rsrc_data->last_line - + if (rsrc_data->fps == CAM_ISP_FPS_60) { + epoch0_irq_mask = ((rsrc_data->last_line - + rsrc_data->first_line) / 2) + + rsrc_data->first_line; + } else { + epoch0_irq_mask = (((rsrc_data->last_line - rsrc_data->first_line) * 2) / 3) + rsrc_data->first_line; + } epoch1_irq_mask = rsrc_data->reg_data->epoch_line_cfg & 0xFFFF; computed_epoch_line_cfg = (epoch0_irq_mask << 16) | @@ -514,6 +521,20 @@ static int cam_vfe_camif_sof_irq_debug( return 0; } +static int cam_vfe_camif_set_fps_config( + struct cam_isp_resource_node *rsrc_node, void *cmd_args) +{ + struct cam_vfe_mux_camif_data *camif_priv = NULL; + struct cam_vfe_fps_config_args *fps_args = cmd_args; + + camif_priv = + (struct cam_vfe_mux_camif_data *)rsrc_node->res_priv; + + camif_priv->fps = fps_args->fps; + + return 0; + +} static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) @@ -545,6 +566,9 @@ static int cam_vfe_camif_process_cmd(struct cam_isp_resource_node *rsrc_node, case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP: rc = cam_vfe_camif_irq_reg_dump(rsrc_node); break; + case CAM_ISP_HW_CMD_FPS_CONFIG: + rc = cam_vfe_camif_set_fps_config(rsrc_node, cmd_args); + break; default: CAM_ERR(CAM_ISP, "unsupported process command:%d", cmd_type); diff --git a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c index b0ac94b895f1..9d03cbad7ff0 100644 --- a/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c +++ b/drivers/media/platform/msm/camera_v3/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c @@ -283,6 +283,22 @@ static int cam_vfe_top_fs_update( return 0; } +static int cam_vfe_top_fps_config( + struct cam_vfe_top_ver2_priv *top_priv, + void *cmd_args, uint32_t arg_size) +{ + struct cam_vfe_fps_config_args *cmd_update = NULL; + + cmd_update = + (struct cam_vfe_fps_config_args *)cmd_args; + + if (cmd_update->node_res->process_cmd) + return cmd_update->node_res->process_cmd(cmd_update->node_res, + CAM_ISP_HW_CMD_FPS_CONFIG, cmd_args, arg_size); + + return 0; +} + static int cam_vfe_top_clock_update( struct cam_vfe_top_ver2_priv *top_priv, void *cmd_args, uint32_t arg_size) @@ -740,6 +756,10 @@ int cam_vfe_top_process_cmd(void *device_priv, uint32_t cmd_type, rc = cam_vfe_get_irq_register_dump(top_priv, cmd_args, arg_size); break; + case CAM_ISP_HW_CMD_FPS_CONFIG: + rc = cam_vfe_top_fps_config(top_priv, cmd_args, + arg_size); + break; default: rc = -EINVAL; CAM_ERR(CAM_ISP, "Error! Invalid cmd:%d", cmd_type); diff --git a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c index f7b42d5a7699..1a3a7cb38878 100644 --- a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c +++ b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c @@ -634,8 +634,13 @@ static void cam_jpeg_mgr_print_io_bufs(struct cam_packet *packet, for (i = 0; i < packet->num_io_configs; i++) { for (j = 0; j < CAM_PACKET_MAX_PLANES; j++) { - if (!io_cfg[i].mem_handle[j]) + if (!io_cfg[i].mem_handle[j]) { + CAM_ERR(CAM_JPEG, + "Mem Handle %d is NULL for %d io config", + j, i); break; + } + if (GET_FD_FROM_HANDLE(io_cfg[i].mem_handle[j]) == GET_FD_FROM_HANDLE(pf_buf_info)) { diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c index c8e2a023b0d4..b2994d52d83c 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.c @@ -48,6 +48,9 @@ void cam_req_mgr_core_link_reset(struct cam_req_mgr_core_link *link) link->last_flush_id = 0; link->initial_sync_req = -1; link->in_msync_mode = false; + link->initial_skip = true; + link->sof_timestamp = 0; + link->prev_sof_timestamp = 0; } void cam_req_mgr_handle_core_shutdown(void) @@ -610,6 +613,19 @@ static int __cam_req_mgr_check_link_is_ready(struct cam_req_mgr_core_link *link, traverse_data.open_req_cnt = link->open_req_cnt; /* + * Some no-sync mode requests are processed after link config, + * then process the sync mode requests after no-sync mode requests + * are handled, the initial_skip should be false when processing + * the sync mode requests. + */ + if (link->initial_skip) { + CAM_DBG(CAM_CRM, + "Set initial_skip to false for link %x", + link->link_hdl); + link->initial_skip = false; + } + + /* * Traverse through all pd tables, if result is success, * apply the settings */ @@ -894,9 +910,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( struct cam_req_mgr_slot *slot) { struct cam_req_mgr_core_link *sync_link = NULL; - int64_t req_id = 0; + struct cam_req_mgr_slot *sync_rd_slot = NULL; + int64_t req_id = 0, sync_req_id = 0; int sync_slot_idx = 0, sync_rd_idx = 0, rc = 0; int32_t sync_num_slots = 0; + uint64_t sync_frame_duration = 0; bool ready = true, sync_ready = true; if (!link->sync_link) { @@ -907,11 +925,65 @@ static int __cam_req_mgr_check_sync_req_is_ready( sync_link = link->sync_link; req_id = slot->req_id; sync_num_slots = sync_link->req.in_q->num_slots; + sync_rd_idx = sync_link->req.in_q->rd_idx; + sync_rd_slot = &sync_link->req.in_q->slot[sync_rd_idx]; + sync_req_id = sync_rd_slot->req_id; CAM_DBG(CAM_REQ, "link_hdl %x req %lld frame_skip_flag %d ", link->link_hdl, req_id, link->sync_link_sof_skip); + if (sync_link->initial_skip) { + link->initial_skip = false; + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + CAM_DBG(CAM_CRM, + "sync link %x not streamed on", + sync_link->link_hdl); + return -EAGAIN; + } + + if (sync_link->prev_sof_timestamp) + sync_frame_duration = sync_link->sof_timestamp + - sync_link->prev_sof_timestamp; + else + sync_frame_duration = DEFAULT_FRAME_DURATION; + + CAM_DBG(CAM_CRM, + "sync link %x last frame duration is %d ns", + sync_link->link_hdl, sync_frame_duration); + + if (link->initial_skip) { + link->initial_skip = false; + + if (link->sof_timestamp > sync_link->sof_timestamp && + sync_link->sof_timestamp > 0 && + link->sof_timestamp - sync_link->sof_timestamp < + sync_frame_duration / 2) { + /* + * If this frame sync with the previous frame of sync + * link, then we need to skip this frame, since the + * previous frame of sync link is also skipped. + */ + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + CAM_DBG(CAM_CRM, + "This frame sync with previous sync_link %x frame", + sync_link->link_hdl); + return -EAGAIN; + } else if (link->sof_timestamp <= sync_link->sof_timestamp) { + /* + * Sometimes, link receives the SOF event is eariler + * than sync link in IFE CSID side, but link's SOF + * event is processed later than sync link's, then + * we need to skip this SOF event since the sync + * link's SOF event is also skipped. + */ + __cam_req_mgr_inject_delay(link->req.l_tbl, slot->idx); + CAM_DBG(CAM_CRM, + "The previous frame of sync link is skipped"); + return -EAGAIN; + } + } + if (sync_link->sync_link_sof_skip) { CAM_DBG(CAM_REQ, "No req applied on corresponding SOF on sync link: %x", @@ -937,12 +1009,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( sync_ready = false; } - sync_rd_idx = sync_link->req.in_q->rd_idx; if ((sync_link->req.in_q->slot[sync_slot_idx].status != CRM_SLOT_STATUS_REQ_APPLIED) && (((sync_slot_idx - sync_rd_idx + sync_num_slots) % sync_num_slots) >= 1) && - (sync_link->req.in_q->slot[sync_rd_idx].status != + (sync_rd_slot->status != CRM_SLOT_STATUS_REQ_APPLIED)) { CAM_DBG(CAM_CRM, "Req: %lld [other link] not next req to be applied on link: %x", @@ -975,7 +1046,15 @@ static int __cam_req_mgr_check_sync_req_is_ready( CAM_DBG(CAM_CRM, "Req: %lld ready %d sync_ready %d, ignore sync link next SOF", req_id, ready, sync_ready); - link->sync_link_sof_skip = true; + + /* + * Only skip the frames if current frame sync with + * next frame of sync link. + */ + if (link->sof_timestamp - sync_link->sof_timestamp > + sync_frame_duration / 2) + link->sync_link_sof_skip = true; + return -EINVAL; } else if (ready == false) { CAM_DBG(CAM_CRM, @@ -984,6 +1063,61 @@ static int __cam_req_mgr_check_sync_req_is_ready( return -EINVAL; } + /* + * Do the self-correction when the frames are sync, + * we consider that the frames are synced if the + * difference of two SOF timestamp less than + * (sync_frame_duration / 5). + */ + if ((link->sof_timestamp > sync_link->sof_timestamp) && + (sync_link->sof_timestamp > 0) && + (link->sof_timestamp - sync_link->sof_timestamp < + sync_frame_duration / 5) && + (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { + + /* + * This means current frame should sync with next + * frame of sync link, then the request id of in + * rd slot of two links should be same. + */ + CAM_DBG(CAM_CRM, + "link %x req_id %lld, sync_link %x req_id %lld", + link->link_hdl, req_id, + sync_link->link_hdl, sync_req_id); + + if (req_id > sync_req_id) { + CAM_DBG(CAM_CRM, + "link %x too quickly, skip this frame", + link->link_hdl); + return -EAGAIN; + } else if (req_id < sync_req_id) { + CAM_DBG(CAM_CRM, + "sync link %x too quickly, skip next frame of sync link", + sync_link->link_hdl); + link->sync_link_sof_skip = true; + } + } else if ((sync_link->sof_timestamp > 0) && + (link->sof_timestamp < sync_link->sof_timestamp) && + (sync_link->sof_timestamp - link->sof_timestamp < + sync_frame_duration / 5) && + (sync_rd_slot->sync_mode == CAM_REQ_MGR_SYNC_MODE_SYNC)) { + + /* + * There is a timing issue once enter this condition, + * it means link receives the SOF event earlier than + * sync link in IFE CSID side, but the process in CRM + * is sync_link earlier than link, then previous SOF + * event of sync link is skipped, so we also need to + * skip this SOF event. + */ + if (req_id >= sync_req_id) { + CAM_DBG(CAM_CRM, + "Timing issue, the sof event of link %x is delayed", + link->link_hdl); + return -EAGAIN; + } + } + CAM_DBG(CAM_REQ, "Req: %lld ready to apply on link: %x [validation successful]", req_id, link->link_hdl); @@ -1011,10 +1145,11 @@ static int __cam_req_mgr_check_sync_req_is_ready( * */ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, - uint32_t trigger) + struct cam_req_mgr_trigger_notify *trigger_data) { int rc = 0, idx, last_app_idx; int reset_step = 0; + uint32_t trigger = trigger_data->trigger; struct cam_req_mgr_slot *slot = NULL; struct cam_req_mgr_req_queue *in_q; struct cam_req_mgr_core_session *session; @@ -1052,6 +1187,13 @@ static int __cam_req_mgr_process_req(struct cam_req_mgr_core_link *link, } if (trigger == CAM_TRIGGER_POINT_SOF) { + /* + * Update the timestamp in session lock protection + * to avoid timing issue. + */ + link->prev_sof_timestamp = link->sof_timestamp; + link->sof_timestamp = trigger_data->sof_timestamp_val; + if (link->trigger_mask) { CAM_ERR_RATE_LIMIT(CAM_CRM, "Applying for last EOF fails"); @@ -2141,7 +2283,7 @@ static int cam_req_mgr_process_trigger(void *priv, void *data) __cam_req_mgr_inc_idx(&in_q->rd_idx, 1, in_q->num_slots); } - rc = __cam_req_mgr_process_req(link, trigger_data->trigger); + rc = __cam_req_mgr_process_req(link, trigger_data); release_lock: mutex_unlock(&link->req.lock); @@ -2372,6 +2514,7 @@ static int cam_req_mgr_cb_notify_trigger( notify_trigger->link_hdl = trigger_data->link_hdl; notify_trigger->dev_hdl = trigger_data->dev_hdl; notify_trigger->trigger = trigger_data->trigger; + notify_trigger->sof_timestamp_val = trigger_data->sof_timestamp_val; task->process_cb = &cam_req_mgr_process_trigger; rc = cam_req_mgr_workq_enqueue_task(task, link, CRM_TASK_PRIORITY_0); @@ -3125,8 +3268,6 @@ int cam_req_mgr_sync_config( link1->is_master = false; link2->is_master = false; - link1->initial_skip = false; - link2->initial_skip = false; link1->in_msync_mode = false; link2->in_msync_mode = false; @@ -3137,6 +3278,16 @@ int cam_req_mgr_sync_config( link1->sync_link = link2; link2->sync_link = link1; __cam_req_mgr_set_master_link(link1, link2); + } else { + /* + * Reset below info after the mode is configured + * to NO-SYNC mode since they may be overridden + * if the sync config is invoked after SOF comes. + */ + link1->initial_skip = true; + link2->initial_skip = true; + link1->sof_timestamp = 0; + link2->sof_timestamp = 0; } cam_session->sync_mode = sync_info->sync_mode; diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h index 05fe0860bfa0..94f26dee8917 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_core.h @@ -32,6 +32,9 @@ #define MAX_SYNC_COUNT 65535 +/* Default frame rate is 30 */ +#define DEFAULT_FRAME_DURATION 33333333 + #define SYNC_LINK_SOF_CNT_MAX_LMT 1 #define MAXIMUM_LINKS_PER_SESSION 4 @@ -321,7 +324,10 @@ struct cam_req_mgr_connected_device { * master-slave sync * @in_msync_mode : Flag to determine if a link is in master-slave mode * @initial_sync_req : The initial req which is required to sync with the - * other link + * other link, it means current hasn't receive any + * stream after streamon if it is true + * @sof_timestamp_value : SOF timestamp value + * @prev_sof_timestamp : Previous SOF timestamp value * */ struct cam_req_mgr_core_link { @@ -349,6 +355,8 @@ struct cam_req_mgr_core_link { bool initial_skip; bool in_msync_mode; int64_t initial_sync_req; + uint64_t sof_timestamp; + uint64_t prev_sof_timestamp; }; /** diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h index 1d1df45c6ea5..934bc76014a5 100644 --- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h +++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_interface.h @@ -201,12 +201,14 @@ enum cam_req_mgr_link_evt_type { * @frame_id : frame id for internal tracking * @trigger : trigger point of this notification, CRM will send apply * only to the devices which subscribe to this point. + * @sof_timestamp_val: Captured time stamp value at sof hw event */ struct cam_req_mgr_trigger_notify { int32_t link_hdl; int32_t dev_hdl; int64_t frame_id; uint32_t trigger; + uint64_t sof_timestamp_val; }; /** diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c index 0181a4d8e2ff..f66d86ce091e 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_cci/cam_cci_soc.c @@ -410,7 +410,9 @@ int cam_cci_soc_release(struct cci_device *cci_dev) cci_dev->cci_state = CCI_STATE_DISABLED; cci_dev->cycles_per_us = 0; - cam_cpas_stop(cci_dev->cpas_handle); + rc = cam_cpas_stop(cci_dev->cpas_handle); + if (rc) + CAM_ERR(CAM_CCI, "cpas stop failed %d", rc); return rc; } diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c index 8074ecd9112a..b8605596aa6c 100644 --- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c +++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_csiphy/cam_csiphy_core.c @@ -551,7 +551,7 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev) void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) { struct cam_hw_soc_info *soc_info; - int32_t i = 0; + int32_t i = 0, rc = 0; if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT) return; @@ -574,7 +574,10 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev) cam_csiphy_reset(csiphy_dev); cam_soc_util_disable_platform_resource(soc_info, true, true); - cam_cpas_stop(csiphy_dev->cpas_handle); + rc = cam_cpas_stop(csiphy_dev->cpas_handle); + if (rc) + CAM_ERR(CAM_CSIPHY, "cpas stop failed %d", rc); + csiphy_dev->csiphy_state = CAM_CSIPHY_ACQUIRE; } @@ -934,7 +937,10 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, if (rc < 0) { csiphy_dev->csiphy_info.secure_mode[offset] = CAM_SECURE_MODE_NON_SECURE; - cam_cpas_stop(csiphy_dev->cpas_handle); + rc = cam_cpas_stop(csiphy_dev->cpas_handle); + if (rc < 0) + CAM_ERR(CAM_CSIPHY, + "de-voting CPAS: %d", rc); goto release_mutex; } } @@ -942,7 +948,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, rc = cam_csiphy_enable_hw(csiphy_dev); if (rc != 0) { CAM_ERR(CAM_CSIPHY, "cam_csiphy_enable_hw failed"); - cam_cpas_stop(csiphy_dev->cpas_handle); + rc = cam_cpas_stop(csiphy_dev->cpas_handle); + if (rc < 0) + CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc); goto release_mutex; } rc = cam_csiphy_config_dev(csiphy_dev); @@ -952,7 +960,9 @@ int32_t cam_csiphy_core_cfg(void *phy_dev, if (rc < 0) { CAM_ERR(CAM_CSIPHY, "cam_csiphy_config_dev failed"); cam_csiphy_disable_hw(csiphy_dev); - cam_cpas_stop(csiphy_dev->cpas_handle); + rc = cam_cpas_stop(csiphy_dev->cpas_handle); + if (rc < 0) + CAM_ERR(CAM_CSIPHY, "de-voting CPAS: %d", rc); goto release_mutex; } csiphy_dev->start_dev_count++; diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c index 3708c212d57b..185e0608e547 100644 --- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c +++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.c @@ -182,11 +182,15 @@ int cam_packet_util_process_patches(struct cam_packet *packet, int i; int rc = 0; int32_t hdl; + uint64_t requestId; + uint32_t num_patches; /* process patch descriptor */ patch_desc = (struct cam_patch_desc *) ((uint32_t *) &packet->payload + packet->patch_offset/4); + requestId = packet->header.request_id; + num_patches = packet->num_patches; CAM_DBG(CAM_UTIL, "packet = %pK patch_desc = %pK size = %lu", (void *)packet, (void *)patch_desc, sizeof(struct cam_patch_desc)); @@ -197,7 +201,16 @@ int cam_packet_util_process_patches(struct cam_packet *packet, rc = cam_mem_get_io_buf(patch_desc[i].src_buf_hdl, hdl, &iova_addr, &src_buf_size); if (rc < 0) { - CAM_ERR(CAM_UTIL, "unable to get src buf address"); + CAM_ERR(CAM_UTIL, + "unable to get src buf address ReqId: %llu, num_patches = %d", + requestId, num_patches); + CAM_ERR(CAM_UTIL, + "i = %d patch info = %x %x %x %x src_bfsz:0x%x", + i, patch_desc[i].dst_buf_hdl, + patch_desc[i].dst_offset, + patch_desc[i].src_buf_hdl, + patch_desc[i].src_offset, + (uint32_t)src_buf_size); return rc; } src_buf_iova_addr = (uint32_t *)iova_addr; @@ -206,18 +219,37 @@ int cam_packet_util_process_patches(struct cam_packet *packet, rc = cam_mem_get_cpu_buf(patch_desc[i].dst_buf_hdl, &cpu_addr, &dst_buf_len); if (rc < 0 || !cpu_addr || (dst_buf_len == 0)) { - CAM_ERR(CAM_UTIL, "unable to get dst buf address"); + CAM_ERR(CAM_UTIL, + "unable to get dst buf address ReqId: %llu, num_patches = %d", + requestId, num_patches); + CAM_ERR(CAM_UTIL, + "i = %d patch info = %x %x %x %x dst_bfsz:0x%x", + i, patch_desc[i].dst_buf_hdl, + patch_desc[i].dst_offset, + patch_desc[i].src_buf_hdl, + patch_desc[i].src_offset, + (uint32_t)dst_buf_len); return rc; } dst_cpu_addr = (uint32_t *)cpu_addr; - CAM_DBG(CAM_UTIL, "i = %d patch info = %x %x %x %x", i, - patch_desc[i].dst_buf_hdl, patch_desc[i].dst_offset, + CAM_DBG(CAM_UTIL, + "ReqId: %llu, i = %d patch info = %x %x %x %x", + requestId, i, patch_desc[i].dst_buf_hdl, + patch_desc[i].dst_offset, patch_desc[i].src_buf_hdl, patch_desc[i].src_offset); if ((size_t)patch_desc[i].src_offset >= src_buf_size) { CAM_ERR(CAM_UTIL, - "Invalid src buf patch offset"); + "Invalid src buf patch offset ReqId: %llu, num_patches = %d", + requestId, num_patches); + CAM_ERR(CAM_UTIL, + "i = %d patch info = %x %x %x %x src_bfsz:0x%x", + i, patch_desc[i].dst_buf_hdl, + patch_desc[i].dst_offset, + patch_desc[i].src_buf_hdl, + patch_desc[i].src_offset, + (uint32_t)src_buf_size); return -EINVAL; } @@ -225,7 +257,15 @@ int cam_packet_util_process_patches(struct cam_packet *packet, ((dst_buf_len - sizeof(void *)) < (size_t)patch_desc[i].dst_offset)) { CAM_ERR(CAM_UTIL, - "Invalid dst buf patch offset"); + "Invalid dst buf patch offset ReqId: %llu, num_patches = %d", + requestId, num_patches); + CAM_ERR(CAM_UTIL, + "i = %d patch info = %x %x %x %x dst_bfsz:0x%x", + i, patch_desc[i].dst_buf_hdl, + patch_desc[i].dst_offset, + patch_desc[i].src_buf_hdl, + patch_desc[i].src_offset, + (uint32_t)dst_buf_len); return -EINVAL; } diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c index 25d4fd4f4c0b..a72982df4777 100644 --- a/drivers/media/platform/vivid/vivid-vid-cap.c +++ b/drivers/media/platform/vivid/vivid-vid-cap.c @@ -984,7 +984,7 @@ int vivid_vid_cap_s_selection(struct file *file, void *fh, struct v4l2_selection v4l2_rect_map_inside(&s->r, &dev->fmt_cap_rect); if (dev->bitmap_cap && (compose->width != s->r.width || compose->height != s->r.height)) { - kfree(dev->bitmap_cap); + vfree(dev->bitmap_cap); dev->bitmap_cap = NULL; } *compose = s->r; diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 642b89c66bcb..c1457cf46698 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -494,7 +494,8 @@ int fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload, return -EIO; } /* Send response data to caller */ - if (response != NULL && response_len != NULL && evt_hdr->dlen) { + if (response != NULL && response_len != NULL && evt_hdr->dlen && + evt_hdr->dlen <= payload_len) { /* Skip header info and copy only response data */ skb_pull(skb, sizeof(struct fm_event_msg_hdr)); memcpy(response, skb->data, evt_hdr->dlen); @@ -590,6 +591,8 @@ static void fm_irq_handle_flag_getcmd_resp(struct fmdev *fmdev) return; fm_evt_hdr = (void *)skb->data; + if (fm_evt_hdr->dlen > sizeof(fmdev->irq_info.flag)) + return; /* Skip header info and copy only response data */ skb_pull(skb, sizeof(struct fm_event_msg_hdr)); @@ -1315,7 +1318,7 @@ static int load_default_rx_configuration(struct fmdev *fmdev) static int fm_power_up(struct fmdev *fmdev, u8 mode) { u16 payload; - __be16 asic_id, asic_ver; + __be16 asic_id = 0, asic_ver = 0; int resp_len, ret; u8 fw_name[50]; diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c index 85dd9a8e83ff..48eeb5a6a209 100644 --- a/drivers/media/usb/au0828/au0828-video.c +++ b/drivers/media/usb/au0828/au0828-video.c @@ -764,6 +764,9 @@ static int au0828_analog_stream_enable(struct au0828_dev *d) dprintk(1, "au0828_analog_stream_enable called\n"); + if (test_bit(DEV_DISCONNECTED, &d->dev_state)) + return -ENODEV; + iface = usb_ifnum_to_if(d->usbdev, 0); if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) { dprintk(1, "Changing intf#0 to alt 5\n"); @@ -852,9 +855,9 @@ int au0828_start_analog_streaming(struct vb2_queue *vq, unsigned int count) return rc; } + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1); + if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - v4l2_device_call_all(&dev->v4l2_dev, 0, video, - s_stream, 1); dev->vid_timeout_running = 1; mod_timer(&dev->vid_timeout, jiffies + (HZ / 10)); } else if (vq->type == V4L2_BUF_TYPE_VBI_CAPTURE) { @@ -874,10 +877,11 @@ static void au0828_stop_streaming(struct vb2_queue *vq) dprintk(1, "au0828_stop_streaming called %d\n", dev->streaming_users); - if (dev->streaming_users-- == 1) + if (dev->streaming_users-- == 1) { au0828_uninit_isoc(dev); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); + } - v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); dev->vid_timeout_running = 0; del_timer_sync(&dev->vid_timeout); @@ -906,8 +910,10 @@ void au0828_stop_vbi_streaming(struct vb2_queue *vq) dprintk(1, "au0828_stop_vbi_streaming called %d\n", dev->streaming_users); - if (dev->streaming_users-- == 1) + if (dev->streaming_users-- == 1) { au0828_uninit_isoc(dev); + v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0); + } spin_lock_irqsave(&dev->slock, flags); if (dev->isoc_ctl.vbi_buf != NULL) { diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c index d793c630f1dd..05e7edb213de 100644 --- a/drivers/media/usb/cpia2/cpia2_v4l.c +++ b/drivers/media/usb/cpia2/cpia2_v4l.c @@ -1248,8 +1248,7 @@ static int __init cpia2_init(void) LOG("%s v%s\n", ABOUT, CPIA_VERSION); check_parameters(); - cpia2_usb_init(); - return 0; + return cpia2_usb_init(); } diff --git a/drivers/media/usb/go7007/go7007-fw.c b/drivers/media/usb/go7007/go7007-fw.c index 60bf5f0644d1..a5efcd4f7b4f 100644 --- a/drivers/media/usb/go7007/go7007-fw.c +++ b/drivers/media/usb/go7007/go7007-fw.c @@ -1499,8 +1499,8 @@ static int modet_to_package(struct go7007 *go, __le16 *code, int space) return cnt; } -static int do_special(struct go7007 *go, u16 type, __le16 *code, int space, - int *framelen) +static noinline_for_stack int do_special(struct go7007 *go, u16 type, + __le16 *code, int space, int *framelen) { switch (type) { case SPECIAL_FRM_HEAD: diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c index 1eb4f7ba2967..ff489645e070 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c @@ -670,6 +670,8 @@ static int ctrl_get_input(struct pvr2_ctrl *cptr,int *vp) static int ctrl_check_input(struct pvr2_ctrl *cptr,int v) { + if (v < 0 || v > PVR2_CVAL_INPUT_MAX) + return 0; return ((1 << v) & cptr->hdw->input_allowed_mask) != 0; } diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h index a82a00dd7329..80869990ffbb 100644 --- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.h +++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.h @@ -54,6 +54,7 @@ #define PVR2_CVAL_INPUT_COMPOSITE 2 #define PVR2_CVAL_INPUT_SVIDEO 3 #define PVR2_CVAL_INPUT_RADIO 4 +#define PVR2_CVAL_INPUT_MAX PVR2_CVAL_INPUT_RADIO enum pvr2_config { pvr2_config_empty, /* No configuration */ diff --git a/drivers/media/usb/siano/smsusb.c b/drivers/media/usb/siano/smsusb.c index 18b41b9dc2e4..73889d6cfd50 100644 --- a/drivers/media/usb/siano/smsusb.c +++ b/drivers/media/usb/siano/smsusb.c @@ -402,6 +402,7 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) struct smsusb_device_t *dev; void *mdev; int i, rc; + int align = 0; /* create device object */ dev = kzalloc(sizeof(struct smsusb_device_t), GFP_KERNEL); @@ -413,6 +414,24 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) dev->udev = interface_to_usbdev(intf); dev->state = SMSUSB_DISCONNECTED; + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { + struct usb_endpoint_descriptor *desc = + &intf->cur_altsetting->endpoint[i].desc; + + if (desc->bEndpointAddress & USB_DIR_IN) { + dev->in_ep = desc->bEndpointAddress; + align = usb_endpoint_maxp(desc) - sizeof(struct sms_msg_hdr); + } else { + dev->out_ep = desc->bEndpointAddress; + } + } + + pr_debug("in_ep = %02x, out_ep = %02x\n", dev->in_ep, dev->out_ep); + if (!dev->in_ep || !dev->out_ep || align < 0) { /* Missing endpoints? */ + smsusb_term_device(intf); + return -ENODEV; + } + params.device_type = sms_get_board(board_id)->type; switch (params.device_type) { @@ -427,24 +446,12 @@ static int smsusb_init_device(struct usb_interface *intf, int board_id) /* fall-thru */ default: dev->buffer_size = USB2_BUFFER_SIZE; - dev->response_alignment = - le16_to_cpu(dev->udev->ep_in[1]->desc.wMaxPacketSize) - - sizeof(struct sms_msg_hdr); + dev->response_alignment = align; params.flags |= SMS_DEVICE_FAMILY2; break; } - for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { - if (intf->cur_altsetting->endpoint[i].desc. bEndpointAddress & USB_DIR_IN) - dev->in_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; - else - dev->out_ep = intf->cur_altsetting->endpoint[i].desc.bEndpointAddress; - } - - pr_debug("in_ep = %02x, out_ep = %02x\n", - dev->in_ep, dev->out_ep); - params.device = &dev->udev->dev; params.buffer_size = dev->buffer_size; params.num_buffers = MAX_BUFFERS; diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c index f4e2ee70033f..24487d5fd83b 100644 --- a/drivers/media/usb/uvc/uvc_driver.c +++ b/drivers/media/usb/uvc/uvc_driver.c @@ -868,7 +868,7 @@ static struct uvc_entity *uvc_alloc_entity(u16 type, u8 id, unsigned int size; unsigned int i; - extra_size = ALIGN(extra_size, sizeof(*entity->pads)); + extra_size = roundup(extra_size, sizeof(*entity->pads)); num_inputs = (type & UVC_TERM_OUTPUT) ? num_pads : num_pads - 1; size = sizeof(*entity) + extra_size + sizeof(*entity->pads) * num_pads + num_inputs; diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index 9ae687bf5e67..de8aef07016b 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -2052,7 +2052,22 @@ static int v4l_s_parm(const struct v4l2_ioctl_ops *ops, struct v4l2_streamparm *p = arg; int ret = check_fmt(file, p->type); - return ret ? ret : ops->vidioc_s_parm(file, fh, p); + if (ret) + return ret; + + /* Note: extendedmode is never used in drivers */ + if (V4L2_TYPE_IS_OUTPUT(p->type)) { + memset(p->parm.output.reserved, 0, + sizeof(p->parm.output.reserved)); + p->parm.output.extendedmode = 0; + p->parm.output.outputmode &= V4L2_MODE_HIGHQUALITY; + } else { + memset(p->parm.capture.reserved, 0, + sizeof(p->parm.capture.reserved)); + p->parm.capture.extendedmode = 0; + p->parm.capture.capturemode &= V4L2_MODE_HIGHQUALITY; + } + return ops->vidioc_s_parm(file, fh, p); } static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops, diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c index 19ac8bc8e7ea..22dd8c055048 100644 --- a/drivers/mfd/intel-lpss.c +++ b/drivers/mfd/intel-lpss.c @@ -273,6 +273,9 @@ static void intel_lpss_init_dev(const struct intel_lpss *lpss) { u32 value = LPSS_PRIV_SSP_REG_DIS_DMA_FIN; + /* Set the device in reset state */ + writel(0, lpss->priv + LPSS_PRIV_RESETS); + intel_lpss_deassert_reset(lpss); intel_lpss_set_remap_addr(lpss); diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c index 9d167c9af2c6..e153276ed954 100644 --- a/drivers/mfd/omap-usb-tll.c +++ b/drivers/mfd/omap-usb-tll.c @@ -131,12 +131,12 @@ static inline u32 usbtll_read(void __iomem *base, u32 reg) return readl_relaxed(base + reg); } -static inline void usbtll_writeb(void __iomem *base, u8 reg, u8 val) +static inline void usbtll_writeb(void __iomem *base, u32 reg, u8 val) { writeb_relaxed(val, base + reg); } -static inline u8 usbtll_readb(void __iomem *base, u8 reg) +static inline u8 usbtll_readb(void __iomem *base, u32 reg) { return readb_relaxed(base + reg); } diff --git a/drivers/mfd/tps65912-spi.c b/drivers/mfd/tps65912-spi.c index 4aeba9b6942a..ec37cfe32ca3 100644 --- a/drivers/mfd/tps65912-spi.c +++ b/drivers/mfd/tps65912-spi.c @@ -27,6 +27,7 @@ static const struct of_device_id tps65912_spi_of_match_table[] = { { .compatible = "ti,tps65912", }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(of, tps65912_spi_of_match_table); static int tps65912_spi_probe(struct spi_device *spi) { diff --git a/drivers/mfd/twl6040.c b/drivers/mfd/twl6040.c index dd19f17a1b63..2b8c479dbfa6 100644 --- a/drivers/mfd/twl6040.c +++ b/drivers/mfd/twl6040.c @@ -322,8 +322,19 @@ int twl6040_power(struct twl6040 *twl6040, int on) } } + /* + * Register access can produce errors after power-up unless we + * wait at least 8ms based on measurements on duovero. + */ + usleep_range(10000, 12000); + /* Sync with the HW */ - regcache_sync(twl6040->regmap); + ret = regcache_sync(twl6040->regmap); + if (ret) { + dev_err(twl6040->dev, "Failed to sync with the HW: %i\n", + ret); + goto out; + } /* Default PLL configuration after power up */ twl6040->pll = TWL6040_SYSCLK_SEL_LPPLL; diff --git a/drivers/misc/genwqe/card_dev.c b/drivers/misc/genwqe/card_dev.c index c0012ca4229e..74923ffb0df1 100644 --- a/drivers/misc/genwqe/card_dev.c +++ b/drivers/misc/genwqe/card_dev.c @@ -782,6 +782,8 @@ static int genwqe_pin_mem(struct genwqe_file *cfile, struct genwqe_mem *m) if ((m->addr == 0x0) || (m->size == 0)) return -EINVAL; + if (m->size > ULONG_MAX - PAGE_SIZE - (m->addr & ~PAGE_MASK)) + return -EINVAL; map_addr = (m->addr & PAGE_MASK); map_size = round_up(m->size + (m->addr & ~PAGE_MASK), PAGE_SIZE); diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 466a9b711480..b642b4fd731b 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -582,6 +582,10 @@ int genwqe_user_vmap(struct genwqe_dev *cd, struct dma_mapping *m, void *uaddr, /* determine space needed for page_list. */ data = (unsigned long)uaddr; offs = offset_in_page(data); + if (size > ULONG_MAX - PAGE_SIZE - offs) { + m->size = 0; /* mark unused and not added */ + return -EINVAL; + } m->nr_pages = DIV_ROUND_UP(offs + size, PAGE_SIZE); m->page_list = kcalloc(m->nr_pages, diff --git a/drivers/misc/kgdbts.c b/drivers/misc/kgdbts.c index 2290845eaba5..01e0fa74c7bc 100644 --- a/drivers/misc/kgdbts.c +++ b/drivers/misc/kgdbts.c @@ -1133,7 +1133,7 @@ static void kgdbts_put_char(u8 chr) static int param_set_kgdbts_var(const char *kmessage, const struct kernel_param *kp) { - int len = strlen(kmessage); + size_t len = strlen(kmessage); if (len >= MAX_CONFIG_LEN) { printk(KERN_ERR "kgdbts: config string too long\n"); @@ -1153,7 +1153,7 @@ static int param_set_kgdbts_var(const char *kmessage, strcpy(config, kmessage); /* Chop out \n char as a result of echo */ - if (config[len - 1] == '\n') + if (len && config[len - 1] == '\n') config[len - 1] = '\0'; /* Go and configure with the new params. */ diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 1fcafc19a9d3..8a76b649f09c 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -1497,20 +1497,17 @@ static int __qseecom_decrease_clk_ref_count(enum qseecom_ce_hw_instance ce) else qclk = &qseecom.ce_drv; - if (qclk->clk_access_cnt > 2) { + if (qclk->clk_access_cnt > 0) { + qclk->clk_access_cnt--; + } else { pr_err("Invalid clock ref count %d\n", qclk->clk_access_cnt); ret = -EINVAL; - goto err_dec_ref_cnt; } - if (qclk->clk_access_cnt == 2) - qclk->clk_access_cnt--; -err_dec_ref_cnt: mutex_unlock(&clk_access_lock); return ret; } - static int qseecom_scale_bus_bandwidth_timer(uint32_t mode) { int32_t ret = 0; @@ -7537,6 +7534,13 @@ static long qseecom_ioctl(struct file *file, break; } case QSEECOM_IOCTL_APP_LOADED_QUERY_REQ: { + if ((data->type != QSEECOM_GENERIC) && + (data->type != QSEECOM_CLIENT_APP)) { + pr_err("app loaded query req: invalid handle (%d)\n", + data->type); + ret = -EINVAL; + break; + } data->type = QSEECOM_CLIENT_APP; mutex_lock(&app_access_lock); atomic_inc(&data->ioctl_count); diff --git a/drivers/misc/vmw_vmci/vmci_context.c b/drivers/misc/vmw_vmci/vmci_context.c index f866a4baecb5..b9da2c6cc981 100644 --- a/drivers/misc/vmw_vmci/vmci_context.c +++ b/drivers/misc/vmw_vmci/vmci_context.c @@ -28,6 +28,9 @@ #include "vmci_driver.h" #include "vmci_event.h" +/* Use a wide upper bound for the maximum contexts. */ +#define VMCI_MAX_CONTEXTS 2000 + /* * List of current VMCI contexts. Contexts can be added by * vmci_ctx_create() and removed via vmci_ctx_destroy(). @@ -124,19 +127,22 @@ struct vmci_ctx *vmci_ctx_create(u32 cid, u32 priv_flags, /* Initialize host-specific VMCI context. */ init_waitqueue_head(&context->host_context.wait_queue); - context->queue_pair_array = vmci_handle_arr_create(0); + context->queue_pair_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_QP_COUNT); if (!context->queue_pair_array) { error = -ENOMEM; goto err_free_ctx; } - context->doorbell_array = vmci_handle_arr_create(0); + context->doorbell_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT); if (!context->doorbell_array) { error = -ENOMEM; goto err_free_qp_array; } - context->pending_doorbell_array = vmci_handle_arr_create(0); + context->pending_doorbell_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT); if (!context->pending_doorbell_array) { error = -ENOMEM; goto err_free_db_array; @@ -211,7 +217,7 @@ static int ctx_fire_notification(u32 context_id, u32 priv_flags) * We create an array to hold the subscribers we find when * scanning through all contexts. */ - subscriber_array = vmci_handle_arr_create(0); + subscriber_array = vmci_handle_arr_create(0, VMCI_MAX_CONTEXTS); if (subscriber_array == NULL) return VMCI_ERROR_NO_MEM; @@ -630,20 +636,26 @@ int vmci_ctx_add_notification(u32 context_id, u32 remote_cid) spin_lock(&context->lock); - list_for_each_entry(n, &context->notifier_list, node) { - if (vmci_handle_is_equal(n->handle, notifier->handle)) { - exists = true; - break; + if (context->n_notifiers < VMCI_MAX_CONTEXTS) { + list_for_each_entry(n, &context->notifier_list, node) { + if (vmci_handle_is_equal(n->handle, notifier->handle)) { + exists = true; + break; + } } - } - if (exists) { - kfree(notifier); - result = VMCI_ERROR_ALREADY_EXISTS; + if (exists) { + kfree(notifier); + result = VMCI_ERROR_ALREADY_EXISTS; + } else { + list_add_tail_rcu(¬ifier->node, + &context->notifier_list); + context->n_notifiers++; + result = VMCI_SUCCESS; + } } else { - list_add_tail_rcu(¬ifier->node, &context->notifier_list); - context->n_notifiers++; - result = VMCI_SUCCESS; + kfree(notifier); + result = VMCI_ERROR_NO_MEM; } spin_unlock(&context->lock); @@ -728,8 +740,7 @@ static int vmci_ctx_get_chkpt_doorbells(struct vmci_ctx *context, u32 *buf_size, void **pbuf) { struct dbell_cpt_state *dbells; - size_t n_doorbells; - int i; + u32 i, n_doorbells; n_doorbells = vmci_handle_arr_get_size(context->doorbell_array); if (n_doorbells > 0) { @@ -867,7 +878,8 @@ int vmci_ctx_rcv_notifications_get(u32 context_id, spin_lock(&context->lock); *db_handle_array = context->pending_doorbell_array; - context->pending_doorbell_array = vmci_handle_arr_create(0); + context->pending_doorbell_array = + vmci_handle_arr_create(0, VMCI_MAX_GUEST_DOORBELL_COUNT); if (!context->pending_doorbell_array) { context->pending_doorbell_array = *db_handle_array; *db_handle_array = NULL; @@ -949,12 +961,11 @@ int vmci_ctx_dbell_create(u32 context_id, struct vmci_handle handle) return VMCI_ERROR_NOT_FOUND; spin_lock(&context->lock); - if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) { - vmci_handle_arr_append_entry(&context->doorbell_array, handle); - result = VMCI_SUCCESS; - } else { + if (!vmci_handle_arr_has_entry(context->doorbell_array, handle)) + result = vmci_handle_arr_append_entry(&context->doorbell_array, + handle); + else result = VMCI_ERROR_DUPLICATE_ENTRY; - } spin_unlock(&context->lock); vmci_ctx_put(context); @@ -1090,15 +1101,16 @@ int vmci_ctx_notify_dbell(u32 src_cid, if (!vmci_handle_arr_has_entry( dst_context->pending_doorbell_array, handle)) { - vmci_handle_arr_append_entry( + result = vmci_handle_arr_append_entry( &dst_context->pending_doorbell_array, handle); - - ctx_signal_notify(dst_context); - wake_up(&dst_context->host_context.wait_queue); - + if (result == VMCI_SUCCESS) { + ctx_signal_notify(dst_context); + wake_up(&dst_context->host_context.wait_queue); + } + } else { + result = VMCI_SUCCESS; } - result = VMCI_SUCCESS; } spin_unlock(&dst_context->lock); } @@ -1125,13 +1137,11 @@ int vmci_ctx_qp_create(struct vmci_ctx *context, struct vmci_handle handle) if (context == NULL || vmci_handle_is_invalid(handle)) return VMCI_ERROR_INVALID_ARGS; - if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) { - vmci_handle_arr_append_entry(&context->queue_pair_array, - handle); - result = VMCI_SUCCESS; - } else { + if (!vmci_handle_arr_has_entry(context->queue_pair_array, handle)) + result = vmci_handle_arr_append_entry( + &context->queue_pair_array, handle); + else result = VMCI_ERROR_DUPLICATE_ENTRY; - } return result; } diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.c b/drivers/misc/vmw_vmci/vmci_handle_array.c index 344973a0fb0a..917e18a8af95 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.c +++ b/drivers/misc/vmw_vmci/vmci_handle_array.c @@ -16,24 +16,29 @@ #include <linux/slab.h> #include "vmci_handle_array.h" -static size_t handle_arr_calc_size(size_t capacity) +static size_t handle_arr_calc_size(u32 capacity) { - return sizeof(struct vmci_handle_arr) + + return VMCI_HANDLE_ARRAY_HEADER_SIZE + capacity * sizeof(struct vmci_handle); } -struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity) +struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity) { struct vmci_handle_arr *array; + if (max_capacity == 0 || capacity > max_capacity) + return NULL; + if (capacity == 0) - capacity = VMCI_HANDLE_ARRAY_DEFAULT_SIZE; + capacity = min((u32)VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY, + max_capacity); array = kmalloc(handle_arr_calc_size(capacity), GFP_ATOMIC); if (!array) return NULL; array->capacity = capacity; + array->max_capacity = max_capacity; array->size = 0; return array; @@ -44,27 +49,34 @@ void vmci_handle_arr_destroy(struct vmci_handle_arr *array) kfree(array); } -void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, - struct vmci_handle handle) +int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, + struct vmci_handle handle) { struct vmci_handle_arr *array = *array_ptr; if (unlikely(array->size >= array->capacity)) { /* reallocate. */ struct vmci_handle_arr *new_array; - size_t new_capacity = array->capacity * VMCI_ARR_CAP_MULT; - size_t new_size = handle_arr_calc_size(new_capacity); + u32 capacity_bump = min(array->max_capacity - array->capacity, + array->capacity); + size_t new_size = handle_arr_calc_size(array->capacity + + capacity_bump); + + if (array->size >= array->max_capacity) + return VMCI_ERROR_NO_MEM; new_array = krealloc(array, new_size, GFP_ATOMIC); if (!new_array) - return; + return VMCI_ERROR_NO_MEM; - new_array->capacity = new_capacity; + new_array->capacity += capacity_bump; *array_ptr = array = new_array; } array->entries[array->size] = handle; array->size++; + + return VMCI_SUCCESS; } /* @@ -74,7 +86,7 @@ struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle entry_handle) { struct vmci_handle handle = VMCI_INVALID_HANDLE; - size_t i; + u32 i; for (i = 0; i < array->size; i++) { if (vmci_handle_is_equal(array->entries[i], entry_handle)) { @@ -109,7 +121,7 @@ struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array) * Handle at given index, VMCI_INVALID_HANDLE if invalid index. */ struct vmci_handle -vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) +vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index) { if (unlikely(index >= array->size)) return VMCI_INVALID_HANDLE; @@ -120,7 +132,7 @@ vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index) bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, struct vmci_handle entry_handle) { - size_t i; + u32 i; for (i = 0; i < array->size; i++) if (vmci_handle_is_equal(array->entries[i], entry_handle)) diff --git a/drivers/misc/vmw_vmci/vmci_handle_array.h b/drivers/misc/vmw_vmci/vmci_handle_array.h index b5f3a7f98cf1..0fc58597820e 100644 --- a/drivers/misc/vmw_vmci/vmci_handle_array.h +++ b/drivers/misc/vmw_vmci/vmci_handle_array.h @@ -17,32 +17,41 @@ #define _VMCI_HANDLE_ARRAY_H_ #include <linux/vmw_vmci_defs.h> +#include <linux/limits.h> #include <linux/types.h> -#define VMCI_HANDLE_ARRAY_DEFAULT_SIZE 4 -#define VMCI_ARR_CAP_MULT 2 /* Array capacity multiplier */ - struct vmci_handle_arr { - size_t capacity; - size_t size; + u32 capacity; + u32 max_capacity; + u32 size; + u32 pad; struct vmci_handle entries[]; }; -struct vmci_handle_arr *vmci_handle_arr_create(size_t capacity); +#define VMCI_HANDLE_ARRAY_HEADER_SIZE \ + offsetof(struct vmci_handle_arr, entries) +/* Select a default capacity that results in a 64 byte sized array */ +#define VMCI_HANDLE_ARRAY_DEFAULT_CAPACITY 6 +/* Make sure that the max array size can be expressed by a u32 */ +#define VMCI_HANDLE_ARRAY_MAX_CAPACITY \ + ((U32_MAX - VMCI_HANDLE_ARRAY_HEADER_SIZE - 1) / \ + sizeof(struct vmci_handle)) + +struct vmci_handle_arr *vmci_handle_arr_create(u32 capacity, u32 max_capacity); void vmci_handle_arr_destroy(struct vmci_handle_arr *array); -void vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, - struct vmci_handle handle); +int vmci_handle_arr_append_entry(struct vmci_handle_arr **array_ptr, + struct vmci_handle handle); struct vmci_handle vmci_handle_arr_remove_entry(struct vmci_handle_arr *array, struct vmci_handle entry_handle); struct vmci_handle vmci_handle_arr_remove_tail(struct vmci_handle_arr *array); struct vmci_handle -vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, size_t index); +vmci_handle_arr_get_entry(const struct vmci_handle_arr *array, u32 index); bool vmci_handle_arr_has_entry(const struct vmci_handle_arr *array, struct vmci_handle entry_handle); struct vmci_handle *vmci_handle_arr_get_handles(struct vmci_handle_arr *array); -static inline size_t vmci_handle_arr_get_size( +static inline u32 vmci_handle_arr_get_size( const struct vmci_handle_arr *array) { return array->size; diff --git a/drivers/mmc/core/pwrseq_emmc.c b/drivers/mmc/core/pwrseq_emmc.c index adc9c0c614fb..4493c299d85e 100644 --- a/drivers/mmc/core/pwrseq_emmc.c +++ b/drivers/mmc/core/pwrseq_emmc.c @@ -30,19 +30,14 @@ struct mmc_pwrseq_emmc { #define to_pwrseq_emmc(p) container_of(p, struct mmc_pwrseq_emmc, pwrseq) -static void __mmc_pwrseq_emmc_reset(struct mmc_pwrseq_emmc *pwrseq) -{ - gpiod_set_value(pwrseq->reset_gpio, 1); - udelay(1); - gpiod_set_value(pwrseq->reset_gpio, 0); - udelay(200); -} - static void mmc_pwrseq_emmc_reset(struct mmc_host *host) { struct mmc_pwrseq_emmc *pwrseq = to_pwrseq_emmc(host->pwrseq); - __mmc_pwrseq_emmc_reset(pwrseq); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 1); + udelay(1); + gpiod_set_value_cansleep(pwrseq->reset_gpio, 0); + udelay(200); } static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, @@ -50,8 +45,11 @@ static int mmc_pwrseq_emmc_reset_nb(struct notifier_block *this, { struct mmc_pwrseq_emmc *pwrseq = container_of(this, struct mmc_pwrseq_emmc, reset_nb); + gpiod_set_value(pwrseq->reset_gpio, 1); + udelay(1); + gpiod_set_value(pwrseq->reset_gpio, 0); + udelay(200); - __mmc_pwrseq_emmc_reset(pwrseq); return NOTIFY_DONE; } @@ -72,14 +70,18 @@ static int mmc_pwrseq_emmc_probe(struct platform_device *pdev) if (IS_ERR(pwrseq->reset_gpio)) return PTR_ERR(pwrseq->reset_gpio); - /* - * register reset handler to ensure emmc reset also from - * emergency_reboot(), priority 255 is the highest priority - * so it will be executed before any system reboot handler. - */ - pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; - pwrseq->reset_nb.priority = 255; - register_restart_handler(&pwrseq->reset_nb); + if (!gpiod_cansleep(pwrseq->reset_gpio)) { + /* + * register reset handler to ensure emmc reset also from + * emergency_reboot(), priority 255 is the highest priority + * so it will be executed before any system reboot handler. + */ + pwrseq->reset_nb.notifier_call = mmc_pwrseq_emmc_reset_nb; + pwrseq->reset_nb.priority = 255; + register_restart_handler(&pwrseq->reset_nb); + } else { + dev_notice(dev, "EMMC reset pin tied to a sleepy GPIO driver; reset on emergency-reboot disabled\n"); + } pwrseq->pwrseq.ops = &mmc_pwrseq_emmc_ops; pwrseq->pwrseq.dev = dev; diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 088b3c77f50e..0e709224bdb5 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c @@ -220,6 +220,14 @@ static int mmc_decode_scr(struct mmc_card *card) if (scr->sda_spec3) scr->cmds = UNSTUFF_BITS(resp, 32, 2); + + /* SD Spec says: any SD Card shall set at least bits 0 and 2 */ + if (!(scr->bus_widths & SD_SCR_BUS_WIDTH_1) || + !(scr->bus_widths & SD_SCR_BUS_WIDTH_4)) { + pr_err("%s: invalid bus width\n", mmc_hostname(card->host)); + return -EINVAL; + } + return 0; } diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 6224ad37fd80..c2df68e958b3 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c @@ -819,6 +819,10 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t, } status = spi_sync_locked(spi, &host->m); + if (status < 0) { + dev_dbg(&spi->dev, "read error %d\n", status); + return status; + } if (host->dma_dev) { dma_sync_single_for_cpu(host->dma_dev, diff --git a/drivers/mmc/host/sdhci-of-esdhc.c b/drivers/mmc/host/sdhci-of-esdhc.c index a51d636c2312..6f11cd95bb5f 100644 --- a/drivers/mmc/host/sdhci-of-esdhc.c +++ b/drivers/mmc/host/sdhci-of-esdhc.c @@ -636,6 +636,11 @@ static int sdhci_esdhc_probe(struct platform_device *pdev) if (esdhc->vendor_ver > VENDOR_V_22) host->quirks &= ~SDHCI_QUIRK_NO_BUSY_IRQ; + if (of_find_compatible_node(NULL, NULL, "fsl,p2020-esdhc")) { + host->quirks2 |= SDHCI_QUIRK_RESET_AFTER_REQUEST; + host->quirks2 |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL; + } + if (of_device_is_compatible(np, "fsl,p5040-esdhc") || of_device_is_compatible(np, "fsl,p5020-esdhc") || of_device_is_compatible(np, "fsl,p4080-esdhc") || diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 93169729dfc9..fd01138c411e 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -4241,12 +4241,12 @@ void bond_setup(struct net_device *bond_dev) bond_dev->features |= NETIF_F_NETNS_LOCAL; bond_dev->hw_features = BOND_VLAN_FEATURES | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; bond_dev->hw_features |= NETIF_F_GSO_ENCAP_ALL; bond_dev->features |= bond_dev->hw_features; + bond_dev->features |= NETIF_F_HW_VLAN_CTAG_TX; } /* Destroy a bonding device. diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 47f43bdecd51..baef09b9449f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -171,7 +171,7 @@ #define FLEXCAN_MB_CNT_LENGTH(x) (((x) & 0xf) << 16) #define FLEXCAN_MB_CNT_TIMESTAMP(x) ((x) & 0xffff) -#define FLEXCAN_TIMEOUT_US (50) +#define FLEXCAN_TIMEOUT_US (250) /* FLEXCAN hardware feature flags * diff --git a/drivers/net/can/spi/Kconfig b/drivers/net/can/spi/Kconfig index 6a5476aa7214..5cd8a56ff96f 100644 --- a/drivers/net/can/spi/Kconfig +++ b/drivers/net/can/spi/Kconfig @@ -2,10 +2,11 @@ menu "CAN SPI interfaces" depends on SPI config CAN_MCP251X - tristate "Microchip MCP251x SPI CAN controllers" + tristate "Microchip MCP251x and MCP25625 SPI CAN controllers" depends on HAS_DMA ---help--- - Driver for the Microchip MCP251x SPI CAN controllers. + Driver for the Microchip MCP251x and MCP25625 SPI CAN + controllers. config QTI_CAN diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index f3f05fea8e1f..d8c448beab24 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -1,5 +1,5 @@ /* - * CAN bus driver for Microchip 251x CAN Controller with SPI Interface + * CAN bus driver for Microchip 251x/25625 CAN Controller with SPI Interface * * MCP2510 support and bug fixes by Christian Pellegrin * <chripell@evolware.org> @@ -41,7 +41,7 @@ * static struct spi_board_info spi_board_info[] = { * { * .modalias = "mcp2510", - * // or "mcp2515" depending on your controller + * // "mcp2515" or "mcp25625" depending on your controller * .platform_data = &mcp251x_info, * .irq = IRQ_EINT13, * .max_speed_hz = 2*1000*1000, @@ -238,6 +238,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = { enum mcp251x_model { CAN_MCP251X_MCP2510 = 0x2510, CAN_MCP251X_MCP2515 = 0x2515, + CAN_MCP251X_MCP25625 = 0x25625, }; struct mcp251x_priv { @@ -280,7 +281,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \ } MCP251X_IS(2510); -MCP251X_IS(2515); static void mcp251x_clean(struct net_device *net) { @@ -640,7 +640,7 @@ static int mcp251x_hw_reset(struct spi_device *spi) /* Wait for oscillator startup timer after reset */ mdelay(MCP251X_OST_DELAY_MS); - + reg = mcp251x_read_reg(spi, CANSTAT); if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) return -ENODEV; @@ -821,9 +821,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) /* receive buffer 0 */ if (intf & CANINTF_RX0IF) { mcp251x_hw_rx(spi, 0); - /* - * Free one buffer ASAP - * (The MCP2515 does this automatically.) + /* Free one buffer ASAP + * (The MCP2515/25625 does this automatically.) */ if (mcp251x_is_2510(spi)) mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); @@ -832,7 +831,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) /* receive buffer 1 */ if (intf & CANINTF_RX1IF) { mcp251x_hw_rx(spi, 1); - /* the MCP2515 does this automatically */ + /* The MCP2515/25625 does this automatically. */ if (mcp251x_is_2510(spi)) clear_intf |= CANINTF_RX1IF; } @@ -1007,6 +1006,10 @@ static const struct of_device_id mcp251x_of_match[] = { .compatible = "microchip,mcp2515", .data = (void *)CAN_MCP251X_MCP2515, }, + { + .compatible = "microchip,mcp25625", + .data = (void *)CAN_MCP251X_MCP25625, + }, { } }; MODULE_DEVICE_TABLE(of, mcp251x_of_match); @@ -1020,6 +1023,10 @@ static const struct spi_device_id mcp251x_id_table[] = { .name = "mcp2515", .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, }, + { + .name = "mcp25625", + .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP25625, + }, { } }; MODULE_DEVICE_TABLE(spi, mcp251x_id_table); @@ -1260,5 +1267,5 @@ module_spi_driver(mcp251x_can_driver); MODULE_AUTHOR("Chris Elston <celston@katalix.com>, " "Christian Pellegrin <chripell@evolware.org>"); -MODULE_DESCRIPTION("Microchip 251x CAN driver"); +MODULE_DESCRIPTION("Microchip 251x/25625 CAN driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 3aa93951daba..013114861e6b 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -1049,6 +1049,40 @@ static int qti_can_convert_ioctl_cmd_to_spi_cmd(int ioctl_cmd) return -EINVAL; } +static int qti_can_end_fwupgrade_ioctl(struct net_device *netdev, + struct ifreq *ifr, int cmd) +{ + int spi_cmd, ret; + + struct qti_can *priv_data; + struct qti_can_netdev_privdata *netdev_priv_data; + struct spi_device *spi; + int len = 0; + u8 *data = NULL; + + netdev_priv_data = netdev_priv(netdev); + priv_data = netdev_priv_data->qti_can; + spi = priv_data->spidev; + spi_cmd = qti_can_convert_ioctl_cmd_to_spi_cmd(cmd); + LOGDI("%s spi_cmd %x\n", __func__, spi_cmd); + if (spi_cmd < 0) { + LOGDE("%s wrong command %d\n", __func__, cmd); + return spi_cmd; + } + + if (!ifr) + return -EINVAL; + + mutex_lock(&priv_data->spi_lock); + LOGDI("%s len %d\n", __func__, len); + + ret = qti_can_send_spi_locked(priv_data, spi_cmd, len, data); + + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + static int qti_can_do_blocking_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) { @@ -1184,10 +1218,12 @@ static int qti_can_netdev_do_ioctl(struct net_device *netdev, qti_can_frame_filter(netdev, ifr, cmd); ret = 0; break; + case IOCTL_END_FIRMWARE_UPGRADE: + ret = qti_can_end_fwupgrade_ioctl(netdev, ifr, cmd); + break; case IOCTL_GET_FW_BR_VERSION: case IOCTL_BEGIN_FIRMWARE_UPGRADE: case IOCTL_FIRMWARE_UPGRADE_DATA: - case IOCTL_END_FIRMWARE_UPGRADE: case IOCTL_BEGIN_BOOT_ROM_UPGRADE: case IOCTL_BOOT_ROM_UPGRADE_DATA: case IOCTL_END_BOOT_ROM_UPGRADE: diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 7cee3e5db56c..2edd193c96ab 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -789,7 +789,7 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, err = mv88e6xxx_port_read(chip, port, s->reg + 1, ®); if (err) return UINT64_MAX; - high = reg; + low |= ((u32)reg) << 16; } break; case BANK0: @@ -1742,7 +1742,7 @@ static int _mv88e6xxx_vtu_get(struct mv88e6xxx_chip *chip, u16 vid, int err; if (!vid) - return -EINVAL; + return -EOPNOTSUPP; err = _mv88e6xxx_vtu_vid_write(chip, vid - 1); if (err) diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 0c298878bf46..0780900b37c7 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -2116,7 +2116,7 @@ static void ena_config_host_info(struct ena_com_dev *ena_dev) host_info->os_type = ENA_ADMIN_OS_LINUX; host_info->kernel_ver = LINUX_VERSION_CODE; - strncpy(host_info->kernel_ver_str, utsname()->version, + strlcpy(host_info->kernel_ver_str, utsname()->version, sizeof(host_info->kernel_ver_str) - 1); host_info->os_dist = 0; strncpy(host_info->os_dist_str, utsname()->release, diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 8aecd8ef6542..15a0850e6bde 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -1562,7 +1562,8 @@ static int bnx2x_get_module_info(struct net_device *dev, } if (!sff8472_comp || - (diag_type & SFP_EEPROM_DIAG_ADDR_CHANGE_REQ)) { + (diag_type & SFP_EEPROM_DIAG_ADDR_CHANGE_REQ) || + !(diag_type & SFP_EEPROM_DDM_IMPLEMENTED)) { modinfo->type = ETH_MODULE_SFF_8079; modinfo->eeprom_len = ETH_MODULE_SFF_8079_LEN; } else { diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index b7d251108c19..7115f5025664 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h @@ -62,6 +62,7 @@ #define SFP_EEPROM_DIAG_TYPE_ADDR 0x5c #define SFP_EEPROM_DIAG_TYPE_SIZE 1 #define SFP_EEPROM_DIAG_ADDR_CHANGE_REQ (1<<2) +#define SFP_EEPROM_DDM_IMPLEMENTED (1<<6) #define SFP_EEPROM_SFF_8472_COMP_ADDR 0x5e #define SFP_EEPROM_SFF_8472_COMP_SIZE 1 diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 620a470eb4c8..fbe3c2c114f9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1425,6 +1425,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_napi *bnapi, u32 *raw_cons, skb = bnxt_copy_skb(bnapi, data, len, dma_addr); bnxt_reuse_rx_data(rxr, cons, data); if (!skb) { + if (agg_bufs) + bnxt_reuse_rx_agg_bufs(bnapi, cp_cons, agg_bufs); rc = -ENOMEM; goto next_rx; } diff --git a/drivers/net/ethernet/chelsio/cxgb3/l2t.h b/drivers/net/ethernet/chelsio/cxgb3/l2t.h index 8cffcdfd5678..38b5858c335a 100644 --- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h +++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h @@ -75,8 +75,8 @@ struct l2t_data { struct l2t_entry *rover; /* starting point for next allocation */ atomic_t nfree; /* number of free entries */ rwlock_t lock; - struct l2t_entry l2tab[0]; struct rcu_head rcu_head; /* to handle rcu cleanup */ + struct l2t_entry l2tab[]; }; typedef void (*arp_failure_handler_func)(struct t3cdev * dev, diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index c71a52a2f801..5478a2ab45c4 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5203,15 +5203,24 @@ static int __init cxgb4_init_module(void) ret = pci_register_driver(&cxgb4_driver); if (ret < 0) - debugfs_remove(cxgb4_debugfs_root); + goto err_pci; #if IS_ENABLED(CONFIG_IPV6) if (!inet6addr_registered) { - register_inet6addr_notifier(&cxgb4_inet6addr_notifier); - inet6addr_registered = true; + ret = register_inet6addr_notifier(&cxgb4_inet6addr_notifier); + if (ret) + pci_unregister_driver(&cxgb4_driver); + else + inet6addr_registered = true; } #endif + if (ret == 0) + return ret; + +err_pci: + debugfs_remove(cxgb4_debugfs_root); + return ret; } diff --git a/drivers/net/ethernet/dec/tulip/de4x5.c b/drivers/net/ethernet/dec/tulip/de4x5.c index 6620fc861c47..005c79b5b3f0 100644 --- a/drivers/net/ethernet/dec/tulip/de4x5.c +++ b/drivers/net/ethernet/dec/tulip/de4x5.c @@ -2109,7 +2109,6 @@ static struct eisa_driver de4x5_eisa_driver = { .remove = de4x5_eisa_remove, } }; -MODULE_DEVICE_TABLE(eisa, de4x5_eisa_ids); #endif #ifdef CONFIG_PCI diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index 0a48a31225e6..56db37d92937 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -898,7 +898,7 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test, u64 *data) { struct be_adapter *adapter = netdev_priv(netdev); - int status; + int status, cnt; u8 link_status = 0; if (adapter->function_caps & BE_FUNCTION_CAPS_SUPER_NIC) { @@ -909,6 +909,9 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test, memset(data, 0, sizeof(u64) * ETHTOOL_TESTS_NUM); + /* check link status before offline tests */ + link_status = netif_carrier_ok(netdev); + if (test->flags & ETH_TEST_FL_OFFLINE) { if (be_loopback_test(adapter, BE_MAC_LOOPBACK, &data[0]) != 0) test->flags |= ETH_TEST_FL_FAILED; @@ -929,13 +932,26 @@ static void be_self_test(struct net_device *netdev, struct ethtool_test *test, test->flags |= ETH_TEST_FL_FAILED; } - status = be_cmd_link_status_query(adapter, NULL, &link_status, 0); - if (status) { - test->flags |= ETH_TEST_FL_FAILED; - data[4] = -1; - } else if (!link_status) { + /* link status was down prior to test */ + if (!link_status) { test->flags |= ETH_TEST_FL_FAILED; data[4] = 1; + return; + } + + for (cnt = 10; cnt; cnt--) { + status = be_cmd_link_status_query(adapter, NULL, &link_status, + 0); + if (status) { + test->flags |= ETH_TEST_FL_FAILED; + data[4] = -1; + break; + } + + if (link_status) + break; + + msleep_interruptible(500); } } @@ -1108,7 +1124,7 @@ static int be_get_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd, cmd->data = be_get_rss_hash_opts(adapter, cmd->flow_type); break; case ETHTOOL_GRXRINGS: - cmd->data = adapter->num_rx_qs - 1; + cmd->data = adapter->num_rx_qs; break; default: return -EINVAL; diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 051ecc76a7ef..1eb34109b207 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -3508,7 +3508,7 @@ failed_init: if (fep->reg_phy) regulator_disable(fep->reg_phy); failed_reset: - pm_runtime_put(&pdev->dev); + pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); failed_regulator: failed_clk_ipg: diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 4cd163390dcc..f38848c4f69d 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -367,6 +367,7 @@ static int __lb_setup(struct net_device *ndev, static int __lb_up(struct net_device *ndev, enum hnae_loop loop_mode) { +#define NIC_LB_TEST_WAIT_PHY_LINK_TIME 300 struct hns_nic_priv *priv = netdev_priv(ndev); struct hnae_handle *h = priv->ae_handle; int speed, duplex; @@ -393,6 +394,9 @@ static int __lb_up(struct net_device *ndev, h->dev->ops->adjust_link(h, speed, duplex); + /* wait adjust link done and phy ready */ + msleep(NIC_LB_TEST_WAIT_PHY_LINK_TIME); + return 0; } diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index 8bbedfc9c48f..a0f97c5ab6ef 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c @@ -4212,7 +4212,7 @@ void e1000e_up(struct e1000_adapter *adapter) e1000_configure_msix(adapter); e1000_irq_enable(adapter); - netif_start_queue(adapter->netdev); + /* Tx queue started by watchdog timer when link is up */ e1000e_trigger_lsc(adapter); } @@ -4588,6 +4588,7 @@ int e1000e_open(struct net_device *netdev) pm_runtime_get_sync(&pdev->dev); netif_carrier_off(netdev); + netif_stop_queue(netdev); /* allocate transmit descriptors */ err = e1000e_setup_tx_resources(adapter->tx_ring); @@ -4648,7 +4649,6 @@ int e1000e_open(struct net_device *netdev) e1000_irq_enable(adapter); adapter->tx_hang_recheck = false; - netif_start_queue(netdev); hw->mac.get_link_status = true; pm_runtime_put(&pdev->dev); @@ -5271,6 +5271,7 @@ static void e1000_watchdog_task(struct work_struct *work) if (phy->ops.cfg_on_link_up) phy->ops.cfg_on_link_up(hw); + netif_wake_queue(netdev); netif_carrier_on(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) @@ -5284,6 +5285,7 @@ static void e1000_watchdog_task(struct work_struct *work) /* Link status message must follow this format */ pr_info("%s NIC Link is Down\n", adapter->netdev->name); netif_carrier_off(netdev); + netif_stop_queue(netdev); if (!test_bit(__E1000_DOWN, &adapter->state)) mod_timer(&adapter->phy_info_timer, round_jiffies(jiffies + 2 * HZ)); @@ -5291,13 +5293,8 @@ static void e1000_watchdog_task(struct work_struct *work) /* 8000ES2LAN requires a Rx packet buffer work-around * on link down event; reset the controller to flush * the Rx packet buffer. - * - * If the link is lost the controller stops DMA, but - * if there is queued Tx work it cannot be done. So - * reset the controller to flush the Tx packet buffers. */ - if ((adapter->flags & FLAG_RX_NEEDS_RESTART) || - e1000_desc_unused(tx_ring) + 1 < tx_ring->count) + if (adapter->flags & FLAG_RX_NEEDS_RESTART) adapter->flags |= FLAG_RESTART_NOW; else pm_schedule_suspend(netdev->dev.parent, @@ -5320,6 +5317,14 @@ link_up: adapter->gotc_old = adapter->stats.gotc; spin_unlock(&adapter->stats64_lock); + /* If the link is lost the controller stops DMA, but + * if there is queued Tx work it cannot be done. So + * reset the controller to flush the Tx packet buffers. + */ + if (!netif_carrier_ok(netdev) && + (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) + adapter->flags |= FLAG_RESTART_NOW; + /* If reset is necessary, do it outside of interrupt context. */ if (adapter->flags & FLAG_RESTART_NOW) { schedule_work(&adapter->reset_task); diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 7836072d3f63..886378c5334f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2285,6 +2285,10 @@ void i40e_vlan_stripping_enable(struct i40e_vsi *vsi) struct i40e_vsi_context ctxt; i40e_status ret; + /* Don't modify stripping options if a port VLAN is active */ + if (vsi->info.pvid) + return; + if ((vsi->info.valid_sections & cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID)) && ((vsi->info.port_vlan_flags & I40E_AQ_VSI_PVLAN_MODE_MASK) == 0)) @@ -2315,6 +2319,10 @@ void i40e_vlan_stripping_disable(struct i40e_vsi *vsi) struct i40e_vsi_context ctxt; i40e_status ret; + /* Don't modify stripping options if a port VLAN is active */ + if (vsi->info.pvid) + return; + if ((vsi->info.valid_sections & cpu_to_le16(I40E_AQ_VSI_PROP_VLAN_VALID)) && ((vsi->info.port_vlan_flags & I40E_AQ_VSI_PVLAN_EMOD_MASK) == diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index d98b874a7238..f2904afe10e4 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -4162,7 +4162,7 @@ static int mvneta_probe(struct platform_device *pdev) err = register_netdev(dev); if (err < 0) { dev_err(&pdev->dev, "failed to register\n"); - goto err_free_stats; + goto err_netdev; } netdev_info(dev, "Using %s mac address %pM\n", mac_from, @@ -4181,13 +4181,11 @@ static int mvneta_probe(struct platform_device *pdev) return 0; err_netdev: - unregister_netdev(dev); if (pp->bm_priv) { mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_long, 1 << pp->id); mvneta_bm_pool_destroy(pp->bm_priv, pp->pool_short, 1 << pp->id); } -err_free_stats: free_percpu(pp->stats); err_free_ports: free_percpu(pp->ports); diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index ff62dc7485d5..0ea1c05f5f0e 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -3938,7 +3938,7 @@ static inline void mvpp2_gmac_max_rx_size_set(struct mvpp2_port *port) /* Set defaults to the MVPP2 port */ static void mvpp2_defaults_set(struct mvpp2_port *port) { - int tx_port_num, val, queue, ptxq, lrxq; + int tx_port_num, val, queue, lrxq; /* Configure port to loopback if needed */ if (port->flags & MVPP2_F_LOOPBACK) @@ -3958,11 +3958,9 @@ static void mvpp2_defaults_set(struct mvpp2_port *port) mvpp2_write(port->priv, MVPP2_TXP_SCHED_CMD_1_REG, 0); /* Close bandwidth for all queues */ - for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) { - ptxq = mvpp2_txq_phys(port->id, queue); + for (queue = 0; queue < MVPP2_MAX_TXQ; queue++) mvpp2_write(port->priv, - MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(ptxq), 0); - } + MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(queue), 0); /* Set refill period to 1 usec, refill tokens * and bucket size to maximum @@ -4709,7 +4707,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port, txq->descs_phys = 0; /* Set minimum bandwidth for disabled TXQs */ - mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->id), 0); + mvpp2_write(port->priv, MVPP2_TXQ_SCHED_TOKEN_CNTR_REG(txq->log_id), 0); /* Set Tx descriptors queue starting address and size */ mvpp2_write(port->priv, MVPP2_TXQ_NUM_REG, txq->id); diff --git a/drivers/net/ethernet/mediatek/mtk_eth_soc.c b/drivers/net/ethernet/mediatek/mtk_eth_soc.c index 20de37a414fe..d10c8a8156bc 100644 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c @@ -1700,6 +1700,7 @@ static void mtk_poll_controller(struct net_device *dev) static int mtk_start_dma(struct mtk_eth *eth) { + u32 rx_2b_offset = (NET_IP_ALIGN == 2) ? MTK_RX_2B_OFFSET : 0; int err; err = mtk_dma_init(eth); @@ -1714,7 +1715,7 @@ static int mtk_start_dma(struct mtk_eth *eth) MTK_QDMA_GLO_CFG); mtk_w32(eth, - MTK_RX_DMA_EN | MTK_RX_2B_OFFSET | + MTK_RX_DMA_EN | rx_2b_offset | MTK_RX_BT_32DWORDS | MTK_MULTI_EN, MTK_PDMA_GLO_CFG); @@ -2175,13 +2176,13 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, switch (cmd->cmd) { case ETHTOOL_GRXRINGS: - if (dev->features & NETIF_F_LRO) { + if (dev->hw_features & NETIF_F_LRO) { cmd->data = MTK_MAX_RX_RING_NUM; ret = 0; } break; case ETHTOOL_GRXCLSRLCNT: - if (dev->features & NETIF_F_LRO) { + if (dev->hw_features & NETIF_F_LRO) { struct mtk_mac *mac = netdev_priv(dev); cmd->rule_cnt = mac->hwlro_ip_cnt; @@ -2189,11 +2190,11 @@ static int mtk_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, } break; case ETHTOOL_GRXCLSRULE: - if (dev->features & NETIF_F_LRO) + if (dev->hw_features & NETIF_F_LRO) ret = mtk_hwlro_get_fdir_entry(dev, cmd); break; case ETHTOOL_GRXCLSRLALL: - if (dev->features & NETIF_F_LRO) + if (dev->hw_features & NETIF_F_LRO) ret = mtk_hwlro_get_fdir_all(dev, cmd, rule_locs); break; @@ -2210,11 +2211,11 @@ static int mtk_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) switch (cmd->cmd) { case ETHTOOL_SRXCLSRLINS: - if (dev->features & NETIF_F_LRO) + if (dev->hw_features & NETIF_F_LRO) ret = mtk_hwlro_add_ipaddr(dev, cmd); break; case ETHTOOL_SRXCLSRLDEL: - if (dev->features & NETIF_F_LRO) + if (dev->hw_features & NETIF_F_LRO) ret = mtk_hwlro_del_ipaddr(dev, cmd); break; default: diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index 8a9a332d78b4..74d2db505866 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -1930,6 +1930,8 @@ static int mlx4_en_set_tunable(struct net_device *dev, return ret; } +#define MLX4_EEPROM_PAGE_LEN 256 + static int mlx4_en_get_module_info(struct net_device *dev, struct ethtool_modinfo *modinfo) { @@ -1964,7 +1966,7 @@ static int mlx4_en_get_module_info(struct net_device *dev, break; case MLX4_MODULE_ID_SFP: modinfo->type = ETH_MODULE_SFF_8472; - modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; + modinfo->eeprom_len = MLX4_EEPROM_PAGE_LEN; break; default: return -ENOSYS; diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index b656dd5772e5..3173875a715f 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -1960,11 +1960,6 @@ int mlx4_get_module_info(struct mlx4_dev *dev, u8 port, size -= offset + size - I2C_PAGE_SIZE; i2c_addr = I2C_ADDR_LOW; - if (offset >= I2C_PAGE_SIZE) { - /* Reset offset to high page */ - i2c_addr = I2C_ADDR_HIGH; - offset -= I2C_PAGE_SIZE; - } cable_info = (struct mlx4_cable_info *)inmad->data; cable_info->dev_mem_address = cpu_to_be16(offset); diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index a01e6c0d0cd1..b2a745b579fd 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -935,7 +935,7 @@ static inline void mlxsw_reg_spaft_pack(char *payload, u8 local_port, MLXSW_REG_ZERO(spaft, payload); mlxsw_reg_spaft_local_port_set(payload, local_port); mlxsw_reg_spaft_allow_untagged_set(payload, allow_untagged); - mlxsw_reg_spaft_allow_prio_tagged_set(payload, true); + mlxsw_reg_spaft_allow_prio_tagged_set(payload, allow_untagged); mlxsw_reg_spaft_allow_tagged_set(payload, true); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index e3ed70a24029..585a40cc6470 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -2044,6 +2044,10 @@ mlxsw_sp_port_set_link_ksettings(struct net_device *dev, mlxsw_reg_ptys_unpack(ptys_pl, ð_proto_cap, NULL, NULL); autoneg = cmd->base.autoneg == AUTONEG_ENABLE; + if (!autoneg && cmd->base.speed == SPEED_56000) { + netdev_err(dev, "56G not supported with autoneg off\n"); + return -EINVAL; + } eth_proto_new = autoneg ? mlxsw_sp_to_ptys_advert_link(cmd) : mlxsw_sp_to_ptys_speed(cmd->base.speed); diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index c59e8fe37069..49300194d3f9 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c @@ -1388,6 +1388,10 @@ static void sh_eth_dev_exit(struct net_device *ndev) sh_eth_get_stats(ndev); sh_eth_reset(ndev); + /* Set the RMII mode again if required */ + if (mdp->cd->rmiimode) + sh_eth_write(ndev, 0x1, RMIIMODE); + /* Set MAC address again */ update_mac_address(ndev); } diff --git a/drivers/net/ethernet/sis/sis900.c b/drivers/net/ethernet/sis/sis900.c index 6f85276376e8..ae9b983e8e5c 100644 --- a/drivers/net/ethernet/sis/sis900.c +++ b/drivers/net/ethernet/sis/sis900.c @@ -1058,7 +1058,7 @@ sis900_open(struct net_device *net_dev) sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); /* Enable all known interrupts by setting the interrupt mask. */ - sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); + sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC); sw32(cr, RxENA | sr32(cr)); sw32(ier, IE); @@ -1581,7 +1581,7 @@ static void sis900_tx_timeout(struct net_device *net_dev) sw32(txdp, sis_priv->tx_ring_dma); /* Enable all known interrupts by setting the interrupt mask. */ - sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); + sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC); } /** @@ -1621,7 +1621,7 @@ sis900_start_xmit(struct sk_buff *skb, struct net_device *net_dev) spin_unlock_irqrestore(&sis_priv->lock, flags); return NETDEV_TX_OK; } - sis_priv->tx_ring[entry].cmdsts = (OWN | skb->len); + sis_priv->tx_ring[entry].cmdsts = (OWN | INTR | skb->len); sw32(cr, TxENA | sr32(cr)); sis_priv->cur_tx ++; @@ -1677,7 +1677,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance) do { status = sr32(isr); - if ((status & (HIBERR|TxURN|TxERR|TxIDLE|RxORN|RxERR|RxOK)) == 0) + if ((status & (HIBERR|TxURN|TxERR|TxIDLE|TxDESC|RxORN|RxERR|RxOK)) == 0) /* nothing intresting happened */ break; handled = 1; @@ -1687,7 +1687,7 @@ static irqreturn_t sis900_interrupt(int irq, void *dev_instance) /* Rx interrupt */ sis900_rx(net_dev); - if (status & (TxURN | TxERR | TxIDLE)) + if (status & (TxURN | TxERR | TxIDLE | TxDESC)) /* Tx interrupt */ sis900_finish_xmit(net_dev); @@ -1899,8 +1899,8 @@ static void sis900_finish_xmit (struct net_device *net_dev) if (tx_status & OWN) { /* The packet is not transmitted yet (owned by hardware) ! - * Note: the interrupt is generated only when Tx Machine - * is idle, so this is an almost impossible case */ + * Note: this is an almost impossible condition + * in case of TxDESC ('descriptor interrupt') */ break; } @@ -2476,7 +2476,7 @@ static int sis900_resume(struct pci_dev *pci_dev) sis900_set_mode(sis_priv, HW_SPEED_10_MBPS, FDX_CAPABLE_HALF_SELECTED); /* Enable all known interrupts by setting the interrupt mask. */ - sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE); + sw32(imr, RxSOVR | RxORN | RxERR | RxOK | TxURN | TxERR | TxIDLE | TxDESC); sw32(cr, RxENA | sr32(cr)); sw32(ier, IE); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c index f4074e25fb71..25136941a964 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c @@ -125,7 +125,7 @@ static int stmmac_adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec, * programmed with (2^32 – <new_sec_value>) */ if (gmac4) - sec = (100000000ULL - sec); + sec = -sec; value = readl(ioaddr + PTP_TCR); if (value & PTP_TCR_TSCTRLSSR) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 2abeba41c0af..5fe3622d27d7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -240,7 +240,8 @@ int stmmac_mdio_reset(struct mii_bus *bus) of_property_read_u32_array(np, "snps,reset-delays-us", data->delays, 3); - if (gpio_request(data->reset_gpio, "mdio-reset")) + if (devm_gpio_request(priv->device, data->reset_gpio, + "mdio-reset")) return 0; } diff --git a/drivers/net/ppp/ppp_mppe.c b/drivers/net/ppp/ppp_mppe.c index f60f7660b451..92f52a73ec0e 100644 --- a/drivers/net/ppp/ppp_mppe.c +++ b/drivers/net/ppp/ppp_mppe.c @@ -63,6 +63,7 @@ MODULE_AUTHOR("Frank Cusack <fcusack@fcusack.com>"); MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); +MODULE_SOFTDEP("pre: arc4"); MODULE_VERSION("1.0.2"); static unsigned int diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 3eb6d48c3148..0acdf73aa1b0 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -2136,12 +2136,12 @@ static void team_setup(struct net_device *dev) dev->features |= NETIF_F_NETNS_LOCAL; dev->hw_features = TEAM_VLAN_FEATURES | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_FILTER; dev->hw_features |= NETIF_F_GSO_ENCAP_ALL; dev->features |= dev->hw_features; + dev->features |= NETIF_F_HW_VLAN_CTAG_TX; } static int team_newlink(struct net *src_net, struct net_device *dev, diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 994205489ca5..e33a45e5ec0d 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -828,18 +828,8 @@ static void tun_net_uninit(struct net_device *dev) /* Net device open. */ static int tun_net_open(struct net_device *dev) { - struct tun_struct *tun = netdev_priv(dev); - int i; - netif_tx_start_all_queues(dev); - for (i = 0; i < tun->numqueues; i++) { - struct tun_file *tfile; - - tfile = rtnl_dereference(tun->tfiles[i]); - tfile->socket.sk->sk_write_space(tfile->socket.sk); - } - return 0; } @@ -2544,6 +2534,7 @@ static int tun_device_event(struct notifier_block *unused, { struct net_device *dev = netdev_notifier_info_to_dev(ptr); struct tun_struct *tun = netdev_priv(dev); + int i; if (dev->rtnl_link_ops != &tun_link_ops) return NOTIFY_DONE; @@ -2553,6 +2544,14 @@ static int tun_device_event(struct notifier_block *unused, if (tun_queue_resize(tun)) return NOTIFY_BAD; break; + case NETDEV_UP: + for (i = 0; i < tun->numqueues; i++) { + struct tun_file *tfile; + + tfile = rtnl_dereference(tun->tfiles[i]); + tfile->socket.sk->sk_write_space(tfile->socket.sk); + } + break; default: break; } diff --git a/drivers/net/usb/ipheth.c b/drivers/net/usb/ipheth.c index 01f95d192d25..2b16a5fed9de 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -437,17 +437,18 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net) dev); dev->tx_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + netif_stop_queue(net); retval = usb_submit_urb(dev->tx_urb, GFP_ATOMIC); if (retval) { dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n", __func__, retval); dev->net->stats.tx_errors++; dev_kfree_skb_any(skb); + netif_wake_queue(net); } else { dev->net->stats.tx_packets++; dev->net->stats.tx_bytes += skb->len; dev_consume_skb_any(skb); - netif_stop_queue(net); } return NETDEV_TX_OK; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 4ab82b998a0f..a5acbcb3c044 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -508,6 +508,7 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) if (netif_running (dev->net) && netif_device_present (dev->net) && + test_bit(EVENT_DEV_OPEN, &dev->flags) && !test_bit (EVENT_RX_HALT, &dev->flags) && !test_bit (EVENT_DEV_ASLEEP, &dev->flags)) { switch (retval = usb_submit_urb (urb, GFP_ATOMIC)) { @@ -1394,6 +1395,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, spin_unlock_irqrestore(&dev->txq.lock, flags); goto drop; } + if (netif_queue_stopped(net)) { + usb_autopm_put_interface_async(dev->intf); + spin_unlock_irqrestore(&dev->txq.lock, flags); + goto drop; + } #ifdef CONFIG_PM /* if this triggers the device is still a sleep */ diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c index 99ab20334d21..37c3cbe0ff2b 100644 --- a/drivers/net/wireless/ath/carl9170/usb.c +++ b/drivers/net/wireless/ath/carl9170/usb.c @@ -128,6 +128,8 @@ static struct usb_device_id carl9170_usb_ids[] = { }; MODULE_DEVICE_TABLE(usb, carl9170_usb_ids); +static struct usb_driver carl9170_driver; + static void carl9170_usb_submit_data_urb(struct ar9170 *ar) { struct urb *urb; @@ -966,32 +968,28 @@ err_out: static void carl9170_usb_firmware_failed(struct ar9170 *ar) { - struct device *parent = ar->udev->dev.parent; - struct usb_device *udev; - - /* - * Store a copy of the usb_device pointer locally. - * This is because device_release_driver initiates - * carl9170_usb_disconnect, which in turn frees our - * driver context (ar). + /* Store a copies of the usb_interface and usb_device pointer locally. + * This is because release_driver initiates carl9170_usb_disconnect, + * which in turn frees our driver context (ar). */ - udev = ar->udev; + struct usb_interface *intf = ar->intf; + struct usb_device *udev = ar->udev; complete(&ar->fw_load_wait); + /* at this point 'ar' could be already freed. Don't use it anymore */ + ar = NULL; /* unbind anything failed */ - if (parent) - device_lock(parent); - - device_release_driver(&udev->dev); - if (parent) - device_unlock(parent); + usb_lock_device(udev); + usb_driver_release_interface(&carl9170_driver, intf); + usb_unlock_device(udev); - usb_put_dev(udev); + usb_put_intf(intf); } static void carl9170_usb_firmware_finish(struct ar9170 *ar) { + struct usb_interface *intf = ar->intf; int err; err = carl9170_parse_firmware(ar); @@ -1009,7 +1007,7 @@ static void carl9170_usb_firmware_finish(struct ar9170 *ar) goto err_unrx; complete(&ar->fw_load_wait); - usb_put_dev(ar->udev); + usb_put_intf(intf); return; err_unrx: @@ -1052,7 +1050,6 @@ static int carl9170_usb_probe(struct usb_interface *intf, return PTR_ERR(ar); udev = interface_to_usbdev(intf); - usb_get_dev(udev); ar->udev = udev; ar->intf = intf; ar->features = id->driver_info; @@ -1094,15 +1091,14 @@ static int carl9170_usb_probe(struct usb_interface *intf, atomic_set(&ar->rx_anch_urbs, 0); atomic_set(&ar->rx_pool_urbs, 0); - usb_get_dev(ar->udev); + usb_get_intf(intf); carl9170_set_state(ar, CARL9170_STOPPED); err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME, &ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2); if (err) { - usb_put_dev(udev); - usb_put_dev(udev); + usb_put_intf(intf); carl9170_free(ar); } return err; @@ -1131,7 +1127,6 @@ static void carl9170_usb_disconnect(struct usb_interface *intf) carl9170_release_firmware(ar); carl9170_free(ar); - usb_put_dev(udev); } #ifdef CONFIG_PM diff --git a/drivers/net/wireless/atmel/at76c50x-usb.c b/drivers/net/wireless/atmel/at76c50x-usb.c index 0e180677c7fc..09dbab464fe1 100644 --- a/drivers/net/wireless/atmel/at76c50x-usb.c +++ b/drivers/net/wireless/atmel/at76c50x-usb.c @@ -2583,8 +2583,8 @@ static int __init at76_mod_init(void) if (result < 0) printk(KERN_ERR DRIVER_NAME ": usb_register failed (status %d)\n", result); - - led_trigger_register_simple("at76_usb-tx", &ledtrig_tx); + else + led_trigger_register_simple("at76_usb-tx", &ledtrig_tx); return result; } diff --git a/drivers/net/wireless/broadcom/b43/phy_lp.c b/drivers/net/wireless/broadcom/b43/phy_lp.c index 6922cbb99a04..5a0699fb4b9a 100644 --- a/drivers/net/wireless/broadcom/b43/phy_lp.c +++ b/drivers/net/wireless/broadcom/b43/phy_lp.c @@ -1834,7 +1834,7 @@ static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains, static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) { struct b43_phy_lp *lpphy = dev->phy.lp; - struct lpphy_tx_gains gains, oldgains; + struct lpphy_tx_gains oldgains; int old_txpctl, old_afe_ovr, old_rf, old_bbmult; lpphy_read_tx_pctl_mode_from_hardware(dev); @@ -1848,9 +1848,9 @@ static void lpphy_papd_cal_txpwr(struct b43_wldev *dev) lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0) - lpphy_papd_cal(dev, gains, 0, 1, 30); + lpphy_papd_cal(dev, oldgains, 0, 1, 30); else - lpphy_papd_cal(dev, gains, 0, 1, 65); + lpphy_papd_cal(dev, oldgains, 0, 1, 65); if (old_afe_ovr) lpphy_set_tx_gains(dev, oldgains); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index bfddabb446a8..fc82bf0b5120 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -3222,6 +3222,7 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, struct brcmf_pno_scanresults_le *pfn_result; u32 result_count; u32 status; + u32 datalen; brcmf_dbg(SCAN, "Enter\n"); @@ -3247,6 +3248,14 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, if (result_count > 0) { int i; + data += sizeof(struct brcmf_pno_scanresults_le); + netinfo_start = (struct brcmf_pno_net_info_le *)data; + datalen = e->datalen - ((void *)netinfo_start - (void *)pfn_result); + if (datalen < result_count * sizeof(*netinfo)) { + brcmf_err("insufficient event data\n"); + goto out_err; + } + request = kzalloc(sizeof(*request), GFP_KERNEL); ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL); channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL); @@ -3256,9 +3265,6 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, } request->wiphy = wiphy; - data += sizeof(struct brcmf_pno_scanresults_le); - netinfo_start = (struct brcmf_pno_net_info_le *)data; - for (i = 0; i < result_count; i++) { netinfo = &netinfo_start[i]; if (!netinfo) { @@ -3268,6 +3274,8 @@ brcmf_notify_sched_scan_results(struct brcmf_if *ifp, goto out_err; } + if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN) + netinfo->SSID_len = IEEE80211_MAX_SSID_LEN; brcmf_dbg(SCAN, "SSID:%s Channel:%d\n", netinfo->SSID, netinfo->channel); memcpy(ssid[i].ssid, netinfo->SSID, netinfo->SSID_len); @@ -3573,6 +3581,8 @@ brcmf_wowl_nd_results(struct brcmf_if *ifp, const struct brcmf_event_msg *e, data += sizeof(struct brcmf_pno_scanresults_le); netinfo = (struct brcmf_pno_net_info_le *)data; + if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN) + netinfo->SSID_len = IEEE80211_MAX_SSID_LEN; memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len); cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len; cfg->wowl.nd->n_channels = 1; @@ -5376,6 +5386,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, conn_info->req_ie = kmemdup(cfg->extra_buf, conn_info->req_ie_len, GFP_KERNEL); + if (!conn_info->req_ie) + conn_info->req_ie_len = 0; } else { conn_info->req_ie_len = 0; conn_info->req_ie = NULL; @@ -5392,6 +5404,8 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg, conn_info->resp_ie = kmemdup(cfg->extra_buf, conn_info->resp_ie_len, GFP_KERNEL); + if (!conn_info->resp_ie) + conn_info->resp_ie_len = 0; } else { conn_info->resp_ie_len = 0; conn_info->resp_ie = NULL; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index f877301c9454..349cc5cb9e80 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -339,7 +339,8 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb, bool handle_event) } else { /* Process special event packets */ if (handle_event) - brcmf_fweh_process_skb(ifp->drvr, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, + BCMILCP_SUBTYPE_VENDOR_LONG); brcmf_netif_rx(ifp, skb); } @@ -356,7 +357,7 @@ void brcmf_rx_event(struct device *dev, struct sk_buff *skb) if (brcmf_rx_hdrpull(drvr, skb, &ifp)) return; - brcmf_fweh_process_skb(ifp->drvr, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, 0); brcmu_pkt_buf_free_skb(skb); } @@ -685,17 +686,17 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, bool rtnl_locked) { struct brcmf_if *ifp; + int ifidx; ifp = drvr->iflist[bsscfgidx]; - drvr->iflist[bsscfgidx] = NULL; if (!ifp) { brcmf_err("Null interface, bsscfgidx=%d\n", bsscfgidx); return; } brcmf_dbg(TRACE, "Enter, bsscfgidx=%d, ifidx=%d\n", bsscfgidx, ifp->ifidx); - if (drvr->if2bss[ifp->ifidx] == bsscfgidx) - drvr->if2bss[ifp->ifidx] = BRCMF_BSSIDX_INVALID; + ifidx = ifp->ifidx; + if (ifp->ndev) { if (bsscfgidx == 0) { if (ifp->ndev->netdev_ops == &brcmf_netdev_ops_pri) { @@ -723,6 +724,10 @@ static void brcmf_del_if(struct brcmf_pub *drvr, s32 bsscfgidx, brcmf_p2p_ifp_removed(ifp, rtnl_locked); kfree(ifp); } + + drvr->iflist[bsscfgidx] = NULL; + if (drvr->if2bss[ifidx] == bsscfgidx) + drvr->if2bss[ifidx] = BRCMF_BSSIDX_INVALID; } void brcmf_remove_interface(struct brcmf_if *ifp, bool rtnl_locked) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h index 26ff5a9648f3..9cd112ef87d7 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h @@ -181,7 +181,7 @@ enum brcmf_fweh_event_code { */ #define BRCM_OUI "\x00\x10\x18" #define BCMILCP_BCM_SUBTYPE_EVENT 1 - +#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 /** * struct brcm_ethhdr - broadcom specific ether header. @@ -302,10 +302,10 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing); static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, - struct sk_buff *skb) + struct sk_buff *skb, u16 stype) { struct brcmf_event *event_packet; - u16 usr_stype; + u16 subtype, usr_stype; /* only process events when protocol matches */ if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL)) @@ -314,8 +314,16 @@ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr, if ((skb->len + ETH_HLEN) < sizeof(*event_packet)) return; - /* check for BRCM oui match */ event_packet = (struct brcmf_event *)skb_mac_header(skb); + + /* check subtype if needed */ + if (unlikely(stype)) { + subtype = get_unaligned_be16(&event_packet->hdr.subtype); + if (subtype != stype) + return; + } + + /* check for BRCM oui match */ if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0], sizeof(event_packet->hdr.oui))) return; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c index 2b9a2bc429d6..ab9f136c1593 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c @@ -1114,7 +1114,7 @@ static void brcmf_msgbuf_process_event(struct brcmf_msgbuf *msgbuf, void *buf) skb->protocol = eth_type_trans(skb, ifp->ndev); - brcmf_fweh_process_skb(ifp->drvr, skb); + brcmf_fweh_process_skb(ifp->drvr, skb, 0); exit: brcmu_pkt_buf_free_skb(skb); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c index 053f3b59f21e..acf513fd9e6d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c @@ -157,7 +157,7 @@ struct brcmf_usbdev_info { struct usb_device *usbdev; struct device *dev; - struct mutex dev_init_lock; + struct completion dev_init_done; int ctl_in_pipe, ctl_out_pipe; struct urb *ctl_urb; /* URB for control endpoint */ @@ -681,12 +681,18 @@ static int brcmf_usb_up(struct device *dev) static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo) { + int i; + if (devinfo->ctl_urb) usb_kill_urb(devinfo->ctl_urb); if (devinfo->bulk_urb) usb_kill_urb(devinfo->bulk_urb); - brcmf_usb_free_q(&devinfo->tx_postq, true); - brcmf_usb_free_q(&devinfo->rx_postq, true); + if (devinfo->tx_reqs) + for (i = 0; i < devinfo->bus_pub.ntxq; i++) + usb_kill_urb(devinfo->tx_reqs[i].urb); + if (devinfo->rx_reqs) + for (i = 0; i < devinfo->bus_pub.nrxq; i++) + usb_kill_urb(devinfo->rx_reqs[i].urb); } static void brcmf_usb_down(struct device *dev) @@ -1189,11 +1195,11 @@ static void brcmf_usb_probe_phase2(struct device *dev, int ret, if (ret) goto error; - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); return; error: brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret); - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); device_release_driver(dev); } @@ -1239,7 +1245,7 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) if (ret) goto fail; /* we are done */ - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); return 0; } bus->chip = bus_pub->devid; @@ -1300,11 +1306,10 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->usbdev = usb; devinfo->dev = &usb->dev; - /* Take an init lock, to protect for disconnect while still loading. + /* Init completion, to protect for disconnect while still loading. * Necessary because of the asynchronous firmware load construction */ - mutex_init(&devinfo->dev_init_lock); - mutex_lock(&devinfo->dev_init_lock); + init_completion(&devinfo->dev_init_done); usb_set_intfdata(intf, devinfo); @@ -1382,7 +1387,7 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id) return 0; fail: - mutex_unlock(&devinfo->dev_init_lock); + complete(&devinfo->dev_init_done); kfree(devinfo); usb_set_intfdata(intf, NULL); return ret; @@ -1397,7 +1402,7 @@ brcmf_usb_disconnect(struct usb_interface *intf) devinfo = (struct brcmf_usbdev_info *)usb_get_intfdata(intf); if (devinfo) { - mutex_lock(&devinfo->dev_init_lock); + wait_for_completion(&devinfo->dev_init_done); /* Make sure that devinfo still exists. Firmware probe routines * may have released the device and cleared the intfdata. */ diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c index 8eff2753abad..d493021f6031 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c @@ -35,9 +35,10 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, struct brcmf_if *ifp; const struct brcmf_vndr_dcmd_hdr *cmdhdr = data; struct sk_buff *reply; - int ret, payload, ret_len; + unsigned int payload, ret_len; void *dcmd_buf = NULL, *wr_pointer; u16 msglen, maxmsglen = PAGE_SIZE - 0x100; + int ret; if (len < sizeof(*cmdhdr)) { brcmf_err("vendor command too short: %d\n", len); @@ -65,7 +66,7 @@ static int brcmf_cfg80211_vndr_cmds_dcmd_handler(struct wiphy *wiphy, brcmf_err("oversize return buffer %d\n", ret_len); ret_len = BRCMF_DCMD_MAXLEN; } - payload = max(ret_len, len) + 1; + payload = max_t(unsigned int, ret_len, len) + 1; dcmd_buf = vzalloc(payload); if (NULL == dcmd_buf) return -ENOMEM; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index c21f8bd32d08..25f2a0aceaa2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1225,10 +1225,15 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, static void iwl_pcie_rx_handle(struct iwl_trans *trans, int queue) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - struct iwl_rxq *rxq = &trans_pcie->rxq[queue]; + struct iwl_rxq *rxq; u32 r, i, count = 0; bool emergency = false; + if (WARN_ON_ONCE(!trans_pcie->rxq || !trans_pcie->rxq[queue].bd)) + return; + + rxq = &trans_pcie->rxq[queue]; + restart: spin_lock(&rxq->lock); /* uCode's read index (stored in shared DRAM) indicates the last Rx diff --git a/drivers/net/wireless/intersil/p54/p54usb.c b/drivers/net/wireless/intersil/p54/p54usb.c index 043bd1c23c19..4a197a32d78c 100644 --- a/drivers/net/wireless/intersil/p54/p54usb.c +++ b/drivers/net/wireless/intersil/p54/p54usb.c @@ -33,6 +33,8 @@ MODULE_ALIAS("prism54usb"); MODULE_FIRMWARE("isl3886usb"); MODULE_FIRMWARE("isl3887usb"); +static struct usb_driver p54u_driver; + /* * Note: * @@ -921,9 +923,9 @@ static void p54u_load_firmware_cb(const struct firmware *firmware, { struct p54u_priv *priv = context; struct usb_device *udev = priv->udev; + struct usb_interface *intf = priv->intf; int err; - complete(&priv->fw_wait_load); if (firmware) { priv->fw = firmware; err = p54u_start_ops(priv); @@ -932,26 +934,22 @@ static void p54u_load_firmware_cb(const struct firmware *firmware, dev_err(&udev->dev, "Firmware not found.\n"); } - if (err) { - struct device *parent = priv->udev->dev.parent; - - dev_err(&udev->dev, "failed to initialize device (%d)\n", err); - - if (parent) - device_lock(parent); + complete(&priv->fw_wait_load); + /* + * At this point p54u_disconnect may have already freed + * the "priv" context. Do not use it anymore! + */ + priv = NULL; - device_release_driver(&udev->dev); - /* - * At this point p54u_disconnect has already freed - * the "priv" context. Do not use it anymore! - */ - priv = NULL; + if (err) { + dev_err(&intf->dev, "failed to initialize device (%d)\n", err); - if (parent) - device_unlock(parent); + usb_lock_device(udev); + usb_driver_release_interface(&p54u_driver, intf); + usb_unlock_device(udev); } - usb_put_dev(udev); + usb_put_intf(intf); } static int p54u_load_firmware(struct ieee80211_hw *dev, @@ -972,14 +970,14 @@ static int p54u_load_firmware(struct ieee80211_hw *dev, dev_info(&priv->udev->dev, "Loading firmware file %s\n", p54u_fwlist[i].fw); - usb_get_dev(udev); + usb_get_intf(intf); err = request_firmware_nowait(THIS_MODULE, 1, p54u_fwlist[i].fw, device, GFP_KERNEL, priv, p54u_load_firmware_cb); if (err) { dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " "(%d)!\n", p54u_fwlist[i].fw, err); - usb_put_dev(udev); + usb_put_intf(intf); } return err; @@ -1011,8 +1009,6 @@ static int p54u_probe(struct usb_interface *intf, skb_queue_head_init(&priv->rx_queue); init_usb_anchor(&priv->submitted); - usb_get_dev(udev); - /* really lazy and simple way of figuring out if we're a 3887 */ /* TODO: should just stick the identification in the device table */ i = intf->altsetting->desc.bNumEndpoints; @@ -1053,10 +1049,8 @@ static int p54u_probe(struct usb_interface *intf, priv->upload_fw = p54u_upload_firmware_net2280; } err = p54u_load_firmware(dev, intf); - if (err) { - usb_put_dev(udev); + if (err) p54_free_common(dev); - } return err; } @@ -1072,7 +1066,6 @@ static void p54u_disconnect(struct usb_interface *intf) wait_for_completion(&priv->fw_wait_load); p54_unregister_common(dev); - usb_put_dev(interface_to_usbdev(intf)); release_firmware(priv->fw); p54_free_common(dev); } diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c index 4da3541471e6..46d0099fd6e8 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c +++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c @@ -4018,16 +4018,20 @@ static int mwifiex_tm_cmd(struct wiphy *wiphy, struct wireless_dev *wdev, if (mwifiex_send_cmd(priv, 0, 0, 0, hostcmd, true)) { dev_err(priv->adapter->dev, "Failed to process hostcmd\n"); + kfree(hostcmd); return -EFAULT; } /* process hostcmd response*/ skb = cfg80211_testmode_alloc_reply_skb(wiphy, hostcmd->len); - if (!skb) + if (!skb) { + kfree(hostcmd); return -ENOMEM; + } err = nla_put(skb, MWIFIEX_TM_ATTR_DATA, hostcmd->len, hostcmd->cmd); if (err) { + kfree(hostcmd); kfree_skb(skb); return -EMSGSIZE; } diff --git a/drivers/net/wireless/marvell/mwifiex/cfp.c b/drivers/net/wireless/marvell/mwifiex/cfp.c index 1ff22055e54f..9ddaa767ea74 100644 --- a/drivers/net/wireless/marvell/mwifiex/cfp.c +++ b/drivers/net/wireless/marvell/mwifiex/cfp.c @@ -533,5 +533,8 @@ u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ? rx_rate - 1 : rx_rate; + if (rate_index >= MWIFIEX_MAX_AC_RX_RATES) + rate_index = MWIFIEX_MAX_AC_RX_RATES - 1; + return rate_index; } diff --git a/drivers/net/wireless/marvell/mwifiex/fw.h b/drivers/net/wireless/marvell/mwifiex/fw.h index 4b1894b4757f..395d6ece2cac 100644 --- a/drivers/net/wireless/marvell/mwifiex/fw.h +++ b/drivers/net/wireless/marvell/mwifiex/fw.h @@ -1719,9 +1719,10 @@ struct mwifiex_ie_types_wmm_queue_status { struct ieee_types_vendor_header { u8 element_id; u8 len; - u8 oui[4]; /* 0~2: oui, 3: oui_type */ - u8 oui_subtype; - u8 version; + struct { + u8 oui[3]; + u8 oui_type; + } __packed oui; } __packed; struct ieee_types_wmm_parameter { @@ -1735,6 +1736,9 @@ struct ieee_types_wmm_parameter { * Version [1] */ struct ieee_types_vendor_header vend_hdr; + u8 oui_subtype; + u8 version; + u8 qos_info_bitmap; u8 reserved; struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; @@ -1752,6 +1756,8 @@ struct ieee_types_wmm_info { * Version [1] */ struct ieee_types_vendor_header vend_hdr; + u8 oui_subtype; + u8 version; u8 qos_info_bitmap; } __packed; diff --git a/drivers/net/wireless/marvell/mwifiex/ie.c b/drivers/net/wireless/marvell/mwifiex/ie.c index c488c3068abc..0f977dc556ca 100644 --- a/drivers/net/wireless/marvell/mwifiex/ie.c +++ b/drivers/net/wireless/marvell/mwifiex/ie.c @@ -328,6 +328,8 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, struct ieee80211_vendor_ie *vendorhdr; u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; int left_len, parsed_len = 0; + unsigned int token_len; + int err = 0; if (!info->tail || !info->tail_len) return 0; @@ -343,6 +345,12 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, */ while (left_len > sizeof(struct ieee_types_header)) { hdr = (void *)(info->tail + parsed_len); + token_len = hdr->len + sizeof(struct ieee_types_header); + if (token_len > left_len) { + err = -EINVAL; + goto out; + } + switch (hdr->element_id) { case WLAN_EID_SSID: case WLAN_EID_SUPP_RATES: @@ -356,13 +364,16 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, case WLAN_EID_VENDOR_SPECIFIC: break; default: - memcpy(gen_ie->ie_buffer + ie_len, hdr, - hdr->len + sizeof(struct ieee_types_header)); - ie_len += hdr->len + sizeof(struct ieee_types_header); + if (ie_len + token_len > IEEE_MAX_IE_SIZE) { + err = -EINVAL; + goto out; + } + memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len); + ie_len += token_len; break; } - left_len -= hdr->len + sizeof(struct ieee_types_header); - parsed_len += hdr->len + sizeof(struct ieee_types_header); + left_len -= token_len; + parsed_len += token_len; } /* parse only WPA vendor IE from tail, WMM IE is configured by @@ -372,15 +383,17 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, WLAN_OUI_TYPE_MICROSOFT_WPA, info->tail, info->tail_len); if (vendorhdr) { - memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, - vendorhdr->len + sizeof(struct ieee_types_header)); - ie_len += vendorhdr->len + sizeof(struct ieee_types_header); + token_len = vendorhdr->len + sizeof(struct ieee_types_header); + if (ie_len + token_len > IEEE_MAX_IE_SIZE) { + err = -EINVAL; + goto out; + } + memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len); + ie_len += token_len; } - if (!ie_len) { - kfree(gen_ie); - return 0; - } + if (!ie_len) + goto out; gen_ie->ie_index = cpu_to_le16(gen_idx); gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | @@ -390,13 +403,15 @@ static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL, NULL, NULL)) { - kfree(gen_ie); - return -1; + err = -EINVAL; + goto out; } priv->gen_idx = gen_idx; + + out: kfree(gen_ie); - return 0; + return err; } /* This function parses different IEs-head & tail IEs, beacon IEs, diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c index 78d59a67f7e1..97847eee2dfb 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1236,6 +1236,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, } switch (element_id) { case WLAN_EID_SSID: + if (element_len > IEEE80211_MAX_SSID_LEN) + return -EINVAL; bss_entry->ssid.ssid_len = element_len; memcpy(bss_entry->ssid.ssid, (current_ptr + 2), element_len); @@ -1245,6 +1247,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break; case WLAN_EID_SUPP_RATES: + if (element_len > MWIFIEX_SUPPORTED_RATES) + return -EINVAL; memcpy(bss_entry->data_rates, current_ptr + 2, element_len); memcpy(bss_entry->supported_rates, current_ptr + 2, @@ -1254,6 +1258,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break; case WLAN_EID_FH_PARAMS: + if (element_len + 2 < sizeof(*fh_param_set)) + return -EINVAL; fh_param_set = (struct ieee_types_fh_param_set *) current_ptr; memcpy(&bss_entry->phy_param_set.fh_param_set, @@ -1262,6 +1268,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break; case WLAN_EID_DS_PARAMS: + if (element_len + 2 < sizeof(*ds_param_set)) + return -EINVAL; ds_param_set = (struct ieee_types_ds_param_set *) current_ptr; @@ -1273,6 +1281,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break; case WLAN_EID_CF_PARAMS: + if (element_len + 2 < sizeof(*cf_param_set)) + return -EINVAL; cf_param_set = (struct ieee_types_cf_param_set *) current_ptr; memcpy(&bss_entry->ss_param_set.cf_param_set, @@ -1281,6 +1291,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break; case WLAN_EID_IBSS_PARAMS: + if (element_len + 2 < sizeof(*ibss_param_set)) + return -EINVAL; ibss_param_set = (struct ieee_types_ibss_param_set *) current_ptr; @@ -1290,10 +1302,14 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, break; case WLAN_EID_ERP_INFO: + if (!element_len) + return -EINVAL; bss_entry->erp_flags = *(current_ptr + 2); break; case WLAN_EID_PWR_CONSTRAINT: + if (!element_len) + return -EINVAL; bss_entry->local_constraint = *(current_ptr + 2); bss_entry->sensed_11h = true; break; @@ -1336,15 +1352,22 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, vendor_ie = (struct ieee_types_vendor_specific *) current_ptr; - if (!memcmp - (vendor_ie->vend_hdr.oui, wpa_oui, - sizeof(wpa_oui))) { + /* 802.11 requires at least 3-byte OUI. */ + if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui)) + return -EINVAL; + + /* Not long enough for a match? Skip it. */ + if (element_len < sizeof(wpa_oui)) + break; + + if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui, + sizeof(wpa_oui))) { bss_entry->bcn_wpa_ie = (struct ieee_types_vendor_specific *) current_ptr; bss_entry->wpa_offset = (u16) (current_ptr - bss_entry->beacon_buf); - } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, + } else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui, sizeof(wmm_oui))) { if (total_ie_len == sizeof(struct ieee_types_wmm_parameter) || diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c index 1532ac9cee0b..7f9645703d96 100644 --- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c @@ -1374,7 +1374,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, /* Test to see if it is a WPA IE, if not, then it is a * gen IE */ - if (!memcmp(pvendor_ie->oui, wpa_oui, + if (!memcmp(&pvendor_ie->oui, wpa_oui, sizeof(wpa_oui))) { find_wpa_ie = 1; break; @@ -1383,7 +1383,7 @@ mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, /* Test to see if it is a WPS IE, if so, enable * wps session flag */ - if (!memcmp(pvendor_ie->oui, wps_oui, + if (!memcmp(&pvendor_ie->oui, wps_oui, sizeof(wps_oui))) { priv->wps.session_enable = true; mwifiex_dbg(priv->adapter, MSG, diff --git a/drivers/net/wireless/marvell/mwifiex/wmm.c b/drivers/net/wireless/marvell/mwifiex/wmm.c index dea2fe671dfe..9843560e784f 100644 --- a/drivers/net/wireless/marvell/mwifiex/wmm.c +++ b/drivers/net/wireless/marvell/mwifiex/wmm.c @@ -240,7 +240,7 @@ mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, mwifiex_dbg(priv->adapter, INFO, "info: WMM Parameter IE: version=%d,\t" "qos_info Parameter Set Count=%d, Reserved=%#x\n", - wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & + wmm_ie->version, wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, wmm_ie->reserved); diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c index 4ac928bf1f8e..7de18ed10db8 100644 --- a/drivers/net/wireless/realtek/rtlwifi/base.c +++ b/drivers/net/wireless/realtek/rtlwifi/base.c @@ -466,6 +466,11 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) /* <2> work queue */ rtlpriv->works.hw = hw; rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); + if (unlikely(!rtlpriv->works.rtl_wq)) { + pr_err("Failed to allocate work queue\n"); + return; + } + INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, (void *)rtl_watchdog_wq_callback); INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, diff --git a/drivers/net/wireless/st/cw1200/main.c b/drivers/net/wireless/st/cw1200/main.c index dc478cedbde0..84624c812a15 100644 --- a/drivers/net/wireless/st/cw1200/main.c +++ b/drivers/net/wireless/st/cw1200/main.c @@ -345,6 +345,11 @@ static struct ieee80211_hw *cw1200_init_common(const u8 *macaddr, mutex_init(&priv->wsm_cmd_mux); mutex_init(&priv->conf_mutex); priv->workqueue = create_singlethread_workqueue("cw1200_wq"); + if (!priv->workqueue) { + ieee80211_free_hw(hw); + return NULL; + } + sema_init(&priv->scan.lock, 1); INIT_WORK(&priv->scan.work, cw1200_scan_work); INIT_DELAYED_WORK(&priv->scan.probe_work, cw1200_probe_work); diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c index 66a089d561cf..9108004a0d9b 100644 --- a/drivers/nvdimm/label.c +++ b/drivers/nvdimm/label.c @@ -490,15 +490,26 @@ static unsigned long nd_label_offset(struct nvdimm_drvdata *ndd, - (unsigned long) to_namespace_index(ndd, 0); } +static void reap_victim(struct nd_mapping *nd_mapping, + struct nd_label_ent *victim) +{ + struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); + u32 slot = to_slot(ndd, victim->label); + + dev_dbg(ndd->dev, "free: %d\n", slot); + nd_label_free_slot(ndd, slot); + victim->label = NULL; +} + static int __pmem_label_update(struct nd_region *nd_region, struct nd_mapping *nd_mapping, struct nd_namespace_pmem *nspm, int pos, unsigned long flags) { u64 cookie = nd_region_interleave_set_cookie(nd_region); struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); - struct nd_label_ent *label_ent, *victim = NULL; struct nd_namespace_label *nd_label; struct nd_namespace_index *nsindex; + struct nd_label_ent *label_ent; struct nd_label_id label_id; struct resource *res; unsigned long *free; @@ -551,18 +562,10 @@ static int __pmem_label_update(struct nd_region *nd_region, list_for_each_entry(label_ent, &nd_mapping->labels, list) { if (!label_ent->label) continue; - if (memcmp(nspm->uuid, label_ent->label->uuid, - NSLABEL_UUID_LEN) != 0) - continue; - victim = label_ent; - list_move_tail(&victim->list, &nd_mapping->labels); - break; - } - if (victim) { - dev_dbg(ndd->dev, "%s: free: %d\n", __func__, slot); - slot = to_slot(ndd, victim->label); - nd_label_free_slot(ndd, slot); - victim->label = NULL; + if (test_and_clear_bit(ND_LABEL_REAP, &label_ent->flags) + || memcmp(nspm->uuid, label_ent->label->uuid, + NSLABEL_UUID_LEN) == 0) + reap_victim(nd_mapping, label_ent); } /* update index */ diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index cf4a90b50f8b..e83453e1b308 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1210,12 +1210,27 @@ static int namespace_update_uuid(struct nd_region *nd_region, for (i = 0; i < nd_region->ndr_mappings; i++) { struct nd_mapping *nd_mapping = &nd_region->mapping[i]; struct nvdimm_drvdata *ndd = to_ndd(nd_mapping); + struct nd_label_ent *label_ent; struct resource *res; for_each_dpa_resource(ndd, res) if (strcmp(res->name, old_label_id.id) == 0) sprintf((void *) res->name, "%s", new_label_id.id); + + mutex_lock(&nd_mapping->lock); + list_for_each_entry(label_ent, &nd_mapping->labels, list) { + struct nd_namespace_label *nd_label = label_ent->label; + struct nd_label_id label_id; + + if (!nd_label) + continue; + nd_label_gen_id(&label_id, nd_label->uuid, + __le32_to_cpu(nd_label->flags)); + if (strcmp(old_label_id.id, label_id.id) == 0) + set_bit(ND_LABEL_REAP, &label_ent->flags); + } + mutex_unlock(&nd_mapping->lock); } kfree(*old_uuid); out: diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index d869236b474f..bd29e598bac1 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -113,8 +113,12 @@ struct nd_percpu_lane { spinlock_t lock; }; +enum nd_label_flags { + ND_LABEL_REAP, +}; struct nd_label_ent { struct list_head list; + unsigned long flags; struct nd_namespace_label *label; }; diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index 979c6ecc6446..8705bfe7bb73 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1765,7 +1765,8 @@ static int nvme_scan_ns_list(struct nvme_ctrl *ctrl, unsigned nn) { struct nvme_ns *ns; __le32 *ns_list; - unsigned i, j, nsid, prev = 0, num_lists = DIV_ROUND_UP(nn, 1024); + unsigned i, j, nsid, prev = 0; + unsigned num_lists = DIV_ROUND_UP_ULL((u64)nn, 1024); int ret = 0; ns_list = kzalloc(0x1000, GFP_KERNEL); diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 5b8208b8958e..814373de8c9d 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -703,7 +703,7 @@ static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, void *buf) { u8 *p, *b; - int i, bit_offset = cell->bit_offset; + int i, extra, bit_offset = cell->bit_offset; p = b = buf; if (bit_offset) { @@ -718,11 +718,16 @@ static inline void nvmem_shift_read_buffer_in_place(struct nvmem_cell *cell, p = b; *b++ >>= bit_offset; } - - /* result fits in less bytes */ - if (cell->bytes != DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE)) - *p-- = 0; + } else { + /* point to the msb */ + p += cell->bytes - 1; } + + /* result fits in less bytes */ + extra = cell->bytes - DIV_ROUND_UP(cell->nbits, BITS_PER_BYTE); + while (--extra >= 0) + *p-- = 0; + /* clear msb bits if any leftover in the last byte */ *p &= GENMASK((cell->nbits%BITS_PER_BYTE) - 1, 0); } diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index c4953eca907d..7a5306bf56c8 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -563,8 +563,6 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, /* We currently only support kernel addresses */ BUG_ON(sid != KERNEL_SPACE); - mtsp(sid,1); - /* ** WORD 1 - low order word ** "hints" parm includes the VALID bit! @@ -595,7 +593,7 @@ ccio_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, ** Grab virtual index [0:11] ** Deposit virt_idx bits into I/O PDIR word */ - asm volatile ("lci %%r0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba)); + asm volatile ("lci %%r0(%1), %0" : "=r" (ci) : "r" (vba)); asm volatile ("extru %1,19,12,%0" : "+r" (ci) : "r" (ci)); asm volatile ("depw %1,15,12,%0" : "+r" (pa) : "r" (ci)); diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 56918d1c0ed3..188fab57d170 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -573,8 +573,7 @@ sba_io_pdir_entry(u64 *pdir_ptr, space_t sid, unsigned long vba, pa = virt_to_phys(vba); pa &= IOVP_MASK; - mtsp(sid,1); - asm("lci 0(%%sr1, %1), %0" : "=r" (ci) : "r" (vba)); + asm("lci 0(%1), %0" : "=r" (ci) : "r" (vba)); pa |= (ci >> PAGE_SHIFT) & 0xff; /* move CI (8 bits) into lowest byte */ pa |= SBA_PDIR_VALID_BIT; /* set "valid" bit */ diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 4399de34054a..daa2eb3050df 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c @@ -895,6 +895,7 @@ parport_register_dev_model(struct parport *port, const char *name, par_dev->devmodel = true; ret = device_register(&par_dev->dev); if (ret) { + kfree(par_dev->state); put_device(&par_dev->dev); goto err_put_port; } @@ -912,6 +913,7 @@ parport_register_dev_model(struct parport *port, const char *name, spin_unlock(&port->physport->pardevice_lock); pr_debug("%s: cannot grant exclusive access for device %s\n", port->name, name); + kfree(par_dev->state); device_unregister(&par_dev->dev); goto err_put_port; } diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index a1dab5515c46..b8a8a92d6d05 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -517,6 +517,7 @@ struct msm_pcie_dev_t { struct platform_device *pdev; struct pci_dev *dev; struct regulator *gdsc; + struct regulator *vreg_pcie; struct regulator *gdsc_smmu; struct msm_pcie_vreg_info_t vreg[MSM_PCIE_MAX_VREG]; struct msm_pcie_gpio_info_t gpio[MSM_PCIE_MAX_GPIO]; @@ -633,7 +634,6 @@ struct msm_pcie_dev_t { bool use_pinctrl; struct pinctrl *pinctrl; struct pinctrl_state *pins_default; - struct pinctrl_state *pins_power_on; struct pinctrl_state *pins_sleep; struct msm_pcie_device_info pcidev_table[MAX_DEVICE_NUM]; }; @@ -3422,6 +3422,18 @@ static int msm_pcie_get_resources(struct msm_pcie_dev_t *dev, } } + dev->vreg_pcie = devm_regulator_get(&pdev->dev, "vreg-pcie"); + + if (IS_ERR(dev->vreg_pcie)) { + PCIE_ERR(dev, "PCIe: RC%d Failed to get %s VREG_PCIE:%ld\n", + dev->rc_idx, dev->pdev->name, PTR_ERR(dev->gdsc)); + if (PTR_ERR(dev->vreg_pcie) == -EPROBE_DEFER) + PCIE_DBG(dev, "PCIe: EPROBE_DEFER for %s VREG_PCIE\n", + dev->pdev->name); + ret = PTR_ERR(dev->vreg_pcie); + goto out; + } + dev->gdsc = devm_regulator_get(&pdev->dev, "gdsc-vdd"); if (IS_ERR(dev->gdsc)) { @@ -4287,6 +4299,19 @@ int msm_pcie_enumerate(u32 rc_idx) } if (!dev->enumerated) { + + /*Open the PCIE VCC before enable the pcie */ + if (dev->vreg_pcie) { + ret = regulator_enable(dev->vreg_pcie); + + if (ret) { + PCIE_ERR(dev, + "PCIe: fail to open vcc for RC%d (%s)\n", + dev->rc_idx, dev->pdev->name); + return ret; + } + } + ret = msm_pcie_enable(dev, PM_ALL); /* kick start ARM PCI configuration framework */ @@ -6013,16 +6038,6 @@ static int msm_pcie_probe(struct platform_device *pdev) msm_pcie_dev[rc_idx].pins_default = NULL; } - msm_pcie_dev[rc_idx].pins_power_on = - pinctrl_lookup_state(msm_pcie_dev[rc_idx].pinctrl, - "slot_power_on"); - if (IS_ERR(msm_pcie_dev[rc_idx].pins_power_on)) { - PCIE_ERR(&msm_pcie_dev[rc_idx], - "PCIe: RC%d could not get pinctrl power_on state\n", - rc_idx); - msm_pcie_dev[rc_idx].pins_power_on = NULL; - } - msm_pcie_dev[rc_idx].pins_sleep = pinctrl_lookup_state(msm_pcie_dev[rc_idx].pinctrl, "sleep"); @@ -6050,11 +6065,6 @@ static int msm_pcie_probe(struct platform_device *pdev) msm_pcie_sysfs_init(&msm_pcie_dev[rc_idx]); msm_pcie_dev[rc_idx].drv_ready = true; - if (msm_pcie_dev[rc_idx].use_pinctrl && - msm_pcie_dev[rc_idx].pins_power_on) { - pinctrl_select_state(msm_pcie_dev[rc_idx].pinctrl, - msm_pcie_dev[rc_idx].pins_power_on); - } if (msm_pcie_dev[rc_idx].boot_option & MSM_PCIE_NO_PROBE_ENUMERATION) { @@ -6122,6 +6132,15 @@ static int msm_pcie_remove(struct platform_device *pdev) msm_pcie_gpio_deinit(&msm_pcie_dev[rc_idx]); msm_pcie_release_resources(&msm_pcie_dev[rc_idx]); + /*Close the PCIE VCC when remove the pcie*/ + if (msm_pcie_dev[rc_idx].vreg_pcie) { + ret = regulator_disable(msm_pcie_dev[rc_idx].vreg_pcie); + + if (ret) + pr_err("%s: PCIe: fail to close VCC.\n", __func__); + + } + out: mutex_unlock(&pcie_drv.drv_lock); diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c index d6196f7b1d58..7f6b454bca65 100644 --- a/drivers/pci/host/pcie-rcar.c +++ b/drivers/pci/host/pcie-rcar.c @@ -847,7 +847,7 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie) { struct device *dev = pcie->dev; struct rcar_msi *msi = &pcie->msi; - unsigned long base; + phys_addr_t base; int err, i; mutex_init(&msi->lock); @@ -886,10 +886,14 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie) /* setup MSI data target */ msi->pages = __get_free_pages(GFP_KERNEL, 0); + if (!msi->pages) { + err = -ENOMEM; + goto err; + } base = virt_to_phys((void *)msi->pages); - rcar_pci_write_reg(pcie, base | MSIFE, PCIEMSIALR); - rcar_pci_write_reg(pcie, 0, PCIEMSIAUR); + rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR); + rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR); /* enable all MSI interrupts */ rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER); diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c index 61332f4d51c3..c3964fca57b0 100644 --- a/drivers/pci/host/pcie-xilinx.c +++ b/drivers/pci/host/pcie-xilinx.c @@ -337,14 +337,19 @@ static const struct irq_domain_ops msi_domain_ops = { * xilinx_pcie_enable_msi - Enable MSI support * @port: PCIe port information */ -static void xilinx_pcie_enable_msi(struct xilinx_pcie_port *port) +static int xilinx_pcie_enable_msi(struct xilinx_pcie_port *port) { phys_addr_t msg_addr; port->msi_pages = __get_free_pages(GFP_KERNEL, 0); + if (!port->msi_pages) + return -ENOMEM; + msg_addr = virt_to_phys((void *)port->msi_pages); pcie_write(port, 0x0, XILINX_PCIE_REG_MSIBASE1); pcie_write(port, msg_addr, XILINX_PCIE_REG_MSIBASE2); + + return 0; } /* INTx Functions */ @@ -516,6 +521,7 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port) struct device *dev = port->dev; struct device_node *node = dev->of_node; struct device_node *pcie_intc_node; + int ret; /* Setup INTx */ pcie_intc_node = of_get_next_child(node, NULL); @@ -544,7 +550,9 @@ static int xilinx_pcie_init_irq_domain(struct xilinx_pcie_port *port) return -ENODEV; } - xilinx_pcie_enable_msi(port); + ret = xilinx_pcie_enable_msi(port); + if (ret) + return ret; } return 0; diff --git a/drivers/pci/hotplug/rpadlpar_core.c b/drivers/pci/hotplug/rpadlpar_core.c index c614ff7c3bc3..d3562df64456 100644 --- a/drivers/pci/hotplug/rpadlpar_core.c +++ b/drivers/pci/hotplug/rpadlpar_core.c @@ -55,6 +55,7 @@ static struct device_node *find_vio_slot_node(char *drc_name) if ((rc == 0) && (!strcmp(drc_name, name))) break; } + of_node_put(parent); return dn; } @@ -78,6 +79,7 @@ static struct device_node *find_php_slot_pci_node(char *drc_name, return np; } +/* Returns a device_node with its reference count incremented */ static struct device_node *find_dlpar_node(char *drc_name, int *node_type) { struct device_node *dn; @@ -313,6 +315,7 @@ int dlpar_add_slot(char *drc_name) rc = dlpar_add_phb(drc_name, dn); break; } + of_node_put(dn); printk(KERN_INFO "%s: slot %s added\n", DLPAR_MODULE_NAME, drc_name); exit: @@ -446,6 +449,7 @@ int dlpar_remove_slot(char *drc_name) rc = dlpar_remove_pci_slot(drc_name, dn); break; } + of_node_put(dn); vm_unmap_aliases(); printk(KERN_INFO "%s: slot %s removed\n", DLPAR_MODULE_NAME, drc_name); diff --git a/drivers/pinctrl/pinctrl-pistachio.c b/drivers/pinctrl/pinctrl-pistachio.c index 55375b1b3cc8..b2b7e238bda9 100644 --- a/drivers/pinctrl/pinctrl-pistachio.c +++ b/drivers/pinctrl/pinctrl-pistachio.c @@ -1368,6 +1368,7 @@ static int pistachio_gpio_register(struct pistachio_pinctrl *pctl) if (!of_find_property(child, "gpio-controller", NULL)) { dev_err(pctl->dev, "No gpio-controller property for bank %u\n", i); + of_node_put(child); ret = -ENODEV; goto err; } @@ -1375,6 +1376,7 @@ static int pistachio_gpio_register(struct pistachio_pinctrl *pctl) irq = irq_of_parse_and_map(child, 0); if (irq < 0) { dev_err(pctl->dev, "No IRQ for bank %u: %d\n", i, irq); + of_node_put(child); ret = irq; goto err; } diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index cfa3e850c49f..d225a835a64c 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -67,6 +67,17 @@ static int send_command(struct cros_ec_device *ec_dev, else xfer_fxn = ec_dev->cmd_xfer; + if (!xfer_fxn) { + /* + * This error can happen if a communication error happened and + * the EC is trying to use protocol v2, on an underlying + * communication mechanism that does not support v2. + */ + dev_err_once(ec_dev->dev, + "missing EC transfer API, cannot send command\n"); + return -EIO; + } + ret = (*xfer_fxn)(ec_dev, msg); if (msg->result == EC_RES_IN_PROGRESS) { int i; diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c index 0ab6e9084e99..2c1146427409 100644 --- a/drivers/platform/msm/ipa/ipa_api.c +++ b/drivers/platform/msm/ipa/ipa_api.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2019, 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 @@ -187,7 +187,19 @@ const char *ipa_clients_strings[IPA_CLIENT_MAX] = { __stringify(RESERVERD_PROD_74), __stringify(IPA_CLIENT_MHI_DPL_CONS), __stringify(RESERVERD_PROD_76), - __stringify(IPA_CLIENT_DUMMY_CONS1) + __stringify(IPA_CLIENT_DUMMY_CONS1), + __stringify(IPA_CLIENT_WIGIG_PROD), + __stringify(IPA_CLIENT_WIGIG1_CONS), + __stringify(RESERVERD_PROD_80), + __stringify(IPA_CLIENT_WIGIG2_CONS), + __stringify(RESERVERD_PROD_82), + __stringify(IPA_CLIENT_WIGIG3_CONS), + __stringify(RESERVERD_PROD_84), + __stringify(IPA_CLIENT_WIGIG4_CONS), + __stringify(IPA_CLIENT_MHI2_PROD), + __stringify(IPA_CLIENT_MHI2_CONS), + __stringify(IPA_CLIENT_Q6_CV2X_PROD), + __stringify(IPA_CLIENT_Q6_CV2X_CONS) }; /** diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c index 7c9738178eeb..e21147318aae 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c @@ -66,8 +66,8 @@ #define IPA_MHI_SUSPEND_SLEEP_MIN 900 #define IPA_MHI_SUSPEND_SLEEP_MAX 1100 -#define IPA_MHI_MAX_UL_CHANNELS 1 -#define IPA_MHI_MAX_DL_CHANNELS 2 +#define IPA_MHI_MAX_UL_CHANNELS 2 +#define IPA_MHI_MAX_DL_CHANNELS 3 /* bit #40 in address should be asserted for MHI transfers over pcie */ #define IPA_MHI_CLIENT_HOST_ADDR_COND(addr) \ diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c index 095d60b67eeb..50bb9bcf9674 100644 --- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c +++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c @@ -1067,9 +1067,8 @@ static int __ipa_add_rt_rule(enum ipa_ip_type ip, const char *name, * tables */ if (!strcmp(tbl->name, IPA_DFLT_RT_TBL_NAME) && - (tbl->rule_cnt > 0) && (at_rear != 0)) { - IPAERR("cannot add rule at end of tbl rule_cnt=%d at_rear=%d\n", - tbl->rule_cnt, at_rear); + (tbl->rule_cnt > 0)) { + IPAERR_RL("cannot add rules to default rt table\n"); goto error; } @@ -1608,6 +1607,11 @@ static int __ipa_mdfy_rt_rule(struct ipa_rt_rule_mdfy *rtrule) goto error; } + if (!strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) { + IPAERR_RL("Default tbl rule cannot be modified\n"); + return -EINVAL; + } + /* Adding check to confirm still * header entry present in header table or not */ diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index f882bd785872..80513d239a28 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -2854,9 +2854,14 @@ void ipa3_q6_pre_shutdown_cleanup(void) ipa3_q6_pipe_delay(true); ipa3_q6_avoid_holb(); - if (ipa3_ctx->ipa_config_is_mhi) + if (ipa3_ctx->ipa_config_is_mhi) { ipa3_set_reset_client_cons_pipe_sus_holb(true, IPA_CLIENT_MHI_CONS); + if (ipa3_ctx->ipa_config_is_auto) + ipa3_set_reset_client_cons_pipe_sus_holb(true, + IPA_CLIENT_MHI2_CONS); + } + if (ipa3_q6_clean_q6_tables()) { IPAERR("Failed to clean Q6 tables\n"); BUG(); @@ -2874,9 +2879,13 @@ void ipa3_q6_pre_shutdown_cleanup(void) if (ipa3_ctx->ipa_config_is_auto) ipa3_set_reset_client_prod_pipe_delay(true, IPA_CLIENT_USB2_PROD); - if (ipa3_ctx->ipa_config_is_mhi) + if (ipa3_ctx->ipa_config_is_mhi) { ipa3_set_reset_client_prod_pipe_delay(true, IPA_CLIENT_MHI_PROD); + if (ipa3_ctx->ipa_config_is_auto) + ipa3_set_reset_client_prod_pipe_delay(true, + IPA_CLIENT_MHI2_PROD); + } IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG_LOW("Exit with success\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index c4eb731562a3..cc15baa7511b 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2018 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2019 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 @@ -383,6 +383,7 @@ int ipa3_mhi_init_engine(struct ipa_mhi_init_engine *params) int res; struct gsi_device_scratch gsi_scratch; const struct ipa_gsi_ep_config *gsi_ep_info; + u32 ipa_mhi_max_ul_channels, ipa_mhi_max_dl_channels; IPA_MHI_FUNC_ENTRY(); @@ -391,7 +392,16 @@ int ipa3_mhi_init_engine(struct ipa_mhi_init_engine *params) return -EINVAL; } - if ((IPA_MHI_MAX_UL_CHANNELS + IPA_MHI_MAX_DL_CHANNELS) > + ipa_mhi_max_ul_channels = IPA_MHI_MAX_UL_CHANNELS; + ipa_mhi_max_dl_channels = IPA_MHI_MAX_DL_CHANNELS; + + /* In case of Auto-pcie config, MHI2_PROD and MHI2_CONS is used */ + if (ipa3_ctx->ipa_config_is_auto == true) { + ipa_mhi_max_ul_channels++; + ipa_mhi_max_dl_channels++; + } + + if ((ipa_mhi_max_ul_channels + ipa_mhi_max_dl_channels) > ((ipa3_ctx->mhi_evid_limits[1] - ipa3_ctx->mhi_evid_limits[0]) + 1)) { IPAERR("Not enough event rings for MHI\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 090cfa08057f..60af28dc1805 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -1593,12 +1593,12 @@ static const struct ipa_ep_configuration ipa3_ep_mapping IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY, QMB_MASTER_SELECT_DDR, { 5, 7, 20, 24, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } }, - [IPA_4_0_AUTO][IPA_CLIENT_ODU_PROD] = { - false, IPA_v4_0_GROUP_UL_DL, + [IPA_4_0_AUTO][IPA_CLIENT_Q6_CV2X_PROD] = { + true, IPA_v4_0_GROUP_CV2X, true, IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, - { 1, 0, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } }, + { 1, 2, 8, 16, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY } }, [IPA_4_0_AUTO][IPA_CLIENT_ETHERNET_PROD] = { true, IPA_v4_0_GROUP_UL_DL, true, @@ -1606,13 +1606,13 @@ static const struct ipa_ep_configuration ipa3_ep_mapping QMB_MASTER_SELECT_DDR, { 9, 0, 8, 16, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO][IPA_CLIENT_Q6_WAN_PROD] = { - false, IPA_v4_0_GROUP_UL_DL, + true, IPA_v4_0_GROUP_UL_DL, true, IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 3, 0, 16, 32, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO][IPA_CLIENT_Q6_CMD_PROD] = { - false, IPA_v4_0_GROUP_UL_DL, + true, IPA_v4_0_GROUP_UL_DL, false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, @@ -1711,23 +1711,23 @@ static const struct ipa_ep_configuration ipa3_ep_mapping QMB_MASTER_SELECT_DDR, { 22, 1, 9, 9, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO][IPA_CLIENT_Q6_LAN_CONS] = { - false, IPA_v4_0_GROUP_UL_DL, + true, IPA_v4_0_GROUP_UL_DL, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 14, 4, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO][IPA_CLIENT_Q6_WAN_CONS] = { - false, IPA_v4_0_GROUP_UL_DL, + true, IPA_v4_0_GROUP_UL_DL, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 13, 3, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, - [IPA_4_0_AUTO][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = { - false, IPA_v4_0_GROUP_UL_DL, + [IPA_4_0_AUTO][IPA_CLIENT_Q6_CV2X_CONS] = { + true, IPA_v4_0_GROUP_CV2X, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, - { 16, 5, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, + { 16, 5, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY } }, /* Only for test purpose */ /* MBIM aggregation test pipes should have the same QMB as USB_CONS */ [IPA_4_0_AUTO][IPA_CLIENT_TEST_CONS] = { @@ -1799,14 +1799,20 @@ static const struct ipa_ep_configuration ipa3_ep_mapping IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, QMB_MASTER_SELECT_DDR, { 9, 0, 8, 16, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } }, + [IPA_4_0_AUTO_MHI][IPA_CLIENT_Q6_CV2X_PROD] = { + true, IPA_v4_0_GROUP_CV2X, + true, + IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP, + QMB_MASTER_SELECT_DDR, + { 1, 2, 8, 16, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO_MHI][IPA_CLIENT_Q6_WAN_PROD] = { - false, IPA_v4_0_GROUP_UL_DL, + true, IPA_v4_0_GROUP_UL_DL, true, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, { 3, 0, 16, 32, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO_MHI][IPA_CLIENT_Q6_CMD_PROD] = { - false, IPA_v4_0_MHI_GROUP_PCIE, + true, IPA_v4_0_MHI_GROUP_PCIE, false, IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP, QMB_MASTER_SELECT_DDR, @@ -1887,17 +1893,23 @@ static const struct ipa_ep_configuration ipa3_ep_mapping QMB_MASTER_SELECT_DDR, { 22, 1, 9, 9, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO_MHI][IPA_CLIENT_Q6_LAN_CONS] = { - false, IPA_v4_0_MHI_GROUP_DDR, + true, IPA_v4_0_MHI_GROUP_DDR, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 14, 4, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, [IPA_4_0_AUTO_MHI][IPA_CLIENT_Q6_WAN_CONS] = { - false, IPA_v4_0_MHI_GROUP_DDR, + true, IPA_v4_0_MHI_GROUP_DDR, false, IPA_DPS_HPS_SEQ_TYPE_INVALID, QMB_MASTER_SELECT_DDR, { 13, 3, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } }, + [IPA_4_0_AUTO_MHI][IPA_CLIENT_Q6_CV2X_CONS] = { + true, IPA_v4_0_GROUP_CV2X, + false, + IPA_DPS_HPS_SEQ_TYPE_INVALID, + QMB_MASTER_SELECT_DDR, + { 16, 5, 9, 9, IPA_EE_Q6, GSI_ESCAPE_BUF_ONLY } }, [IPA_4_0_AUTO_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = { true, IPA_v4_0_MHI_GROUP_DMA, false, @@ -5414,8 +5426,8 @@ void ipa3_set_resorce_groups_min_max_limits(void) case IPA_4_0_AUTO_MHI: src_rsrc_type_max = IPA_v4_0_RSRC_GRP_TYPE_SRC_MAX; dst_rsrc_type_max = IPA_v4_0_RSRC_GRP_TYPE_DST_MAX; - src_grp_idx_max = IPA_v4_0_GROUP_CV2X; - dst_grp_idx_max = IPA_v4_0_GROUP_CV2X; + src_grp_idx_max = IPA_v4_0_SRC_GROUP_MAX; + dst_grp_idx_max = IPA_v4_0_DST_GROUP_MAX; break; default: IPAERR("invalid hw type index\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c index 530adef46f09..35d5efcda4c7 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_fltrt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2019, 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 @@ -3479,6 +3479,7 @@ bdy_alloc_fail: int ipahal_fltrt_allocate_hw_sys_tbl(struct ipa_mem_buffer *tbl_mem) { struct ipahal_fltrt_obj *obj; + gfp_t flag = GFP_KERNEL; IPAHAL_DBG_LOW("Entry\n"); @@ -3496,10 +3497,14 @@ int ipahal_fltrt_allocate_hw_sys_tbl(struct ipa_mem_buffer *tbl_mem) /* add word for rule-set terminator */ tbl_mem->size += obj->tbl_width; - +alloc: tbl_mem->base = dma_alloc_coherent(ipahal_ctx->ipa_pdev, tbl_mem->size, - &tbl_mem->phys_base, GFP_KERNEL); + &tbl_mem->phys_base, flag); if (!tbl_mem->base) { + if (flag == GFP_KERNEL) { + flag = GFP_ATOMIC; + goto alloc; + } IPAHAL_ERR("fail to alloc DMA buf of size %d\n", tbl_mem->size); return -ENOMEM; diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index 0bf51d574fa9..f2b9dd82128f 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -620,13 +620,17 @@ static int ipc_create_pmc_devices(void) if (ret) { dev_err(ipcdev.dev, "Failed to add punit platform device\n"); platform_device_unregister(ipcdev.tco_dev); + return ret; } if (!ipcdev.telem_res_inval) { ret = ipc_create_telemetry_device(); - if (ret) + if (ret) { dev_warn(ipcdev.dev, "Failed to add telemetry platform device\n"); + platform_device_unregister(ipcdev.punit_dev); + platform_device_unregister(ipcdev.tco_dev); + } } return ret; diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c index 1b7af04730ba..addc387e8b8d 100644 --- a/drivers/pwm/core.c +++ b/drivers/pwm/core.c @@ -303,10 +303,12 @@ int pwmchip_add_with_polarity(struct pwm_chip *chip, if (IS_ENABLED(CONFIG_OF)) of_pwmchip_add(chip); - pwmchip_sysfs_export(chip); - out: mutex_unlock(&pwm_lock); + + if (!ret) + pwmchip_sysfs_export(chip); + return ret; } EXPORT_SYMBOL_GPL(pwmchip_add_with_polarity); @@ -340,7 +342,7 @@ int pwmchip_remove(struct pwm_chip *chip) unsigned int i; int ret = 0; - pwmchip_sysfs_unexport_children(chip); + pwmchip_sysfs_unexport(chip); mutex_lock(&pwm_lock); @@ -360,8 +362,6 @@ int pwmchip_remove(struct pwm_chip *chip) free_pwms(chip); - pwmchip_sysfs_unexport(chip); - out: mutex_unlock(&pwm_lock); return ret; diff --git a/drivers/pwm/pwm-meson.c b/drivers/pwm/pwm-meson.c index 9d5bd7d5c610..f58a4867b519 100644 --- a/drivers/pwm/pwm-meson.c +++ b/drivers/pwm/pwm-meson.c @@ -110,6 +110,10 @@ struct meson_pwm { const struct meson_pwm_data *data; void __iomem *base; u8 inverter_mask; + /* + * Protects register (write) access to the REG_MISC_AB register + * that is shared between the two PWMs. + */ spinlock_t lock; }; @@ -230,6 +234,7 @@ static void meson_pwm_enable(struct meson_pwm *meson, { u32 value, clk_shift, clk_enable, enable; unsigned int offset; + unsigned long flags; switch (id) { case 0: @@ -250,6 +255,8 @@ static void meson_pwm_enable(struct meson_pwm *meson, return; } + spin_lock_irqsave(&meson->lock, flags); + value = readl(meson->base + REG_MISC_AB); value &= ~(MISC_CLK_DIV_MASK << clk_shift); value |= channel->pre_div << clk_shift; @@ -262,11 +269,14 @@ static void meson_pwm_enable(struct meson_pwm *meson, value = readl(meson->base + REG_MISC_AB); value |= enable; writel(value, meson->base + REG_MISC_AB); + + spin_unlock_irqrestore(&meson->lock, flags); } static void meson_pwm_disable(struct meson_pwm *meson, unsigned int id) { u32 value, enable; + unsigned long flags; switch (id) { case 0: @@ -281,9 +291,13 @@ static void meson_pwm_disable(struct meson_pwm *meson, unsigned int id) return; } + spin_lock_irqsave(&meson->lock, flags); + value = readl(meson->base + REG_MISC_AB); value &= ~enable; writel(value, meson->base + REG_MISC_AB); + + spin_unlock_irqrestore(&meson->lock, flags); } static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, @@ -291,19 +305,16 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, { struct meson_pwm_channel *channel = pwm_get_chip_data(pwm); struct meson_pwm *meson = to_meson_pwm(chip); - unsigned long flags; int err = 0; if (!state) return -EINVAL; - spin_lock_irqsave(&meson->lock, flags); - if (!state->enabled) { meson_pwm_disable(meson, pwm->hwpwm); channel->state.enabled = false; - goto unlock; + return 0; } if (state->period != channel->state.period || @@ -324,7 +335,7 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, err = meson_pwm_calc(meson, channel, pwm->hwpwm, state->duty_cycle, state->period); if (err < 0) - goto unlock; + return err; channel->state.polarity = state->polarity; channel->state.period = state->period; @@ -336,9 +347,7 @@ static int meson_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, channel->state.enabled = true; } -unlock: - spin_unlock_irqrestore(&meson->lock, flags); - return err; + return 0; } static void meson_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index c0e06f0c19d1..9a232ebbbf96 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -383,6 +383,8 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) } /* Update shadow register first before modifying active register */ + ehrpwm_modify(pc->mmio_base, AQSFRC, AQSFRC_RLDCSF_MASK, + AQSFRC_RLDCSF_ZRO); ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); /* * Changes to immediate action on Action Qualifier. This puts diff --git a/drivers/pwm/sysfs.c b/drivers/pwm/sysfs.c index 50b7a3b278c1..a0c361297b0e 100644 --- a/drivers/pwm/sysfs.c +++ b/drivers/pwm/sysfs.c @@ -449,19 +449,6 @@ void pwmchip_sysfs_export(struct pwm_chip *chip) void pwmchip_sysfs_unexport(struct pwm_chip *chip) { struct device *parent; - - parent = class_find_device(&pwm_class, NULL, chip, - pwmchip_sysfs_match); - if (parent) { - /* for class_find_device() */ - put_device(parent); - device_unregister(parent); - } -} - -void pwmchip_sysfs_unexport_children(struct pwm_chip *chip) -{ - struct device *parent; unsigned int i; parent = class_find_device(&pwm_class, NULL, chip, @@ -477,6 +464,7 @@ void pwmchip_sysfs_unexport_children(struct pwm_chip *chip) } put_device(parent); + device_unregister(parent); } static int __init pwm_sysfs_init(void) diff --git a/drivers/rapidio/rio_cm.c b/drivers/rapidio/rio_cm.c index bad0e0ea4f30..ef989a15aefc 100644 --- a/drivers/rapidio/rio_cm.c +++ b/drivers/rapidio/rio_cm.c @@ -2145,6 +2145,14 @@ static int riocm_add_mport(struct device *dev, mutex_init(&cm->rx_lock); riocm_rx_fill(cm, RIOCM_RX_RING_SIZE); cm->rx_wq = create_workqueue(DRV_NAME "/rxq"); + if (!cm->rx_wq) { + riocm_error("failed to allocate IBMBOX_%d on %s", + cmbox, mport->name); + rio_release_outb_mbox(mport, cmbox); + kfree(cm); + return -ENOMEM; + } + INIT_WORK(&cm->rx_work, rio_ibmsg_handler); cm->tx_slot = 0; diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c index 19e53b3b8e00..166faae3a59c 100644 --- a/drivers/rtc/rtc-88pm860x.c +++ b/drivers/rtc/rtc-88pm860x.c @@ -414,7 +414,7 @@ static int pm860x_rtc_remove(struct platform_device *pdev) struct pm860x_rtc_info *info = platform_get_drvdata(pdev); #ifdef VRTC_CALIBRATION - flush_scheduled_work(); + cancel_delayed_work_sync(&info->calib_work); /* disable measurement */ pm860x_set_bits(info->i2c, PM8607_MEAS_EN2, MEAS2_VRTC, 0); #endif /* VRTC_CALIBRATION */ diff --git a/drivers/rtc/rtc-pcf8523.c b/drivers/rtc/rtc-pcf8523.c index 28c48b3c1946..3c8c6f942e67 100644 --- a/drivers/rtc/rtc-pcf8523.c +++ b/drivers/rtc/rtc-pcf8523.c @@ -82,6 +82,18 @@ static int pcf8523_write(struct i2c_client *client, u8 reg, u8 value) return 0; } +static int pcf8523_voltage_low(struct i2c_client *client) +{ + u8 value; + int err; + + err = pcf8523_read(client, REG_CONTROL3, &value); + if (err < 0) + return err; + + return !!(value & REG_CONTROL3_BLF); +} + static int pcf8523_select_capacitance(struct i2c_client *client, bool high) { u8 value; @@ -164,6 +176,14 @@ static int pcf8523_rtc_read_time(struct device *dev, struct rtc_time *tm) struct i2c_msg msgs[2]; int err; + err = pcf8523_voltage_low(client); + if (err < 0) { + return err; + } else if (err > 0) { + dev_err(dev, "low voltage detected, time is unreliable\n"); + return -EINVAL; + } + msgs[0].addr = client->addr; msgs[0].flags = 0; msgs[0].len = 1; @@ -248,17 +268,13 @@ static int pcf8523_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct i2c_client *client = to_i2c_client(dev); - u8 value; - int ret = 0, err; + int ret; switch (cmd) { case RTC_VL_READ: - err = pcf8523_read(client, REG_CONTROL3, &value); - if (err < 0) - return err; - - if (value & REG_CONTROL3_BLF) - ret = 1; + ret = pcf8523_voltage_low(client); + if (ret < 0) + return ret; if (copy_to_user((void __user *)arg, &ret, sizeof(int))) return -EFAULT; diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index f0e57aefb5f2..d167652a6a23 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h @@ -114,7 +114,7 @@ struct subchannel { struct schib_config config; } __attribute__ ((aligned(8))); -DECLARE_PER_CPU(struct irb, cio_irb); +DECLARE_PER_CPU_ALIGNED(struct irb, cio_irb); #define to_subchannel(n) container_of(n, struct subchannel, dev) diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 35286907c636..d0090c5c88e7 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -150,6 +150,7 @@ static int __qdio_allocate_qs(struct qdio_q **irq_ptr_qs, int nr_queues) return -ENOMEM; } irq_ptr_qs[i] = q; + INIT_LIST_HEAD(&q->entry); } return 0; } @@ -178,6 +179,7 @@ static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, q->mask = 1 << (31 - i); q->nr = i; q->handler = handler; + INIT_LIST_HEAD(&q->entry); } static void setup_storage_lists(struct qdio_q *q, struct qdio_irq *irq_ptr, diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 30e9fbbff051..debe69adfc70 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -80,7 +80,6 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) mutex_lock(&tiq_list_lock); list_add_rcu(&irq_ptr->input_qs[0]->entry, &tiq_list); mutex_unlock(&tiq_list_lock); - xchg(irq_ptr->dsci, 1 << 7); } void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) @@ -88,14 +87,14 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) struct qdio_q *q; q = irq_ptr->input_qs[0]; - /* if establish triggered an error */ - if (!q || !q->entry.prev || !q->entry.next) + if (!q) return; mutex_lock(&tiq_list_lock); list_del_rcu(&q->entry); mutex_unlock(&tiq_list_lock); synchronize_rcu(); + INIT_LIST_HEAD(&q->entry); } static inline int has_multiple_inq_on_dsci(struct qdio_irq *irq_ptr) diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 58404e69aa4b..6ba4e921d2fd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -2124,7 +2124,7 @@ static void qeth_bridgeport_an_set_cb(void *priv, l2entry = (struct qdio_brinfo_entry_l2 *)entry; code = IPA_ADDR_CHANGE_CODE_MACADDR; - if (l2entry->addr_lnid.lnid) + if (l2entry->addr_lnid.lnid < VLAN_N_VID) code |= IPA_ADDR_CHANGE_CODE_VLANID; qeth_bridge_emit_host_event(card, anev_reg_unreg, code, (struct net_if_token *)&l2entry->nit, diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index a39a74500e23..aeb93478482f 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -161,6 +161,7 @@ extern const struct attribute_group *zfcp_port_attr_groups[]; extern struct mutex zfcp_sysfs_port_units_mutex; extern struct device_attribute *zfcp_sysfs_sdev_attrs[]; extern struct device_attribute *zfcp_sysfs_shost_attrs[]; +bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port); /* zfcp_unit.c */ extern int zfcp_unit_add(struct zfcp_port *, u64); diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index bdb257eaa2e5..68146b398603 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -124,6 +124,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) zfcp_sdev->erp_action.port = port; + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (zfcp_sysfs_port_is_removing(port)) { + /* port is already gone */ + mutex_unlock(&zfcp_sysfs_port_units_mutex); + put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */ + return -ENXIO; + } + mutex_unlock(&zfcp_sysfs_port_units_mutex); + unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); if (unit) put_device(&unit->dev); diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c index 96a0be13e841..5df597d1b978 100644 --- a/drivers/s390/scsi/zfcp_sysfs.c +++ b/drivers/s390/scsi/zfcp_sysfs.c @@ -237,6 +237,53 @@ static ZFCP_DEV_ATTR(adapter, port_rescan, S_IWUSR, NULL, DEFINE_MUTEX(zfcp_sysfs_port_units_mutex); +static void zfcp_sysfs_port_set_removing(struct zfcp_port *const port) +{ + lockdep_assert_held(&zfcp_sysfs_port_units_mutex); + atomic_set(&port->units, -1); +} + +bool zfcp_sysfs_port_is_removing(const struct zfcp_port *const port) +{ + lockdep_assert_held(&zfcp_sysfs_port_units_mutex); + return atomic_read(&port->units) == -1; +} + +static bool zfcp_sysfs_port_in_use(struct zfcp_port *const port) +{ + struct zfcp_adapter *const adapter = port->adapter; + unsigned long flags; + struct scsi_device *sdev; + bool in_use = true; + + mutex_lock(&zfcp_sysfs_port_units_mutex); + if (atomic_read(&port->units) > 0) + goto unlock_port_units_mutex; /* zfcp_unit(s) under port */ + + spin_lock_irqsave(adapter->scsi_host->host_lock, flags); + __shost_for_each_device(sdev, adapter->scsi_host) { + const struct zfcp_scsi_dev *zsdev = sdev_to_zfcp(sdev); + + if (sdev->sdev_state == SDEV_DEL || + sdev->sdev_state == SDEV_CANCEL) + continue; + if (zsdev->port != port) + continue; + /* alive scsi_device under port of interest */ + goto unlock_host_lock; + } + + /* port is about to be removed, so no more unit_add or slave_alloc */ + zfcp_sysfs_port_set_removing(port); + in_use = false; + +unlock_host_lock: + spin_unlock_irqrestore(adapter->scsi_host->host_lock, flags); +unlock_port_units_mutex: + mutex_unlock(&zfcp_sysfs_port_units_mutex); + return in_use; +} + static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -259,15 +306,11 @@ static ssize_t zfcp_sysfs_port_remove_store(struct device *dev, else retval = 0; - mutex_lock(&zfcp_sysfs_port_units_mutex); - if (atomic_read(&port->units) > 0) { + if (zfcp_sysfs_port_in_use(port)) { retval = -EBUSY; - mutex_unlock(&zfcp_sysfs_port_units_mutex); + put_device(&port->dev); /* undo zfcp_get_port_by_wwpn() */ goto out; } - /* port is about to be removed, so no more unit_add */ - atomic_set(&port->units, -1); - mutex_unlock(&zfcp_sysfs_port_units_mutex); write_lock_irq(&adapter->port_list_lock); list_del(&port->list); diff --git a/drivers/s390/scsi/zfcp_unit.c b/drivers/s390/scsi/zfcp_unit.c index 9310a547b89f..1435029ade55 100644 --- a/drivers/s390/scsi/zfcp_unit.c +++ b/drivers/s390/scsi/zfcp_unit.c @@ -123,7 +123,7 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) int retval = 0; mutex_lock(&zfcp_sysfs_port_units_mutex); - if (atomic_read(&port->units) == -1) { + if (zfcp_sysfs_port_is_removing(port)) { /* port is already gone */ retval = -ENODEV; goto out; @@ -167,8 +167,14 @@ int zfcp_unit_add(struct zfcp_port *port, u64 fcp_lun) write_lock_irq(&port->unit_list_lock); list_add_tail(&unit->list, &port->unit_list); write_unlock_irq(&port->unit_list_lock); + /* + * lock order: shost->scan_mutex before zfcp_sysfs_port_units_mutex + * due to zfcp_unit_scsi_scan() => zfcp_scsi_slave_alloc() + */ + mutex_unlock(&zfcp_sysfs_port_units_mutex); zfcp_unit_scsi_scan(unit); + return retval; out: mutex_unlock(&zfcp_sysfs_port_units_mutex); diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 5ff9f89c17c7..39b2f60149d9 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -829,7 +829,7 @@ ret_err_rqe: ((u64)err_entry->data.err_warn_bitmap_hi << 32) | (u64)err_entry->data.err_warn_bitmap_lo; for (i = 0; i < BNX2FC_NUM_ERR_BITS; i++) { - if (err_warn_bit_map & (u64) (1 << i)) { + if (err_warn_bit_map & ((u64)1 << i)) { err_warn = i; break; } diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 2ffe029ff2b6..e974106f2bb5 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -637,6 +637,10 @@ static struct cxgbi_sock *cxgbi_check_route(struct sockaddr *dst_addr) if (ndev->flags & IFF_LOOPBACK) { ndev = ip_dev_find(&init_net, daddr->sin_addr.s_addr); + if (!ndev) { + err = -ENETUNREACH; + goto rel_neigh; + } mtu = ndev->mtu; pr_info("rt dev %s, loopback -> %s, mtu %u.\n", n->dev->name, ndev->name, mtu); diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0b8db8a74d50..9f98c7211ec2 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4815,7 +4815,7 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, curr_sg->reserved[0] = 0; curr_sg->reserved[1] = 0; curr_sg->reserved[2] = 0; - curr_sg->chain_indicator = 0x80; + curr_sg->chain_indicator = IOACCEL2_CHAIN; curr_sg = h->ioaccel2_cmd_sg_list[c->cmdindex]; } @@ -4832,6 +4832,11 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h, curr_sg++; } + /* + * Set the last s/g element bit + */ + (curr_sg - 1)->chain_indicator = IOACCEL2_LAST_SG; + switch (cmd->sc_data_direction) { case DMA_TO_DEVICE: cp->direction &= ~IOACCEL2_DIRECTION_MASK; diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 5961705eef76..39bcbec93c60 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -516,6 +516,7 @@ struct ioaccel2_sg_element { u8 reserved[3]; u8 chain_indicator; #define IOACCEL2_CHAIN 0x80 +#define IOACCEL2_LAST_SG 0x40 }; /* diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 1a6f65db615e..400eee9d7783 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c @@ -978,6 +978,8 @@ static struct domain_device *sas_ex_discover_expander( list_del(&child->dev_list_node); spin_unlock_irq(&parent->port->dev_list_lock); sas_put_device(child); + sas_port_delete(phy->port); + phy->port = NULL; return NULL; } list_add_tail(&child->siblings, &parent->ex_dev.children); @@ -2027,6 +2029,11 @@ static int sas_rediscover_dev(struct domain_device *dev, int phy_id, bool last) if ((SAS_ADDR(sas_addr) == 0) || (res == -ECOMM)) { phy->phy_state = PHY_EMPTY; sas_unregister_devs_sas_addr(dev, phy_id, last); + /* + * Even though the PHY is empty, for convenience we discover + * the PHY to update the PHY info, like negotiated linkrate. + */ + sas_ex_phy_discover(dev, phy_id); return res; } else if (SAS_ADDR(sas_addr) == SAS_ADDR(phy->attached_sas_addr) && dev_type_flutter(type, phy->attached_dev_type)) { diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index 4ac03b16d17f..52afbcff362f 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -1561,6 +1561,9 @@ lpfc_fdmi_hba_attr_manufacturer(struct lpfc_vport *vport, ae = (struct lpfc_fdmi_attr_entry *)&ad->AttrValue; memset(ae, 0, 256); + /* This string MUST be consistent with other FC platforms + * supported by Broadcom. + */ strncpy(ae->un.AttrString, "Emulex Corporation", sizeof(ae->un.AttrString)); diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 4905455bbfc7..b5be4df05733 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -6789,7 +6789,10 @@ int lpfc_send_rrq(struct lpfc_hba *phba, struct lpfc_node_rrq *rrq) { struct lpfc_nodelist *ndlp = lpfc_findnode_did(rrq->vport, - rrq->nlp_DID); + rrq->nlp_DID); + if (!ndlp) + return 1; + if (lpfc_test_rrq_active(phba, ndlp, rrq->xritag)) return lpfc_issue_els_rrq(rrq->vport, ndlp, rrq->nlp_DID, rrq); diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 81736457328a..9cca5ddbc50c 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -901,7 +901,11 @@ lpfc_linkdown(struct lpfc_hba *phba) lpfc_linkdown_port(vports[i]); } lpfc_destroy_vport_work_array(phba, vports); - /* Clean up any firmware default rpi's */ + + /* Clean up any SLI3 firmware default rpi's */ + if (phba->sli_rev > LPFC_SLI_REV3) + goto skip_unreg_did; + mb = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mb) { lpfc_unreg_did(phba, 0xffff, LPFC_UNREG_ALL_DFLT_RPIS, mb); @@ -913,6 +917,7 @@ lpfc_linkdown(struct lpfc_hba *phba) } } + skip_unreg_did: /* Setup myDID for link up if we are in pt2pt mode */ if (phba->pport->fc_flag & FC_PT2PT) { phba->pport->fc_myDID = 0; @@ -4654,6 +4659,10 @@ lpfc_unreg_default_rpis(struct lpfc_vport *vport) LPFC_MBOXQ_t *mbox; int rc; + /* Unreg DID is an SLI3 operation. */ + if (phba->sli_rev > LPFC_SLI_REV3) + return; + mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL); if (mbox) { lpfc_unreg_did(phba, vport->vpi, LPFC_UNREG_ALL_DFLT_RPIS, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 73c99f237b10..f0fcff032f8a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -3089,7 +3089,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp) ql_log(ql_log_fatal, vha, 0x00c8, "Failed to allocate memory for ha->msix_entries.\n"); ret = -ENOMEM; - goto msix_out; + goto free_irqs; } ha->flags.msix_enabled = 1; @@ -3177,6 +3177,10 @@ msix_register_fail: msix_out: kfree(entries); return ret; + +free_irqs: + pci_free_irq_vectors(ha->pdev); + goto msix_out; } int diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index c158967b59d7..d220b4f691c7 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -5939,7 +5939,7 @@ static int get_fw_boot_info(struct scsi_qla_host *ha, uint16_t ddb_index[]) val = rd_nvram_byte(ha, sec_addr); if (val & BIT_7) ddb_index[1] = (val & 0x7f); - + goto exit_boot_info; } else if (is_qla80XX(ha)) { buf = dma_alloc_coherent(&ha->pdev->dev, size, &buf_dma, GFP_KERNEL); diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 4fba09b309cb..f50c74156992 100755 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -2324,6 +2324,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) struct scsi_device *sdp = sdkp->device; struct scsi_mode_data data; int disk_ro = get_disk_ro(sdkp->disk); + int old_wp = sdkp->write_prot; set_disk_ro(sdkp->disk, 0); if (sdp->skip_ms_page_3f) { @@ -2364,6 +2365,13 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer) } else { sdkp->write_prot = ((data.device_specific & 0x80) != 0); set_disk_ro(sdkp->disk, sdkp->write_prot || disk_ro); + if (sdkp->first_scan || old_wp != sdkp->write_prot) { + sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n", + sdkp->write_prot ? "on" : "off"); + sd_printk(KERN_DEBUG, sdkp, + "Mode Sense: %02x %02x %02x %02x\n", + buffer[0], buffer[1], buffer[2], buffer[3]); + } } } diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index 06a062455404..b12f7f952b70 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -5478,7 +5478,7 @@ static int pqi_pci_init(struct pqi_ctrl_info *ctrl_info) else mask = DMA_BIT_MASK(32); - rc = dma_set_mask(&ctrl_info->pci_dev->dev, mask); + rc = dma_set_mask_and_coherent(&ctrl_info->pci_dev->dev, mask); if (rc) { dev_err(&ctrl_info->pci_dev->dev, "failed to set DMA mask\n"); goto disable_device; diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index f5a67360b61c..6226d75a117c 100644..100755 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -491,6 +491,7 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, pm_runtime_enable(&pdev->dev); return 0; + dealloc_host: ufshcd_dealloc_host(hba); out: diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index a90e66171d38..c62184f25934 100755 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -2471,7 +2471,8 @@ int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr, QUERY_OSF_SIZE); /* Get the descriptor */ - if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) { + if (hba->dev_cmd.query.descriptor && + lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) { u8 *descp = (u8 *)lrbp->ucd_rsp_ptr + GENERAL_UPIU_REQUEST_SIZE; u16 resp_len; @@ -7492,19 +7493,19 @@ static u32 ufshcd_find_max_sup_active_icc_level(struct ufs_hba *hba, goto out; } - if (hba->vreg_info.vcc) + if (hba->vreg_info.vcc && hba->vreg_info.vcc->max_uA) icc_level = ufshcd_get_max_icc_level( hba->vreg_info.vcc->max_uA, POWER_DESC_MAX_ACTV_ICC_LVLS - 1, &desc_buf[PWR_DESC_ACTIVE_LVLS_VCC_0]); - if (hba->vreg_info.vccq) + if (hba->vreg_info.vccq && hba->vreg_info.vccq->max_uA) icc_level = ufshcd_get_max_icc_level( hba->vreg_info.vccq->max_uA, icc_level, &desc_buf[PWR_DESC_ACTIVE_LVLS_VCCQ_0]); - if (hba->vreg_info.vccq2) + if (hba->vreg_info.vccq2 && hba->vreg_info.vccq2->max_uA) icc_level = ufshcd_get_max_icc_level( hba->vreg_info.vccq2->max_uA, icc_level, @@ -8630,6 +8631,15 @@ static int ufshcd_config_vreg_load(struct device *dev, struct ufs_vreg *vreg, if (!vreg) return 0; + /* + * "set_load" operation shall be required on those regulators + * which specifically configured current limitation. Otherwise + * zero max_uA may cause unexpected behavior when regulator is + * enabled or set as high power mode. + */ + if (!vreg->max_uA) + return 0; + ret = regulator_set_load(vreg->reg, ua); if (ret < 0) { dev_err(dev, "%s: %s set load (ua=%d) failed, err=%d\n", @@ -8681,12 +8691,15 @@ static int ufshcd_config_vreg(struct device *dev, if (ret) goto out; - min_uV = on ? vreg->min_uV : 0; - ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); - if (ret) { - dev_err(dev, "%s: %s set voltage failed, err=%d\n", + if (vreg->min_uV && vreg->max_uV) { + min_uV = on ? vreg->min_uV : 0; + ret = regulator_set_voltage(reg, min_uV, vreg->max_uV); + if (ret) { + dev_err(dev, + "%s: %s set voltage failed, err=%d\n", __func__, name, ret); - goto out; + goto out; + } } } out: diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index fcfbe2dcd025..df6fabcce4f7 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -766,6 +766,7 @@ static int pvscsi_queue_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd struct pvscsi_adapter *adapter = shost_priv(host); struct pvscsi_ctx *ctx; unsigned long flags; + unsigned char op; spin_lock_irqsave(&adapter->hw_lock, flags); @@ -778,13 +779,14 @@ static int pvscsi_queue_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd } cmd->scsi_done = done; + op = cmd->cmnd[0]; dev_dbg(&cmd->device->sdev_gendev, - "queued cmd %p, ctx %p, op=%x\n", cmd, ctx, cmd->cmnd[0]); + "queued cmd %p, ctx %p, op=%x\n", cmd, ctx, op); spin_unlock_irqrestore(&adapter->hw_lock, flags); - pvscsi_kick_io(adapter, cmd->cmnd[0]); + pvscsi_kick_io(adapter, op); return 0; } diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c index e929f5142862..36226976773f 100644 --- a/drivers/soc/mediatek/mtk-pmic-wrap.c +++ b/drivers/soc/mediatek/mtk-pmic-wrap.c @@ -778,7 +778,7 @@ static bool pwrap_is_pmic_cipher_ready(struct pmic_wrapper *wrp) static int pwrap_init_cipher(struct pmic_wrapper *wrp) { int ret; - u32 rdata; + u32 rdata = 0; pwrap_writel(wrp, 0x1, PWRAP_CIPHER_SWRST); pwrap_writel(wrp, 0x0, PWRAP_CIPHER_SWRST); diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c index e7f689ad4e05..4cdf6130b0f9 100644 --- a/drivers/soc/qcom/glink_smem_native_xprt.c +++ b/drivers/soc/qcom/glink_smem_native_xprt.c @@ -907,9 +907,8 @@ static void tx_wakeup_worker(struct edge_info *einfo) einfo->tx_resume_needed = false; trigger_resume = true; } - } - if (waitqueue_active(&einfo->tx_blocked_queue)) { /* tx waiting ?*/ - trigger_wakeup = true; + if (waitqueue_active(&einfo->tx_blocked_queue))/* tx waiting ?*/ + trigger_wakeup = true; } spin_unlock_irqrestore(&einfo->write_lock, flags); if (trigger_wakeup) @@ -963,8 +962,9 @@ static void __rx_worker(struct edge_info *einfo, bool atomic_ctx) einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if); } - if ((atomic_ctx) && ((einfo->tx_resume_needed) || - (waitqueue_active(&einfo->tx_blocked_queue)))) /* tx waiting ?*/ + if ((atomic_ctx) && ((einfo->tx_resume_needed) + || (einfo->tx_blocked_signal_sent) + || (waitqueue_active(&einfo->tx_blocked_queue)))) /* tx waiting ?*/ tx_wakeup_worker(einfo); /* diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index c9489e3e97a8..e82b6ef1cfe7 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -643,6 +643,9 @@ static struct msm_soc_info cpu_of_id[] = { /* QM215 ID */ [386] = {MSM_CPU_QM215, "QM215"}, + /* QCM2150 ID */ + [436] = {MSM_CPU_QCM2150, "QCM2150"}, + /* SDM429W IDs*/ [416] = {MSM_CPU_SDM429W, "SDM429W"}, /* Uninitialized IDs are not known to run Linux. @@ -1644,6 +1647,10 @@ static void * __init setup_dummy_socinfo(void) dummy_socinfo.id = 386; strlcpy(dummy_socinfo.build_id, "qm215 - ", sizeof(dummy_socinfo.build_id)); + } else if (early_machine_is_qcm2150()) { + dummy_socinfo.id = 436; + strlcpy(dummy_socinfo.build_id, "qcm2150 - ", + sizeof(dummy_socinfo.build_id)); } strlcat(dummy_socinfo.build_id, "Dummy socinfo", diff --git a/drivers/spi/spi-bitbang.c b/drivers/spi/spi-bitbang.c index 3aa9e6e3dac8..4ef54436b9d4 100644 --- a/drivers/spi/spi-bitbang.c +++ b/drivers/spi/spi-bitbang.c @@ -392,7 +392,7 @@ int spi_bitbang_start(struct spi_bitbang *bitbang) if (ret) spi_master_put(master); - return 0; + return ret; } EXPORT_SYMBOL_GPL(spi_bitbang_start); diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c index f2209ec4cb68..6dd195b94c57 100644 --- a/drivers/spi/spi-pxa2xx.c +++ b/drivers/spi/spi-pxa2xx.c @@ -921,10 +921,14 @@ static unsigned int ssp_get_clk_div(struct driver_data *drv_data, int rate) rate = min_t(int, ssp_clk, rate); + /* + * Calculate the divisor for the SCR (Serial Clock Rate), avoiding + * that the SSP transmission rate can be greater than the device rate + */ if (ssp->type == PXA25x_SSP || ssp->type == CE4100_SSP) - return (ssp_clk / (2 * rate) - 1) & 0xff; + return (DIV_ROUND_UP(ssp_clk, 2 * rate) - 1) & 0xff; else - return (ssp_clk / rate - 1) & 0xfff; + return (DIV_ROUND_UP(ssp_clk, rate) - 1) & 0xfff; } static unsigned int pxa2xx_ssp_get_clk_div(struct driver_data *drv_data, @@ -1471,12 +1475,7 @@ static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = { static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param) { - struct device *dev = param; - - if (dev != chan->device->dev->parent) - return false; - - return true; + return param == chan->device->dev; } static struct pxa2xx_spi_master * diff --git a/drivers/spi/spi-rspi.c b/drivers/spi/spi-rspi.c index 093c9cf92bfd..07612e8c58ee 100644 --- a/drivers/spi/spi-rspi.c +++ b/drivers/spi/spi-rspi.c @@ -279,7 +279,8 @@ static int rspi_set_config_register(struct rspi_data *rspi, int access_size) /* Sets parity, interrupt mask */ rspi_write8(rspi, 0x00, RSPI_SPCR2); - /* Sets SPCMD */ + /* Resets sequencer */ + rspi_write8(rspi, 0, RSPI_SPSCR); rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); @@ -323,7 +324,8 @@ static int rspi_rz_set_config_register(struct rspi_data *rspi, int access_size) rspi_write8(rspi, 0x00, RSPI_SSLND); rspi_write8(rspi, 0x00, RSPI_SPND); - /* Sets SPCMD */ + /* Resets sequencer */ + rspi_write8(rspi, 0, RSPI_SPSCR); rspi->spcmd |= SPCMD_SPB_8_TO_16(access_size); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); @@ -374,7 +376,8 @@ static int qspi_set_config_register(struct rspi_data *rspi, int access_size) /* Sets buffer to allow normal operation */ rspi_write8(rspi, 0x00, QSPI_SPBFCR); - /* Sets SPCMD */ + /* Resets sequencer */ + rspi_write8(rspi, 0, RSPI_SPSCR); rspi_write16(rspi, rspi->spcmd, RSPI_SPCMD0); /* Enables SPI function in master mode */ diff --git a/drivers/spi/spi-tegra114.c b/drivers/spi/spi-tegra114.c index 73779cecc3bb..705f515863d4 100644 --- a/drivers/spi/spi-tegra114.c +++ b/drivers/spi/spi-tegra114.c @@ -1067,27 +1067,19 @@ static int tegra_spi_probe(struct platform_device *pdev) spi_irq = platform_get_irq(pdev, 0); tspi->irq = spi_irq; - ret = request_threaded_irq(tspi->irq, tegra_spi_isr, - tegra_spi_isr_thread, IRQF_ONESHOT, - dev_name(&pdev->dev), tspi); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", - tspi->irq); - goto exit_free_master; - } tspi->clk = devm_clk_get(&pdev->dev, "spi"); if (IS_ERR(tspi->clk)) { dev_err(&pdev->dev, "can not get clock\n"); ret = PTR_ERR(tspi->clk); - goto exit_free_irq; + goto exit_free_master; } tspi->rst = devm_reset_control_get(&pdev->dev, "spi"); if (IS_ERR(tspi->rst)) { dev_err(&pdev->dev, "can not get reset\n"); ret = PTR_ERR(tspi->rst); - goto exit_free_irq; + goto exit_free_master; } tspi->max_buf_size = SPI_FIFO_DEPTH << 2; @@ -1095,7 +1087,7 @@ static int tegra_spi_probe(struct platform_device *pdev) ret = tegra_spi_init_dma_param(tspi, true); if (ret < 0) - goto exit_free_irq; + goto exit_free_master; ret = tegra_spi_init_dma_param(tspi, false); if (ret < 0) goto exit_rx_dma_free; @@ -1117,18 +1109,32 @@ static int tegra_spi_probe(struct platform_device *pdev) dev_err(&pdev->dev, "pm runtime get failed, e = %d\n", ret); goto exit_pm_disable; } + + reset_control_assert(tspi->rst); + udelay(2); + reset_control_deassert(tspi->rst); tspi->def_command1_reg = SPI_M_S; tegra_spi_writel(tspi, tspi->def_command1_reg, SPI_COMMAND1); pm_runtime_put(&pdev->dev); + ret = request_threaded_irq(tspi->irq, tegra_spi_isr, + tegra_spi_isr_thread, IRQF_ONESHOT, + dev_name(&pdev->dev), tspi); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to register ISR for IRQ %d\n", + tspi->irq); + goto exit_pm_disable; + } master->dev.of_node = pdev->dev.of_node; ret = devm_spi_register_master(&pdev->dev, master); if (ret < 0) { dev_err(&pdev->dev, "can not register to master err %d\n", ret); - goto exit_pm_disable; + goto exit_free_irq; } return ret; +exit_free_irq: + free_irq(spi_irq, tspi); exit_pm_disable: pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) @@ -1136,8 +1142,6 @@ exit_pm_disable: tegra_spi_deinit_dma_param(tspi, false); exit_rx_dma_free: tegra_spi_deinit_dma_param(tspi, true); -exit_free_irq: - free_irq(spi_irq, tspi); exit_free_master: spi_master_put(master); return ret; diff --git a/drivers/spi/spi-topcliff-pch.c b/drivers/spi/spi-topcliff-pch.c index c54ee6674471..fe707440f8c3 100644 --- a/drivers/spi/spi-topcliff-pch.c +++ b/drivers/spi/spi-topcliff-pch.c @@ -1306,18 +1306,27 @@ static void pch_free_dma_buf(struct pch_spi_board_data *board_dat, return; } -static void pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, +static int pch_alloc_dma_buf(struct pch_spi_board_data *board_dat, struct pch_spi_data *data) { struct pch_spi_dma_ctrl *dma; + int ret; dma = &data->dma; + ret = 0; /* Get Consistent memory for Tx DMA */ dma->tx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, &dma->tx_buf_dma, GFP_KERNEL); + if (!dma->tx_buf_virt) + ret = -ENOMEM; + /* Get Consistent memory for Rx DMA */ dma->rx_buf_virt = dma_alloc_coherent(&board_dat->pdev->dev, PCH_BUF_SIZE, &dma->rx_buf_dma, GFP_KERNEL); + if (!dma->rx_buf_virt) + ret = -ENOMEM; + + return ret; } static int pch_spi_pd_probe(struct platform_device *plat_dev) @@ -1394,7 +1403,9 @@ static int pch_spi_pd_probe(struct platform_device *plat_dev) if (use_dma) { dev_info(&plat_dev->dev, "Use DMA for data transfers\n"); - pch_alloc_dma_buf(board_dat, data); + ret = pch_alloc_dma_buf(board_dat, data); + if (ret) + goto err_spi_register_master; } ret = spi_register_master(master); diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index c2e85e23d538..d74d341f9890 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -955,6 +955,8 @@ static int spi_map_msg(struct spi_master *master, struct spi_message *msg) if (max_tx || max_rx) { list_for_each_entry(xfer, &msg->transfers, transfer_list) { + if (!xfer->len) + continue; if (!xfer->tx_buf) xfer->tx_buf = master->dummy_tx; if (!xfer->rx_buf) diff --git a/drivers/ssb/bridge_pcmcia_80211.c b/drivers/ssb/bridge_pcmcia_80211.c index d70568ea02d5..2ff7d90e166a 100644 --- a/drivers/ssb/bridge_pcmcia_80211.c +++ b/drivers/ssb/bridge_pcmcia_80211.c @@ -113,16 +113,21 @@ static struct pcmcia_driver ssb_host_pcmcia_driver = { .resume = ssb_host_pcmcia_resume, }; +static int pcmcia_init_failed; + /* * These are not module init/exit functions! * The module_pcmcia_driver() helper cannot be used here. */ int ssb_host_pcmcia_init(void) { - return pcmcia_register_driver(&ssb_host_pcmcia_driver); + pcmcia_init_failed = pcmcia_register_driver(&ssb_host_pcmcia_driver); + + return pcmcia_init_failed; } void ssb_host_pcmcia_exit(void) { - pcmcia_unregister_driver(&ssb_host_pcmcia_driver); + if (!pcmcia_init_failed) + pcmcia_unregister_driver(&ssb_host_pcmcia_driver); } diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c index 42945de31fe2..d23aa5d8e62a 100644 --- a/drivers/staging/comedi/drivers/amplc_pci230.c +++ b/drivers/staging/comedi/drivers/amplc_pci230.c @@ -2337,7 +2337,8 @@ static irqreturn_t pci230_interrupt(int irq, void *d) devpriv->intr_running = false; spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags); - comedi_handle_events(dev, s_ao); + if (s_ao) + comedi_handle_events(dev, s_ao); comedi_handle_events(dev, s_ai); return IRQ_HANDLED; diff --git a/drivers/staging/comedi/drivers/dt282x.c b/drivers/staging/comedi/drivers/dt282x.c index d5295bbdd28c..37133d54dda1 100644 --- a/drivers/staging/comedi/drivers/dt282x.c +++ b/drivers/staging/comedi/drivers/dt282x.c @@ -566,7 +566,8 @@ static irqreturn_t dt282x_interrupt(int irq, void *d) } #endif comedi_handle_events(dev, s); - comedi_handle_events(dev, s_ao); + if (s_ao) + comedi_handle_events(dev, s_ao); return IRQ_RETVAL(handled); } diff --git a/drivers/staging/iio/cdc/ad7150.c b/drivers/staging/iio/cdc/ad7150.c index 50a5b0c2cc7b..7ab95efcf1dc 100644 --- a/drivers/staging/iio/cdc/ad7150.c +++ b/drivers/staging/iio/cdc/ad7150.c @@ -6,6 +6,7 @@ * Licensed under the GPL-2 or later. */ +#include <linux/bitfield.h> #include <linux/interrupt.h> #include <linux/device.h> #include <linux/kernel.h> @@ -129,7 +130,7 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, { int ret; u8 threshtype; - bool adaptive; + bool thrfixed; struct ad7150_chip_info *chip = iio_priv(indio_dev); ret = i2c_smbus_read_byte_data(chip->client, AD7150_CFG); @@ -137,21 +138,23 @@ static int ad7150_read_event_config(struct iio_dev *indio_dev, return ret; threshtype = (ret >> 5) & 0x03; - adaptive = !!(ret & 0x80); + + /*check if threshold mode is fixed or adaptive*/ + thrfixed = FIELD_GET(AD7150_CFG_FIX, ret); switch (type) { case IIO_EV_TYPE_MAG_ADAPTIVE: if (dir == IIO_EV_DIR_RISING) - return adaptive && (threshtype == 0x1); - return adaptive && (threshtype == 0x0); + return !thrfixed && (threshtype == 0x1); + return !thrfixed && (threshtype == 0x0); case IIO_EV_TYPE_THRESH_ADAPTIVE: if (dir == IIO_EV_DIR_RISING) - return adaptive && (threshtype == 0x3); - return adaptive && (threshtype == 0x2); + return !thrfixed && (threshtype == 0x3); + return !thrfixed && (threshtype == 0x2); case IIO_EV_TYPE_THRESH: if (dir == IIO_EV_DIR_RISING) - return !adaptive && (threshtype == 0x1); - return !adaptive && (threshtype == 0x0); + return thrfixed && (threshtype == 0x1); + return thrfixed && (threshtype == 0x0); default: break; } diff --git a/drivers/thermal/qcom/tsens.c b/drivers/thermal/qcom/tsens.c index 3f9fe6aa51cc..ebbe1ec7b9e8 100644 --- a/drivers/thermal/qcom/tsens.c +++ b/drivers/thermal/qcom/tsens.c @@ -162,7 +162,8 @@ static int tsens_probe(struct platform_device *pdev) if (tmdev->ops->calibrate) { ret = tmdev->ops->calibrate(tmdev); if (ret < 0) { - dev_err(dev, "tsens calibration failed\n"); + if (ret != -EPROBE_DEFER) + dev_err(dev, "tsens calibration failed\n"); return ret; } } diff --git a/drivers/tty/ipwireless/main.c b/drivers/tty/ipwireless/main.c index 655c7948261c..2fa4f9123469 100644 --- a/drivers/tty/ipwireless/main.c +++ b/drivers/tty/ipwireless/main.c @@ -113,6 +113,10 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) ipw->common_memory = ioremap(p_dev->resource[2]->start, resource_size(p_dev->resource[2])); + if (!ipw->common_memory) { + ret = -ENOMEM; + goto exit1; + } if (!request_mem_region(p_dev->resource[2]->start, resource_size(p_dev->resource[2]), IPWIRELESS_PCCARD_NAME)) { @@ -133,6 +137,10 @@ static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data) ipw->attr_memory = ioremap(p_dev->resource[3]->start, resource_size(p_dev->resource[3])); + if (!ipw->attr_memory) { + ret = -ENOMEM; + goto exit3; + } if (!request_mem_region(p_dev->resource[3]->start, resource_size(p_dev->resource[3]), IPWIRELESS_PCCARD_NAME)) { diff --git a/drivers/tty/rocket.c b/drivers/tty/rocket.c index e8e8973939d3..447d791bde22 100644 --- a/drivers/tty/rocket.c +++ b/drivers/tty/rocket.c @@ -279,7 +279,7 @@ MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc1 module_param_array(pc104_4, ulong, NULL, 0); MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,..."); -static int rp_init(void); +static int __init rp_init(void); static void rp_cleanup_module(void); module_init(rp_init); diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 3177264a1166..22d65a33059e 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -269,7 +269,7 @@ static bool dw8250_fallback_dma_filter(struct dma_chan *chan, void *param) static bool dw8250_idma_filter(struct dma_chan *chan, void *param) { - return param == chan->device->dev->parent; + return param == chan->device->dev; } static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) @@ -311,7 +311,7 @@ static void dw8250_quirks(struct uart_port *p, struct dw8250_data *data) p->set_termios = dw8250_set_termios; } - /* Platforms with iDMA */ + /* Platforms with iDMA 64-bit */ if (platform_get_resource_byname(to_platform_device(p->dev), IORESOURCE_MEM, "lpss_priv")) { p->set_termios = dw8250_set_termios; diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 5b54439a8a9b..84474f06dbcf 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1814,8 +1814,7 @@ int serial8250_handle_irq(struct uart_port *port, unsigned int iir) status = serial_port_in(port, UART_LSR); - if (status & (UART_LSR_DR | UART_LSR_BI) && - iir & UART_IIR_RDI) { + if (status & (UART_LSR_DR | UART_LSR_BI)) { if (!up->dma || handle_rx_dma(up, iir)) status = serial8250_rx_chars(up, status); } diff --git a/drivers/tty/serial/max310x.c b/drivers/tty/serial/max310x.c index 5331baf3f699..ec3db8d8306c 100644 --- a/drivers/tty/serial/max310x.c +++ b/drivers/tty/serial/max310x.c @@ -579,7 +579,7 @@ static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq, } /* Configure clock source */ - clksrc = xtal ? MAX310X_CLKSRC_CRYST_BIT : MAX310X_CLKSRC_EXTCLK_BIT; + clksrc = MAX310X_CLKSRC_EXTCLK_BIT | (xtal ? MAX310X_CLKSRC_CRYST_BIT : 0); /* Configure PLL */ if (pllcfg) { diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c index 99b40d990d03..7700e8a0435f 100644 --- a/drivers/tty/serial/msm_serial.c +++ b/drivers/tty/serial/msm_serial.c @@ -890,6 +890,7 @@ static void msm_handle_tx(struct uart_port *port) struct circ_buf *xmit = &msm_port->uart.state->xmit; struct msm_dma *dma = &msm_port->tx_dma; unsigned int pio_count, dma_count, dma_min; + char buf[4] = { 0 }; void __iomem *tf; int err = 0; @@ -899,10 +900,12 @@ static void msm_handle_tx(struct uart_port *port) else tf = port->membase + UART_TF; + buf[0] = port->x_char; + if (msm_port->is_uartdm) msm_reset_dm_count(port, 1); - iowrite8_rep(tf, &port->x_char, 1); + iowrite32_rep(tf, buf, 1); port->icount.tx++; port->x_char = 0; return; diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 2a5979f15588..ccf99889ebd0 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -144,9 +144,6 @@ static void uart_start(struct tty_struct *tty) struct uart_port *port; unsigned long flags; - if (!state) - return; - port = uart_port_lock(state, flags); __uart_start(tty); uart_port_unlock(port, flags); @@ -1717,11 +1714,8 @@ static void uart_dtr_rts(struct tty_port *port, int onoff) */ static int uart_open(struct tty_struct *tty, struct file *filp) { - struct uart_driver *drv = tty->driver->driver_state; - int retval, line = tty->index; - struct uart_state *state = drv->state + line; - - tty->driver_data = state; + struct uart_state *state = tty->driver_data; + int retval; retval = tty_port_open(&state->port, tty, filp); if (retval > 0) @@ -2412,9 +2406,6 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch) struct uart_state *state = drv->state + line; struct uart_port *port; - if (!state) - return; - port = uart_port_ref(state); if (!port) return; @@ -2426,7 +2417,18 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch) } #endif +static int uart_install(struct tty_driver *driver, struct tty_struct *tty) +{ + struct uart_driver *drv = driver->driver_state; + struct uart_state *state = drv->state + tty->index; + + tty->driver_data = state; + + return tty_standard_install(driver, tty); +} + static const struct tty_operations uart_ops = { + .install = uart_install, .open = uart_open, .close = uart_close, .write = uart_write, diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c index 59828d819145..5ad978acd90c 100644 --- a/drivers/tty/serial/sunhv.c +++ b/drivers/tty/serial/sunhv.c @@ -392,7 +392,7 @@ static struct uart_ops sunhv_pops = { static struct uart_driver sunhv_reg = { .owner = THIS_MODULE, .driver_name = "sunhv", - .dev_name = "ttyS", + .dev_name = "ttyHV", .major = TTY_MAJOR, }; diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 6a15b7250e9c..0f9859478649 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -1621,6 +1621,25 @@ static int ci_udc_pullup(struct usb_gadget *_gadget, int is_on) static int ci_udc_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver); static int ci_udc_stop(struct usb_gadget *gadget); + +/* Match ISOC IN from the highest endpoint */ +static struct usb_ep *ci_udc_match_ep(struct usb_gadget *gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *comp_desc) +{ + struct ci_hdrc *ci = container_of(gadget, struct ci_hdrc, gadget); + struct usb_ep *ep; + + if (usb_endpoint_xfer_isoc(desc) && usb_endpoint_dir_in(desc)) { + list_for_each_entry_reverse(ep, &ci->gadget.ep_list, ep_list) { + if (ep->caps.dir_in && !ep->claimed) + return ep; + } + } + + return NULL; +} + /** * Device operations part of the API to the USB controller hardware, * which don't involve endpoints (or i/o) @@ -1634,6 +1653,7 @@ static const struct usb_gadget_ops usb_gadget_ops = { .vbus_draw = ci_udc_vbus_draw, .udc_start = ci_udc_start, .udc_stop = ci_udc_stop, + .match_ep = ci_udc_match_ep, }; static int init_eps(struct ci_hdrc *ci) diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 876679a84f50..2476d660319e 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -931,8 +931,8 @@ int usb_get_bos_descriptor(struct usb_device *dev) /* Get BOS descriptor */ ret = usb_get_descriptor(dev, USB_DT_BOS, 0, bos, USB_DT_BOS_SIZE); - if (ret < USB_DT_BOS_SIZE) { - dev_err(ddev, "unable to get BOS descriptor\n"); + if (ret < USB_DT_BOS_SIZE || bos->bLength < USB_DT_BOS_SIZE) { + dev_err(ddev, "unable to get BOS descriptor or descriptor too short\n"); if (ret >= 0) ret = -ENOMSG; kfree(bos); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6a4ea986734b..184a1fb74dc7 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -3111,6 +3111,9 @@ usb_hcd_platform_shutdown(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); + /* No need for pm_runtime_put(), we're shutting down */ + pm_runtime_get_sync(&dev->dev); + if (hcd->driver->shutdown) hcd->driver->shutdown(hcd); } diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d6c3df6f963f..4ebc1a8ac605 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5738,7 +5738,10 @@ int usb_reset_device(struct usb_device *udev) cintf->needs_binding = 1; } } - usb_unbind_and_rebind_marked_interfaces(udev); + + /* If the reset failed, hub_wq will unbind drivers later */ + if (ret == 0) + usb_unbind_and_rebind_marked_interfaces(udev); } usb_autosuspend_device(udev); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 733479ddf8a7..19e819aa2419 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -64,9 +64,15 @@ static const struct usb_device_id usb_quirk_list[] = { /* Microsoft LifeCam-VX700 v2.0 */ { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Microsoft Surface Dock Ethernet (RTL8153 GigE) */ + { USB_DEVICE(0x045e, 0x07c6), .driver_info = USB_QUIRK_NO_LPM }, + /* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */ { USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech HD Webcam C270 */ + { USB_DEVICE(0x046d, 0x0825), .driver_info = USB_QUIRK_RESET_RESUME }, + /* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */ { USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT }, { USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 0e5435330c07..120c8f716acf 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -2552,8 +2552,10 @@ static void dwc2_free_dma_aligned_buffer(struct urb *urb) return; /* Restore urb->transfer_buffer from the end of the allocated area */ - memcpy(&stored_xfer_buffer, urb->transfer_buffer + - urb->transfer_buffer_length, sizeof(urb->transfer_buffer)); + memcpy(&stored_xfer_buffer, + PTR_ALIGN(urb->transfer_buffer + urb->transfer_buffer_length, + dma_get_cache_alignment()), + sizeof(urb->transfer_buffer)); if (usb_urb_dir_in(urb)) memcpy(stored_xfer_buffer, urb->transfer_buffer, @@ -2580,6 +2582,7 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) * DMA */ kmalloc_size = urb->transfer_buffer_length + + (dma_get_cache_alignment() - 1) + sizeof(urb->transfer_buffer); kmalloc_ptr = kmalloc(kmalloc_size, mem_flags); @@ -2590,7 +2593,8 @@ static int dwc2_alloc_dma_aligned_buffer(struct urb *urb, gfp_t mem_flags) * Position value of original urb->transfer_buffer pointer to the end * of allocation for later referencing */ - memcpy(kmalloc_ptr + urb->transfer_buffer_length, + memcpy(PTR_ALIGN(kmalloc_ptr + urb->transfer_buffer_length, + dma_get_cache_alignment()), &urb->transfer_buffer, sizeof(urb->transfer_buffer)); if (usb_urb_dir_out(urb)) diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c index 948845c90e47..351012c498c5 100644 --- a/drivers/usb/gadget/udc/fusb300_udc.c +++ b/drivers/usb/gadget/udc/fusb300_udc.c @@ -1345,12 +1345,15 @@ static const struct usb_gadget_ops fusb300_gadget_ops = { static int fusb300_remove(struct platform_device *pdev) { struct fusb300 *fusb300 = platform_get_drvdata(pdev); + int i; usb_del_gadget_udc(&fusb300->gadget); iounmap(fusb300->reg); free_irq(platform_get_irq(pdev, 0), fusb300); fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req); + for (i = 0; i < FUSB300_MAX_NUM_EP; i++) + kfree(fusb300->ep[i]); kfree(fusb300); return 0; @@ -1494,6 +1497,8 @@ clean_up: if (fusb300->ep0_req) fusb300_free_request(&fusb300->ep[0]->ep, fusb300->ep0_req); + for (i = 0; i < FUSB300_MAX_NUM_EP; i++) + kfree(fusb300->ep[i]); kfree(fusb300); } if (reg) diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c index 8f32b5ee7734..6df1aded4503 100644 --- a/drivers/usb/gadget/udc/lpc32xx_udc.c +++ b/drivers/usb/gadget/udc/lpc32xx_udc.c @@ -935,8 +935,7 @@ static struct lpc32xx_usbd_dd_gad *udc_dd_alloc(struct lpc32xx_udc *udc) dma_addr_t dma; struct lpc32xx_usbd_dd_gad *dd; - dd = (struct lpc32xx_usbd_dd_gad *) dma_pool_alloc( - udc->dd_cache, (GFP_KERNEL | GFP_DMA), &dma); + dd = dma_pool_alloc(udc->dd_cache, GFP_ATOMIC | GFP_DMA, &dma); if (dd) dd->this_dma = dma; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index fe5db15b571d..a142339d9028 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -668,6 +668,7 @@ void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, struct xhci_ring *ring, struct device *dev = xhci_to_hcd(xhci)->self.sysdev; struct xhci_segment *seg = td->bounce_seg; struct urb *urb = td->urb; + size_t len; if (!seg || !urb) return; @@ -678,11 +679,14 @@ void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci, struct xhci_ring *ring, return; } - /* for in tranfers we need to copy the data from bounce to sg */ - sg_pcopy_from_buffer(urb->sg, urb->num_mapped_sgs, seg->bounce_buf, - seg->bounce_len, seg->bounce_offs); dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len, DMA_FROM_DEVICE); + /* for in tranfers we need to copy the data from bounce to sg */ + len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf, + seg->bounce_len, seg->bounce_offs); + if (len != seg->bounce_len) + xhci_warn(xhci, "WARN Wrong bounce buffer read length: %zu != %d\n", + len, seg->bounce_len); seg->bounce_len = 0; seg->bounce_offs = 0; } @@ -3153,6 +3157,7 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, unsigned int unalign; unsigned int max_pkt; u32 new_buff_len; + size_t len; max_pkt = GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); unalign = (enqd_len + *trb_buff_len) % max_pkt; @@ -3183,8 +3188,12 @@ static int xhci_align_td(struct xhci_hcd *xhci, struct urb *urb, u32 enqd_len, /* create a max max_pkt sized bounce buffer pointed to by last trb */ if (usb_urb_dir_out(urb)) { - sg_pcopy_to_buffer(urb->sg, urb->num_mapped_sgs, + len = sg_pcopy_to_buffer(urb->sg, urb->num_sgs, seg->bounce_buf, new_buff_len, enqd_len); + if (len != seg->bounce_len) + xhci_warn(xhci, + "WARN Wrong bounce buffer write length: %zu != %d\n", + len, seg->bounce_len); seg->bounce_dma = dma_map_single(dev, seg->bounce_buf, max_pkt, DMA_TO_DEVICE); } else { diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 201bd55afb63..52495fced86d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -21,6 +21,7 @@ */ #include <linux/pci.h> +#include <linux/iopoll.h> #include <linux/irq.h> #include <linux/log2.h> #include <linux/module.h> @@ -47,7 +48,6 @@ static unsigned int quirks; module_param(quirks, uint, S_IRUGO); MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); -/* TODO: copied from ehci-hcd.c - can this be refactored? */ /* * xhci_handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read @@ -64,18 +64,16 @@ MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default"); int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; + int ret; - do { - result = readl(ptr); - if (result == ~(u32)0) /* card removed */ - return -ENODEV; - result &= mask; - if (result == done) - return 0; - udelay(1); - usec--; - } while (usec > 0); - return -ETIMEDOUT; + ret = readl_poll_timeout_atomic(ptr, result, + (result & mask) == done || + result == U32_MAX, + 1, usec); + if (result == U32_MAX) /* card removed */ + return -ENODEV; + + return ret; } int xhci_handshake_check_state(struct xhci_hcd *xhci, @@ -4220,7 +4218,6 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, pm_addr = port_array[port_num] + PORTPMSC; pm_val = readl(pm_addr); hlpm_addr = port_array[port_num] + PORTHLPMC; - field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); xhci_dbg(xhci, "%s port %d USB2 hardware LPM\n", enable ? "enable" : "disable", port_num + 1); @@ -4232,6 +4229,7 @@ int xhci_set_usb2_hardware_lpm(struct usb_hcd *hcd, * default one which works with mixed HIRD and BESL * systems. See XHCI_DEFAULT_BESL definition in xhci.h */ + field = le32_to_cpu(udev->bos->ext_cap->bmAttributes); if ((field & USB_BESL_SUPPORT) && (field & USB_BESL_BASELINE_VALID)) hird = USB_GET_BESL_BASELINE(field); diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 13731d512624..6e761fabffca 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -103,9 +103,22 @@ static int close_rio(struct inode *inode, struct file *file) { struct rio_usb_data *rio = &rio_instance; - rio->isopen = 0; + /* against disconnect() */ + mutex_lock(&rio500_mutex); + mutex_lock(&(rio->lock)); - dev_info(&rio->rio_dev->dev, "Rio closed.\n"); + rio->isopen = 0; + if (!rio->present) { + /* cleanup has been delayed */ + kfree(rio->ibuf); + kfree(rio->obuf); + rio->ibuf = NULL; + rio->obuf = NULL; + } else { + dev_info(&rio->rio_dev->dev, "Rio closed.\n"); + } + mutex_unlock(&(rio->lock)); + mutex_unlock(&rio500_mutex); return 0; } @@ -464,15 +477,23 @@ static int probe_rio(struct usb_interface *intf, { struct usb_device *dev = interface_to_usbdev(intf); struct rio_usb_data *rio = &rio_instance; - int retval; + int retval = 0; - dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); + mutex_lock(&rio500_mutex); + if (rio->present) { + dev_info(&intf->dev, "Second USB Rio at address %d refused\n", dev->devnum); + retval = -EBUSY; + goto bail_out; + } else { + dev_info(&intf->dev, "USB Rio found at address %d\n", dev->devnum); + } retval = usb_register_dev(intf, &usb_rio_class); if (retval) { dev_err(&dev->dev, "Not able to get a minor for this device.\n"); - return -ENOMEM; + retval = -ENOMEM; + goto bail_out; } rio->rio_dev = dev; @@ -481,7 +502,8 @@ static int probe_rio(struct usb_interface *intf, dev_err(&dev->dev, "probe_rio: Not enough memory for the output buffer\n"); usb_deregister_dev(intf, &usb_rio_class); - return -ENOMEM; + retval = -ENOMEM; + goto bail_out; } dev_dbg(&intf->dev, "obuf address:%p\n", rio->obuf); @@ -490,7 +512,8 @@ static int probe_rio(struct usb_interface *intf, "probe_rio: Not enough memory for the input buffer\n"); usb_deregister_dev(intf, &usb_rio_class); kfree(rio->obuf); - return -ENOMEM; + retval = -ENOMEM; + goto bail_out; } dev_dbg(&intf->dev, "ibuf address:%p\n", rio->ibuf); @@ -498,8 +521,10 @@ static int probe_rio(struct usb_interface *intf, usb_set_intfdata (intf, rio); rio->present = 1; +bail_out: + mutex_unlock(&rio500_mutex); - return 0; + return retval; } static void disconnect_rio(struct usb_interface *intf) diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index 05bd39d62568..b7a4ba020893 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3041,6 +3041,13 @@ static int sisusb_probe(struct usb_interface *intf, mutex_init(&(sisusb->lock)); + sisusb->sisusb_dev = dev; + sisusb->vrambase = SISUSB_PCI_MEMBASE; + sisusb->mmiobase = SISUSB_PCI_MMIOBASE; + sisusb->mmiosize = SISUSB_PCI_MMIOSIZE; + sisusb->ioportbase = SISUSB_PCI_IOPORTBASE; + /* Everything else is zero */ + /* Register device */ retval = usb_register_dev(intf, &usb_sisusb_class); if (retval) { @@ -3051,13 +3058,7 @@ static int sisusb_probe(struct usb_interface *intf, goto error_1; } - sisusb->sisusb_dev = dev; - sisusb->minor = intf->minor; - sisusb->vrambase = SISUSB_PCI_MEMBASE; - sisusb->mmiobase = SISUSB_PCI_MMIOBASE; - sisusb->mmiosize = SISUSB_PCI_MMIOSIZE; - sisusb->ioportbase = SISUSB_PCI_IOPORTBASE; - /* Everything else is zero */ + sisusb->minor = intf->minor; /* Allocate buffers */ sisusb->ibufsize = SISUSB_IBUF_SIZE; diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index 968ade5a35f5..696560529e6a 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -821,9 +821,8 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map) } static void usbhsf_dma_complete(void *arg); -static void xfer_work(struct work_struct *work) +static void usbhsf_dma_xfer_preparing(struct usbhs_pkt *pkt) { - struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work); struct usbhs_pipe *pipe = pkt->pipe; struct usbhs_fifo *fifo; struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); @@ -831,12 +830,10 @@ static void xfer_work(struct work_struct *work) struct dma_chan *chan; struct device *dev = usbhs_priv_to_dev(priv); enum dma_transfer_direction dir; - unsigned long flags; - usbhs_lock(priv, flags); fifo = usbhs_pipe_to_fifo(pipe); if (!fifo) - goto xfer_work_end; + return; chan = usbhsf_dma_chan_get(fifo, pkt); dir = usbhs_pipe_is_dir_in(pipe) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV; @@ -845,7 +842,7 @@ static void xfer_work(struct work_struct *work) pkt->trans, dir, DMA_PREP_INTERRUPT | DMA_CTRL_ACK); if (!desc) - goto xfer_work_end; + return; desc->callback = usbhsf_dma_complete; desc->callback_param = pipe; @@ -853,7 +850,7 @@ static void xfer_work(struct work_struct *work) pkt->cookie = dmaengine_submit(desc); if (pkt->cookie < 0) { dev_err(dev, "Failed to submit dma descriptor\n"); - goto xfer_work_end; + return; } dev_dbg(dev, " %s %d (%d/ %d)\n", @@ -864,8 +861,17 @@ static void xfer_work(struct work_struct *work) dma_async_issue_pending(chan); usbhsf_dma_start(pipe, fifo); usbhs_pipe_enable(pipe); +} + +static void xfer_work(struct work_struct *work) +{ + struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work); + struct usbhs_pipe *pipe = pkt->pipe; + struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + unsigned long flags; -xfer_work_end: + usbhs_lock(priv, flags); + usbhsf_dma_xfer_preparing(pkt); usbhs_unlock(priv, flags); } @@ -918,8 +924,13 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) pkt->trans = len; usbhsf_tx_irq_ctrl(pipe, 0); - INIT_WORK(&pkt->work, xfer_work); - schedule_work(&pkt->work); + /* FIXME: Workaound for usb dmac that driver can be used in atomic */ + if (usbhs_get_dparam(priv, has_usb_dmac)) { + usbhsf_dma_xfer_preparing(pkt); + } else { + INIT_WORK(&pkt->work, xfer_work); + schedule_work(&pkt->work); + } return 0; @@ -1025,8 +1036,7 @@ static int usbhsf_dma_prepare_pop_with_usb_dmac(struct usbhs_pkt *pkt, pkt->trans = pkt->length; - INIT_WORK(&pkt->work, xfer_work); - schedule_work(&pkt->work); + usbhsf_dma_xfer_preparing(pkt); return 0; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f54931aa7528..63ff1a4f2e41 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1024,6 +1024,7 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(AIRBUS_DS_VID, AIRBUS_DS_P8GR) }, /* EZPrototypes devices */ { USB_DEVICE(EZPROTOTYPES_VID, HJELMSLUND_USB485_ISO_PID) }, + { USB_DEVICE_INTERFACE_NUMBER(UNJO_VID, UNJO_ISODEBUG_V1_PID, 1) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 15d220eaf6e6..ed6b36674c15 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -1542,3 +1542,9 @@ #define CHETCO_SEASMART_DISPLAY_PID 0xA5AD /* SeaSmart NMEA2000 Display */ #define CHETCO_SEASMART_LITE_PID 0xA5AE /* SeaSmart Lite USB Adapter */ #define CHETCO_SEASMART_ANALOG_PID 0xA5AF /* SeaSmart Analog Adapter */ + +/* + * Unjo AB + */ +#define UNJO_VID 0x22B7 +#define UNJO_ISODEBUG_V1_PID 0x150D diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 9f96dd274370..d7b31fdce94d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1166,6 +1166,10 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1213, 0xff) }, { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920A4_1214), .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) | RSVD(3) }, + { USB_DEVICE(TELIT_VENDOR_ID, 0x1260), + .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, + { USB_DEVICE(TELIT_VENDOR_ID, 0x1261), + .driver_info = NCTRL(0) | RSVD(1) | RSVD(2) }, { USB_DEVICE(TELIT_VENDOR_ID, 0x1900), /* Telit LN940 (QMI) */ .driver_info = NCTRL(0) | RSVD(1) }, { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x1901, 0xff), /* Telit LN940 (MBIM) */ @@ -1334,6 +1338,7 @@ static const struct usb_device_id option_ids[] = { .driver_info = RSVD(4) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0414, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0417, 0xff, 0xff, 0xff) }, + { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0601, 0xff) }, /* GosunCn ZTE WeLink ME3630 (RNDIS mode) */ { USB_DEVICE_INTERFACE_CLASS(ZTE_VENDOR_ID, 0x0602, 0xff) }, /* GosunCn ZTE WeLink ME3630 (MBIM mode) */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1008, 0xff, 0xff, 0xff), .driver_info = RSVD(4) }, @@ -1767,6 +1772,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(ALINK_VENDOR_ID, SIMCOM_PRODUCT_SIM7100E), .driver_info = RSVD(5) | RSVD(6) }, { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9003, 0xff) }, /* Simcom SIM7500/SIM7600 MBIM mode */ + { USB_DEVICE_INTERFACE_CLASS(0x1e0e, 0x9011, 0xff), /* Simcom SIM7500/SIM7600 RNDIS mode */ + .driver_info = RSVD(7) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S_X200), .driver_info = NCTRL(0) | NCTRL(1) | RSVD(4) }, { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D), diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 9706d214c409..8fd5e19846ef 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -101,6 +101,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { USB_DEVICE(ADLINK_VENDOR_ID, ADLINK_ND6530_PRODUCT_ID) }, { USB_DEVICE(SMART_VENDOR_ID, SMART_PRODUCT_ID) }, + { USB_DEVICE(AT_VENDOR_ID, AT_VTKIT3_PRODUCT_ID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/pl2303.h b/drivers/usb/serial/pl2303.h index d84c3b3d477b..496cbccbf26c 100644 --- a/drivers/usb/serial/pl2303.h +++ b/drivers/usb/serial/pl2303.h @@ -159,3 +159,6 @@ #define SMART_VENDOR_ID 0x0b8c #define SMART_PRODUCT_ID 0x2303 +/* Allied Telesis VT-Kit3 */ +#define AT_VENDOR_ID 0x0caa +#define AT_VTKIT3_PRODUCT_ID 0x3001 diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h index 7ca779493671..dee100dd02e1 100644 --- a/drivers/usb/storage/unusual_realtek.h +++ b/drivers/usb/storage/unusual_realtek.h @@ -29,6 +29,11 @@ UNUSUAL_DEV(0x0bda, 0x0138, 0x0000, 0x9999, "USB Card Reader", USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), +UNUSUAL_DEV(0x0bda, 0x0153, 0x0000, 0x9999, + "Realtek", + "USB Card Reader", + USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), + UNUSUAL_DEV(0x0bda, 0x0158, 0x0000, 0x9999, "Realtek", "USB Card Reader", diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 8e629b6a6f3f..a5a6a114219a 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -315,9 +315,17 @@ static int stub_probe(struct usb_device *udev) const char *udev_busid = dev_name(&udev->dev); struct bus_id_priv *busid_priv; int rc = 0; + char save_status; dev_dbg(&udev->dev, "Enter probe\n"); + /* Not sure if this is our device. Allocate here to avoid + * calling alloc while holding busid_table lock. + */ + sdev = stub_device_alloc(udev); + if (!sdev) + return -ENOMEM; + /* check we should claim or not by busid_table */ busid_priv = get_busid_priv(udev_busid); if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) || @@ -332,6 +340,9 @@ static int stub_probe(struct usb_device *udev) * See driver_probe_device() in driver/base/dd.c */ rc = -ENODEV; + if (!busid_priv) + goto sdev_free; + goto call_put_busid_priv; } @@ -351,12 +362,6 @@ static int stub_probe(struct usb_device *udev) goto call_put_busid_priv; } - /* ok, this is my device */ - sdev = stub_device_alloc(udev); - if (!sdev) { - rc = -ENOMEM; - goto call_put_busid_priv; - } dev_info(&udev->dev, "usbip-host: register new device (bus %u dev %u)\n", @@ -366,9 +371,16 @@ static int stub_probe(struct usb_device *udev) /* set private data to usb_device */ dev_set_drvdata(&udev->dev, sdev); + busid_priv->sdev = sdev; busid_priv->udev = udev; + save_status = busid_priv->status; + busid_priv->status = STUB_BUSID_ALLOC; + + /* release the busid_lock */ + put_busid_priv(busid_priv); + /* * Claim this hub port. * It doesn't matter what value we pass as owner @@ -386,10 +398,8 @@ static int stub_probe(struct usb_device *udev) dev_err(&udev->dev, "stub_add_files for %s\n", udev_busid); goto err_files; } - busid_priv->status = STUB_BUSID_ALLOC; - rc = 0; - goto call_put_busid_priv; + return 0; err_files: usb_hub_release_port(udev->parent, udev->portnum, @@ -398,23 +408,30 @@ err_port: dev_set_drvdata(&udev->dev, NULL); usb_put_dev(udev); + /* we already have busid_priv, just lock busid_lock */ + spin_lock(&busid_priv->busid_lock); busid_priv->sdev = NULL; - stub_device_free(sdev); + busid_priv->status = save_status; + spin_unlock(&busid_priv->busid_lock); + /* lock is released - go to free */ + goto sdev_free; call_put_busid_priv: + /* release the busid_lock */ put_busid_priv(busid_priv); + +sdev_free: + stub_device_free(sdev); + return rc; } static void shutdown_busid(struct bus_id_priv *busid_priv) { - if (busid_priv->sdev && !busid_priv->shutdown_busid) { - busid_priv->shutdown_busid = 1; - usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED); + usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED); - /* wait for the stop of the event handler */ - usbip_stop_eh(&busid_priv->sdev->ud); - } + /* wait for the stop of the event handler */ + usbip_stop_eh(&busid_priv->sdev->ud); } /* @@ -441,11 +458,16 @@ static void stub_disconnect(struct usb_device *udev) /* get stub_device */ if (!sdev) { dev_err(&udev->dev, "could not get device"); - goto call_put_busid_priv; + /* release busid_lock */ + put_busid_priv(busid_priv); + return; } dev_set_drvdata(&udev->dev, NULL); + /* release busid_lock before call to remove device files */ + put_busid_priv(busid_priv); + /* * NOTE: rx/tx threads are invoked for each usb_device. */ @@ -456,27 +478,36 @@ static void stub_disconnect(struct usb_device *udev) (struct usb_dev_state *) udev); if (rc) { dev_dbg(&udev->dev, "unable to release port\n"); - goto call_put_busid_priv; + return; } /* If usb reset is called from event handler */ if (usbip_in_eh(current)) - goto call_put_busid_priv; + return; + + /* we already have busid_priv, just lock busid_lock */ + spin_lock(&busid_priv->busid_lock); + if (!busid_priv->shutdown_busid) + busid_priv->shutdown_busid = 1; + /* release busid_lock */ + spin_unlock(&busid_priv->busid_lock); /* shutdown the current connection */ shutdown_busid(busid_priv); usb_put_dev(sdev->udev); + /* we already have busid_priv, just lock busid_lock */ + spin_lock(&busid_priv->busid_lock); /* free sdev */ busid_priv->sdev = NULL; stub_device_free(sdev); if (busid_priv->status == STUB_BUSID_ALLOC) busid_priv->status = STUB_BUSID_ADDED; - -call_put_busid_priv: - put_busid_priv(busid_priv); + /* release busid_lock */ + spin_unlock(&busid_priv->busid_lock); + return; } #ifdef CONFIG_PM diff --git a/drivers/video/fbdev/core/fbcmap.c b/drivers/video/fbdev/core/fbcmap.c index 68a113594808..2811c4afde01 100644 --- a/drivers/video/fbdev/core/fbcmap.c +++ b/drivers/video/fbdev/core/fbcmap.c @@ -94,6 +94,8 @@ int fb_alloc_cmap_gfp(struct fb_cmap *cmap, int len, int transp, gfp_t flags) int size = len * sizeof(u16); int ret = -ENOMEM; + flags |= __GFP_NOWARN; + if (cmap->len != len) { fb_dealloc_cmap(cmap); if (!len) diff --git a/drivers/video/fbdev/core/modedb.c b/drivers/video/fbdev/core/modedb.c index de119f11b78f..455a15f70172 100644 --- a/drivers/video/fbdev/core/modedb.c +++ b/drivers/video/fbdev/core/modedb.c @@ -933,6 +933,9 @@ void fb_var_to_videomode(struct fb_videomode *mode, if (var->vmode & FB_VMODE_DOUBLE) vtotal *= 2; + if (!htotal || !vtotal) + return; + hfreq = pixclock/htotal; mode->refresh = hfreq/vtotal; } diff --git a/drivers/video/fbdev/hgafb.c b/drivers/video/fbdev/hgafb.c index 463028543173..59e1cae57948 100644 --- a/drivers/video/fbdev/hgafb.c +++ b/drivers/video/fbdev/hgafb.c @@ -285,6 +285,8 @@ static int hga_card_detect(void) hga_vram_len = 0x08000; hga_vram = ioremap(0xb0000, hga_vram_len); + if (!hga_vram) + goto error; if (request_region(0x3b0, 12, "hgafb")) release_io_ports = 1; diff --git a/drivers/video/fbdev/imsttfb.c b/drivers/video/fbdev/imsttfb.c index 4363c64d74e8..4ef9dc94e813 100644 --- a/drivers/video/fbdev/imsttfb.c +++ b/drivers/video/fbdev/imsttfb.c @@ -1516,6 +1516,11 @@ static int imsttfb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) info->fix.smem_start = addr; info->screen_base = (__u8 *)ioremap(addr, par->ramdac == IBM ? 0x400000 : 0x800000); + if (!info->screen_base) { + release_mem_region(addr, size); + framebuffer_release(info); + return -ENOMEM; + } info->fix.mmio_start = addr + 0x800000; par->dc_regs = ioremap(addr + 0x800000, 0x1000); par->cmap_regs_phys = addr + 0x840000; diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c index f4bc8c100a01..a3ac582420ec 100644 --- a/drivers/w1/w1_io.c +++ b/drivers/w1/w1_io.c @@ -437,8 +437,7 @@ int w1_reset_resume_command(struct w1_master *dev) if (w1_reset_bus(dev)) return -1; - /* This will make only the last matched slave perform a skip ROM. */ - w1_write_8(dev, W1_RESUME_CMD); + w1_write_8(dev, dev->slave_count > 1 ? W1_RESUME_CMD : W1_SKIP_ROM); return 0; } EXPORT_SYMBOL_GPL(w1_reset_resume_command); diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 416903ea1406..e7905c4d24a3 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1862,6 +1862,7 @@ comment "Watchdog Pretimeout Governors" config WATCHDOG_PRETIMEOUT_GOV bool "Enable watchdog pretimeout governors" + depends on WATCHDOG_CORE help The option allows to select watchdog pretimeout governors. diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c index 518dfa1047cb..5098982e1a58 100644 --- a/drivers/watchdog/imx2_wdt.c +++ b/drivers/watchdog/imx2_wdt.c @@ -181,8 +181,10 @@ static void __imx2_wdt_set_timeout(struct watchdog_device *wdog, static int imx2_wdt_set_timeout(struct watchdog_device *wdog, unsigned int new_timeout) { - __imx2_wdt_set_timeout(wdog, new_timeout); + unsigned int actual; + actual = min(new_timeout, wdog->max_hw_heartbeat_ms * 1000); + __imx2_wdt_set_timeout(wdog, actual); wdog->timeout = new_timeout; return 0; } diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index f8c77751f330..e7fbed56c044 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c @@ -126,8 +126,6 @@ void xen_pcibk_reset_device(struct pci_dev *dev) if (pci_is_enabled(dev)) pci_disable_device(dev); - pci_write_config_word(dev, PCI_COMMAND, 0); - dev->is_busmaster = 0; } else { pci_read_config_word(dev, PCI_COMMAND, &cmd); diff --git a/drivers/xen/xenbus/xenbus_dev_frontend.c b/drivers/xen/xenbus/xenbus_dev_frontend.c index 0a3c6762df1b..07f6ba6ccaa7 100644 --- a/drivers/xen/xenbus/xenbus_dev_frontend.c +++ b/drivers/xen/xenbus/xenbus_dev_frontend.c @@ -536,7 +536,7 @@ static int xenbus_file_open(struct inode *inode, struct file *filp) if (xen_store_evtchn == 0) return -ENOENT; - nonseekable_open(inode, filp); + stream_open(inode, filp); u = kzalloc(sizeof(*u), GFP_KERNEL); if (u == NULL) diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 082d227fa56b..6261719f6f2a 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -276,7 +276,7 @@ static int v9fs_xattr_set_acl(const struct xattr_handler *handler, switch (handler->flags) { case ACL_TYPE_ACCESS: if (acl) { - struct iattr iattr; + struct iattr iattr = { 0 }; struct posix_acl *old_acl = acl; retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 9b2917a30294..b18543b36ae1 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -859,9 +859,14 @@ err: static int load_flat_shared_library(int id, struct lib_info *libs) { + /* + * This is a fake bprm struct; only the members "buf", "file" and + * "filename" are actually used. + */ struct linux_binprm bprm; int res; char buf[16]; + loff_t pos = 0; memset(&bprm, 0, sizeof(bprm)); @@ -875,25 +880,11 @@ static int load_flat_shared_library(int id, struct lib_info *libs) if (IS_ERR(bprm.file)) return res; - bprm.cred = prepare_exec_creds(); - res = -ENOMEM; - if (!bprm.cred) - goto out; - - /* We don't really care about recalculating credentials at this point - * as we're past the point of no return and are dealing with shared - * libraries. - */ - bprm.cred_prepared = 1; + res = kernel_read(bprm.file, pos, bprm.buf, BINPRM_BUF_SIZE); - res = prepare_binprm(&bprm); - - if (!res) + if (res >= 0) res = load_flat_file(&bprm, libs, id, NULL); - abort_creds(bprm.cred); - -out: allow_write_access(bprm.file); fput(bprm.file); diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c index fb973cc0af66..395b07764269 100644 --- a/fs/btrfs/dev-replace.c +++ b/fs/btrfs/dev-replace.c @@ -511,18 +511,27 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info, } btrfs_wait_ordered_roots(root->fs_info, -1, 0, (u64)-1); - trans = btrfs_start_transaction(root, 0); - if (IS_ERR(trans)) { - mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); - return PTR_ERR(trans); + while (1) { + trans = btrfs_start_transaction(root, 0); + if (IS_ERR(trans)) { + mutex_unlock(&dev_replace->lock_finishing_cancel_unmount); + return PTR_ERR(trans); + } + ret = btrfs_commit_transaction(trans, root); + WARN_ON(ret); + mutex_lock(&uuid_mutex); + /* keep away write_all_supers() during the finishing procedure */ + mutex_lock(&root->fs_info->fs_devices->device_list_mutex); + mutex_lock(&root->fs_info->chunk_mutex); + if (src_device->has_pending_chunks) { + mutex_unlock(&root->fs_info->chunk_mutex); + mutex_unlock(&root->fs_info->fs_devices->device_list_mutex); + mutex_unlock(&uuid_mutex); + } else { + break; + } } - ret = btrfs_commit_transaction(trans, root); - WARN_ON(ret); - mutex_lock(&uuid_mutex); - /* keep away write_all_supers() during the finishing procedure */ - mutex_lock(&root->fs_info->fs_devices->device_list_mutex); - mutex_lock(&root->fs_info->chunk_mutex); btrfs_dev_replace_lock(dev_replace, 1); dev_replace->replace_state = scrub_ret ? BTRFS_IOCTL_DEV_REPLACE_STATE_CANCELED diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 6b29165f766f..7938c48c72ff 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -11150,9 +11150,9 @@ int btrfs_error_unpin_extent_range(struct btrfs_root *root, u64 start, u64 end) * transaction. */ static int btrfs_trim_free_extents(struct btrfs_device *device, - struct fstrim_range *range, u64 *trimmed) + u64 minlen, u64 *trimmed) { - u64 start = range->start, len = 0; + u64 start = 0, len = 0; int ret; *trimmed = 0; @@ -11188,8 +11188,8 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, atomic_inc(&trans->use_count); spin_unlock(&fs_info->trans_lock); - ret = find_free_dev_extent_start(trans, device, range->minlen, - start, &start, &len); + ret = find_free_dev_extent_start(trans, device, minlen, start, + &start, &len); if (trans) btrfs_put_transaction(trans); @@ -11201,16 +11201,6 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, break; } - /* If we are out of the passed range break */ - if (start > range->start + range->len - 1) { - mutex_unlock(&fs_info->chunk_mutex); - ret = 0; - break; - } - - start = max(range->start, start); - len = min(range->len, len); - ret = btrfs_issue_discard(device->bdev, start, len, &bytes); up_read(&fs_info->commit_root_sem); mutex_unlock(&fs_info->chunk_mutex); @@ -11221,10 +11211,6 @@ static int btrfs_trim_free_extents(struct btrfs_device *device, start += len; *trimmed += bytes; - /* We've trimmed enough */ - if (*trimmed >= range->len) - break; - if (fatal_signal_pending(current)) { ret = -ERESTARTSYS; break; @@ -11309,7 +11295,8 @@ int btrfs_trim_fs(struct btrfs_root *root, struct fstrim_range *range) mutex_lock(&fs_info->fs_devices->device_list_mutex); devices = &fs_info->fs_devices->devices; list_for_each_entry(device, devices, dev_list) { - ret = btrfs_trim_free_extents(device, range, &group_trimmed); + ret = btrfs_trim_free_extents(device, range->minlen, + &group_trimmed); if (ret) { dev_failed++; dev_ret = ret; diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 437544846e4e..c77114ce884b 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -1952,6 +1952,18 @@ int btrfs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) u64 len; /* + * If the inode needs a full sync, make sure we use a full range to + * avoid log tree corruption, due to hole detection racing with ordered + * extent completion for adjacent ranges, and assertion failures during + * hole detection. + */ + if (test_bit(BTRFS_INODE_NEEDS_FULL_SYNC, + &BTRFS_I(inode)->runtime_flags)) { + start = 0; + end = LLONG_MAX; + } + + /* * The range length can be represented by u64, we have to do the typecasts * to avoid signed overflow if it's [0, LLONG_MAX] eg. from fsync() */ diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c index 75bab76739be..94441fdb1ecf 100644 --- a/fs/btrfs/reada.c +++ b/fs/btrfs/reada.c @@ -759,6 +759,7 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info) u64 total = 0; int i; +again: do { enqueued = 0; mutex_lock(&fs_devices->device_list_mutex); @@ -771,6 +772,10 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info) mutex_unlock(&fs_devices->device_list_mutex); total += enqueued; } while (enqueued && total < 10000); + if (fs_devices->seed) { + fs_devices = fs_devices->seed; + goto again; + } if (enqueued == 0) return; diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c index edae751e870c..307b8baaf0e9 100644 --- a/fs/btrfs/root-tree.c +++ b/fs/btrfs/root-tree.c @@ -144,10 +144,8 @@ int btrfs_update_root(struct btrfs_trans_handle *trans, struct btrfs_root return -ENOMEM; ret = btrfs_search_slot(trans, root, key, path, 0, 1); - if (ret < 0) { - btrfs_abort_transaction(trans, ret); + if (ret < 0) goto out; - } if (ret != 0) { btrfs_print_leaf(root, path->nodes[0]); diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c index 1f157fba8940..510cad48e519 100644 --- a/fs/btrfs/sysfs.c +++ b/fs/btrfs/sysfs.c @@ -751,7 +751,12 @@ int btrfs_sysfs_add_fsid(struct btrfs_fs_devices *fs_devs, fs_devs->fsid_kobj.kset = btrfs_kset; error = kobject_init_and_add(&fs_devs->fsid_kobj, &btrfs_ktype, parent, "%pU", fs_devs->fsid); - return error; + if (error) { + kobject_put(&fs_devs->fsid_kobj); + return error; + } + + return 0; } int btrfs_sysfs_add_mounted(struct btrfs_fs_info *fs_info) diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index a36bb75383dc..02bb7b52cb36 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -2827,6 +2827,12 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, log->log_transid = root->log_transid; root->log_start_pid = 0; /* + * Update or create log root item under the root's log_mutex to prevent + * races with concurrent log syncs that can lead to failure to update + * log root item because it was not created yet. + */ + ret = update_log_root(trans, log); + /* * IO has been started, blocks of the log tree have WRITTEN flag set * in their headers. new modifications of the log will be written to * new positions. so it's safe to allow log writers to go in. @@ -2845,8 +2851,6 @@ int btrfs_sync_log(struct btrfs_trans_handle *trans, mutex_unlock(&log_root_tree->log_mutex); - ret = update_log_root(trans, log); - mutex_lock(&log_root_tree->log_mutex); if (atomic_dec_and_test(&log_root_tree->log_writers)) { /* diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index dbb78c31a9fb..0a829f01ce00 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -4876,6 +4876,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans, for (i = 0; i < map->num_stripes; i++) { num_bytes = map->stripes[i].dev->bytes_used + stripe_size; btrfs_device_set_bytes_used(map->stripes[i].dev, num_bytes); + map->stripes[i].dev->has_pending_chunks = true; } spin_lock(&extent_root->fs_info->free_chunk_lock); @@ -7250,6 +7251,7 @@ void btrfs_update_commit_device_bytes_used(struct btrfs_root *root, for (i = 0; i < map->num_stripes; i++) { dev = map->stripes[i].dev; dev->commit_bytes_used = dev->bytes_used; + dev->has_pending_chunks = false; } } unlock_chunks(root); diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h index 9c09aa29d6bd..663d66828cca 100644 --- a/fs/btrfs/volumes.h +++ b/fs/btrfs/volumes.h @@ -62,6 +62,11 @@ struct btrfs_device { spinlock_t io_lock ____cacheline_aligned; int running_pending; + /* When true means this device has pending chunk alloc in + * current transaction. Protected by chunk_mutex. + */ + bool has_pending_chunks; + /* regular prio bios */ struct btrfs_pending_bios pending_bios; /* WRITE_SYNC bios */ diff --git a/fs/char_dev.c b/fs/char_dev.c index 44a240c4bb65..a112a4745d8b 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -134,6 +134,12 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, ret = -EBUSY; goto out; } + + if (new_min < old_min && new_max > old_max) { + ret = -EBUSY; + goto out; + } + } cd->next = *cp; diff --git a/fs/cifs/file.c b/fs/cifs/file.c index e7f1773b25d6..df3ee0b6264f 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -2892,7 +2892,9 @@ cifs_read_allocate_pages(struct cifs_readdata *rdata, unsigned int nr_pages) } if (rc) { - for (i = 0; i < nr_pages; i++) { + unsigned int nr_page_failed = i; + + for (i = 0; i < nr_page_failed; i++) { put_page(rdata->pages[i]); rdata->pages[i] = NULL; } diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c index d2a1a79fa324..a1985a9ad2d6 100644 --- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -58,15 +58,13 @@ static void configfs_d_iput(struct dentry * dentry, if (sd) { /* Coordinate with configfs_readdir */ spin_lock(&configfs_dirent_lock); - /* Coordinate with configfs_attach_attr where will increase - * sd->s_count and update sd->s_dentry to new allocated one. - * Only set sd->dentry to null when this dentry is the only - * sd owner. - * If not do so, configfs_d_iput may run just after - * configfs_attach_attr and set sd->s_dentry to null - * even it's still in use. + /* + * Set sd->s_dentry to null only when this dentry is the one + * that is going to be killed. Otherwise configfs_d_iput may + * run just after configfs_attach_attr and set sd->s_dentry to + * NULL even it's still in use. */ - if (atomic_read(&sd->s_count) <= 2) + if (sd->s_dentry == dentry) sd->s_dentry = NULL; spin_unlock(&configfs_dirent_lock); @@ -1755,12 +1753,19 @@ int configfs_register_group(struct config_group *parent_group, inode_lock_nested(d_inode(parent), I_MUTEX_PARENT); ret = create_default_group(parent_group, group); - if (!ret) { - spin_lock(&configfs_dirent_lock); - configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata); - spin_unlock(&configfs_dirent_lock); - } + if (ret) + goto err_out; + + spin_lock(&configfs_dirent_lock); + configfs_dir_set_ready(group->cg_item.ci_dentry->d_fsdata); + spin_unlock(&configfs_dirent_lock); + inode_unlock(d_inode(parent)); + return 0; +err_out: inode_unlock(d_inode(parent)); + mutex_lock(&subsys->su_mutex); + unlink_group(group); + mutex_unlock(&subsys->su_mutex); return ret; } EXPORT_SYMBOL(configfs_register_group); diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c index cfe9117dd4e7..9f38e7fe08d3 100755 --- a/fs/crypto/keyinfo.c +++ b/fs/crypto/keyinfo.c @@ -606,8 +606,6 @@ int fscrypt_get_encryption_info(struct inode *inode) if (res) goto out; - memzero_explicit(crypt_info->ci_raw_key, - sizeof(crypt_info->ci_raw_key)); do_ice: if (cmpxchg(&inode->i_crypt_info, NULL, crypt_info) == NULL) crypt_info = NULL; @@ -615,6 +613,7 @@ out: if (res == -ENOKEY) res = 0; put_crypt_info(crypt_info); + kzfree(raw_key); return res; } EXPORT_SYMBOL(fscrypt_get_encryption_info); diff --git a/fs/crypto/policy.c b/fs/crypto/policy.c index 74e8d3d8c48e..e258a354b3e5 100644 --- a/fs/crypto/policy.c +++ b/fs/crypto/policy.c @@ -80,6 +80,10 @@ int fscrypt_ioctl_set_policy(struct file *filp, const void __user *arg) if (ret == -ENODATA) { if (!S_ISDIR(inode->i_mode)) ret = -ENOTDIR; + else if (IS_DEADDIR(inode)) + ret = -ENOENT; + else if (!inode->i_sb->s_cop->empty_dir) + ret = -EOPNOTSUPP; else if (!inode->i_sb->s_cop->empty_dir(inode)) ret = -ENOTEMPTY; else diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 8cb2298bdf6b..5578aa8abfd1 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -5293,7 +5293,7 @@ int ext4_setattr(struct dentry *dentry, struct iattr *attr) up_write(&EXT4_I(inode)->i_data_sem); ext4_journal_stop(handle); if (error) { - if (orphan) + if (orphan && inode->i_nlink) ext4_orphan_del(NULL, inode); goto err_out; } diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c index d4c531028d96..a5403b28de41 100644 --- a/fs/f2fs/checkpoint.c +++ b/fs/f2fs/checkpoint.c @@ -1328,10 +1328,8 @@ static void update_ckpt_flags(struct f2fs_sb_info *sbi, struct cp_control *cpc) if (is_sbi_flag_set(sbi, SBI_QUOTA_SKIP_FLUSH)) __set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); - /* - * TODO: we count on fsck.f2fs to clear this flag until we figure out - * missing cases which clear it incorrectly. - */ + else + __clear_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); if (is_sbi_flag_set(sbi, SBI_QUOTA_NEED_REPAIR)) __set_ckpt_flags(ckpt, CP_QUOTA_NEED_FSCK_FLAG); diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index ae2e39fa09ff..271b93aef0ff 100755 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -517,7 +517,10 @@ int f2fs_submit_page_bio(struct f2fs_io_info *fio) inc_page_count(fio->sbi, is_read_io(fio->op) ? __read_io_type(page): WB_DATA_TYPE(fio->page)); - __f2fs_submit_read_bio(fio->sbi, bio, fio->type); + if (is_read_io(fio->op)) + __f2fs_submit_read_bio(fio->sbi, bio, fio->type); + else + __submit_bio(fio->sbi, bio, fio->type); return 0; } diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c index 24fe54e4a9df..0c76bd1348d6 100644 --- a/fs/f2fs/file.c +++ b/fs/f2fs/file.c @@ -29,6 +29,7 @@ #include "gc.h" #include "trace.h" #include <trace/events/f2fs.h> +#include <trace/events/android_fs.h> static int f2fs_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -220,6 +221,15 @@ static int f2fs_do_sync_file(struct file *file, loff_t start, loff_t end, trace_f2fs_sync_file_enter(inode); + if (trace_android_fs_fsync_start_enabled()) { + char *path, pathbuf[MAX_TRACE_PATHBUF_LEN]; + + path = android_fstrace_get_pathname(pathbuf, + MAX_TRACE_PATHBUF_LEN, inode); + trace_android_fs_fsync_start(inode, + current->pid, path, current->comm); + } + if (S_ISDIR(inode->i_mode)) goto go_write; @@ -325,6 +335,8 @@ flush_out: out: trace_f2fs_sync_file_exit(inode, cp_reason, datasync, ret); f2fs_trace_ios(NULL, 1); + trace_android_fs_fsync_end(inode, start, end - start); + return ret; } diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c index a6de02a49967..09df6417a454 100644 --- a/fs/f2fs/super.c +++ b/fs/f2fs/super.c @@ -3169,10 +3169,7 @@ try_onemore: #ifdef CONFIG_QUOTA sb->dq_op = &f2fs_quota_operations; - if (f2fs_sb_has_quota_ino(sbi)) - sb->s_qcop = &dquot_quotactl_sysfile_ops; - else - sb->s_qcop = &f2fs_quotactl_ops; + sb->s_qcop = &f2fs_quotactl_ops; sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP | QTYPE_MASK_PRJ; if (f2fs_sb_has_quota_ino(sbi)) { diff --git a/fs/fat/file.c b/fs/fat/file.c index 3d04b124bce0..392ec5641f38 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -160,12 +160,17 @@ static int fat_file_release(struct inode *inode, struct file *filp) int fat_file_fsync(struct file *filp, loff_t start, loff_t end, int datasync) { struct inode *inode = filp->f_mapping->host; - int res, err; + int err; + + err = __generic_file_fsync(filp, start, end, datasync); + if (err) + return err; - res = generic_file_fsync(filp, start, end, datasync); err = sync_mapping_buffers(MSDOS_SB(inode->i_sb)->fat_inode->i_mapping); + if (err) + return err; - return res ? res : err; + return blkdev_issue_flush(inode->i_sb->s_bdev, GFP_KERNEL, NULL); } diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index c33cb1f3b876..7dcad4c72efe 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1678,7 +1678,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode, offset = outarg->offset & ~PAGE_MASK; file_size = i_size_read(inode); - num = outarg->size; + num = min(outarg->size, fc->max_write); if (outarg->offset > file_size) num = 0; else if (outarg->offset + num > file_size) @@ -1994,10 +1994,8 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, rem += pipe->bufs[(pipe->curbuf + idx) & (pipe->buffers - 1)].len; ret = -EINVAL; - if (rem < len) { - pipe_unlock(pipe); - goto out; - } + if (rem < len) + goto out_free; rem = len; while (rem) { @@ -2015,7 +2013,9 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, pipe->curbuf = (pipe->curbuf + 1) & (pipe->buffers - 1); pipe->nrbufs--; } else { - pipe_buf_get(pipe, ibuf); + if (!pipe_buf_get(pipe, ibuf)) + goto out_free; + *obuf = *ibuf; obuf->flags &= ~PIPE_BUF_FLAG_GIFT; obuf->len = rem; @@ -2038,11 +2038,11 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, ret = fuse_dev_do_write(fud, &cs, len); pipe_lock(pipe); +out_free: for (idx = 0; idx < nbuf; idx++) pipe_buf_release(pipe, &bufs[idx]); pipe_unlock(pipe); -out: kfree(bufs); return ret; } diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 066efedea79a..5d31bf1a1168 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -194,7 +194,9 @@ void fuse_finish_open(struct inode *inode, struct file *file) file->f_op = &fuse_direct_io_file_operations; if (!(ff->open_flags & FOPEN_KEEP_CACHE)) invalidate_inode_pages2(inode->i_mapping); - if (ff->open_flags & FOPEN_NONSEEKABLE) + if (ff->open_flags & FOPEN_STREAM) + stream_open(inode, file); + else if (ff->open_flags & FOPEN_NONSEEKABLE) nonseekable_open(inode, file); if (fc->atomic_o_trunc && (file->f_flags & O_TRUNC)) { struct fuse_inode *fi = get_fuse_inode(inode); @@ -3002,7 +3004,7 @@ static long fuse_file_fallocate(struct file *file, int mode, loff_t offset, offset + length > i_size_read(inode)) { err = inode_newsize_ok(inode, offset + length); if (err) - return err; + goto out; } if (!(mode & FALLOC_FL_KEEP_SIZE)) diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c index 7a8b1d72e3d9..efd44d5645d8 100644 --- a/fs/gfs2/glock.c +++ b/fs/gfs2/glock.c @@ -136,22 +136,26 @@ static int demote_ok(const struct gfs2_glock *gl) void gfs2_glock_add_to_lru(struct gfs2_glock *gl) { + if (!(gl->gl_ops->go_flags & GLOF_LRU)) + return; + spin_lock(&lru_lock); - if (!list_empty(&gl->gl_lru)) - list_del_init(&gl->gl_lru); - else + list_del(&gl->gl_lru); + list_add_tail(&gl->gl_lru, &lru_list); + + if (!test_bit(GLF_LRU, &gl->gl_flags)) { + set_bit(GLF_LRU, &gl->gl_flags); atomic_inc(&lru_count); + } - list_add_tail(&gl->gl_lru, &lru_list); - set_bit(GLF_LRU, &gl->gl_flags); spin_unlock(&lru_lock); } static void gfs2_glock_remove_from_lru(struct gfs2_glock *gl) { spin_lock(&lru_lock); - if (!list_empty(&gl->gl_lru)) { + if (test_bit(GLF_LRU, &gl->gl_flags)) { list_del_init(&gl->gl_lru); atomic_dec(&lru_count); clear_bit(GLF_LRU, &gl->gl_flags); @@ -1048,8 +1052,7 @@ void gfs2_glock_dq(struct gfs2_holder *gh) !test_bit(GLF_DEMOTE, &gl->gl_flags)) fast_path = 1; } - if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl) && - (glops->go_flags & GLOF_LRU)) + if (!test_bit(GLF_LFLUSH, &gl->gl_flags) && demote_ok(gl)) gfs2_glock_add_to_lru(gl); trace_gfs2_glock_queue(gh, 0); @@ -1349,6 +1352,7 @@ __acquires(&lru_lock) if (!spin_trylock(&gl->gl_lockref.lock)) { add_back_to_lru: list_add(&gl->gl_lru, &lru_list); + set_bit(GLF_LRU, &gl->gl_flags); atomic_inc(&lru_count); continue; } @@ -1356,7 +1360,6 @@ add_back_to_lru: spin_unlock(&gl->gl_lockref.lock); goto add_back_to_lru; } - clear_bit(GLF_LRU, &gl->gl_flags); gl->gl_lockref.count++; if (demote_ok(gl)) handle_callback(gl, LM_ST_UNLOCKED, 0, false); @@ -1392,6 +1395,7 @@ static long gfs2_scan_glock_lru(int nr) if (!test_bit(GLF_LOCK, &gl->gl_flags)) { list_move(&gl->gl_lru, &dispose); atomic_dec(&lru_count); + clear_bit(GLF_LRU, &gl->gl_flags); freed++; continue; } diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c index 8b907c5cc913..3c3d037df824 100644 --- a/fs/gfs2/lock_dlm.c +++ b/fs/gfs2/lock_dlm.c @@ -32,9 +32,10 @@ extern struct workqueue_struct *gfs2_control_wq; * @delta is the difference between the current rtt sample and the * running average srtt. We add 1/8 of that to the srtt in order to * update the current srtt estimate. The variance estimate is a bit - * more complicated. We subtract the abs value of the @delta from - * the current variance estimate and add 1/4 of that to the running - * total. + * more complicated. We subtract the current variance estimate from + * the abs value of the @delta and add 1/4 of that to the running + * total. That's equivalent to 3/4 of the current variance + * estimate plus 1/4 of the abs of @delta. * * Note that the index points at the array entry containing the smoothed * mean value, and the variance is always in the following entry @@ -50,7 +51,7 @@ static inline void gfs2_update_stats(struct gfs2_lkstats *s, unsigned index, s64 delta = sample - s->stats[index]; s->stats[index] += (delta >> 3); index++; - s->stats[index] += ((abs(delta) - s->stats[index]) >> 2); + s->stats[index] += (s64)(abs(delta) - s->stats[index]) >> 2; } /** diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 4acc677ac8fb..253b03451b72 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -451,9 +451,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart, if (next >= end) break; - hash = hugetlb_fault_mutex_hash(h, current->mm, - &pseudo_vma, - mapping, next, 0); + hash = hugetlb_fault_mutex_hash(h, mapping, next, 0); mutex_lock(&hugetlb_fault_mutex_table[hash]); /* @@ -573,7 +571,6 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset, struct address_space *mapping = inode->i_mapping; struct hstate *h = hstate_inode(inode); struct vm_area_struct pseudo_vma; - struct mm_struct *mm = current->mm; loff_t hpage_size = huge_page_size(h); unsigned long hpage_shift = huge_page_shift(h); pgoff_t start, index, end; @@ -637,8 +634,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset, addr = index * hpage_size; /* mutex taken here, fault path and hole punch */ - hash = hugetlb_fault_mutex_hash(h, mm, &pseudo_vma, mapping, - index, addr); + hash = hugetlb_fault_mutex_hash(h, mapping, index, addr); mutex_lock(&hugetlb_fault_mutex_table[hash]); /* See if already present in mapping to avoid alloc/free */ diff --git a/fs/inode.c b/fs/inode.c index 1d1a9573ca70..e64f5e7a8813 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1804,8 +1804,13 @@ int file_remove_privs(struct file *file) int kill; int error = 0; - /* Fast path for nothing security related */ - if (IS_NOSEC(inode)) + /* + * Fast path for nothing security related. + * As well for non-regular files, e.g. blkdev inodes. + * For example, blkdev_write_iter() might get here + * trying to remove privs which it is not allowed to. + */ + if (IS_NOSEC(inode) || !S_ISREG(inode->i_mode)) return 0; kill = dentry_needs_remove_privs(dentry); diff --git a/fs/nfs/flexfilelayout/flexfilelayoutdev.c b/fs/nfs/flexfilelayout/flexfilelayoutdev.c index 90099896b838..c8863563c635 100644 --- a/fs/nfs/flexfilelayout/flexfilelayoutdev.c +++ b/fs/nfs/flexfilelayout/flexfilelayoutdev.c @@ -17,7 +17,7 @@ #define NFSDBG_FACILITY NFSDBG_PNFS_LD -static unsigned int dataserver_timeo = NFS_DEF_TCP_RETRANS; +static unsigned int dataserver_timeo = NFS_DEF_TCP_TIMEO; static unsigned int dataserver_retrans; void nfs4_ff_layout_put_deviceid(struct nfs4_ff_layout_ds *mirror_ds) diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index 0bf9e7bf5800..9140b9cf3870 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -116,8 +116,11 @@ void nfsd_put_raparams(struct file *file, struct raparms *ra); static inline int fh_want_write(struct svc_fh *fh) { - int ret = mnt_want_write(fh->fh_export->ex_path.mnt); + int ret; + if (fh->fh_want_write) + return 0; + ret = mnt_want_write(fh->fh_export->ex_path.mnt); if (!ret) fh->fh_want_write = true; return ret; diff --git a/fs/ocfs2/dcache.c b/fs/ocfs2/dcache.c index 290373024d9d..e8ace3b54e9c 100644 --- a/fs/ocfs2/dcache.c +++ b/fs/ocfs2/dcache.c @@ -310,6 +310,18 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, out_attach: spin_lock(&dentry_attach_lock); + if (unlikely(dentry->d_fsdata && !alias)) { + /* d_fsdata is set by a racing thread which is doing + * the same thing as this thread is doing. Leave the racing + * thread going ahead and we return here. + */ + spin_unlock(&dentry_attach_lock); + iput(dl->dl_inode); + ocfs2_lock_res_free(&dl->dl_lockres); + kfree(dl); + return 0; + } + dentry->d_fsdata = dl; dl->dl_count++; spin_unlock(&dentry_attach_lock); diff --git a/fs/open.c b/fs/open.c index e8818eaaacaf..a0fc37828943 100644 --- a/fs/open.c +++ b/fs/open.c @@ -1205,3 +1205,21 @@ int nonseekable_open(struct inode *inode, struct file *filp) } EXPORT_SYMBOL(nonseekable_open); + +/* + * stream_open is used by subsystems that want stream-like file descriptors. + * Such file descriptors are not seekable and don't have notion of position + * (file.f_pos is always 0). Contrary to file descriptors of other regular + * files, .read() and .write() can run simultaneously. + * + * stream_open never fails and is marked to return int so that it could be + * directly used as file_operations.open . + */ +int stream_open(struct inode *inode, struct file *filp) +{ + filp->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE | FMODE_ATOMIC_POS); + filp->f_mode |= FMODE_STREAM; + return 0; +} + +EXPORT_SYMBOL(stream_open); diff --git a/fs/pipe.c b/fs/pipe.c index 388e09a689de..347c6dc888c8 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -193,9 +193,9 @@ EXPORT_SYMBOL(generic_pipe_buf_steal); * in the tee() system call, when we duplicate the buffers in one * pipe into another. */ -void generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) +bool generic_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { - get_page(buf->page); + return try_get_page(buf->page); } EXPORT_SYMBOL(generic_pipe_buf_get); diff --git a/fs/proc/array.c b/fs/proc/array.c index 712b44c63701..9682bbf325d6 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -448,7 +448,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, * a program is not able to use ptrace(2) in that case. It is * safe because the task has stopped executing permanently. */ - if (permitted && (task->flags & PF_DUMPCORE)) { + if (permitted && (task->flags & (PF_EXITING|PF_DUMPCORE))) { if (try_get_task_stack(task)) { eip = KSTK_EIP(task); esp = KSTK_ESP(task); diff --git a/fs/read_write.c b/fs/read_write.c index ce77e76a6c89..901231269242 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -572,12 +572,13 @@ EXPORT_SYMBOL(vfs_write); static inline loff_t file_pos_read(struct file *file) { - return file->f_pos; + return file->f_mode & FMODE_STREAM ? 0 : file->f_pos; } static inline void file_pos_write(struct file *file, loff_t pos) { - file->f_pos = pos; + if ((file->f_mode & FMODE_STREAM) == 0) + file->f_pos = pos; } SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) diff --git a/fs/splice.c b/fs/splice.c index 01983bea760c..8bfbc8a50164 100644 --- a/fs/splice.c +++ b/fs/splice.c @@ -1585,7 +1585,11 @@ retry: * Get a reference to this pipe buffer, * so we can copy the contents over. */ - pipe_buf_get(ipipe, ibuf); + if (!pipe_buf_get(ipipe, ibuf)) { + if (ret == 0) + ret = -EFAULT; + break; + } *obuf = *ibuf; /* @@ -1659,7 +1663,11 @@ static int link_pipe(struct pipe_inode_info *ipipe, * Get a reference to this pipe buffer, * so we can copy the contents over. */ - pipe_buf_get(ipipe, ibuf); + if (!pipe_buf_get(ipipe, ibuf)) { + if (ret == 0) + ret = -EFAULT; + break; + } obuf = opipe->bufs + nbuf; *obuf = *ibuf; diff --git a/fs/udf/inode.c b/fs/udf/inode.c index fd817022cb9b..9e66d85021fc 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c @@ -478,13 +478,15 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block, return NULL; } -/* Extend the file by 'blocks' blocks, return the number of extents added */ +/* Extend the file with new blocks totaling 'new_block_bytes', + * return the number of extents added + */ static int udf_do_extend_file(struct inode *inode, struct extent_position *last_pos, struct kernel_long_ad *last_ext, - sector_t blocks) + loff_t new_block_bytes) { - sector_t add; + uint32_t add; int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); struct super_block *sb = inode->i_sb; struct kernel_lb_addr prealloc_loc = {}; @@ -494,7 +496,7 @@ static int udf_do_extend_file(struct inode *inode, /* The previous extent is fake and we should not extend by anything * - there's nothing to do... */ - if (!blocks && fake) + if (!new_block_bytes && fake) return 0; iinfo = UDF_I(inode); @@ -525,13 +527,12 @@ static int udf_do_extend_file(struct inode *inode, /* Can we merge with the previous extent? */ if ((last_ext->extLength & UDF_EXTENT_FLAG_MASK) == EXT_NOT_RECORDED_NOT_ALLOCATED) { - add = ((1 << 30) - sb->s_blocksize - - (last_ext->extLength & UDF_EXTENT_LENGTH_MASK)) >> - sb->s_blocksize_bits; - if (add > blocks) - add = blocks; - blocks -= add; - last_ext->extLength += add << sb->s_blocksize_bits; + add = (1 << 30) - sb->s_blocksize - + (last_ext->extLength & UDF_EXTENT_LENGTH_MASK); + if (add > new_block_bytes) + add = new_block_bytes; + new_block_bytes -= add; + last_ext->extLength += add; } if (fake) { @@ -552,28 +553,27 @@ static int udf_do_extend_file(struct inode *inode, } /* Managed to do everything necessary? */ - if (!blocks) + if (!new_block_bytes) goto out; /* All further extents will be NOT_RECORDED_NOT_ALLOCATED */ last_ext->extLocation.logicalBlockNum = 0; last_ext->extLocation.partitionReferenceNum = 0; - add = (1 << (30-sb->s_blocksize_bits)) - 1; - last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | - (add << sb->s_blocksize_bits); + add = (1 << 30) - sb->s_blocksize; + last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | add; /* Create enough extents to cover the whole hole */ - while (blocks > add) { - blocks -= add; + while (new_block_bytes > add) { + new_block_bytes -= add; err = udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); if (err) return err; count++; } - if (blocks) { + if (new_block_bytes) { last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | - (blocks << sb->s_blocksize_bits); + new_block_bytes; err = udf_add_aext(inode, last_pos, &last_ext->extLocation, last_ext->extLength, 1); if (err) @@ -604,6 +604,24 @@ out: return count; } +/* Extend the final block of the file to final_block_len bytes */ +static void udf_do_extend_final_block(struct inode *inode, + struct extent_position *last_pos, + struct kernel_long_ad *last_ext, + uint32_t final_block_len) +{ + struct super_block *sb = inode->i_sb; + uint32_t added_bytes; + + added_bytes = final_block_len - + (last_ext->extLength & (sb->s_blocksize - 1)); + last_ext->extLength += added_bytes; + UDF_I(inode)->i_lenExtents += added_bytes; + + udf_write_aext(inode, last_pos, &last_ext->extLocation, + last_ext->extLength, 1); +} + static int udf_extend_file(struct inode *inode, loff_t newsize) { @@ -613,10 +631,12 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) int8_t etype; struct super_block *sb = inode->i_sb; sector_t first_block = newsize >> sb->s_blocksize_bits, offset; + unsigned long partial_final_block; int adsize; struct udf_inode_info *iinfo = UDF_I(inode); struct kernel_long_ad extent; - int err; + int err = 0; + int within_final_block; if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) adsize = sizeof(struct short_ad); @@ -626,18 +646,8 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) BUG(); etype = inode_bmap(inode, first_block, &epos, &eloc, &elen, &offset); + within_final_block = (etype != -1); - /* File has extent covering the new size (could happen when extending - * inside a block)? */ - if (etype != -1) - return 0; - if (newsize & (sb->s_blocksize - 1)) - offset++; - /* Extended file just to the boundary of the last file block? */ - if (offset == 0) - return 0; - - /* Truncate is extending the file by 'offset' blocks */ if ((!epos.bh && epos.offset == udf_file_entry_alloc_offset(inode)) || (epos.bh && epos.offset == sizeof(struct allocExtDesc))) { /* File has no extents at all or has empty last @@ -651,7 +661,22 @@ static int udf_extend_file(struct inode *inode, loff_t newsize) &extent.extLength, 0); extent.extLength |= etype << 30; } - err = udf_do_extend_file(inode, &epos, &extent, offset); + + partial_final_block = newsize & (sb->s_blocksize - 1); + + /* File has extent covering the new size (could happen when extending + * inside a block)? + */ + if (within_final_block) { + /* Extending file within the last file block */ + udf_do_extend_final_block(inode, &epos, &extent, + partial_final_block); + } else { + loff_t add = ((loff_t)offset << sb->s_blocksize_bits) | + partial_final_block; + err = udf_do_extend_file(inode, &epos, &extent, add); + } + if (err < 0) goto out; err = 0; @@ -756,6 +781,7 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, /* Are we beyond EOF? */ if (etype == -1) { int ret; + loff_t hole_len; isBeyondEOF = true; if (count) { if (c) @@ -771,7 +797,8 @@ static sector_t inode_getblk(struct inode *inode, sector_t block, startnum = (offset > 0); } /* Create extents for the hole between EOF and offset */ - ret = udf_do_extend_file(inode, &prev_epos, laarr, offset); + hole_len = (loff_t)offset << inode->i_blkbits; + ret = udf_do_extend_file(inode, &prev_epos, laarr, hole_len); if (ret < 0) { brelse(prev_epos.bh); brelse(cur_epos.bh); diff --git a/include/asm-generic/bug.h b/include/asm-generic/bug.h index 6f96247226a4..89f079d6b41b 100644 --- a/include/asm-generic/bug.h +++ b/include/asm-generic/bug.h @@ -47,6 +47,7 @@ struct bug_entry { #ifndef HAVE_ARCH_BUG #define BUG() do { \ printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \ + barrier_before_unreachable(); \ panic("BUG!"); \ } while (0) #endif diff --git a/include/linux/bio.h b/include/linux/bio.h index 0885c9ff8ba8..e65830342c75 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -245,7 +245,7 @@ static inline void bio_cnt_set(struct bio *bio, unsigned int count) { if (count != 1) { bio->bi_flags |= (1 << BIO_REFFED); - smp_mb__before_atomic(); + smp_mb(); } atomic_set(&bio->__bi_cnt, count); } diff --git a/include/linux/bitops.h b/include/linux/bitops.h index d4b167fc9ecb..76ad8a957ffa 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -58,7 +58,7 @@ static __always_inline unsigned long hweight_long(unsigned long w) */ static inline __u64 rol64(__u64 word, unsigned int shift) { - return (word << shift) | (word >> (64 - shift)); + return (word << (shift & 63)) | (word >> ((-shift) & 63)); } /** @@ -68,7 +68,7 @@ static inline __u64 rol64(__u64 word, unsigned int shift) */ static inline __u64 ror64(__u64 word, unsigned int shift) { - return (word >> shift) | (word << (64 - shift)); + return (word >> (shift & 63)) | (word << ((-shift) & 63)); } /** @@ -78,7 +78,7 @@ static inline __u64 ror64(__u64 word, unsigned int shift) */ static inline __u32 rol32(__u32 word, unsigned int shift) { - return (word << shift) | (word >> ((-shift) & 31)); + return (word << (shift & 31)) | (word >> ((-shift) & 31)); } /** @@ -88,7 +88,7 @@ static inline __u32 rol32(__u32 word, unsigned int shift) */ static inline __u32 ror32(__u32 word, unsigned int shift) { - return (word >> shift) | (word << (32 - shift)); + return (word >> (shift & 31)) | (word << ((-shift) & 31)); } /** @@ -98,7 +98,7 @@ static inline __u32 ror32(__u32 word, unsigned int shift) */ static inline __u16 rol16(__u16 word, unsigned int shift) { - return (word << shift) | (word >> (16 - shift)); + return (word << (shift & 15)) | (word >> ((-shift) & 15)); } /** @@ -108,7 +108,7 @@ static inline __u16 rol16(__u16 word, unsigned int shift) */ static inline __u16 ror16(__u16 word, unsigned int shift) { - return (word >> shift) | (word << (16 - shift)); + return (word >> (shift & 15)) | (word << ((-shift) & 15)); } /** @@ -118,7 +118,7 @@ static inline __u16 ror16(__u16 word, unsigned int shift) */ static inline __u8 rol8(__u8 word, unsigned int shift) { - return (word << shift) | (word >> (8 - shift)); + return (word << (shift & 7)) | (word >> ((-shift) & 7)); } /** @@ -128,7 +128,7 @@ static inline __u8 rol8(__u8 word, unsigned int shift) */ static inline __u8 ror8(__u8 word, unsigned int shift) { - return (word >> shift) | (word << (8 - shift)); + return (word >> (shift & 7)) | (word << ((-shift) & 7)); } /** diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 5a232e8c9267..f9a2c23a5363 100755 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h @@ -472,7 +472,7 @@ static inline struct cgroup_subsys_state *task_css(struct task_struct *task, * * Find the css for the (@task, @subsys_id) combination, increment a * reference on and return it. This function is guaranteed to return a - * valid css. + * valid css. The returned css may already have been offlined. */ static inline struct cgroup_subsys_state * task_get_css(struct task_struct *task, int subsys_id) @@ -482,7 +482,13 @@ task_get_css(struct task_struct *task, int subsys_id) rcu_read_lock(); while (true) { css = task_css(task, subsys_id); - if (likely(css_tryget_online(css))) + /* + * Can't use css_tryget_online() here. A task which has + * PF_EXITING set may stay associated with an offline css. + * If such task calls this function, css_tryget_online() + * will keep failing. + */ + if (likely(css_tryget(css))) break; cpu_relax(); } diff --git a/include/linux/compiler-gcc.h b/include/linux/compiler-gcc.h index 8e9b0cb8db41..61650c1830d4 100644 --- a/include/linux/compiler-gcc.h +++ b/include/linux/compiler-gcc.h @@ -234,6 +234,15 @@ #endif /* + * calling noreturn functions, __builtin_unreachable() and __builtin_trap() + * confuse the stack allocation in gcc, leading to overly large stack + * frames, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82365 + * + * Adding an empty inline assembly before it works around the problem + */ +#define barrier_before_unreachable() asm volatile("") + +/* * Mark a position in code as unreachable. This can be used to * suppress control flow warnings after asm blocks that transfer * control elsewhere. @@ -243,7 +252,11 @@ * unreleased. Really, we need to have autoconf for the kernel. */ #define unreachable() \ - do { annotate_unreachable(); __builtin_unreachable(); } while (0) + do { \ + annotate_unreachable(); \ + barrier_before_unreachable(); \ + __builtin_unreachable(); \ + } while (0) /* Mark a function definition as prohibited from being cloned. */ #define __noclone __attribute__((__noclone__, __optimize__("no-tracer"))) diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 7385c7f1b60d..51c2f5b5b0e0 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -177,6 +177,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); # define barrier_data(ptr) barrier() #endif +/* workaround for GCC PR82365 if needed */ +#ifndef barrier_before_unreachable +# define barrier_before_unreachable() do { } while (0) +#endif + /* Unreachable code */ #ifndef unreachable # define unreachable() do { } while (1) diff --git a/include/linux/cpu.h b/include/linux/cpu.h index fcdc27cf73d4..b2547d96e24c 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -273,11 +273,15 @@ extern enum cpuhp_smt_control cpu_smt_control; extern void cpu_smt_disable(bool force); extern void cpu_smt_check_topology_early(void); extern void cpu_smt_check_topology(void); +extern int cpuhp_smt_enable(void); +extern int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval); #else # define cpu_smt_control (CPU_SMT_ENABLED) static inline void cpu_smt_disable(bool force) { } static inline void cpu_smt_check_topology_early(void) { } static inline void cpu_smt_check_topology(void) { } +static inline int cpuhp_smt_enable(void) { return 0; } +static inline int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { return 0; } #endif /* diff --git a/include/linux/fs.h b/include/linux/fs.h index 9ca212118bf1..1877a8e48603 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -144,6 +144,9 @@ typedef int (dio_iodone_t)(struct kiocb *iocb, loff_t offset, /* Has write method(s) */ #define FMODE_CAN_WRITE ((__force fmode_t)0x40000) +/* File is stream-like */ +#define FMODE_STREAM ((__force fmode_t)0x200000) + /* File was opened by fanotify and shouldn't generate fanotify events */ #define FMODE_NONOTIFY ((__force fmode_t)0x4000000) @@ -2887,6 +2890,7 @@ extern loff_t no_seek_end_llseek_size(struct file *, loff_t, int, loff_t); extern loff_t no_seek_end_llseek(struct file *, loff_t, int); extern int generic_file_open(struct inode * inode, struct file * filp); extern int nonseekable_open(struct inode * inode, struct file * filp); +extern int stream_open(struct inode * inode, struct file * filp); #ifdef CONFIG_BLOCK typedef void (dio_submit_t)(struct bio *bio, struct inode *inode, diff --git a/include/linux/hid.h b/include/linux/hid.h index fab65b61d6d4..04bdf5477ec5 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -374,6 +374,7 @@ struct hid_global { struct hid_local { unsigned usage[HID_MAX_USAGES]; /* usage array */ + u8 usage_size[HID_MAX_USAGES]; /* usage size array */ unsigned collection_index[HID_MAX_USAGES]; /* collection index array */ unsigned usage_index; unsigned usage_minimum; diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index b699d59d0f4f..6b8a7b654771 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -92,9 +92,7 @@ void putback_active_hugepage(struct page *page); void free_huge_page(struct page *page); void hugetlb_fix_reserve_counts(struct inode *inode); extern struct mutex *hugetlb_fault_mutex_table; -u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm, - struct vm_area_struct *vma, - struct address_space *mapping, +u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping, pgoff_t idx, unsigned long address); pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud); diff --git a/include/linux/iio/adc/ad_sigma_delta.h b/include/linux/iio/adc/ad_sigma_delta.h index 6cc48ac55fd2..40b14736c73d 100644 --- a/include/linux/iio/adc/ad_sigma_delta.h +++ b/include/linux/iio/adc/ad_sigma_delta.h @@ -66,6 +66,7 @@ struct ad_sigma_delta { bool irq_dis; bool bus_locked; + bool keep_cs_asserted; uint8_t comm; diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h index fa7fd03cb5f9..f2e966937e39 100644 --- a/include/linux/list_lru.h +++ b/include/linux/list_lru.h @@ -51,6 +51,7 @@ struct list_lru { struct list_lru_node *node; #if defined(CONFIG_MEMCG) && !defined(CONFIG_SLOB) struct list_head list; + bool memcg_aware; #endif }; diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index fd77f8303ab9..5fbbfa6ce1f2 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -494,17 +494,6 @@ struct mem_cgroup *lock_page_memcg(struct page *page); void __unlock_page_memcg(struct mem_cgroup *memcg); void unlock_page_memcg(struct page *page); -static inline void __mem_cgroup_update_page_stat(struct page *page, - struct mem_cgroup *memcg, - enum mem_cgroup_stat_index idx, - int val) -{ - VM_BUG_ON(!(rcu_read_lock_held() || PageLocked(page))); - - if (memcg && memcg->stat) - this_cpu_add(memcg->stat->count[idx], val); -} - /** * mem_cgroup_update_page_stat - update page state statistics * @page: the page @@ -520,12 +509,13 @@ static inline void __mem_cgroup_update_page_stat(struct page *page, * mem_cgroup_update_page_stat(page, state, -1); * unlock_page(page) or unlock_page_memcg(page) */ - static inline void mem_cgroup_update_page_stat(struct page *page, enum mem_cgroup_stat_index idx, int val) { + VM_BUG_ON(!(rcu_read_lock_held() || PageLocked(page))); - __mem_cgroup_update_page_stat(page, page->mem_cgroup, idx, val); + if (page->mem_cgroup) + this_cpu_add(page->mem_cgroup->stat->count[idx], val); } static inline void mem_cgroup_inc_page_stat(struct page *page, @@ -540,6 +530,27 @@ static inline void mem_cgroup_dec_page_stat(struct page *page, mem_cgroup_update_page_stat(page, idx, -1); } +static inline void mem_cgroup_update_stat(struct mem_cgroup *memcg, + enum mem_cgroup_stat_index idx, int val) +{ + VM_BUG_ON(!(rcu_read_lock_held())); + + if (memcg) + this_cpu_add(memcg->stat->count[idx], val); +} + +static inline void mem_cgroup_inc_stat(struct mem_cgroup *memcg, + enum mem_cgroup_stat_index idx) +{ + mem_cgroup_update_stat(memcg, idx, 1); +} + +static inline void mem_cgroup_dec_stat(struct mem_cgroup *memcg, + enum mem_cgroup_stat_index idx) +{ + mem_cgroup_update_stat(memcg, idx, -1); +} + unsigned long mem_cgroup_soft_limit_reclaim(pg_data_t *pgdat, int order, gfp_t gfp_mask, unsigned long *total_scanned); @@ -761,13 +772,6 @@ static inline void mem_cgroup_update_page_stat(struct page *page, { } -static inline void __mem_cgroup_update_page_stat(struct page *page, - struct mem_cgroup *memcg, - enum mem_cgroup_stat_index idx, - int nr) -{ -} - static inline void mem_cgroup_inc_page_stat(struct page *page, enum mem_cgroup_stat_index idx) { @@ -794,6 +798,11 @@ static inline void mem_cgroup_count_vm_event(struct mm_struct *mm, enum vm_event_item idx) { } + +static inline void mem_cgroup_dec_stat(struct mem_cgroup *memcg, + enum mem_cgroup_stat_index idx) +{ +} #endif /* CONFIG_MEMCG */ #ifdef CONFIG_CGROUP_WRITEBACK diff --git a/include/linux/mm.h b/include/linux/mm.h index 309f1654e591..e25ecba26d5d 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -782,6 +782,10 @@ static inline bool is_zone_device_page(const struct page *page) } #endif +/* 127: arbitrary random number, small enough to assemble well */ +#define page_ref_zero_or_close_to_overflow(page) \ + ((unsigned int) page_ref_count(page) + 127u <= 127u) + static inline void get_page(struct page *page) { page = compound_head(page); @@ -789,7 +793,7 @@ static inline void get_page(struct page *page) * Getting a normal page or the head of a compound page * requires to already have an elevated page->_refcount. */ - VM_BUG_ON_PAGE(page_ref_count(page) <= 0, page); + VM_BUG_ON_PAGE(page_ref_zero_or_close_to_overflow(page), page); page_ref_inc(page); if (unlikely(is_zone_device_page(page))) diff --git a/include/linux/pipe_fs_i.h b/include/linux/pipe_fs_i.h index 4f7129389855..c6ae0d5e9f0f 100644 --- a/include/linux/pipe_fs_i.h +++ b/include/linux/pipe_fs_i.h @@ -107,18 +107,20 @@ struct pipe_buf_operations { /* * Get a reference to the pipe buffer. */ - void (*get)(struct pipe_inode_info *, struct pipe_buffer *); + bool (*get)(struct pipe_inode_info *, struct pipe_buffer *); }; /** * pipe_buf_get - get a reference to a pipe_buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer to get a reference to + * + * Return: %true if the reference was successfully obtained. */ -static inline void pipe_buf_get(struct pipe_inode_info *pipe, +static inline __must_check bool pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { - buf->ops->get(pipe, buf); + return buf->ops->get(pipe, buf); } /** @@ -178,7 +180,7 @@ struct pipe_inode_info *alloc_pipe_info(void); void free_pipe_info(struct pipe_inode_info *); /* Generic pipe buffer ops functions */ -void generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); +bool generic_pipe_buf_get(struct pipe_inode_info *, struct pipe_buffer *); int generic_pipe_buf_confirm(struct pipe_inode_info *, struct pipe_buffer *); int generic_pipe_buf_steal(struct pipe_inode_info *, struct pipe_buffer *); void generic_pipe_buf_release(struct pipe_inode_info *, struct pipe_buffer *); diff --git a/include/linux/pwm.h b/include/linux/pwm.h index b40287e0ce16..ef2743cc3390 100644 --- a/include/linux/pwm.h +++ b/include/linux/pwm.h @@ -776,7 +776,6 @@ static inline void pwm_remove_table(struct pwm_lookup *table, size_t num) #ifdef CONFIG_PWM_SYSFS void pwmchip_sysfs_export(struct pwm_chip *chip); void pwmchip_sysfs_unexport(struct pwm_chip *chip); -void pwmchip_sysfs_unexport_children(struct pwm_chip *chip); #else static inline void pwmchip_sysfs_export(struct pwm_chip *chip) { @@ -785,10 +784,6 @@ static inline void pwmchip_sysfs_export(struct pwm_chip *chip) static inline void pwmchip_sysfs_unexport(struct pwm_chip *chip) { } - -static inline void pwmchip_sysfs_unexport_children(struct pwm_chip *chip) -{ -} #endif /* CONFIG_PWM_SYSFS */ #endif /* __LINUX_PWM_H */ diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 01f71e1d2e94..aa2935779e43 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -306,14 +306,12 @@ void synchronize_rcu(void); static inline void __rcu_read_lock(void) { - if (IS_ENABLED(CONFIG_PREEMPT_COUNT)) - preempt_disable(); + preempt_disable(); } static inline void __rcu_read_unlock(void) { - if (IS_ENABLED(CONFIG_PREEMPT_COUNT)) - preempt_enable(); + preempt_enable(); } static inline void synchronize_rcu(void) diff --git a/include/linux/smpboot.h b/include/linux/smpboot.h index 12910cf19869..12a4b09f4d08 100644 --- a/include/linux/smpboot.h +++ b/include/linux/smpboot.h @@ -30,7 +30,7 @@ struct smpboot_thread_data; * @thread_comm: The base name of the thread */ struct smp_hotplug_thread { - struct task_struct __percpu **store; + struct task_struct * __percpu *store; struct list_head list; int (*thread_should_run)(unsigned int cpu); void (*thread_fn)(unsigned int cpu); diff --git a/include/linux/tcp.h b/include/linux/tcp.h index b8ea15ad3790..4fd7dd9f26fe 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -434,4 +434,7 @@ static inline void tcp_saved_syn_free(struct tcp_sock *tp) tp->saved_syn = NULL; } +int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, int pcount, + int shiftlen); + #endif /* _LINUX_TCP_H */ diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h index 1bd31a38c51e..ce13d4677f1d 100644 --- a/include/linux/vmw_vmci_defs.h +++ b/include/linux/vmw_vmci_defs.h @@ -75,9 +75,18 @@ enum { /* * A single VMCI device has an upper limit of 128MB on the amount of - * memory that can be used for queue pairs. + * memory that can be used for queue pairs. Since each queue pair + * consists of at least two pages, the memory limit also dictates the + * number of queue pairs a guest can create. */ #define VMCI_MAX_GUEST_QP_MEMORY (128 * 1024 * 1024) +#define VMCI_MAX_GUEST_QP_COUNT (VMCI_MAX_GUEST_QP_MEMORY / PAGE_SIZE / 2) + +/* + * There can be at most PAGE_SIZE doorbells since there is one doorbell + * per byte in the doorbell bitmap page. + */ +#define VMCI_MAX_GUEST_DOORBELL_COUNT PAGE_SIZE /* * Queues with pre-mapped data pages must be small, so that we don't pin diff --git a/include/net/arp.h b/include/net/arp.h index 1b3f86981757..92d2f7d7d1cb 100644 --- a/include/net/arp.h +++ b/include/net/arp.h @@ -17,6 +17,7 @@ static inline u32 arp_hashfn(const void *pkey, const struct net_device *dev, u32 return val * hash_rnd[0]; } +#ifdef CONFIG_INET static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) { if (dev->flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) @@ -24,6 +25,13 @@ static inline struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev return ___neigh_lookup_noref(&arp_tbl, neigh_key_eq32, arp_hashfn, &key, dev); } +#else +static inline +struct neighbour *__ipv4_neigh_lookup_noref(struct net_device *dev, u32 key) +{ + return NULL; +} +#endif static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 key) { diff --git a/include/net/ip6_tunnel.h b/include/net/ip6_tunnel.h index 1b1cf33cbfb0..2b6abd046087 100644 --- a/include/net/ip6_tunnel.h +++ b/include/net/ip6_tunnel.h @@ -149,9 +149,12 @@ static inline void ip6tunnel_xmit(struct sock *sk, struct sk_buff *skb, memset(skb->cb, 0, sizeof(struct inet6_skb_parm)); pkt_len = skb->len - skb_inner_network_offset(skb); err = ip6_local_out(dev_net(skb_dst(skb)->dev), sk, skb); - if (unlikely(net_xmit_eval(err))) - pkt_len = -1; - iptunnel_xmit_stats(dev, pkt_len); + + if (dev) { + if (unlikely(net_xmit_eval(err))) + pkt_len = -1; + iptunnel_xmit_stats(dev, pkt_len); + } } #endif #endif diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h index 7adf4386ac8f..bf619a67ec03 100644 --- a/include/net/netns/ipv4.h +++ b/include/net/netns/ipv4.h @@ -94,6 +94,7 @@ struct netns_ipv4 { #endif int sysctl_tcp_mtu_probing; int sysctl_tcp_base_mss; + int sysctl_tcp_min_snd_mss; int sysctl_tcp_probe_threshold; u32 sysctl_tcp_probe_interval; diff --git a/include/net/tcp.h b/include/net/tcp.h index 96c2b19a1e88..6b7f98827918 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -53,6 +53,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo); #define MAX_TCP_HEADER (128 + MAX_HEADER) #define MAX_TCP_OPTION_SPACE 40 +#define TCP_MIN_SND_MSS 48 +#define TCP_MIN_GSO_SIZE (TCP_MIN_SND_MSS - MAX_TCP_OPTION_SPACE) /* * Never offer a window over 32767 without using window scaling. Some diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h index f6fc1e0d5fea..855c13dc32bf 100644 --- a/include/soc/qcom/socinfo.h +++ b/include/soc/qcom/socinfo.h @@ -144,6 +144,8 @@ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9650") #define early_machine_is_qm215() \ of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qm215") +#define early_machine_is_qcm2150() \ + of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,qcm2150") #else #define of_board_is_sim() 0 #define of_board_is_rumi() 0 @@ -204,6 +206,7 @@ #define early_machine_is_sdm429w() 0 #define early_machine_is_mdm9650() 0 #define early_machine_is_qm215() 0 +#define early_machine_is_qcm2150() 0 #define early_machine_is_sdm712() 0 #endif @@ -289,6 +292,7 @@ enum msm_cpu { MSM_CPU_SDM429W, MSM_CPU_9650, MSM_CPU_QM215, + MSM_CPU_QCM2150, }; struct msm_soc_info { diff --git a/include/trace/events/android_fs.h b/include/trace/events/android_fs.h index 49509533d3fa..0ee4a07f0240 100644 --- a/include/trace/events/android_fs.h +++ b/include/trace/events/android_fs.h @@ -25,6 +25,15 @@ DEFINE_EVENT(android_fs_data_end_template, android_fs_datawrite_end, TP_PROTO(struct inode *inode, loff_t offset, int bytes), TP_ARGS(inode, offset, bytes)); +DEFINE_EVENT(android_fs_fsync_start_template, android_fs_fsync_start, + TP_PROTO(struct inode *inode, + pid_t pid, char *pathname, char *command), + TP_ARGS(inode, pid, pathname, command)); + +DEFINE_EVENT(android_fs_data_end_template, android_fs_fsync_end, + TP_PROTO(struct inode *inode, loff_t offset, int bytes), + TP_ARGS(inode, offset, bytes)); + #endif /* _TRACE_ANDROID_FS_H */ /* This part must be outside protection */ diff --git a/include/trace/events/android_fs_template.h b/include/trace/events/android_fs_template.h index b23d17b56c63..0832c26acaed 100644 --- a/include/trace/events/android_fs_template.h +++ b/include/trace/events/android_fs_template.h @@ -61,4 +61,38 @@ DECLARE_EVENT_CLASS(android_fs_data_end_template, __entry->offset, __entry->bytes) ); +DECLARE_EVENT_CLASS(android_fs_fsync_start_template, + TP_PROTO(struct inode *inode, + pid_t pid, char *pathname, char *command), + TP_ARGS(inode, pid, pathname, command), + TP_STRUCT__entry( + __string(pathbuf, pathname); + __field(loff_t, i_size); + __string(cmdline, command); + __field(pid_t, pid); + __field(ino_t, ino); + ), + TP_fast_assign( + { + /* + * Replace the spaces in filenames and cmdlines + * because this screws up the tooling that parses + * the traces. + */ + __assign_str(pathbuf, pathname); + (void)strreplace(__get_str(pathbuf), ' ', '_'); + __entry->i_size = i_size_read(inode); + __assign_str(cmdline, command); + (void)strreplace(__get_str(cmdline), ' ', '_'); + __entry->pid = pid; + __entry->ino = inode->i_ino; + } + ), + TP_printk("entry_name %s, cmdline %s," + " pid %d, i_size %llu, ino %lu", + __get_str(pathbuf), + __get_str(cmdline), __entry->pid, __entry->i_size, + (unsigned long) __entry->ino) +); + #endif /* _TRACE_ANDROID_FS_TEMPLATE_H */ diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 03725fe89859..02137b508666 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -756,7 +756,7 @@ struct drm_i915_gem_execbuffer2 { __u32 num_cliprects; /** This is a struct drm_clip_rect *cliprects */ __u64 cliprects_ptr; -#define I915_EXEC_RING_MASK (7<<0) +#define I915_EXEC_RING_MASK (0x3f) #define I915_EXEC_DEFAULT (0<<0) #define I915_EXEC_RENDER (1<<0) #define I915_EXEC_BSD (2<<0) diff --git a/include/uapi/linux/fuse.h b/include/uapi/linux/fuse.h index e645f17027a0..56186b6bbf18 100644 --- a/include/uapi/linux/fuse.h +++ b/include/uapi/linux/fuse.h @@ -215,10 +215,12 @@ struct fuse_file_lock { * FOPEN_DIRECT_IO: bypass page cache for this open file * FOPEN_KEEP_CACHE: don't invalidate the data cache on open * FOPEN_NONSEEKABLE: the file is not seekable + * FOPEN_STREAM: the file is stream-like (no file position at all) */ #define FOPEN_DIRECT_IO (1 << 0) #define FOPEN_KEEP_CACHE (1 << 1) #define FOPEN_NONSEEKABLE (1 << 2) +#define FOPEN_STREAM (1 << 4) /** * INIT request/reply flags diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index 3c810c2ceccf..73d65a6718ba 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -334,11 +334,14 @@ enum ipa_client_type { IPA_CLIENT_MHI2_PROD = 86, IPA_CLIENT_MHI2_CONS = 87, + + IPA_CLIENT_Q6_CV2X_PROD = 88, + IPA_CLIENT_Q6_CV2X_CONS = 89, }; #define IPA_CLIENT_DUMMY_CONS IPA_CLIENT_DUMMY_CONS1 #define IPA_CLIENT_WIGIG4_CONS IPA_CLIENT_WIGIG4_CONS -#define IPA_CLIENT_MAX (IPA_CLIENT_MHI2_CONS + 1) +#define IPA_CLIENT_MAX (IPA_CLIENT_Q6_CV2X_CONS + 1) #define IPA_CLIENT_IS_APPS_CONS(client) \ ((client) == IPA_CLIENT_APPS_LAN_CONS || \ @@ -367,20 +370,23 @@ enum ipa_client_type { (client) == IPA_CLIENT_Q6_DUN_CONS || \ (client) == IPA_CLIENT_Q6_DECOMP_CONS || \ (client) == IPA_CLIENT_Q6_DECOMP2_CONS || \ - (client) == IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS) + (client) == IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS || \ + (client) == IPA_CLIENT_Q6_CV2X_CONS) #define IPA_CLIENT_IS_Q6_PROD(client) \ ((client) == IPA_CLIENT_Q6_LAN_PROD || \ (client) == IPA_CLIENT_Q6_WAN_PROD || \ (client) == IPA_CLIENT_Q6_CMD_PROD || \ (client) == IPA_CLIENT_Q6_DECOMP_PROD || \ - (client) == IPA_CLIENT_Q6_DECOMP2_PROD) + (client) == IPA_CLIENT_Q6_DECOMP2_PROD || \ + (client) == IPA_CLIENT_Q6_CV2X_PROD) #define IPA_CLIENT_IS_Q6_NON_ZIP_CONS(client) \ ((client) == IPA_CLIENT_Q6_LAN_CONS || \ (client) == IPA_CLIENT_Q6_WAN_CONS || \ (client) == IPA_CLIENT_Q6_DUN_CONS || \ - (client) == IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS) + (client) == IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS || \ + (client) == IPA_CLIENT_Q6_CV2X_CONS) #define IPA_CLIENT_IS_Q6_ZIP_CONS(client) \ ((client) == IPA_CLIENT_Q6_DECOMP_CONS || \ @@ -389,7 +395,8 @@ enum ipa_client_type { #define IPA_CLIENT_IS_Q6_NON_ZIP_PROD(client) \ ((client) == IPA_CLIENT_Q6_LAN_PROD || \ (client) == IPA_CLIENT_Q6_WAN_PROD || \ - (client) == IPA_CLIENT_Q6_CMD_PROD) + (client) == IPA_CLIENT_Q6_CMD_PROD || \ + (client) == IPA_CLIENT_Q6_CV2X_PROD) #define IPA_CLIENT_IS_Q6_ZIP_PROD(client) \ ((client) == IPA_CLIENT_Q6_DECOMP_PROD || \ @@ -411,6 +418,8 @@ enum ipa_client_type { #define IPA_CLIENT_IS_MHI(client) \ ((client) == IPA_CLIENT_MHI_CONS || \ (client) == IPA_CLIENT_MHI_PROD || \ + (client) == IPA_CLIENT_MHI2_PROD || \ + (client) == IPA_CLIENT_MHI2_CONS || \ (client) == IPA_CLIENT_MHI_DPL_CONS) #define IPA_CLIENT_IS_TEST_PROD(client) \ diff --git a/include/uapi/linux/nilfs2_ondisk.h b/include/uapi/linux/nilfs2_ondisk.h index 2a8a3addb675..f9b6b5be7ddf 100644 --- a/include/uapi/linux/nilfs2_ondisk.h +++ b/include/uapi/linux/nilfs2_ondisk.h @@ -28,7 +28,7 @@ #include <linux/types.h> #include <linux/magic.h> - +#include <asm/byteorder.h> #define NILFS_INODE_BMAP_SIZE 7 @@ -532,19 +532,19 @@ enum { static inline void \ nilfs_checkpoint_set_##name(struct nilfs_checkpoint *cp) \ { \ - cp->cp_flags = cpu_to_le32(le32_to_cpu(cp->cp_flags) | \ - (1UL << NILFS_CHECKPOINT_##flag)); \ + cp->cp_flags = __cpu_to_le32(__le32_to_cpu(cp->cp_flags) | \ + (1UL << NILFS_CHECKPOINT_##flag)); \ } \ static inline void \ nilfs_checkpoint_clear_##name(struct nilfs_checkpoint *cp) \ { \ - cp->cp_flags = cpu_to_le32(le32_to_cpu(cp->cp_flags) & \ + cp->cp_flags = __cpu_to_le32(__le32_to_cpu(cp->cp_flags) & \ ~(1UL << NILFS_CHECKPOINT_##flag)); \ } \ static inline int \ nilfs_checkpoint_##name(const struct nilfs_checkpoint *cp) \ { \ - return !!(le32_to_cpu(cp->cp_flags) & \ + return !!(__le32_to_cpu(cp->cp_flags) & \ (1UL << NILFS_CHECKPOINT_##flag)); \ } @@ -594,20 +594,20 @@ enum { static inline void \ nilfs_segment_usage_set_##name(struct nilfs_segment_usage *su) \ { \ - su->su_flags = cpu_to_le32(le32_to_cpu(su->su_flags) | \ + su->su_flags = __cpu_to_le32(__le32_to_cpu(su->su_flags) | \ (1UL << NILFS_SEGMENT_USAGE_##flag));\ } \ static inline void \ nilfs_segment_usage_clear_##name(struct nilfs_segment_usage *su) \ { \ su->su_flags = \ - cpu_to_le32(le32_to_cpu(su->su_flags) & \ + __cpu_to_le32(__le32_to_cpu(su->su_flags) & \ ~(1UL << NILFS_SEGMENT_USAGE_##flag)); \ } \ static inline int \ nilfs_segment_usage_##name(const struct nilfs_segment_usage *su) \ { \ - return !!(le32_to_cpu(su->su_flags) & \ + return !!(__le32_to_cpu(su->su_flags) & \ (1UL << NILFS_SEGMENT_USAGE_##flag)); \ } @@ -618,15 +618,15 @@ NILFS_SEGMENT_USAGE_FNS(ERROR, error) static inline void nilfs_segment_usage_set_clean(struct nilfs_segment_usage *su) { - su->su_lastmod = cpu_to_le64(0); - su->su_nblocks = cpu_to_le32(0); - su->su_flags = cpu_to_le32(0); + su->su_lastmod = __cpu_to_le64(0); + su->su_nblocks = __cpu_to_le32(0); + su->su_flags = __cpu_to_le32(0); } static inline int nilfs_segment_usage_clean(const struct nilfs_segment_usage *su) { - return !le32_to_cpu(su->su_flags); + return !__le32_to_cpu(su->su_flags); } /** diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h index 3442a26d36d9..56e3460d1f9f 100644 --- a/include/uapi/linux/snmp.h +++ b/include/uapi/linux/snmp.h @@ -282,6 +282,7 @@ enum LINUX_MIB_TCPKEEPALIVE, /* TCPKeepAlive */ LINUX_MIB_TCPMTUPFAIL, /* TCPMTUPFail */ LINUX_MIB_TCPMTUPSUCCESS, /* TCPMTUPSuccess */ + LINUX_MIB_TCPWQUEUETOOBIG, /* TCPWqueueTooBig */ __LINUX_MIB_MAX }; diff --git a/include/uapi/linux/tipc_config.h b/include/uapi/linux/tipc_config.h index 087b0ef82c07..bbebd258cf07 100644 --- a/include/uapi/linux/tipc_config.h +++ b/include/uapi/linux/tipc_config.h @@ -301,8 +301,10 @@ static inline int TLV_SET(void *tlv, __u16 type, void *data, __u16 len) tlv_ptr = (struct tlv_desc *)tlv; tlv_ptr->tlv_type = htons(type); tlv_ptr->tlv_len = htons(tlv_len); - if (len && data) - memcpy(TLV_DATA(tlv_ptr), data, tlv_len); + if (len && data) { + memcpy(TLV_DATA(tlv_ptr), data, len); + memset(TLV_DATA(tlv_ptr) + len, 0, TLV_SPACE(len) - tlv_len); + } return TLV_SPACE(len); } @@ -399,8 +401,10 @@ static inline int TCM_SET(void *msg, __u16 cmd, __u16 flags, tcm_hdr->tcm_len = htonl(msg_len); tcm_hdr->tcm_type = htons(cmd); tcm_hdr->tcm_flags = htons(flags); - if (data_len && data) + if (data_len && data) { memcpy(TCM_DATA(msg), data, data_len); + memset(TCM_DATA(msg) + data_len, 0, TCM_SPACE(data_len) - msg_len); + } return TCM_SPACE(data_len); } diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h index 7489b72031b7..50d95c4da9d8 100644 --- a/include/uapi/media/cam_isp.h +++ b/include/uapi/media/cam_isp.h @@ -84,14 +84,16 @@ #define CAM_ISP_DSP_MODE_ROUND 2 /* ISP Generic Cmd Buffer Blob types */ -#define CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG 0 -#define CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 -#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG 2 -#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG 3 -#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 4 -#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 5 -#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 6 -#define CAM_ISP_GENERIC_BLOB_TYPE_INIT_FRAME_DROP 10 +#define CAM_ISP_GENERIC_BLOB_TYPE_HFR_CONFIG 0 +#define CAM_ISP_GENERIC_BLOB_TYPE_CLOCK_CONFIG 1 +#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG 2 +#define CAM_ISP_GENERIC_BLOB_TYPE_UBWC_CONFIG 3 +#define CAM_ISP_GENERIC_BLOB_TYPE_CSID_CLOCK_CONFIG 4 +#define CAM_ISP_GENERIC_BLOB_TYPE_FE_CONFIG 5 +#define CAM_ISP_GENERIC_BLOB_TYPE_BW_CONFIG_V2 6 +#define CAM_ISP_GENERIC_BLOB_TYPE_INIT_FRAME_DROP 10 +#define CAM_ISP_GENERIC_BLOB_TYPE_SENSOR_DIMENSION_CONFIG 11 +#define CAM_ISP_GENERIC_BLOB_TYPE_FPS_CONFIG 12 /* Per Path Usage Data */ #define CAM_ISP_USAGE_INVALID 0 @@ -464,6 +466,36 @@ struct cam_fe_config { uint32_t latency_buf_size; } __attribute__((packed)); +/** + * struct cam_isp_sensor_path_dimension + * + * @width expected width + * @height expected height + * @measure_enabled flag to indicate if pixel measurement is to be enabled + */ +struct cam_isp_sensor_dimension { + uint32_t width; + uint32_t height; + uint32_t measure_enabled; +} __attribute__((packed)); + +/** + * struct cam_isp_sensor_config - Sensor Dimension configuration + * + * @pix_path: expected ppp path configuration + * @pix_path: expected ipp path configuration + * @rdi_path: expected rdi path configuration + * @hbi: HBI value + * @vbi: VBI value + */ +struct cam_isp_sensor_config { + struct cam_isp_sensor_dimension ppp_path; + struct cam_isp_sensor_dimension ipp_path; + struct cam_isp_sensor_dimension rdi_path[4]; + uint32_t hbi; + uint32_t vbi; +} __attribute__((packed)); + /* Acquire Device/HW v2 */ /** @@ -489,6 +521,15 @@ struct cam_isp_acquire_hw_info { uint64_t data; }; +/** + * struct cam_fps_config - FPS blob support + * + * @fps: FPS value + */ +struct cam_fps_config { + uint32_t fps; +} __attribute__((packed)); + #define CAM_ISP_ACQUIRE_COMMON_VER0 0x1000 #define CAM_ISP_ACQUIRE_COMMON_SIZE_VER0 0x0 diff --git a/init/Kconfig b/init/Kconfig index 158e2c15a791..dddd37832eec 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -860,6 +860,15 @@ config IKCONFIG_PROC This option enables access to the kernel configuration file through /proc/config.gz. +config IKHEADERS + tristate "Enable kernel headers through /sys/kernel/kheaders.tar.xz" + depends on SYSFS + help + This option enables access to the in-kernel headers that are generated during + the build process. These can be used to build eBPF tracing programs, + or similar programs. If you build the headers as a module, a module called + kheaders.ko is built which can be loaded on-demand to get access to headers. + config LOG_BUF_SHIFT int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" range 12 25 diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 02fb438fd3af..7d8b2918746e 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -371,7 +371,8 @@ static void mqueue_evict_inode(struct inode *inode) struct user_struct *user; unsigned long mq_bytes, mq_treesize; struct ipc_namespace *ipc_ns; - struct msg_msg *msg; + struct msg_msg *msg, *nmsg; + LIST_HEAD(tmp_msg); clear_inode(inode); @@ -382,10 +383,15 @@ static void mqueue_evict_inode(struct inode *inode) info = MQUEUE_I(inode); spin_lock(&info->lock); while ((msg = msg_get(info)) != NULL) - free_msg(msg); + list_add_tail(&msg->m_list, &tmp_msg); kfree(info->node_cache); spin_unlock(&info->lock); + list_for_each_entry_safe(msg, nmsg, &tmp_msg, m_list) { + list_del(&msg->m_list); + free_msg(msg); + } + /* Total amount of bytes accounted for the mqueue */ mq_treesize = info->attr.mq_maxmsg * sizeof(struct msg_msg) + min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) * diff --git a/ipc/msgutil.c b/ipc/msgutil.c index bf74eaa5c39f..6d90b191c638 100644 --- a/ipc/msgutil.c +++ b/ipc/msgutil.c @@ -18,6 +18,7 @@ #include <linux/utsname.h> #include <linux/proc_ns.h> #include <linux/uaccess.h> +#include <linux/sched.h> #include "util.h" @@ -64,6 +65,9 @@ static struct msg_msg *alloc_msg(size_t len) pseg = &msg->next; while (len > 0) { struct msg_msgseg *seg; + + cond_resched(); + alen = min(len, DATALEN_SEG); seg = kmalloc(sizeof(*seg) + alen, GFP_KERNEL_ACCOUNT); if (seg == NULL) @@ -176,6 +180,8 @@ void free_msg(struct msg_msg *msg) kfree(msg); while (seg != NULL) { struct msg_msgseg *tmp = seg->next; + + cond_resched(); kfree(seg); seg = tmp; } diff --git a/kernel/.gitignore b/kernel/.gitignore index b3097bde4e9c..084572ac1290 100644 --- a/kernel/.gitignore +++ b/kernel/.gitignore @@ -3,5 +3,6 @@ # config_data.h config_data.gz +kheaders.md5 timeconst.h hz.bc diff --git a/kernel/Makefile b/kernel/Makefile index 108f5bee0111..29071ac3c66b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -28,6 +28,7 @@ KCOV_INSTRUMENT_extable.o := n # Don't self-instrument. KCOV_INSTRUMENT_kcov.o := n KASAN_SANITIZE_kcov.o := n +CFLAGS_kcov.o := $(call cc-option, -fno-conserve-stack -fno-stack-protector) # cond_syscall is currently not LTO compatible CFLAGS_sys_ni.o = $(DISABLE_LTO) @@ -75,6 +76,7 @@ obj-$(CONFIG_UTS_NS) += utsname.o obj-$(CONFIG_USER_NS) += user_namespace.o obj-$(CONFIG_PID_NS) += pid_namespace.o obj-$(CONFIG_IKCONFIG) += configs.o +obj-$(CONFIG_IKHEADERS) += kheaders.o obj-$(CONFIG_SMP) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o @@ -130,3 +132,12 @@ $(obj)/config_data.gz: $(KCONFIG_CONFIG) FORCE targets += config_data.h $(obj)/config_data.h: $(obj)/config_data.gz FORCE $(call filechk,ikconfiggz) + +$(obj)/kheaders.o: $(obj)/kheaders_data.tar.xz + +quiet_cmd_genikh = CHK $(obj)/kheaders_data.tar.xz +cmd_genikh = $(CONFIG_SHELL) $(srctree)/kernel/gen_kheaders.sh $@ +$(obj)/kheaders_data.tar.xz: FORCE + $(call cmd,genikh) + +clean-files := kheaders_data.tar.xz kheaders.md5 diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index cd4f41397c7e..42b7251c597f 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c @@ -1095,22 +1095,24 @@ int audit_rule_change(int type, __u32 portid, int seq, void *data, int err = 0; struct audit_entry *entry; - entry = audit_data_to_entry(data, datasz); - if (IS_ERR(entry)) - return PTR_ERR(entry); - switch (type) { case AUDIT_ADD_RULE: + entry = audit_data_to_entry(data, datasz); + if (IS_ERR(entry)) + return PTR_ERR(entry); err = audit_add_rule(entry); audit_log_rule_change("add_rule", &entry->rule, !err); break; case AUDIT_DEL_RULE: + entry = audit_data_to_entry(data, datasz); + if (IS_ERR(entry)) + return PTR_ERR(entry); err = audit_del_rule(entry); audit_log_rule_change("remove_rule", &entry->rule, !err); break; default: - err = -EINVAL; WARN_ON(1); + return -EINVAL; } if (err || type == AUDIT_DEL_RULE) { diff --git a/kernel/cpu.c b/kernel/cpu.c index 641fc19ead27..f102c4d6e952 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -2064,7 +2064,7 @@ static void cpuhp_online_cpu_device(unsigned int cpu) kobject_uevent(&dev->kobj, KOBJ_ONLINE); } -static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) +int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) { int cpu, ret = 0; @@ -2098,7 +2098,7 @@ static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval) return ret; } -static int cpuhp_smt_enable(void) +int cpuhp_smt_enable(void) { int cpu, ret = 0; @@ -2322,6 +2322,9 @@ static int __init mitigations_parse_cmdline(char *arg) cpu_mitigations = CPU_MITIGATIONS_AUTO; else if (!strcmp(arg, "auto,nosmt")) cpu_mitigations = CPU_MITIGATIONS_AUTO_NOSMT; + else + pr_crit("Unsupported mitigations=%s, system may still be vulnerable\n", + arg); return 0; } diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 2714a17c80a9..df64cb9ba63a 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -420,14 +420,19 @@ static struct cpuset *alloc_trial_cpuset(struct cpuset *cs) if (!alloc_cpumask_var(&trial->cpus_allowed, GFP_KERNEL)) goto free_cs; + if (!alloc_cpumask_var(&trial->cpus_requested, GFP_KERNEL)) + goto free_allowed; if (!alloc_cpumask_var(&trial->effective_cpus, GFP_KERNEL)) goto free_cpus; cpumask_copy(trial->cpus_allowed, cs->cpus_allowed); + cpumask_copy(trial->cpus_requested, cs->cpus_requested); cpumask_copy(trial->effective_cpus, cs->effective_cpus); return trial; free_cpus: + free_cpumask_var(trial->cpus_requested); +free_allowed: free_cpumask_var(trial->cpus_allowed); free_cs: kfree(trial); @@ -441,6 +446,7 @@ free_cs: static void free_trial_cpuset(struct cpuset *trial) { free_cpumask_var(trial->effective_cpus); + free_cpumask_var(trial->cpus_requested); free_cpumask_var(trial->cpus_allowed); kfree(trial); } @@ -963,23 +969,23 @@ static int update_cpumask(struct cpuset *cs, struct cpuset *trialcs, return -EACCES; /* - * An empty cpus_allowed is ok only if the cpuset has no tasks. + * An empty cpus_requested is ok only if the cpuset has no tasks. * Since cpulist_parse() fails on an empty mask, we special case * that parsing. The validate_change() call ensures that cpusets * with tasks have cpus. */ if (!*buf) { - cpumask_clear(trialcs->cpus_allowed); + cpumask_clear(trialcs->cpus_requested); } else { retval = cpulist_parse(buf, trialcs->cpus_requested); if (retval < 0) return retval; + } - if (!cpumask_subset(trialcs->cpus_requested, cpu_present_mask)) - return -EINVAL; + if (!cpumask_subset(trialcs->cpus_requested, cpu_present_mask)) + return -EINVAL; - cpumask_and(trialcs->cpus_allowed, trialcs->cpus_requested, cpu_active_mask); - } + cpumask_and(trialcs->cpus_allowed, trialcs->cpus_requested, cpu_active_mask); /* Nothing to do if the cpus didn't change */ if (cpumask_equal(cs->cpus_requested, trialcs->cpus_requested)) diff --git a/kernel/cred.c b/kernel/cred.c index 5f264fb5737d..7b925925be95 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -447,6 +447,15 @@ int commit_creds(struct cred *new) if (task->mm) set_dumpable(task->mm, suid_dumpable); task->pdeath_signal = 0; + /* + * If a task drops privileges and becomes nondumpable, + * the dumpability change must become visible before + * the credential change; otherwise, a __ptrace_may_access() + * racing with this change may be able to attach to a task it + * shouldn't be able to attach to (as if the task had dropped + * privileges without becoming nondumpable). + * Pairs with a read barrier in __ptrace_may_access(). + */ smp_wmb(); } diff --git a/kernel/events/core.c b/kernel/events/core.c index 1dbbc811d139..f990ddc9074c 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5668,7 +5668,7 @@ static void perf_sample_regs_user(struct perf_regs *regs_user, if (user_mode(regs)) { regs_user->abi = perf_reg_abi(current); regs_user->regs = regs; - } else if (current->mm) { + } else if (!(current->flags & PF_KTHREAD)) { perf_get_regs_user(regs_user, regs, regs_user_copy); } else { regs_user->abi = PERF_SAMPLE_REGS_ABI_NONE; diff --git a/kernel/events/ring_buffer.c b/kernel/events/ring_buffer.c index 99becab2c1ce..8e8b903b7613 100644 --- a/kernel/events/ring_buffer.c +++ b/kernel/events/ring_buffer.c @@ -49,14 +49,30 @@ static void perf_output_put_handle(struct perf_output_handle *handle) unsigned long head; again: + /* + * In order to avoid publishing a head value that goes backwards, + * we must ensure the load of @rb->head happens after we've + * incremented @rb->nest. + * + * Otherwise we can observe a @rb->head value before one published + * by an IRQ/NMI happening between the load and the increment. + */ + barrier(); head = local_read(&rb->head); /* - * IRQ/NMI can happen here, which means we can miss a head update. + * IRQ/NMI can happen here and advance @rb->head, causing our + * load above to be stale. */ - if (!local_dec_and_test(&rb->nest)) + /* + * If this isn't the outermost nesting, we don't have to update + * @rb->user_page->data_head. + */ + if (local_read(&rb->nest) > 1) { + local_dec(&rb->nest); goto out; + } /* * Since the mmap() consumer (userspace) can run on a different CPU: @@ -88,9 +104,18 @@ again: rb->user_page->data_head = head; /* - * Now check if we missed an update -- rely on previous implied - * compiler barriers to force a re-read. + * We must publish the head before decrementing the nest count, + * otherwise an IRQ/NMI can publish a more recent head value and our + * write will (temporarily) publish a stale value. + */ + barrier(); + local_set(&rb->nest, 0); + + /* + * Ensure we decrement @rb->nest before we validate the @rb->head. + * Otherwise we cannot be sure we caught the 'last' nested update. */ + barrier(); if (unlikely(head != local_read(&rb->head))) { local_inc(&rb->nest); goto again; diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh new file mode 100755 index 000000000000..9a34e1d9bd7f --- /dev/null +++ b/kernel/gen_kheaders.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0 + +# This script generates an archive consisting of kernel headers +# for CONFIG_IKHEADERS. +set -e +spath="$(dirname "$(readlink -f "$0")")" +kroot="$spath/.." +outdir="$(pwd)" +tarfile=$1 +cpio_dir=$outdir/$tarfile.tmp + +# Script filename relative to the kernel source root +# We add it to the archive because it is small and any changes +# to this script will also cause a rebuild of the archive. +sfile="$(realpath --relative-to $kroot "$(readlink -f "$0")")" + +src_file_list=" +include/ +arch/$SRCARCH/include/ +$sfile +" + +obj_file_list=" +include/ +arch/$SRCARCH/include/ +" + +# Support incremental builds by skipping archive generation +# if timestamps of files being archived are not changed. + +# This block is useful for debugging the incremental builds. +# Uncomment it for debugging. +# if [ ! -f /tmp/iter ]; then iter=1; echo 1 > /tmp/iter; +# else iter=$(($(cat /tmp/iter) + 1)); echo $iter > /tmp/iter; fi +# find $src_file_list -type f | xargs ls -lR > /tmp/src-ls-$iter +# find $obj_file_list -type f | xargs ls -lR > /tmp/obj-ls-$iter + +# include/generated/compile.h is ignored because it is touched even when none +# of the source files changed. This causes pointless regeneration, so let us +# ignore them for md5 calculation. +pushd $kroot > /dev/null +src_files_md5="$(find $src_file_list -type f | + grep -v "include/generated/compile.h" | + grep -v "include/generated/autoconf.h" | + grep -v "include/config/auto.conf" | + grep -v "include/config/auto.conf.cmd" | + grep -v "include/config/tristate.conf" | + xargs ls -lR | md5sum | cut -d ' ' -f1)" +popd > /dev/null +obj_files_md5="$(find $obj_file_list -type f | + grep -v "include/generated/compile.h" | + grep -v "include/generated/autoconf.h" | + grep -v "include/config/auto.conf" | + grep -v "include/config/auto.conf.cmd" | + grep -v "include/config/tristate.conf" | + xargs ls -lR | md5sum | cut -d ' ' -f1)" + +if [ -f $tarfile ]; then tarfile_md5="$(md5sum $tarfile | cut -d ' ' -f1)"; fi +if [ -f kernel/kheaders.md5 ] && + [ "$(cat kernel/kheaders.md5|head -1)" == "$src_files_md5" ] && + [ "$(cat kernel/kheaders.md5|head -2|tail -1)" == "$obj_files_md5" ] && + [ "$(cat kernel/kheaders.md5|tail -1)" == "$tarfile_md5" ]; then + exit +fi + +if [ "${quiet}" != "silent_" ]; then + echo " GEN $tarfile" +fi + +rm -rf $cpio_dir +mkdir $cpio_dir + +pushd $kroot > /dev/null +for f in $src_file_list; + do find "$f" ! -name "*.cmd" ! -name ".*"; +done | cpio --quiet -pd $cpio_dir +popd > /dev/null + +# The second CPIO can complain if files already exist which can +# happen with out of tree builds. Just silence CPIO for now. +for f in $obj_file_list; + do find "$f" ! -name "*.cmd" ! -name ".*"; +done | cpio --quiet -pd $cpio_dir >/dev/null 2>&1 + +# Remove comments except SDPX lines +find $cpio_dir -type f -print0 | + xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;' + +tar -Jcf $tarfile -C $cpio_dir/ . > /dev/null + +echo "$src_files_md5" > kernel/kheaders.md5 +echo "$obj_files_md5" >> kernel/kheaders.md5 +echo "$(md5sum $tarfile | cut -d ' ' -f1)" >> kernel/kheaders.md5 + +rm -rf $cpio_dir diff --git a/kernel/kheaders.c b/kernel/kheaders.c new file mode 100644 index 000000000000..8f69772af77b --- /dev/null +++ b/kernel/kheaders.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Provide kernel headers useful to build tracing programs + * such as for running eBPF tracing tools. + * + * (Borrowed code from kernel/configs.c) + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/kobject.h> +#include <linux/init.h> + +/* + * Define kernel_headers_data and kernel_headers_data_end, within which the + * compressed kernel headers are stored. The file is first compressed with xz. + */ + +asm ( +" .pushsection .rodata, \"a\" \n" +" .global kernel_headers_data \n" +"kernel_headers_data: \n" +" .incbin \"kernel/kheaders_data.tar.xz\" \n" +" .global kernel_headers_data_end \n" +"kernel_headers_data_end: \n" +" .popsection \n" +); + +extern char kernel_headers_data; +extern char kernel_headers_data_end; + +static ssize_t +ikheaders_read(struct file *file, struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t len) +{ + memcpy(buf, &kernel_headers_data + off, len); + return len; +} + +static struct bin_attribute kheaders_attr __ro_after_init = { + .attr = { + .name = "kheaders.tar.xz", + .mode = 0444, + }, + .read = &ikheaders_read, +}; + +static int __init ikheaders_init(void) +{ + kheaders_attr.size = (&kernel_headers_data_end - + &kernel_headers_data); + return sysfs_create_bin_file(kernel_kobj, &kheaders_attr); +} + +static void __exit ikheaders_cleanup(void) +{ + sysfs_remove_bin_file(kernel_kobj, &kheaders_attr); +} + +module_init(ikheaders_init); +module_exit(ikheaders_cleanup); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Joel Fernandes"); +MODULE_DESCRIPTION("Echo the kernel header artifacts used to build the kernel"); diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c index b26dbc48c75b..81695a492ebe 100644 --- a/kernel/power/hibernate.c +++ b/kernel/power/hibernate.c @@ -256,6 +256,11 @@ void swsusp_show_speed(ktime_t start, ktime_t stop, kps / 1000, (kps % 1000) / 10); } +__weak int arch_resume_nosmt(void) +{ + return 0; +} + /** * create_image - Create a hibernation image. * @platform_mode: Whether or not to use the platform driver. @@ -322,6 +327,10 @@ static int create_image(int platform_mode) Enable_cpus: enable_nonboot_cpus(); + /* Allow architectures to do nosmt-specific post-resume dances */ + if (!in_suspend) + error = arch_resume_nosmt(); + Platform_finish: platform_finish(platform_mode); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index efba851ee018..ea3370e205fb 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -74,9 +74,7 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent, */ static void ptrace_link(struct task_struct *child, struct task_struct *new_parent) { - rcu_read_lock(); - __ptrace_link(child, new_parent, __task_cred(new_parent)); - rcu_read_unlock(); + __ptrace_link(child, new_parent, current_cred()); } /** @@ -322,6 +320,16 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) return -EPERM; ok: rcu_read_unlock(); + /* + * If a task drops privileges and becomes nondumpable (through a syscall + * like setresuid()) while we are trying to access it, we must ensure + * that the dumpability is read after the credentials; otherwise, + * we may be able to attach to a task that we shouldn't be able to + * attach to (as if the task had dropped privileges without becoming + * nondumpable). + * Pairs with a write barrier in commit_creds(). + */ + smp_rmb(); mm = task->mm; if (mm && ((get_dumpable(mm) != SUID_DUMP_USER) && @@ -710,6 +718,10 @@ static int ptrace_peek_siginfo(struct task_struct *child, if (arg.nr < 0) return -EINVAL; + /* Ensure arg.off fits in an unsigned long */ + if (arg.off > ULONG_MAX) + return 0; + if (arg.flags & PTRACE_PEEKSIGINFO_SHARED) pending = &child->signal->shared_pending; else @@ -717,18 +729,20 @@ static int ptrace_peek_siginfo(struct task_struct *child, for (i = 0; i < arg.nr; ) { siginfo_t info; - s32 off = arg.off + i; + unsigned long off = arg.off + i; + bool found = false; spin_lock_irq(&child->sighand->siglock); list_for_each_entry(q, &pending->list, list) { if (!off--) { + found = true; copy_siginfo(&info, &q->info); break; } } spin_unlock_irq(&child->sighand->siglock); - if (off >= 0) /* beyond the end of the list */ + if (!found) /* beyond the end of the list */ break; #ifdef CONFIG_COMPAT diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c index 123ccbd22449..2b8579d5a544 100644 --- a/kernel/rcu/rcuperf.c +++ b/kernel/rcu/rcuperf.c @@ -453,6 +453,10 @@ rcu_perf_cleanup(void) if (torture_cleanup_begin()) return; + if (!cur_ops) { + torture_cleanup_end(); + return; + } if (reader_tasks) { for (i = 0; i < nrealreaders; i++) @@ -574,6 +578,7 @@ rcu_perf_init(void) pr_alert(" %s", perf_ops[i]->name); pr_alert("\n"); firsterr = -EINVAL; + cur_ops = NULL; goto unwind; } if (cur_ops->init) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index bf08fee53dc7..5393bbcf3c1a 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -1595,6 +1595,10 @@ rcu_torture_cleanup(void) cur_ops->cb_barrier(); return; } + if (!cur_ops) { + torture_cleanup_end(); + return; + } rcu_torture_barrier_cleanup(); torture_stop_kthread(rcu_torture_stall, stall_task); @@ -1730,6 +1734,7 @@ rcu_torture_init(void) pr_alert(" %s", torture_ops[i]->name); pr_alert("\n"); firsterr = -EINVAL; + cur_ops = NULL; goto unwind; } if (cur_ops->fqs == NULL && fqs_duration != 0) { diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 5f10aebeda28..ef1bd778f088 100755 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -9235,6 +9235,8 @@ static void cpu_cgroup_attach(struct cgroup_taskset *tset) static int cpu_shares_write_u64(struct cgroup_subsys_state *css, struct cftype *cftype, u64 shareval) { + if (shareval > scale_load_down(ULONG_MAX)) + shareval = MAX_SHARES; return sched_group_set_shares(css_tg(css), scale_load(shareval)); } @@ -9334,8 +9336,10 @@ int tg_set_cfs_quota(struct task_group *tg, long cfs_quota_us) period = ktime_to_ns(tg->cfs_bandwidth.period); if (cfs_quota_us < 0) quota = RUNTIME_INF; - else + else if ((u64)cfs_quota_us <= U64_MAX / NSEC_PER_USEC) quota = (u64)cfs_quota_us * NSEC_PER_USEC; + else + return -EINVAL; return tg_set_cfs_bandwidth(tg, period, quota); } @@ -9357,6 +9361,9 @@ int tg_set_cfs_period(struct task_group *tg, long cfs_period_us) { u64 quota, period; + if ((u64)cfs_period_us > U64_MAX / NSEC_PER_USEC) + return -EINVAL; + period = (u64)cfs_period_us * NSEC_PER_USEC; quota = tg->cfs_bandwidth.quota; diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c index 0745029cf262..cfe4f40d5819 100644 --- a/kernel/sched/cpufreq_schedutil.c +++ b/kernel/sched/cpufreq_schedutil.c @@ -154,7 +154,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time, trace_cpu_frequency(next_freq, smp_processor_id()); } else { sg_policy->work_in_progress = true; - irq_work_queue(&sg_policy->irq_work); + sched_irq_work_queue(&sg_policy->irq_work); } } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 8b351c8624b9..e8faa552b684 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -2975,3 +2975,13 @@ find_first_cpu_bit(struct task_struct *p, const cpumask_t *search_cpus, #else #define find_first_cpu_bit(...) -1 #endif + +#ifdef CONFIG_SMP +static inline void sched_irq_work_queue(struct irq_work *work) +{ + if (likely(cpu_online(raw_smp_processor_id()))) + irq_work_queue(work); + else + irq_work_queue_on(work, cpumask_any(cpu_online_mask)); +} +#endif diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c index 9a85525bb4a3..c34311bb30cd 100644 --- a/kernel/sched/walt.c +++ b/kernel/sched/walt.c @@ -893,7 +893,7 @@ void fixup_busy_time(struct task_struct *p, int new_cpu) if (!same_freq_domain(new_cpu, task_cpu(p))) { src_rq->notif_pending = true; dest_rq->notif_pending = true; - irq_work_queue(&walt_migration_irq_work); + sched_irq_work_queue(&walt_migration_irq_work); } if (p == src_rq->ed_task) { @@ -1956,7 +1956,7 @@ static inline void run_walt_irq_work(u64 old_window_start, struct rq *rq) result = atomic64_cmpxchg(&walt_irq_work_lastq_ws, old_window_start, rq->window_start); if (result == old_window_start) - irq_work_queue(&walt_cpufreq_irq_work); + sched_irq_work_queue(&walt_cpufreq_irq_work); } /* Reflect task activity on its demand and cpu's busy time statistics */ diff --git a/kernel/signal.c b/kernel/signal.c index 92766f703c14..23113b8fa292 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2249,6 +2249,8 @@ relock: if (signal_group_exit(signal)) { ksig->info.si_signo = signr = SIGKILL; sigdelset(¤t->pending.signal, SIGKILL); + trace_signal_deliver(SIGKILL, SEND_SIG_NOINFO, + &sighand->action[SIGKILL - 1]); recalc_sigpending(); goto fatal; } diff --git a/kernel/sys.c b/kernel/sys.c index 181a7f0431c5..15cf3eea6f2e 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1765,7 +1765,7 @@ static int validate_prctl_map(struct prctl_mm_map *prctl_map) ((unsigned long)prctl_map->__m1 __op \ (unsigned long)prctl_map->__m2) ? 0 : -EINVAL error = __prctl_check_order(start_code, <, end_code); - error |= __prctl_check_order(start_data, <, end_data); + error |= __prctl_check_order(start_data,<=, end_data); error |= __prctl_check_order(start_brk, <=, brk); error |= __prctl_check_order(arg_start, <=, arg_end); error |= __prctl_check_order(env_start, <=, env_end); diff --git a/kernel/sysctl.c b/kernel/sysctl.c index a3c644662029..0dc8c07eb51d 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -2726,8 +2726,10 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int if (neg) continue; val = convmul * val / convdiv; - if ((min && val < *min) || (max && val > *max)) - continue; + if ((min && val < *min) || (max && val > *max)) { + err = -EINVAL; + break; + } *i = val; } else { val = convdiv * (*i) / convmul; diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c index 11e4af2fc2ee..d471752c373b 100644 --- a/kernel/time/hrtimer.c +++ b/kernel/time/hrtimer.c @@ -49,6 +49,7 @@ #include <linux/sched/deadline.h> #include <linux/timer.h> #include <linux/freezer.h> +#include <linux/delay.h> #include <asm/uaccess.h> @@ -149,6 +150,7 @@ struct hrtimer_clock_base *lock_hrtimer_base(const struct hrtimer *timer, raw_spin_unlock_irqrestore(&base->cpu_base->lock, *flags); } cpu_relax(); + ndelay(TIMER_LOCK_TIGHT_LOOP_DELAY_NS); } } @@ -1043,6 +1045,7 @@ int hrtimer_cancel(struct hrtimer *timer) if (ret >= 0) return ret; cpu_relax(); + ndelay(TIMER_LOCK_TIGHT_LOOP_DELAY_NS); } } EXPORT_SYMBOL_GPL(hrtimer_cancel); diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c index 6df8927c58a5..0a16419006f3 100644 --- a/kernel/time/ntp.c +++ b/kernel/time/ntp.c @@ -639,7 +639,7 @@ static inline void process_adjtimex_modes(struct timex *txc, time_constant = max(time_constant, 0l); } - if (txc->modes & ADJ_TAI && txc->constant > 0) + if (txc->modes & ADJ_TAI && txc->constant >= 0) *time_tai = txc->constant; if (txc->modes & ADJ_OFFSET) diff --git a/kernel/time/tick-internal.h b/kernel/time/tick-internal.h index f738251000fe..0059764b8dc7 100644 --- a/kernel/time/tick-internal.h +++ b/kernel/time/tick-internal.h @@ -165,3 +165,4 @@ DECLARE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases); extern u64 get_next_timer_interrupt(unsigned long basej, u64 basem); void timer_clear_idle(void); +#define TIMER_LOCK_TIGHT_LOOP_DELAY_NS 350 diff --git a/kernel/time/timer.c b/kernel/time/timer.c index af9a29ec90a6..018e2f5946ef 100644 --- a/kernel/time/timer.c +++ b/kernel/time/timer.c @@ -942,6 +942,7 @@ static struct timer_base *lock_timer_base(struct timer_list *timer, spin_unlock_irqrestore(&base->lock, *flags); } cpu_relax(); + ndelay(TIMER_LOCK_TIGHT_LOOP_DELAY_NS); } } @@ -1264,6 +1265,7 @@ int del_timer_sync(struct timer_list *timer) if (ret >= 0) return ret; cpu_relax(); + ndelay(TIMER_LOCK_TIGHT_LOOP_DELAY_NS); } } EXPORT_SYMBOL(del_timer_sync); diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 7cc06f267be5..c7aab158ea81 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -81,6 +81,35 @@ static const struct bpf_func_proto bpf_probe_read_proto = { .arg3_type = ARG_ANYTHING, }; +BPF_CALL_3(bpf_probe_read_str, void *, dst, u32, size, const void *, unsafe_ptr) +{ + int ret; + + /* + * The strncpy_from_unsafe() call will likely not fill the entire + * buffer, but that's okay in this circumstance as we're probing + * arbitrary memory anyway similar to bpf_probe_read() and might + * as well probe the stack. Thus, memory is explicitly cleared + * only in error case, so that improper users ignoring return + * code altogether don't copy garbage; otherwise length of string + * is returned that can be used for bpf_perf_event_output() et al. + */ + ret = strncpy_from_unsafe(dst, unsafe_ptr, size); + if (unlikely(ret < 0)) + memset(dst, 0, size); + + return ret; +} + +static const struct bpf_func_proto bpf_probe_read_str_proto = { + .func = bpf_probe_read_str, + .gpl_only = true, + .ret_type = RET_INTEGER, + .arg1_type = ARG_PTR_TO_RAW_STACK, + .arg2_type = ARG_CONST_STACK_SIZE, + .arg3_type = ARG_ANYTHING, +}; + BPF_CALL_3(bpf_probe_write_user, void *, unsafe_ptr, const void *, src, u32, size) { @@ -434,6 +463,8 @@ static const struct bpf_func_proto *tracing_func_proto(enum bpf_func_id func_id) return &bpf_map_delete_elem_proto; case BPF_FUNC_probe_read: return &bpf_probe_read_proto; + case BPF_FUNC_probe_read_str: + return &bpf_probe_read_str_proto; case BPF_FUNC_ktime_get_ns: return &bpf_ktime_get_ns_proto; case BPF_FUNC_tail_call: diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 7dba55cb2c2c..1c8f269f730d 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -6301,12 +6301,16 @@ static void buffer_pipe_buf_release(struct pipe_inode_info *pipe, buf->private = 0; } -static void buffer_pipe_buf_get(struct pipe_inode_info *pipe, +static bool buffer_pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf) { struct buffer_ref *ref = (struct buffer_ref *)buf->private; + if (ref->ref > INT_MAX/2) + return false; + ref->ref++; + return true; } /* Pipe buffer operations for a buffer. */ @@ -7768,12 +7772,8 @@ void ftrace_dump(enum ftrace_dump_mode oops_dump_mode) cnt++; - /* reset all but tr, trace, and overruns */ - memset(&iter.seq, 0, - sizeof(struct trace_iterator) - - offsetof(struct trace_iterator, seq)); + trace_iterator_reset(&iter); iter.iter_flags |= TRACE_FILE_LAT_FMT; - iter.pos = -1; if (trace_find_next_entry_inc(&iter) != NULL) { int ret; diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index e5d06c95de3f..5078a317e284 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h @@ -1681,4 +1681,22 @@ static inline void trace_event_enum_update(struct trace_enum_map **map, int len) extern struct trace_iterator *tracepoint_print_iter; +/* + * Reset the state of the trace_iterator so that it can read consumed data. + * Normally, the trace_iterator is used for reading the data when it is not + * consumed, and must retain state. + */ +static __always_inline void trace_iterator_reset(struct trace_iterator *iter) +{ + const size_t offset = offsetof(struct trace_iterator, seq); + + /* + * Keep gcc from complaining about overwriting more than just one + * member in the structure. + */ + memset((char *)iter + offset, 0, sizeof(struct trace_iterator) - offset); + + iter->pos = -1; +} + #endif /* _LINUX_KERNEL_TRACE_H */ diff --git a/kernel/trace/trace_kdb.c b/kernel/trace/trace_kdb.c index 896458285fdd..cf6337dc41f4 100644 --- a/kernel/trace/trace_kdb.c +++ b/kernel/trace/trace_kdb.c @@ -40,12 +40,8 @@ static void ftrace_dump_buf(int skip_lines, long cpu_file) kdb_printf("Dumping ftrace buffer:\n"); - /* reset all but tr, trace, and overruns */ - memset(&iter.seq, 0, - sizeof(struct trace_iterator) - - offsetof(struct trace_iterator, seq)); + trace_iterator_reset(&iter); iter.iter_flags |= TRACE_FILE_LAT_FMT; - iter.pos = -1; if (cpu_file == RING_BUFFER_ALL_CPUS) { for_each_tracing_cpu(cpu) { diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c index 468fb7cd1221..edf345b7f06b 100644 --- a/lib/mpi/mpi-pow.c +++ b/lib/mpi/mpi-pow.c @@ -37,6 +37,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) { mpi_ptr_t mp_marker = NULL, bp_marker = NULL, ep_marker = NULL; + struct karatsuba_ctx karactx = {}; mpi_ptr_t xp_marker = NULL; mpi_ptr_t tspace = NULL; mpi_ptr_t rp, ep, mp, bp; @@ -164,13 +165,11 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) int c; mpi_limb_t e; mpi_limb_t carry_limb; - struct karatsuba_ctx karactx; xp = xp_marker = mpi_alloc_limb_space(2 * (msize + 1)); if (!xp) goto enomem; - memset(&karactx, 0, sizeof karactx); negative_result = (ep[0] & 1) && base->sign; i = esize - 1; @@ -295,8 +294,6 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) if (mod_shift_cnt) mpihelp_rshift(rp, rp, rsize, mod_shift_cnt); MPN_NORMALIZE(rp, rsize); - - mpihelp_release_karatsuba_ctx(&karactx); } if (negative_result && rsize) { @@ -313,6 +310,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod) leave: rc = 0; enomem: + mpihelp_release_karatsuba_ctx(&karactx); if (assign_rp) mpi_assign_limb_space(res, rp, size); if (mp_marker) diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c index 7e35fc450c5b..5a07f19059c3 100644 --- a/lib/strncpy_from_user.c +++ b/lib/strncpy_from_user.c @@ -22,10 +22,11 @@ * hit it), 'max' is the address space maximum (and we return * -EFAULT if we hit it). */ -static inline long do_strncpy_from_user(char *dst, const char __user *src, long count, unsigned long max) +static inline long do_strncpy_from_user(char *dst, const char __user *src, + unsigned long count, unsigned long max) { const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; - long res = 0; + unsigned long res = 0; /* * Truncate 'max' to the user-specified limit, so that diff --git a/lib/strnlen_user.c b/lib/strnlen_user.c index 8e105ed4df12..9ff4f3bbb1aa 100644 --- a/lib/strnlen_user.c +++ b/lib/strnlen_user.c @@ -27,7 +27,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count, unsigned long max) { const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS; - long align, res = 0; + unsigned long align, res = 0; unsigned long c; /* @@ -41,7 +41,7 @@ static inline long do_strnlen_user(const char __user *src, unsigned long count, * Do everything aligned. But that means that we * need to also expand the maximum.. */ - align = (sizeof(long) - 1) & (unsigned long)src; + align = (sizeof(unsigned long) - 1) & (unsigned long)src; src -= align; max += align; @@ -130,8 +130,10 @@ static int __init cma_activate_area(struct cma *cma) cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL); - if (!cma->bitmap) + if (!cma->bitmap) { + cma->count = 0; return -ENOMEM; + } WARN_ON_ONCE(!pfn_valid(pfn)); zone = page_zone(pfn_to_page(pfn)); diff --git a/mm/cma_debug.c b/mm/cma_debug.c index 3f7f84c7ed2f..a7012893fb88 100644 --- a/mm/cma_debug.c +++ b/mm/cma_debug.c @@ -57,7 +57,7 @@ static int cma_maxchunk_get(void *data, u64 *val) mutex_lock(&cma->lock); for (;;) { start = find_next_zero_bit(cma->bitmap, bitmap_maxno, end); - if (start >= cma->count) + if (start >= bitmap_maxno) break; end = find_next_bit(cma->bitmap, bitmap_maxno, start); maxchunk = max(end - start, maxchunk); @@ -153,7 +153,10 @@ retry: } if (flags & FOLL_GET) { - get_page(page); + if (unlikely(!try_get_page(page))) { + page = ERR_PTR(-ENOMEM); + goto out; + } /* drop the pgmap reference now that we hold the page */ if (pgmap) { @@ -292,7 +295,10 @@ struct page *follow_page_mask(struct vm_area_struct *vma, if (pmd_trans_unstable(pmd)) ret = -EBUSY; } else { - get_page(page); + if (unlikely(!try_get_page(page))) { + spin_unlock(ptl); + return ERR_PTR(-ENOMEM); + } spin_unlock(ptl); lock_page(page); ret = split_huge_page(page); @@ -348,7 +354,10 @@ static int get_gate_page(struct mm_struct *mm, unsigned long address, goto unmap; *page = pte_page(*pte); } - get_page(*page); + if (unlikely(!try_get_page(*page))) { + ret = -ENOMEM; + goto unmap; + } out: ret = 0; unmap: @@ -1231,6 +1240,20 @@ struct page *get_dump_page(unsigned long addr) */ #ifdef CONFIG_HAVE_GENERIC_RCU_GUP +/* + * Return the compund head page with ref appropriately incremented, + * or NULL if that failed. + */ +static inline struct page *try_get_compound_head(struct page *page, int refs) +{ + struct page *head = compound_head(page); + if (WARN_ON_ONCE(page_ref_count(head) < 0)) + return NULL; + if (unlikely(!page_cache_add_speculative(head, refs))) + return NULL; + return head; +} + #ifdef __HAVE_ARCH_PTE_SPECIAL static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, int write, struct page **pages, int *nr) @@ -1263,9 +1286,9 @@ static int gup_pte_range(pmd_t pmd, unsigned long addr, unsigned long end, VM_BUG_ON(!pfn_valid(pte_pfn(pte))); page = pte_page(pte); - head = compound_head(page); - if (!page_cache_get_speculative(head)) + head = try_get_compound_head(page, 1); + if (!head) goto pte_unmap; if (unlikely(pte_val(pte) != pte_val(*ptep))) { @@ -1313,17 +1336,16 @@ static int gup_huge_pmd(pmd_t orig, pmd_t *pmdp, unsigned long addr, return 0; refs = 0; - head = pmd_page(orig); - page = head + ((addr & ~PMD_MASK) >> PAGE_SHIFT); + page = pmd_page(orig) + ((addr & ~PMD_MASK) >> PAGE_SHIFT); do { - VM_BUG_ON_PAGE(compound_head(page) != head, page); pages[*nr] = page; (*nr)++; page++; refs++; } while (addr += PAGE_SIZE, addr != end); - if (!page_cache_add_speculative(head, refs)) { + head = try_get_compound_head(pmd_page(orig), refs); + if (!head) { *nr -= refs; return 0; } @@ -1348,17 +1370,16 @@ static int gup_huge_pud(pud_t orig, pud_t *pudp, unsigned long addr, return 0; refs = 0; - head = pud_page(orig); - page = head + ((addr & ~PUD_MASK) >> PAGE_SHIFT); + page = pud_page(orig) + ((addr & ~PUD_MASK) >> PAGE_SHIFT); do { - VM_BUG_ON_PAGE(compound_head(page) != head, page); pages[*nr] = page; (*nr)++; page++; refs++; } while (addr += PAGE_SIZE, addr != end); - if (!page_cache_add_speculative(head, refs)) { + head = try_get_compound_head(pud_page(orig), refs); + if (!head) { *nr -= refs; return 0; } @@ -1384,17 +1405,16 @@ static int gup_huge_pgd(pgd_t orig, pgd_t *pgdp, unsigned long addr, return 0; refs = 0; - head = pgd_page(orig); - page = head + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); + page = pgd_page(orig) + ((addr & ~PGDIR_MASK) >> PAGE_SHIFT); do { - VM_BUG_ON_PAGE(compound_head(page) != head, page); pages[*nr] = page; (*nr)++; page++; refs++; } while (addr += PAGE_SIZE, addr != end); - if (!page_cache_add_speculative(head, refs)) { + head = try_get_compound_head(pgd_page(orig), refs); + if (!head) { *nr -= refs; return 0; } diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 8b682da98d95..9914da93069e 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -1247,12 +1247,23 @@ void free_huge_page(struct page *page) ClearPagePrivate(page); /* - * A return code of zero implies that the subpool will be under its - * minimum size if the reservation is not restored after page is free. - * Therefore, force restore_reserve operation. + * If PagePrivate() was set on page, page allocation consumed a + * reservation. If the page was associated with a subpool, there + * would have been a page reserved in the subpool before allocation + * via hugepage_subpool_get_pages(). Since we are 'restoring' the + * reservtion, do not call hugepage_subpool_put_pages() as this will + * remove the reserved page from the subpool. */ - if (hugepage_subpool_put_pages(spool, 1) == 0) - restore_reserve = true; + if (!restore_reserve) { + /* + * A return code of zero implies that the subpool will be + * under its minimum size if the reservation is not restored + * after page is free. Therefore, force restore_reserve + * operation. + */ + if (hugepage_subpool_put_pages(spool, 1) == 0) + restore_reserve = true; + } spin_lock(&hugetlb_lock); clear_page_huge_active(page); @@ -3812,21 +3823,14 @@ backout_unlocked: } #ifdef CONFIG_SMP -u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm, - struct vm_area_struct *vma, - struct address_space *mapping, +u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping, pgoff_t idx, unsigned long address) { unsigned long key[2]; u32 hash; - if (vma->vm_flags & VM_SHARED) { - key[0] = (unsigned long) mapping; - key[1] = idx; - } else { - key[0] = (unsigned long) mm; - key[1] = address >> huge_page_shift(h); - } + key[0] = (unsigned long) mapping; + key[1] = idx; hash = jhash2((u32 *)&key, sizeof(key)/sizeof(u32), 0); @@ -3837,9 +3841,7 @@ u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm, * For uniprocesor systems we always use a single mutex, so just * return 0 and avoid the hashing overhead. */ -u32 hugetlb_fault_mutex_hash(struct hstate *h, struct mm_struct *mm, - struct vm_area_struct *vma, - struct address_space *mapping, +u32 hugetlb_fault_mutex_hash(struct hstate *h, struct address_space *mapping, pgoff_t idx, unsigned long address) { return 0; @@ -3885,7 +3887,7 @@ int hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma, * get spurious allocation failures if two CPUs race to instantiate * the same page in the page cache. */ - hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, address); + hash = hugetlb_fault_mutex_hash(h, mapping, idx, address); mutex_lock(&hugetlb_fault_mutex_table[hash]); entry = huge_ptep_get(ptep); @@ -3993,6 +3995,7 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, unsigned long vaddr = *position; unsigned long remainder = *nr_pages; struct hstate *h = hstate_vma(vma); + int err = -EFAULT; while (vaddr < vma->vm_end && remainder) { pte_t *pte; @@ -4064,6 +4067,19 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma, pfn_offset = (vaddr & ~huge_page_mask(h)) >> PAGE_SHIFT; page = pte_page(huge_ptep_get(pte)); + + /* + * Instead of doing 'try_get_page()' below in the same_page + * loop, just check the count once here. + */ + if (unlikely(page_count(page) <= 0)) { + if (pages) { + spin_unlock(ptl); + remainder = 0; + err = -ENOMEM; + break; + } + } same_page: if (pages) { pages[i] = mem_map_offset(page, pfn_offset); @@ -4090,7 +4106,7 @@ same_page: *nr_pages = remainder; *position = vaddr; - return i ? i : -EFAULT; + return i ? i : err; } #ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE diff --git a/mm/list_lru.c b/mm/list_lru.c index 7a40fa2be858..16361c989af9 100644 --- a/mm/list_lru.c +++ b/mm/list_lru.c @@ -42,11 +42,7 @@ static void list_lru_unregister(struct list_lru *lru) #if defined(CONFIG_MEMCG) && !defined(CONFIG_SLOB) static inline bool list_lru_memcg_aware(struct list_lru *lru) { - /* - * This needs node 0 to be always present, even - * in the systems supporting sparse numa ids. - */ - return !!lru->node[0].memcg_lrus; + return lru->memcg_aware; } static inline struct list_lru_one * @@ -317,7 +313,7 @@ static int __memcg_init_list_lru_node(struct list_lru_memcg *memcg_lrus, } return 0; fail: - __memcg_destroy_list_lru_node(memcg_lrus, begin, i - 1); + __memcg_destroy_list_lru_node(memcg_lrus, begin, i); return -ENOMEM; } @@ -389,6 +385,8 @@ static int memcg_init_list_lru(struct list_lru *lru, bool memcg_aware) { int i; + lru->memcg_aware = memcg_aware; + if (!memcg_aware) return 0; diff --git a/mm/memblock.c b/mm/memblock.c index 3b7d23cdbaee..abaed7ae1597 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -929,7 +929,7 @@ void __init_memblock __next_mem_range(u64 *idx, int nid, ulong flags, r = &type_b->regions[idx_b]; r_start = idx_b ? r[-1].base + r[-1].size : 0; r_end = idx_b < type_b->cnt ? - r->base : ULLONG_MAX; + r->base : (phys_addr_t)ULLONG_MAX; /* * if idx_b advanced past idx_a, @@ -1045,7 +1045,7 @@ void __init_memblock __next_mem_range_rev(u64 *idx, int nid, ulong flags, r = &type_b->regions[idx_b]; r_start = idx_b ? r[-1].base + r[-1].size : 0; r_end = idx_b < type_b->cnt ? - r->base : ULLONG_MAX; + r->base : (phys_addr_t)ULLONG_MAX; /* * if idx_b advanced past idx_a, * break out to advance idx_a diff --git a/mm/mlock.c b/mm/mlock.c index f648acb0e1e7..a655a50cdc8d 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -633,11 +633,11 @@ static int apply_vma_lock_flags(unsigned long start, size_t len, * is also counted. * Return value: previously mlocked page counts */ -static int count_mm_mlocked_page_nr(struct mm_struct *mm, +static unsigned long count_mm_mlocked_page_nr(struct mm_struct *mm, unsigned long start, size_t len) { struct vm_area_struct *vma; - int count = 0; + unsigned long count = 0; if (mm == NULL) mm = current->mm; diff --git a/mm/page-writeback.c b/mm/page-writeback.c index 77bc0881dd1e..c047ff55207a 100644 --- a/mm/page-writeback.c +++ b/mm/page-writeback.c @@ -2735,6 +2735,7 @@ int test_clear_page_writeback(struct page *page) } else { ret = TestClearPageWriteback(page); } + /* * NOTE: Page might be free now! Writeback doesn't hold a page * reference on its own, it relies on truncation to wait for @@ -2742,8 +2743,7 @@ int test_clear_page_writeback(struct page *page) * page state that is static across allocation cycles. */ if (ret) { - __mem_cgroup_update_page_stat(page, memcg, - MEM_CGROUP_STAT_WRITEBACK, -1); + mem_cgroup_dec_stat(memcg, MEM_CGROUP_STAT_WRITEBACK); dec_node_page_state(page, NR_WRITEBACK); dec_zone_page_state(page, NR_ZONE_WRITE_PENDING); inc_node_page_state(page, NR_WRITTEN); diff --git a/mm/page_alloc.c b/mm/page_alloc.c index f77c4ced11cb..f07e0c95ca2c 100755 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -5642,13 +5642,15 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid, unsigned long *zone_end_pfn, unsigned long *ignored) { + unsigned long zone_low = arch_zone_lowest_possible_pfn[zone_type]; + unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type]; /* When hotadd a new node from cpu_up(), the node should be empty */ if (!node_start_pfn && !node_end_pfn) return 0; /* Get the start and end of the zone */ - *zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type]; - *zone_end_pfn = arch_zone_highest_possible_pfn[zone_type]; + *zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high); + *zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high); adjust_zone_range_for_zone_movable(nid, zone_type, node_start_pfn, node_end_pfn, zone_start_pfn, zone_end_pfn); diff --git a/mm/page_idle.c b/mm/page_idle.c index ae11aa914e55..ded173d6c5b5 100644 --- a/mm/page_idle.c +++ b/mm/page_idle.c @@ -131,7 +131,7 @@ static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj, end_pfn = pfn + count * BITS_PER_BYTE; if (end_pfn > max_pfn) - end_pfn = ALIGN(max_pfn, BITMAP_CHUNK_BITS); + end_pfn = max_pfn; for (; pfn < end_pfn; pfn++) { bit = pfn % BITMAP_CHUNK_BITS; @@ -176,7 +176,7 @@ static ssize_t page_idle_bitmap_write(struct file *file, struct kobject *kobj, end_pfn = pfn + count * BITS_PER_BYTE; if (end_pfn > max_pfn) - end_pfn = ALIGN(max_pfn, BITMAP_CHUNK_BITS); + end_pfn = max_pfn; for (; pfn < end_pfn; pfn++) { bit = pfn % BITMAP_CHUNK_BITS; diff --git a/mm/slab.c b/mm/slab.c index bd498eff4d73..a671328e0610 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -4362,8 +4362,12 @@ static int leaks_show(struct seq_file *m, void *p) * whole processing. */ do { - set_store_user_clean(cachep); drain_cpu_caches(cachep); + /* + * drain_cpu_caches() could make kmemleak_object and + * debug_objects_cache dirty, so reset afterwards. + */ + set_store_user_clean(cachep); x[1] = 0; diff --git a/net/9p/protocol.c b/net/9p/protocol.c index 7f1b45c082c9..ed1e39ccaebf 100644 --- a/net/9p/protocol.c +++ b/net/9p/protocol.c @@ -622,13 +622,19 @@ int p9dirent_read(struct p9_client *clnt, char *buf, int len, if (ret) { p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); trace_9p_protocol_dump(clnt, &fake_pdu); - goto out; + return ret; } - strcpy(dirent->d_name, nameptr); + ret = strscpy(dirent->d_name, nameptr, sizeof(dirent->d_name)); + if (ret < 0) { + p9_debug(P9_DEBUG_ERROR, + "On the wire dirent name too long: %s\n", + nameptr); + kfree(nameptr); + return ret; + } kfree(nameptr); -out: return fake_pdu.offset; } EXPORT_SYMBOL(p9dirent_read); diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index 38aa6345bdfa..9c0c894b56f8 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c @@ -14,6 +14,7 @@ #include <linux/mm.h> #include <linux/module.h> +#include "trans_common.h" /** * p9_release_req_pages - Release pages after the transaction. diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 5a2ad4707463..8e4313ad3f02 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -254,8 +254,7 @@ p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) case RDMA_CM_EVENT_DISCONNECTED: if (rdma) rdma->state = P9_RDMA_CLOSED; - if (c) - c->status = Disconnected; + c->status = Disconnected; break; case RDMA_CM_EVENT_TIMEWAIT_EXIT: @@ -454,7 +453,7 @@ static int rdma_request(struct p9_client *client, struct p9_req_t *req) err = post_recv(client, rpl_context); if (err) { - p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); + p9_debug(P9_DEBUG_ERROR, "POST RECV failed: %d\n", err); goto recv_error; } /* remove posted receive buffer from request structure */ @@ -523,7 +522,7 @@ dont_need_post_recv: recv_error: kfree(rpl_context); spin_lock_irqsave(&rdma->req_lock, flags); - if (rdma->state < P9_RDMA_CLOSING) { + if (err != -EINTR && rdma->state < P9_RDMA_CLOSING) { rdma->state = P9_RDMA_CLOSING; spin_unlock_irqrestore(&rdma->req_lock, flags); rdma_disconnect(rdma->cm_id); diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index 149f82bd83fd..6ba56f215229 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -443,9 +443,11 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) } if (ax25->sk != NULL) { + local_bh_disable(); bh_lock_sock(ax25->sk); sock_reset_flag(ax25->sk, SOCK_ZAPPED); bh_unlock_sock(ax25->sk); + local_bh_enable(); } put: diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index fe4fb0c1fa61..bd41b78d131d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1165,14 +1165,6 @@ int hci_conn_check_link_mode(struct hci_conn *conn) !test_bit(HCI_CONN_ENCRYPT, &conn->flags)) return 0; - /* The minimum encryption key size needs to be enforced by the - * host stack before establishing any L2CAP connections. The - * specification in theory allows a minimum of 1, but to align - * BR/EDR and LE transports, a minimum of 7 is chosen. - */ - if (conn->enc_key_size < HCI_MIN_ENC_KEY_SIZE) - return 0; - return 1; } @@ -1289,8 +1281,16 @@ auth: return 0; encrypt: - if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) + if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) { + /* Ensure that the encryption key size has been read, + * otherwise stall the upper layer responses. + */ + if (!conn->enc_key_size) + return 0; + + /* Nothing else needed, all requirements are met */ return 1; + } hci_conn_encrypt(conn); return 0; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d49aa4e6c916..ec9b5d159591 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1340,6 +1340,21 @@ static void l2cap_request_info(struct l2cap_conn *conn) sizeof(req), &req); } +static bool l2cap_check_enc_key_size(struct hci_conn *hcon) +{ + /* The minimum encryption key size needs to be enforced by the + * host stack before establishing any L2CAP connections. The + * specification in theory allows a minimum of 1, but to align + * BR/EDR and LE transports, a minimum of 7 is chosen. + * + * This check might also be called for unencrypted connections + * that have no key size requirements. Ensure that the link is + * actually encrypted before enforcing a key size. + */ + return (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags) || + hcon->enc_key_size >= HCI_MIN_ENC_KEY_SIZE); +} + static void l2cap_do_start(struct l2cap_chan *chan) { struct l2cap_conn *conn = chan->conn; @@ -1357,9 +1372,14 @@ static void l2cap_do_start(struct l2cap_chan *chan) if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) return; - if (l2cap_chan_check_security(chan, true) && - __l2cap_no_conn_pending(chan)) + if (!l2cap_chan_check_security(chan, true) || + !__l2cap_no_conn_pending(chan)) + return; + + if (l2cap_check_enc_key_size(conn->hcon)) l2cap_start_connection(chan); + else + __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); } static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) @@ -1438,7 +1458,10 @@ static void l2cap_conn_start(struct l2cap_conn *conn) continue; } - l2cap_start_connection(chan); + if (l2cap_check_enc_key_size(conn->hcon)) + l2cap_start_connection(chan); + else + l2cap_chan_close(chan, ECONNREFUSED); } else if (chan->state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -7447,7 +7470,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) } if (chan->state == BT_CONNECT) { - if (!status) + if (!status && l2cap_check_enc_key_size(hcon)) l2cap_start_connection(chan); else __set_chan_timer(chan, L2CAP_DISC_TIMEOUT); @@ -7456,7 +7479,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) struct l2cap_conn_rsp rsp; __u16 res, stat; - if (!status) { + if (!status && l2cap_check_enc_key_size(hcon)) { if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { res = L2CAP_CR_PEND; stat = L2CAP_CS_AUTHOR_PEND; diff --git a/net/can/af_can.c b/net/can/af_can.c index ac1552d8b4ad..e5a9e3d76e26 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -113,6 +113,7 @@ EXPORT_SYMBOL(can_ioctl); static void can_sock_destruct(struct sock *sk) { skb_queue_purge(&sk->sk_receive_queue); + skb_queue_purge(&sk->sk_error_queue); } static const struct can_proto *can_get_proto(int protocol) diff --git a/net/core/dev.c b/net/core/dev.c index 3db31bac40e5..bcc0aa48ddd7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4932,7 +4932,6 @@ static struct sk_buff *napi_frags_skb(struct napi_struct *napi) skb_reset_mac_header(skb); skb_gro_reset_offset(skb); - eth = skb_gro_header_fast(skb, 0); if (unlikely(skb_gro_header_hard(skb, hlen))) { eth = skb_gro_header_slow(skb, hlen, 0); if (unlikely(!eth)) { @@ -4942,6 +4941,7 @@ static struct sk_buff *napi_frags_skb(struct napi_struct *napi) return NULL; } } else { + eth = (const struct ethhdr *)skb->data; gro_pull_from_frag0(skb, hlen); NAPI_GRO_CB(skb)->frag0 += hlen; NAPI_GRO_CB(skb)->frag0_len -= hlen; @@ -5204,7 +5204,10 @@ bool sk_busy_loop(struct sock *sk, int nonblock) goto out; /* Note: ndo_busy_poll method is optional in linux-4.5 */ - busy_poll = napi->dev->netdev_ops->ndo_busy_poll; + if (napi->dev->netdev_ops) + busy_poll = napi->dev->netdev_ops->ndo_busy_poll; + else + busy_poll = NULL; do { rc = 0; diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 20ae57fbe009..ffe7b03c9ab5 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -878,8 +878,13 @@ static noinline_for_stack int ethtool_get_drvinfo(struct net_device *dev, if (rc >= 0) info.n_priv_flags = rc; } - if (ops->get_regs_len) - info.regdump_len = ops->get_regs_len(dev); + if (ops->get_regs_len) { + int ret = ops->get_regs_len(dev); + + if (ret > 0) + info.regdump_len = ret; + } + if (ops->get_eeprom_len) info.eedump_len = ops->get_eeprom_len(dev); @@ -1380,6 +1385,9 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) return -EFAULT; reglen = ops->get_regs_len(dev); + if (reglen <= 0) + return reglen; + if (regs.len > reglen) regs.len = reglen; @@ -1390,13 +1398,16 @@ static int ethtool_get_regs(struct net_device *dev, char __user *useraddr) return -ENOMEM; } + if (regs.len < reglen) + reglen = regs.len; + ops->get_regs(dev, ®s, regbuf); ret = -EFAULT; if (copy_to_user(useraddr, ®s, sizeof(regs))) goto out; useraddr += offsetof(struct ethtool_regs, data); - if (regbuf && copy_to_user(useraddr, regbuf, regs.len)) + if (copy_to_user(useraddr, regbuf, reglen)) goto out; ret = 0; diff --git a/net/core/neighbour.c b/net/core/neighbour.c index f18791769960..0513c56eeced 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -30,6 +30,7 @@ #include <linux/times.h> #include <net/net_namespace.h> #include <net/neighbour.h> +#include <net/arp.h> #include <net/dst.h> #include <net/sock.h> #include <net/netevent.h> @@ -2510,7 +2511,13 @@ int neigh_xmit(int index, struct net_device *dev, if (!tbl) goto out; rcu_read_lock_bh(); - neigh = __neigh_lookup_noref(tbl, addr, dev); + if (index == NEIGH_ARP_TABLE) { + u32 key = *((u32 *)addr); + + neigh = __ipv4_neigh_lookup_noref(dev, key); + } else { + neigh = __neigh_lookup_noref(tbl, addr, dev); + } if (!neigh) neigh = __neigh_create(tbl, addr, dev, false); err = PTR_ERR(neigh); @@ -2718,6 +2725,7 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos) } void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags) + __acquires(tbl->lock) __acquires(rcu_bh) { struct neigh_seq_state *state = seq->private; @@ -2728,6 +2736,7 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl rcu_read_lock_bh(); state->nht = rcu_dereference_bh(tbl->nht); + read_lock(&tbl->lock); return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN; } @@ -2761,8 +2770,13 @@ out: EXPORT_SYMBOL(neigh_seq_next); void neigh_seq_stop(struct seq_file *seq, void *v) + __releases(tbl->lock) __releases(rcu_bh) { + struct neigh_seq_state *state = seq->private; + struct neigh_table *tbl = state->tbl; + + read_unlock(&tbl->lock); rcu_read_unlock_bh(); } EXPORT_SYMBOL(neigh_seq_stop); diff --git a/net/core/pktgen.c b/net/core/pktgen.c index fc7ec7a6343e..3708301772f9 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -3147,7 +3147,13 @@ static int pktgen_wait_thread_run(struct pktgen_thread *t) { while (thread_is_running(t)) { + /* note: 't' will still be around even after the unlock/lock + * cycle because pktgen_thread threads are only cleared at + * net exit + */ + mutex_unlock(&pktgen_thread_lock); msleep_interruptible(100); + mutex_lock(&pktgen_thread_lock); if (signal_pending(current)) goto signal; @@ -3162,6 +3168,10 @@ static int pktgen_wait_all_threads_run(struct pktgen_net *pn) struct pktgen_thread *t; int sig = 1; + /* prevent from racing with rmmod */ + if (!try_module_get(THIS_MODULE)) + return sig; + mutex_lock(&pktgen_thread_lock); list_for_each_entry(t, &pn->pktgen_threads, th_list) { @@ -3175,6 +3185,7 @@ static int pktgen_wait_all_threads_run(struct pktgen_net *pn) t->control |= (T_STOP); mutex_unlock(&pktgen_thread_lock); + module_put(THIS_MODULE); return sig; } diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index f2e6e874e4ec..780dc6fe899d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -190,6 +190,17 @@ static void ip_ma_put(struct ip_mc_list *im) pmc != NULL; \ pmc = rtnl_dereference(pmc->next_rcu)) +static void ip_sf_list_clear_all(struct ip_sf_list *psf) +{ + struct ip_sf_list *next; + + while (psf) { + next = psf->sf_next; + kfree(psf); + psf = next; + } +} + #ifdef CONFIG_IP_MULTICAST /* @@ -635,6 +646,13 @@ static void igmpv3_clear_zeros(struct ip_sf_list **ppsf) } } +static void kfree_pmc(struct ip_mc_list *pmc) +{ + ip_sf_list_clear_all(pmc->sources); + ip_sf_list_clear_all(pmc->tomb); + kfree(pmc); +} + static void igmpv3_send_cr(struct in_device *in_dev) { struct ip_mc_list *pmc, *pmc_prev, *pmc_next; @@ -671,7 +689,7 @@ static void igmpv3_send_cr(struct in_device *in_dev) else in_dev->mc_tomb = pmc_next; in_dev_put(pmc->interface); - kfree(pmc); + kfree_pmc(pmc); } else pmc_prev = pmc; } @@ -1195,12 +1213,16 @@ static void igmpv3_del_delrec(struct in_device *in_dev, struct ip_mc_list *im) im->crcount = in_dev->mr_qrv ?: net->ipv4.sysctl_igmp_qrv; if (im->sfmode == MCAST_INCLUDE) { im->tomb = pmc->tomb; + pmc->tomb = NULL; + im->sources = pmc->sources; + pmc->sources = NULL; + for (psf = im->sources; psf; psf = psf->sf_next) psf->sf_crcount = im->crcount; } in_dev_put(pmc->interface); - kfree(pmc); + kfree_pmc(pmc); } spin_unlock_bh(&im->lock); } @@ -1221,21 +1243,18 @@ static void igmpv3_clear_delrec(struct in_device *in_dev) nextpmc = pmc->next; ip_mc_clear_src(pmc); in_dev_put(pmc->interface); - kfree(pmc); + kfree_pmc(pmc); } /* clear dead sources, too */ rcu_read_lock(); for_each_pmc_rcu(in_dev, pmc) { - struct ip_sf_list *psf, *psf_next; + struct ip_sf_list *psf; spin_lock_bh(&pmc->lock); psf = pmc->tomb; pmc->tomb = NULL; spin_unlock_bh(&pmc->lock); - for (; psf; psf = psf_next) { - psf_next = psf->sf_next; - kfree(psf); - } + ip_sf_list_clear_all(psf); } rcu_read_unlock(); } @@ -2099,7 +2118,7 @@ static int ip_mc_add_src(struct in_device *in_dev, __be32 *pmca, int sfmode, static void ip_mc_clear_src(struct ip_mc_list *pmc) { - struct ip_sf_list *psf, *nextpsf, *tomb, *sources; + struct ip_sf_list *tomb, *sources; spin_lock_bh(&pmc->lock); tomb = pmc->tomb; @@ -2111,14 +2130,8 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc) pmc->sfcount[MCAST_EXCLUDE] = 1; spin_unlock_bh(&pmc->lock); - for (psf = tomb; psf; psf = nextpsf) { - nextpsf = psf->sf_next; - kfree(psf); - } - for (psf = sources; psf; psf = nextpsf) { - nextpsf = psf->sf_next; - kfree(psf); - } + ip_sf_list_clear_all(tomb); + ip_sf_list_clear_all(sources); } /* Join a multicast group diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index ec48d8eafc7e..8b221398534b 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c @@ -306,6 +306,7 @@ static const struct snmp_mib snmp4_net_list[] = { SNMP_MIB_ITEM("TCPKeepAlive", LINUX_MIB_TCPKEEPALIVE), SNMP_MIB_ITEM("TCPMTUPFail", LINUX_MIB_TCPMTUPFAIL), SNMP_MIB_ITEM("TCPMTUPSuccess", LINUX_MIB_TCPMTUPSUCCESS), + SNMP_MIB_ITEM("TCPWqueueTooBig", LINUX_MIB_TCPWQUEUETOOBIG), SNMP_MIB_SENTINEL }; diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 482cf7c52868..b37e9c421f4c 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -197,7 +197,7 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) } sk = __raw_v4_lookup(net, sk_next(sk), iph->protocol, iph->saddr, iph->daddr, - skb->dev->ifindex); + dif); } out: read_unlock(&raw_v4_hashinfo.lock); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 76da06e4fe90..50f494547ab9 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -35,6 +35,8 @@ static int ip_local_port_range_min[] = { 1, 1 }; static int ip_local_port_range_max[] = { 65535, 65535 }; static int tcp_adv_win_scale_min = -31; static int tcp_adv_win_scale_max = 31; +static int tcp_min_snd_mss_min = TCP_MIN_SND_MSS; +static int tcp_min_snd_mss_max = 65535; static int ip_ttl_min = 1; static int ip_ttl_max = 255; static int tcp_syn_retries_min = 1; @@ -891,6 +893,15 @@ static struct ctl_table ipv4_net_table[] = { .proc_handler = proc_dointvec, }, { + .procname = "tcp_min_snd_mss", + .data = &init_net.ipv4.sysctl_tcp_min_snd_mss, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = &tcp_min_snd_mss_min, + .extra2 = &tcp_min_snd_mss_max, + }, + { .procname = "tcp_probe_threshold", .data = &init_net.ipv4.sysctl_tcp_probe_threshold, .maxlen = sizeof(int), diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index a0e1fc1ba5cd..ac398b72ba67 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -3359,6 +3359,7 @@ void __init tcp_init(void) unsigned long limit; unsigned int i; + BUILD_BUG_ON(TCP_MIN_SND_MSS <= MAX_TCP_OPTION_SPACE); BUILD_BUG_ON(sizeof(struct tcp_skb_cb) > FIELD_SIZEOF(struct sk_buff, cb)); diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 6c42ffce24df..435450febca6 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1321,7 +1321,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, TCP_SKB_CB(skb)->seq += shifted; tcp_skb_pcount_add(prev, pcount); - BUG_ON(tcp_skb_pcount(skb) < pcount); + WARN_ON_ONCE(tcp_skb_pcount(skb) < pcount); tcp_skb_pcount_add(skb, -pcount); /* When we're adding to gso_segs == 1, gso_size will be zero, @@ -1388,6 +1388,21 @@ static int skb_can_shift(const struct sk_buff *skb) return !skb_headlen(skb) && skb_is_nonlinear(skb); } +int tcp_skb_shift(struct sk_buff *to, struct sk_buff *from, + int pcount, int shiftlen) +{ + /* TCP min gso_size is 8 bytes (TCP_MIN_GSO_SIZE) + * Since TCP_SKB_CB(skb)->tcp_gso_segs is 16 bits, we need + * to make sure not storing more than 65535 * 8 bytes per skb, + * even if current MSS is bigger. + */ + if (unlikely(to->len + shiftlen >= 65535 * TCP_MIN_GSO_SIZE)) + return 0; + if (unlikely(tcp_skb_pcount(to) + pcount > 65535)) + return 0; + return skb_shift(to, from, shiftlen); +} + /* Try collapsing SACK blocks spanning across multiple skbs to a single * skb. */ @@ -1399,6 +1414,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *prev; int mss; + int next_pcount; int pcount = 0; int len; int in_sack; @@ -1496,7 +1512,7 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, if (!after(TCP_SKB_CB(skb)->seq + len, tp->snd_una)) goto fallback; - if (!skb_shift(prev, skb, len)) + if (!tcp_skb_shift(prev, skb, pcount, len)) goto fallback; if (!tcp_shifted_skb(sk, skb, state, pcount, len, mss, dup_sack)) goto out; @@ -1515,11 +1531,11 @@ static struct sk_buff *tcp_shift_skb_data(struct sock *sk, struct sk_buff *skb, goto out; len = skb->len; - if (skb_shift(prev, skb, len)) { - pcount += tcp_skb_pcount(skb); - tcp_shifted_skb(sk, skb, state, tcp_skb_pcount(skb), len, mss, 0); + next_pcount = tcp_skb_pcount(skb); + if (tcp_skb_shift(prev, skb, next_pcount, len)) { + pcount += next_pcount; + tcp_shifted_skb(sk, skb, state, next_pcount, len, mss, 0); } - out: state->fack_count += pcount; return prev; @@ -2838,9 +2854,9 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, bool do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && (tcp_fackets_out(tp) > tp->reordering)); - if (WARN_ON(!tp->packets_out && tp->sacked_out)) + if (!tp->packets_out && tp->sacked_out) tp->sacked_out = 0; - if (WARN_ON(!tp->sacked_out && tp->fackets_out)) + if (!tp->sacked_out && tp->fackets_out) tp->fackets_out = 0; /* Now state machine starts. diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 0116d9ef8c7d..d6a95261b0e3 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -2470,6 +2470,7 @@ static int __net_init tcp_sk_init(struct net *net) net->ipv4.sysctl_tcp_ecn_fallback = 1; net->ipv4.sysctl_tcp_base_mss = TCP_BASE_MSS; + net->ipv4.sysctl_tcp_min_snd_mss = TCP_MIN_SND_MSS; net->ipv4.sysctl_tcp_probe_threshold = TCP_PROBE_THRESHOLD; net->ipv4.sysctl_tcp_probe_interval = TCP_PROBE_INTERVAL; diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8d31f60f22ed..3f459811f283 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -1185,6 +1185,11 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, if (nsize < 0) nsize = 0; + if (unlikely((sk->sk_wmem_queued >> 1) > sk->sk_sndbuf + 0x20000)) { + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPWQUEUETOOBIG); + return -ENOMEM; + } + if (skb_unclone(skb, gfp)) return -ENOMEM; @@ -1355,8 +1360,7 @@ static inline int __tcp_mtu_to_mss(struct sock *sk, int pmtu) mss_now -= icsk->icsk_ext_hdr_len; /* Then reserve room for full set of TCP options and 8 bytes of data */ - if (mss_now < 48) - mss_now = 48; + mss_now = max(mss_now, sock_net(sk)->ipv4.sysctl_tcp_min_snd_mss); return mss_now; } diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 93fbacece9fc..d9629228d7a8 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c @@ -172,6 +172,7 @@ static void tcp_mtu_probing(struct inet_connection_sock *icsk, struct sock *sk) mss = tcp_mtu_to_mss(sk, icsk->icsk_mtup.search_low) >> 1; mss = min(net->ipv4.sysctl_tcp_base_mss, mss); mss = max(mss, 68 - tp->tcp_header_len); + mss = max(mss, net->ipv4.sysctl_tcp_min_snd_mss); icsk->icsk_mtup.search_low = tcp_mss_to_mtu(sk, mss); tcp_sync_mss(sk, icsk->icsk_pmtu_cookie); } diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 306d34a5dbfb..405ec0202ad8 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -574,7 +574,11 @@ static inline struct sock *__udp4_lib_lookup_skb(struct sk_buff *skb, struct sock *udp4_lib_lookup_skb(struct sk_buff *skb, __be16 sport, __be16 dport) { - return __udp4_lib_lookup_skb(skb, sport, dport, &udp_table); + const struct iphdr *iph = ip_hdr(skb); + + return __udp4_lib_lookup(dev_net(skb->dev), iph->saddr, sport, + iph->daddr, dport, inet_iif(skb), + &udp_table, NULL); } EXPORT_SYMBOL_GPL(udp4_lib_lookup_skb); diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 8c2f9aedc2af..6a6011160f18 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c @@ -254,9 +254,9 @@ struct ip6_flowlabel *fl6_sock_lookup(struct sock *sk, __be32 label) rcu_read_lock_bh(); for_each_sk_fl_rcu(np, sfl) { struct ip6_flowlabel *fl = sfl->fl; - if (fl->label == label) { + + if (fl->label == label && atomic_inc_not_zero(&fl->users)) { fl->lastuse = jiffies; - atomic_inc(&fl->users); rcu_read_unlock_bh(); return fl; } @@ -623,7 +623,8 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) goto done; } fl1 = sfl->fl; - atomic_inc(&fl1->users); + if (!atomic_inc_not_zero(&fl1->users)) + fl1 = NULL; break; } } diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 1e1fa99b3243..0b53d1907e4a 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -264,8 +264,14 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, prev = fq->q.fragments_tail; err = inet_frag_queue_insert(&fq->q, skb, offset, end); - if (err) + if (err) { + if (err == IPFRAG_DUP) { + /* No error for duplicates, pretend they got queued. */ + kfree_skb(skb); + return -EINPROGRESS; + } goto insert_error; + } if (dev) fq->iif = dev->ifindex; @@ -292,15 +298,17 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, skb->_skb_refdst = 0UL; err = nf_ct_frag6_reasm(fq, skb, prev, dev); skb->_skb_refdst = orefdst; - return err; + + /* After queue has assumed skb ownership, only 0 or + * -EINPROGRESS must be returned. + */ + return err ? -EINPROGRESS : 0; } skb_dst_drop(skb); return -EINPROGRESS; insert_error: - if (err == IPFRAG_DUP) - goto err; inet_frag_kill(&fq->q); err: skb_dst_drop(skb); @@ -480,12 +488,6 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user) ret = 0; } - /* after queue has assumed skb ownership, only 0 or -EINPROGRESS - * must be returned. - */ - if (ret) - ret = -EINPROGRESS; - spin_unlock_bh(&fq->q.lock); inet_frag_put(&fq->q); return ret; diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 55d284a2e266..cae2c9eab912 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -283,7 +283,9 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) /* Binding to link-local address requires an interface */ if (!sk->sk_bound_dev_if) goto out_unlock; + } + if (sk->sk_bound_dev_if) { err = -ENODEV; dev = dev_get_by_index_rcu(sock_net(sk), sk->sk_bound_dev_if); @@ -772,6 +774,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) struct sockcm_cookie sockc; struct ipcm6_cookie ipc6; int addr_len = msg->msg_namelen; + int hdrincl; u16 proto; int err; @@ -785,6 +788,13 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) if (msg->msg_flags & MSG_OOB) return -EOPNOTSUPP; + /* hdrincl should be READ_ONCE(inet->hdrincl) + * but READ_ONCE() doesn't work with bit fields. + * Doing this indirectly yields the same result. + */ + hdrincl = inet->hdrincl; + hdrincl = READ_ONCE(hdrincl); + /* * Get and verify the address. */ @@ -879,11 +889,14 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) opt = ipv6_fixup_options(&opt_space, opt); fl6.flowi6_proto = proto; - rfv.msg = msg; - rfv.hlen = 0; - err = rawv6_probe_proto_opt(&rfv, &fl6); - if (err) - goto out; + + if (!hdrincl) { + rfv.msg = msg; + rfv.hlen = 0; + err = rawv6_probe_proto_opt(&rfv, &fl6); + if (err) + goto out; + } if (!ipv6_addr_any(daddr)) fl6.daddr = *daddr; @@ -900,7 +913,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) fl6.flowi6_oif = np->ucast_oif; security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); - if (inet->hdrincl) + if (hdrincl) fl6.flowi6_flags |= FLOWI_FLAG_KNOWN_NH; if (ipc6.tclass < 0) @@ -923,7 +936,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) goto do_confirm; back_from_confirm: - if (inet->hdrincl) + if (hdrincl) err = rawv6_send_hdrinc(sk, msg, len, &fl6, &dst, msg->msg_flags); else { ipc6.opt = opt; diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 2db6808a91e4..6148952fc6a6 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -291,7 +291,7 @@ struct sock *udp6_lib_lookup_skb(struct sk_buff *skb, return __udp6_lib_lookup(dev_net(skb->dev), &iph->saddr, sport, &iph->daddr, dport, inet6_iif(skb), - &udp_table, skb); + &udp_table, NULL); } EXPORT_SYMBOL_GPL(udp6_lib_lookup_skb); @@ -476,7 +476,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, struct net *net = dev_net(skb->dev); sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, - inet6_iif(skb), udptable, skb); + inet6_iif(skb), udptable, NULL); if (!sk) { __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); diff --git a/net/lapb/lapb_iface.c b/net/lapb/lapb_iface.c index fc60d9d738b5..cdb913e7627e 100644 --- a/net/lapb/lapb_iface.c +++ b/net/lapb/lapb_iface.c @@ -182,6 +182,7 @@ int lapb_unregister(struct net_device *dev) lapb = __lapb_devtostruct(dev); if (!lapb) goto out; + lapb_put(lapb); lapb_stop_t1timer(lapb); lapb_stop_t2timer(lapb); diff --git a/net/llc/llc_output.c b/net/llc/llc_output.c index 94425e421213..9e4b6bcf6920 100644 --- a/net/llc/llc_output.c +++ b/net/llc/llc_output.c @@ -72,6 +72,8 @@ int llc_build_and_send_ui_pkt(struct llc_sap *sap, struct sk_buff *skb, rc = llc_mac_hdr_init(skb, skb->dev->dev_addr, dmac); if (likely(!rc)) rc = dev_queue_xmit(skb); + else + kfree_skb(skb); return rc; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 8a690ebd7374..6708de10a3e5 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1403,7 +1403,7 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata) rcu_read_lock(); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); - if (WARN_ON(!chanctx_conf)) { + if (WARN_ON_ONCE(!chanctx_conf)) { rcu_read_unlock(); return NULL; } diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index b2a27263d6ff..5c347d3a92c9 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -885,6 +885,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) /* flush STAs and mpaths on this iface */ sta_info_flush(sdata); + ieee80211_free_keys(sdata, true); mesh_path_flush_by_iface(sdata); /* stop the beacon */ @@ -1135,7 +1136,8 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) ifmsh->chsw_ttl = 0; /* Remove the CSA and MCSP elements from the beacon */ - tmp_csa_settings = rcu_dereference(ifmsh->csa); + tmp_csa_settings = rcu_dereference_protected(ifmsh->csa, + lockdep_is_held(&sdata->wdev.mtx)); RCU_INIT_POINTER(ifmsh->csa, NULL); if (tmp_csa_settings) kfree_rcu(tmp_csa_settings, rcu_head); @@ -1157,6 +1159,8 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, struct mesh_csa_settings *tmp_csa_settings; int ret = 0; + lockdep_assert_held(&sdata->wdev.mtx); + tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings), GFP_ATOMIC); if (!tmp_csa_settings) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a37fc00e2622..3f54d486a796 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1072,9 +1072,6 @@ static void ieee80211_chswitch_work(struct work_struct *work) goto out; } - /* XXX: shouldn't really modify cfg80211-owned data! */ - ifmgd->associated->channel = sdata->csa_chandef.chan; - ifmgd->csa_waiting_bcn = true; ieee80211_sta_reset_beacon_monitor(sdata); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 23f6c8baae95..3b423c50ec8f 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3568,6 +3568,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) case NL80211_IFTYPE_STATION: if (!bssid && !sdata->u.mgd.use_4addr) return false; + if (ieee80211_is_robust_mgmt_frame(skb) && !rx->sta) + return false; if (multicast) return true; return ether_addr_equal(sdata->vif.addr, hdr->addr1); diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index caa5986cb2e4..c0529c4b60f8 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c @@ -1169,7 +1169,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); struct ieee80211_key *key = rx->key; struct ieee80211_mmie_16 *mmie; - u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN]; + u8 aad[GMAC_AAD_LEN], *mic, ipn[6], nonce[GMAC_NONCE_LEN]; struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; if (!ieee80211_is_mgmt(hdr->frame_control)) @@ -1200,13 +1200,18 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx) memcpy(nonce, hdr->addr2, ETH_ALEN); memcpy(nonce + ETH_ALEN, ipn, 6); + mic = kmalloc(GMAC_MIC_LEN, GFP_ATOMIC); + if (!mic) + return RX_DROP_UNUSABLE; if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce, skb->data + 24, skb->len - 24, mic) < 0 || crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) { key->u.aes_gmac.icverrors++; + kfree(mic); return RX_DROP_UNUSABLE; } + kfree(mic); } memcpy(key->u.aes_gmac.rx_pn, ipn, 6); diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 7233ad8ddcc0..c09ee6c661a9 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2399,6 +2399,9 @@ static void tpacket_destruct_skb(struct sk_buff *skb) ts = __packet_set_timestamp(po, ph, skb); __packet_set_status(po, ph, TP_STATUS_AVAILABLE | ts); + + if (!packet_read_pending(&po->tx_ring)) + complete(&po->skb_completion); } sock_wfree(skb); @@ -2629,7 +2632,7 @@ static int tpacket_parse_header(struct packet_sock *po, void *frame, static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) { - struct sk_buff *skb; + struct sk_buff *skb = NULL; struct net_device *dev; struct virtio_net_hdr *vnet_hdr = NULL; struct sockcm_cookie sockc; @@ -2644,6 +2647,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) int len_sum = 0; int status = TP_STATUS_AVAILABLE; int hlen, tlen, copylen = 0; + long timeo = 0; mutex_lock(&po->pg_vec_lock); @@ -2690,12 +2694,21 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) if ((size_max > dev->mtu + reserve + VLAN_HLEN) && !po->has_vnet_hdr) size_max = dev->mtu + reserve + VLAN_HLEN; + reinit_completion(&po->skb_completion); + do { ph = packet_current_frame(po, &po->tx_ring, TP_STATUS_SEND_REQUEST); if (unlikely(ph == NULL)) { - if (need_wait && need_resched()) - schedule(); + if (need_wait && skb) { + timeo = sock_sndtimeo(&po->sk, msg->msg_flags & MSG_DONTWAIT); + timeo = wait_for_completion_interruptible_timeout(&po->skb_completion, timeo); + if (timeo <= 0) { + err = !timeo ? -ETIMEDOUT : -ERESTARTSYS; + goto out_put; + } + } + /* check for additional frames */ continue; } @@ -3249,6 +3262,7 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, sock_init_data(sock, sk); po = pkt_sk(sk); + init_completion(&po->skb_completion); sk->sk_family = PF_PACKET; po->num = proto; po->xmit = dev_queue_xmit; diff --git a/net/packet/internal.h b/net/packet/internal.h index b8d5618ae19f..650f8a3e3ad5 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h @@ -127,6 +127,7 @@ struct packet_sock { unsigned int tp_hdrlen; unsigned int tp_reserve; unsigned int tp_tstamp; + struct completion skb_completion; struct net_device __rcu *cached_dev; int (*xmit)(struct sk_buff *skb); struct packet_type prot_hook ____cacheline_aligned_in_smp; diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c index 91b53d462fc0..78d5d68cbbce 100644 --- a/net/rds/ib_rdma.c +++ b/net/rds/ib_rdma.c @@ -416,12 +416,14 @@ int rds_ib_flush_mr_pool(struct rds_ib_mr_pool *pool, wait_clean_list_grace(); list_to_llist_nodes(pool, &unmap_list, &clean_nodes, &clean_tail); - if (ibmr_ret) + if (ibmr_ret) { *ibmr_ret = llist_entry(clean_nodes, struct rds_ib_mr, llnode); - + clean_nodes = clean_nodes->next; + } /* more than one entry in llist nodes */ - if (clean_nodes->next) - llist_add_batch(clean_nodes->next, clean_tail, &pool->clean_list); + if (clean_nodes) + llist_add_batch(clean_nodes, clean_tail, + &pool->clean_list); } diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 1f03065686fe..beae42bfa68f 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c @@ -125,10 +125,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, /* Initialize the bind addr area */ sctp_bind_addr_init(&ep->base.bind_addr, 0); - /* Remember who we are attached to. */ - ep->base.sk = sk; - sock_hold(ep->base.sk); - /* Create the lists of associations. */ INIT_LIST_HEAD(&ep->asocs); @@ -165,6 +161,10 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, ep->auth_chunk_list = auth_chunks; ep->prsctp_enable = net->sctp.prsctp_enable; + /* Remember who we are attached to. */ + ep->base.sk = sk; + sock_hold(ep->base.sk); + return ep; nomem_hmacs: diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 244eac1bd648..de18a463ac96 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c @@ -2718,6 +2718,7 @@ int rpc_clnt_add_xprt(struct rpc_clnt *clnt, xprt = xprt_iter_xprt(&clnt->cl_xpi); if (xps == NULL || xprt == NULL) { rcu_read_unlock(); + xprt_switch_put(xps); return -EAGAIN; } resvport = xprt->resvport; diff --git a/net/tipc/core.c b/net/tipc/core.c index 974694121ce9..59980dea2ad7 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c @@ -62,10 +62,6 @@ static int __net_init tipc_init_net(struct net *net) INIT_LIST_HEAD(&tn->node_list); spin_lock_init(&tn->node_list_lock); - err = tipc_socket_init(); - if (err) - goto out_socket; - err = tipc_sk_rht_init(net); if (err) goto out_sk_rht; @@ -75,9 +71,6 @@ static int __net_init tipc_init_net(struct net *net) goto out_nametbl; INIT_LIST_HEAD(&tn->dist_queue); - err = tipc_topsrv_start(net); - if (err) - goto out_subscr; err = tipc_bcast_init(net); if (err) @@ -86,25 +79,19 @@ static int __net_init tipc_init_net(struct net *net) return 0; out_bclink: - tipc_bcast_stop(net); -out_subscr: tipc_nametbl_stop(net); out_nametbl: tipc_sk_rht_destroy(net); out_sk_rht: - tipc_socket_stop(); -out_socket: return err; } static void __net_exit tipc_exit_net(struct net *net) { - tipc_topsrv_stop(net); tipc_net_stop(net); tipc_bcast_stop(net); tipc_nametbl_stop(net); tipc_sk_rht_destroy(net); - tipc_socket_stop(); } static struct pernet_operations tipc_net_ops = { @@ -114,6 +101,11 @@ static struct pernet_operations tipc_net_ops = { .size = sizeof(struct tipc_net), }; +static struct pernet_operations tipc_topsrv_net_ops = { + .init = tipc_topsrv_init_net, + .exit = tipc_topsrv_exit_net, +}; + static int __init tipc_init(void) { int err; @@ -136,10 +128,18 @@ static int __init tipc_init(void) if (err) goto out_sysctl; - err = register_pernet_subsys(&tipc_net_ops); + err = register_pernet_device(&tipc_net_ops); if (err) goto out_pernet; + err = tipc_socket_init(); + if (err) + goto out_socket; + + err = register_pernet_device(&tipc_topsrv_net_ops); + if (err) + goto out_pernet_topsrv; + err = tipc_bearer_setup(); if (err) goto out_bearer; @@ -147,7 +147,11 @@ static int __init tipc_init(void) pr_info("Started in single node mode\n"); return 0; out_bearer: - unregister_pernet_subsys(&tipc_net_ops); + unregister_pernet_device(&tipc_topsrv_net_ops); +out_pernet_topsrv: + tipc_socket_stop(); +out_socket: + unregister_pernet_device(&tipc_net_ops); out_pernet: tipc_unregister_sysctl(); out_sysctl: @@ -162,7 +166,9 @@ out_netlink: static void __exit tipc_exit(void) { tipc_bearer_cleanup(); - unregister_pernet_subsys(&tipc_net_ops); + unregister_pernet_device(&tipc_topsrv_net_ops); + tipc_socket_stop(); + unregister_pernet_device(&tipc_net_ops); tipc_netlink_stop(); tipc_netlink_compat_stop(); tipc_unregister_sysctl(); diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c index 0cf9403b4c44..b7c539a51da3 100644 --- a/net/tipc/netlink_compat.c +++ b/net/tipc/netlink_compat.c @@ -436,7 +436,11 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd, if (!bearer) return -EMSGSIZE; - len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME); + len = TLV_GET_DATA_LEN(msg->req); + if (len <= 0) + return -EINVAL; + + len = min_t(int, len, TIPC_MAX_BEARER_NAME); if (!string_is_valid(name, len)) return -EINVAL; @@ -528,7 +532,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg, name = (char *)TLV_DATA(msg->req); - len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME); + len = TLV_GET_DATA_LEN(msg->req); + if (len <= 0) + return -EINVAL; + + len = min_t(int, len, TIPC_MAX_BEARER_NAME); if (!string_is_valid(name, len)) return -EINVAL; @@ -806,7 +814,11 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd, if (!link) return -EMSGSIZE; - len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME); + len = TLV_GET_DATA_LEN(msg->req); + if (len <= 0) + return -EINVAL; + + len = min_t(int, len, TIPC_MAX_BEARER_NAME); if (!string_is_valid(name, len)) return -EINVAL; diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index d62affeb2a38..5e6dc7276abe 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -358,7 +358,7 @@ static void *tipc_subscrb_connect_cb(int conid) return (void *)tipc_subscrb_create(conid); } -int tipc_topsrv_start(struct net *net) +static int tipc_topsrv_start(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); const char name[] = "topology_server"; @@ -396,7 +396,7 @@ int tipc_topsrv_start(struct net *net) return tipc_server_start(topsrv); } -void tipc_topsrv_stop(struct net *net) +static void tipc_topsrv_stop(struct net *net) { struct tipc_net *tn = net_generic(net, tipc_net_id); struct tipc_server *topsrv = tn->topsrv; @@ -405,3 +405,13 @@ void tipc_topsrv_stop(struct net *net) kfree(topsrv->saddr); kfree(topsrv); } + +int __net_init tipc_topsrv_init_net(struct net *net) +{ + return tipc_topsrv_start(net); +} + +void __net_exit tipc_topsrv_exit_net(struct net *net) +{ + tipc_topsrv_stop(net); +} diff --git a/net/tipc/subscr.h b/net/tipc/subscr.h index ffdc214c117a..814dfcef33c2 100644 --- a/net/tipc/subscr.h +++ b/net/tipc/subscr.h @@ -75,7 +75,8 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, void tipc_subscrp_convert_seq(struct tipc_name_seq *in, int swap, struct tipc_name_seq *out); u32 tipc_subscrp_convert_seq_type(u32 type, int swap); -int tipc_topsrv_start(struct net *net); -void tipc_topsrv_stop(struct net *net); + +int __net_init tipc_topsrv_init_net(struct net *net); +void __net_exit tipc_topsrv_exit_net(struct net *net); #endif diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c index 133e72654e77..05033ab05b8f 100644 --- a/net/tipc/udp_media.c +++ b/net/tipc/udp_media.c @@ -174,7 +174,6 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, goto tx_error; } - skb->dev = rt->dst.dev; ttl = ip4_dst_hoplimit(&rt->dst); udp_tunnel_xmit_skb(rt, ub->ubsock->sk, skb, src->ipv4.s_addr, dst->ipv4.s_addr, 0, ttl, 0, src->port, @@ -193,10 +192,9 @@ static int tipc_udp_xmit(struct net *net, struct sk_buff *skb, if (err) goto tx_error; ttl = ip6_dst_hoplimit(ndst); - err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, - ndst->dev, &src->ipv6, - &dst->ipv6, 0, ttl, 0, src->port, - dst->port, false); + err = udp_tunnel6_xmit_skb(ndst, ub->ubsock->sk, skb, NULL, + &src->ipv6, &dst->ipv6, 0, ttl, 0, + src->port, dst->port, false); #endif } return err; diff --git a/net/wireless/core.c b/net/wireless/core.c index 0a67d80d2470..e13e02a5baf1 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -478,7 +478,7 @@ use_default_name: &rdev->rfkill_ops, rdev); if (!rdev->rfkill) { - kfree(rdev); + wiphy_free(&rdev->wiphy); return NULL; } diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d899a494ef08..3b7d7789f0eb 100755 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -14397,6 +14397,11 @@ void cfg80211_ch_switch_notify(struct net_device *dev, wdev->chandef = *chandef; wdev->preset_chandef = *chandef; + + if (wdev->iftype == NL80211_IFTYPE_STATION && + !WARN_ON(!wdev->current_bss)) + wdev->current_bss->pub.channel = chandef->chan; + nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL, NL80211_CMD_CH_SWITCH_NOTIFY, 0); } diff --git a/samples/bpf/bpf_load.c b/samples/bpf/bpf_load.c index 97913e109b14..99e5a2f63e76 100644 --- a/samples/bpf/bpf_load.c +++ b/samples/bpf/bpf_load.c @@ -369,7 +369,7 @@ void read_trace_pipe(void) static char buf[4096]; ssize_t sz; - sz = read(trace_fd, buf, sizeof(buf)); + sz = read(trace_fd, buf, sizeof(buf) - 1); if (sz > 0) { buf[sz] = 0; puts(buf); diff --git a/scripts/checkstack.pl b/scripts/checkstack.pl index 12a6940741fe..b8f616545277 100755 --- a/scripts/checkstack.pl +++ b/scripts/checkstack.pl @@ -45,7 +45,7 @@ my (@stack, $re, $dre, $x, $xs, $funcre); $x = "[0-9a-f]"; # hex character $xs = "[0-9a-f ]"; # hex character or space $funcre = qr/^$x* <(.*)>:$/; - if ($arch eq 'aarch64') { + if ($arch =~ '^(aarch|arm)64$') { #ffffffc0006325cc: a9bb7bfd stp x29, x30, [sp, #-80]! $re = qr/^.*stp.*sp, \#-([0-9]{1,8})\]\!/o; } elsif ($arch eq 'arm') { diff --git a/scripts/coccinelle/api/stream_open.cocci b/scripts/coccinelle/api/stream_open.cocci new file mode 100644 index 000000000000..350145da7669 --- /dev/null +++ b/scripts/coccinelle/api/stream_open.cocci @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: GPL-2.0 +// Author: Kirill Smelkov (kirr@nexedi.com) +// +// Search for stream-like files that are using nonseekable_open and convert +// them to stream_open. A stream-like file is a file that does not use ppos in +// its read and write. Rationale for the conversion is to avoid deadlock in +// between read and write. + +virtual report +virtual patch +virtual explain // explain decisions in the patch (SPFLAGS="-D explain") + +// stream-like reader & writer - ones that do not depend on f_pos. +@ stream_reader @ +identifier readstream, ppos; +identifier f, buf, len; +type loff_t; +@@ + ssize_t readstream(struct file *f, char *buf, size_t len, loff_t *ppos) + { + ... when != ppos + } + +@ stream_writer @ +identifier writestream, ppos; +identifier f, buf, len; +type loff_t; +@@ + ssize_t writestream(struct file *f, const char *buf, size_t len, loff_t *ppos) + { + ... when != ppos + } + + +// a function that blocks +@ blocks @ +identifier block_f; +identifier wait_event =~ "^wait_event_.*"; +@@ + block_f(...) { + ... when exists + wait_event(...) + ... when exists + } + +// stream_reader that can block inside. +// +// XXX wait_* can be called not directly from current function (e.g. func -> f -> g -> wait()) +// XXX currently reader_blocks supports only direct and 1-level indirect cases. +@ reader_blocks_direct @ +identifier stream_reader.readstream; +identifier wait_event =~ "^wait_event_.*"; +@@ + readstream(...) + { + ... when exists + wait_event(...) + ... when exists + } + +@ reader_blocks_1 @ +identifier stream_reader.readstream; +identifier blocks.block_f; +@@ + readstream(...) + { + ... when exists + block_f(...) + ... when exists + } + +@ reader_blocks depends on reader_blocks_direct || reader_blocks_1 @ +identifier stream_reader.readstream; +@@ + readstream(...) { + ... + } + + +// file_operations + whether they have _any_ .read, .write, .llseek ... at all. +// +// XXX add support for file_operations xxx[N] = ... (sound/core/pcm_native.c) +@ fops0 @ +identifier fops; +@@ + struct file_operations fops = { + ... + }; + +@ has_read @ +identifier fops0.fops; +identifier read_f; +@@ + struct file_operations fops = { + .read = read_f, + }; + +@ has_read_iter @ +identifier fops0.fops; +identifier read_iter_f; +@@ + struct file_operations fops = { + .read_iter = read_iter_f, + }; + +@ has_write @ +identifier fops0.fops; +identifier write_f; +@@ + struct file_operations fops = { + .write = write_f, + }; + +@ has_write_iter @ +identifier fops0.fops; +identifier write_iter_f; +@@ + struct file_operations fops = { + .write_iter = write_iter_f, + }; + +@ has_llseek @ +identifier fops0.fops; +identifier llseek_f; +@@ + struct file_operations fops = { + .llseek = llseek_f, + }; + +@ has_no_llseek @ +identifier fops0.fops; +@@ + struct file_operations fops = { + .llseek = no_llseek, + }; + +@ has_mmap @ +identifier fops0.fops; +identifier mmap_f; +@@ + struct file_operations fops = { + .mmap = mmap_f, + }; + +@ has_copy_file_range @ +identifier fops0.fops; +identifier copy_file_range_f; +@@ + struct file_operations fops = { + .copy_file_range = copy_file_range_f, + }; + +@ has_remap_file_range @ +identifier fops0.fops; +identifier remap_file_range_f; +@@ + struct file_operations fops = { + .remap_file_range = remap_file_range_f, + }; + +@ has_splice_read @ +identifier fops0.fops; +identifier splice_read_f; +@@ + struct file_operations fops = { + .splice_read = splice_read_f, + }; + +@ has_splice_write @ +identifier fops0.fops; +identifier splice_write_f; +@@ + struct file_operations fops = { + .splice_write = splice_write_f, + }; + + +// file_operations that is candidate for stream_open conversion - it does not +// use mmap and other methods that assume @offset access to file. +// +// XXX for simplicity require no .{read/write}_iter and no .splice_{read/write} for now. +// XXX maybe_steam.fops cannot be used in other rules - it gives "bad rule maybe_stream or bad variable fops". +@ maybe_stream depends on (!has_llseek || has_no_llseek) && !has_mmap && !has_copy_file_range && !has_remap_file_range && !has_read_iter && !has_write_iter && !has_splice_read && !has_splice_write @ +identifier fops0.fops; +@@ + struct file_operations fops = { + }; + + +// ---- conversions ---- + +// XXX .open = nonseekable_open -> .open = stream_open +// XXX .open = func -> openfunc -> nonseekable_open + +// read & write +// +// if both are used in the same file_operations together with an opener - +// under that conditions we can use stream_open instead of nonseekable_open. +@ fops_rw depends on maybe_stream @ +identifier fops0.fops, openfunc; +identifier stream_reader.readstream; +identifier stream_writer.writestream; +@@ + struct file_operations fops = { + .open = openfunc, + .read = readstream, + .write = writestream, + }; + +@ report_rw depends on report @ +identifier fops_rw.openfunc; +position p1; +@@ + openfunc(...) { + <... + nonseekable_open@p1 + ...> + } + +@ script:python depends on report && reader_blocks @ +fops << fops0.fops; +p << report_rw.p1; +@@ +coccilib.report.print_report(p[0], + "ERROR: %s: .read() can deadlock .write(); change nonseekable_open -> stream_open to fix." % (fops,)) + +@ script:python depends on report && !reader_blocks @ +fops << fops0.fops; +p << report_rw.p1; +@@ +coccilib.report.print_report(p[0], + "WARNING: %s: .read() and .write() have stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) + + +@ explain_rw_deadlocked depends on explain && reader_blocks @ +identifier fops_rw.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ nonseekable_open /* read & write (was deadlock) */ + ...> + } + + +@ explain_rw_nodeadlock depends on explain && !reader_blocks @ +identifier fops_rw.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ nonseekable_open /* read & write (no direct deadlock) */ + ...> + } + +@ patch_rw depends on patch @ +identifier fops_rw.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ stream_open + ...> + } + + +// read, but not write +@ fops_r depends on maybe_stream && !has_write @ +identifier fops0.fops, openfunc; +identifier stream_reader.readstream; +@@ + struct file_operations fops = { + .open = openfunc, + .read = readstream, + }; + +@ report_r depends on report @ +identifier fops_r.openfunc; +position p1; +@@ + openfunc(...) { + <... + nonseekable_open@p1 + ...> + } + +@ script:python depends on report @ +fops << fops0.fops; +p << report_r.p1; +@@ +coccilib.report.print_report(p[0], + "WARNING: %s: .read() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) + +@ explain_r depends on explain @ +identifier fops_r.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ nonseekable_open /* read only */ + ...> + } + +@ patch_r depends on patch @ +identifier fops_r.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ stream_open + ...> + } + + +// write, but not read +@ fops_w depends on maybe_stream && !has_read @ +identifier fops0.fops, openfunc; +identifier stream_writer.writestream; +@@ + struct file_operations fops = { + .open = openfunc, + .write = writestream, + }; + +@ report_w depends on report @ +identifier fops_w.openfunc; +position p1; +@@ + openfunc(...) { + <... + nonseekable_open@p1 + ...> + } + +@ script:python depends on report @ +fops << fops0.fops; +p << report_w.p1; +@@ +coccilib.report.print_report(p[0], + "WARNING: %s: .write() has stream semantic; safe to change nonseekable_open -> stream_open." % (fops,)) + +@ explain_w depends on explain @ +identifier fops_w.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ nonseekable_open /* write only */ + ...> + } + +@ patch_w depends on patch @ +identifier fops_w.openfunc; +@@ + openfunc(...) { + <... +- nonseekable_open ++ stream_open + ...> + } + + +// no read, no write - don't change anything diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index edde8250195c..381acfc4c59d 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -65,7 +65,7 @@ parse_symbol() { if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then local code=${cache[$module,$address]} else - local code=$(addr2line -i -e "$objfile" "$address") + local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address") cache[$module,$address]=$code fi diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index 12262c0cc691..08fe09c28bd2 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -135,8 +135,12 @@ extern void print_gimple_expr(FILE *, gimple, int, int); extern void dump_gimple_stmt(pretty_printer *, gimple, int, int); #endif +#ifndef __unused #define __unused __attribute__((__unused__)) +#endif +#ifndef __visible #define __visible __attribute__((visibility("default"))) +#endif #define DECL_NAME_POINTER(node) IDENTIFIER_POINTER(DECL_NAME(node)) #define DECL_NAME_LENGTH(node) IDENTIFIER_LENGTH(DECL_NAME(node)) diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 138120698f83..96a8d7115120 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -177,7 +177,7 @@ static bool unpack_nameX(struct aa_ext *e, enum aa_code code, const char *name) char *tag = NULL; size_t size = unpack_u16_chunk(e, &tag); /* if a name is specified it must match. otherwise skip tag */ - if (name && (!size || strcmp(name, tag))) + if (name && (!size || tag[size-1] != '\0' || strcmp(name, tag))) goto fail; } else if (name) { /* if a name is specified and there is no name tag fail */ diff --git a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c index 5b8520177b0e..7d72e3d48ad5 100644 --- a/sound/core/seq/oss/seq_oss_ioctl.c +++ b/sound/core/seq/oss/seq_oss_ioctl.c @@ -62,7 +62,7 @@ static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg) if (copy_from_user(ev, arg, 8)) return -EFAULT; memset(&tmpev, 0, sizeof(tmpev)); - snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.port, dp->addr.client); + snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port); tmpev.time.tick = 0; if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) { snd_seq_oss_dispatch(dp, &tmpev, 0, 0); diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c index 6a7b6aceeca9..499f3e8f4949 100644 --- a/sound/core/seq/oss/seq_oss_rw.c +++ b/sound/core/seq/oss/seq_oss_rw.c @@ -174,7 +174,7 @@ insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt) memset(&event, 0, sizeof(event)); /* set dummy -- to be sure */ event.type = SNDRV_SEQ_EVENT_NOTEOFF; - snd_seq_oss_fill_addr(dp, &event, dp->addr.port, dp->addr.client); + snd_seq_oss_fill_addr(dp, &event, dp->addr.client, dp->addr.port); if (snd_seq_oss_process_event(dp, rec, &event)) return 0; /* invalid event - no need to insert queue */ diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c index 09491b27092e..bc6d371031fc 100644 --- a/sound/core/seq/seq_clientmgr.c +++ b/sound/core/seq/seq_clientmgr.c @@ -1905,20 +1905,14 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client, int result; struct snd_seq_client *sender = NULL; struct snd_seq_client_port *sport = NULL; - struct snd_seq_subscribers *p; result = -EINVAL; if ((sender = snd_seq_client_use_ptr(subs->sender.client)) == NULL) goto __end; if ((sport = snd_seq_port_use_ptr(sender, subs->sender.port)) == NULL) goto __end; - p = snd_seq_port_get_subscription(&sport->c_src, &subs->dest); - if (p) { - result = 0; - *subs = p->info; - } else - result = -ENOENT; - + result = snd_seq_port_get_subscription(&sport->c_src, &subs->dest, + subs); __end: if (sport) snd_seq_port_unlock(sport); diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c index f04714d70bf7..9cfe4fcee9a5 100644 --- a/sound/core/seq/seq_ports.c +++ b/sound/core/seq/seq_ports.c @@ -550,10 +550,10 @@ static void delete_and_unsubscribe_port(struct snd_seq_client *client, list_del_init(list); grp->exclusive = 0; write_unlock_irq(&grp->list_lock); - up_write(&grp->list_mutex); if (!empty) unsubscribe_port(client, port, grp, &subs->info, ack); + up_write(&grp->list_mutex); } /* connect two ports */ @@ -635,20 +635,23 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector, /* get matched subscriber */ -struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, - struct snd_seq_addr *dest_addr) +int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, + struct snd_seq_addr *dest_addr, + struct snd_seq_port_subscribe *subs) { - struct snd_seq_subscribers *s, *found = NULL; + struct snd_seq_subscribers *s; + int err = -ENOENT; down_read(&src_grp->list_mutex); list_for_each_entry(s, &src_grp->list_head, src_list) { if (addr_match(dest_addr, &s->info.dest)) { - found = s; + *subs = s->info; + err = 0; break; } } up_read(&src_grp->list_mutex); - return found; + return err; } /* diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h index 26bd71f36c41..06003b36652e 100644 --- a/sound/core/seq/seq_ports.h +++ b/sound/core/seq/seq_ports.h @@ -135,7 +135,8 @@ int snd_seq_port_subscribe(struct snd_seq_client_port *port, struct snd_seq_port_subscribe *info); /* get matched subscriber */ -struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, - struct snd_seq_addr *dest_addr); +int snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, + struct snd_seq_addr *dest_addr, + struct snd_seq_port_subscribe *subs); #endif diff --git a/sound/firewire/amdtp-am824.c b/sound/firewire/amdtp-am824.c index bebddc60fde8..99654e7eb2d4 100644 --- a/sound/firewire/amdtp-am824.c +++ b/sound/firewire/amdtp-am824.c @@ -388,7 +388,7 @@ static void read_midi_messages(struct amdtp_stream *s, u8 *b; for (f = 0; f < frames; f++) { - port = (s->data_block_counter + f) % 8; + port = (8 - s->tx_first_dbc + s->data_block_counter + f) % 8; b = (u8 *)&buffer[p->midi_position]; len = b[0] - 0x80; diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c index b0395c4209ab..a7ab34d5e7b0 100644 --- a/sound/firewire/oxfw/oxfw.c +++ b/sound/firewire/oxfw/oxfw.c @@ -175,9 +175,6 @@ static int detect_quirks(struct snd_oxfw *oxfw) oxfw->midi_input_ports = 0; oxfw->midi_output_ports = 0; - /* Output stream exists but no data channels are useful. */ - oxfw->has_output = false; - return snd_oxfw_scs1x_add(oxfw); } diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 789eca17fc60..f2f1d9fd848c 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c @@ -1700,9 +1700,6 @@ static int azx_first_init(struct azx *chip) chip->msi = 0; } - if (azx_acquire_irq(chip, 0) < 0) - return -EBUSY; - pci_set_master(pci); synchronize_irq(bus->irq); @@ -1809,6 +1806,9 @@ static int azx_first_init(struct azx *chip) return -ENODEV; } + if (azx_acquire_irq(chip, 0) < 0) + return -EBUSY; + strcpy(card->driver, "HDA-Intel"); strlcpy(card->shortname, driver_short_names[chip->driver_type], sizeof(card->shortname)); diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 822650d907fa..95fb213cf94b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -6317,7 +6317,7 @@ static int patch_alc269(struct hda_codec *codec) spec = codec->spec; spec->gen.shared_mic_vref_pin = 0x18; - codec->power_save_node = 1; + codec->power_save_node = 0; #ifdef CONFIG_PM codec->patch_ops.suspend = alc269_suspend; diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c index 6e8eb1f5a041..bed64723e5d9 100644 --- a/sound/soc/codecs/cs4265.c +++ b/sound/soc/codecs/cs4265.c @@ -60,7 +60,7 @@ static const struct reg_default cs4265_reg_defaults[] = { static bool cs4265_readable_register(struct device *dev, unsigned int reg) { switch (reg) { - case CS4265_CHIP_ID ... CS4265_SPDIF_CTL2: + case CS4265_CHIP_ID ... CS4265_MAX_REGISTER: return true; default: return false; diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c index b4d87379d2bc..462341fef5a9 100644 --- a/sound/soc/codecs/cs42xx8.c +++ b/sound/soc/codecs/cs42xx8.c @@ -569,6 +569,7 @@ static int cs42xx8_runtime_resume(struct device *dev) msleep(5); regcache_cache_only(cs42xx8->regmap, false); + regcache_mark_dirty(cs42xx8->regmap); ret = regcache_sync(cs42xx8->regmap); if (ret) { diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 90b5948e0ff3..cba5b5a29da0 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -137,8 +137,12 @@ static int hdmi_codec_startup(struct snd_pcm_substream *substream, if (!ret) { ret = snd_pcm_hw_constraint_eld(substream->runtime, hcp->eld); - if (ret) + if (ret) { + mutex_lock(&hcp->current_stream_lock); + hcp->current_stream = NULL; + mutex_unlock(&hcp->current_stream_lock); return ret; + } } } return 0; diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 3e65dc74eb33..e7aef841f87d 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1924,6 +1924,21 @@ static int max98090_configure_dmic(struct max98090_priv *max98090, return 0; } +static int max98090_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component); + unsigned int fmt = max98090->dai_fmt; + + /* Remove 24-bit format support if it is not in right justified mode. */ + if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_RIGHT_J) { + substream->runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + snd_pcm_hw_constraint_msbits(substream->runtime, 0, 16, 16); + } + return 0; +} + static int max98090_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) @@ -2331,6 +2346,7 @@ EXPORT_SYMBOL_GPL(max98090_mic_detect); #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) static const struct snd_soc_dai_ops max98090_dai_ops = { + .startup = max98090_dai_startup, .set_sysclk = max98090_dai_set_sysclk, .set_fmt = max98090_dai_set_fmt, .set_tdm_slot = max98090_set_tdm_slot, diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 3c5a9804d3f5..5a0b17ebfc02 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c @@ -43,6 +43,7 @@ #define MCASP_MAX_AFIFO_DEPTH 64 +#ifdef CONFIG_PM static u32 context_regs[] = { DAVINCI_MCASP_TXFMCTL_REG, DAVINCI_MCASP_RXFMCTL_REG, @@ -65,6 +66,7 @@ struct davinci_mcasp_context { u32 *xrsr_regs; /* for serializer configuration */ bool pm_state; }; +#endif struct davinci_mcasp_ruledata { struct davinci_mcasp *mcasp; diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index a732b3a065c9..8a2873a7899a 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -172,16 +172,17 @@ config SND_MPC52xx_SOC_EFIKA endif # SND_POWERPC_SOC +config SND_SOC_IMX_PCM_FIQ + tristate + default y if SND_SOC_IMX_SSI=y && (SND_SOC_FSL_SSI=m || SND_SOC_FSL_SPDIF=m) && (MXC_TZIC || MXC_AVIC) + select FIQ + if SND_IMX_SOC config SND_SOC_IMX_SSI tristate select SND_SOC_FSL_UTILS -config SND_SOC_IMX_PCM_FIQ - tristate - select FIQ - comment "SoC Audio support for Freescale i.MX boards:" config SND_MXC_SOC_WM1133_EV1 diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c index 883087f2b092..38132143b7d5 100644 --- a/sound/soc/fsl/eukrea-tlv320.c +++ b/sound/soc/fsl/eukrea-tlv320.c @@ -119,13 +119,13 @@ static int eukrea_tlv320_probe(struct platform_device *pdev) if (ret) { dev_err(&pdev->dev, "fsl,mux-int-port node missing or invalid.\n"); - return ret; + goto err; } ret = of_property_read_u32(np, "fsl,mux-ext-port", &ext_port); if (ret) { dev_err(&pdev->dev, "fsl,mux-ext-port node missing or invalid.\n"); - return ret; + goto err; } /* diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 1d82f68305c3..88a438f6c2de 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -286,8 +286,8 @@ static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) return -EINVAL; } - if ((outrate > 8000 && outrate < 30000) && - (outrate/inrate > 24 || inrate/outrate > 8)) { + if ((outrate >= 8000 && outrate <= 30000) && + (outrate > 24 * inrate || inrate > 8 * outrate)) { pair_err("exceed supported ratio range [1/24, 8] for \ inrate/outrate: %d/%d\n", inrate, outrate); return -EINVAL; diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 9fadf7e31c5f..cb43f57f978b 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -274,12 +274,14 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai, case SND_SOC_DAIFMT_CBS_CFS: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; val_cr4 |= FSL_SAI_CR4_FSD_MSTR; + sai->is_slave_mode = false; break; case SND_SOC_DAIFMT_CBM_CFM: sai->is_slave_mode = true; break; case SND_SOC_DAIFMT_CBS_CFM: val_cr2 |= FSL_SAI_CR2_BCD_MSTR; + sai->is_slave_mode = false; break; case SND_SOC_DAIFMT_CBM_CFS: val_cr4 |= FSL_SAI_CR4_FSD_MSTR; diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index b9e42b503a37..4f8bdb7650e8 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -75,6 +75,7 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, iprop = of_get_property(dma_np, "cell-index", NULL); if (!iprop) { of_node_put(dma_np); + of_node_put(dma_channel_np); return -EINVAL; } *dma_id = be32_to_cpup(iprop); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2553d9c61c7e..c4c11ae8baae 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2469,7 +2469,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) && (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND)) + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND) && + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED)) continue; dev_dbg(be->dev, "ASoC: prepare BE %s\n", diff --git a/sound/usb/line6/pcm.c b/sound/usb/line6/pcm.c index fab53f58d447..a9f99a6c3909 100644 --- a/sound/usb/line6/pcm.c +++ b/sound/usb/line6/pcm.c @@ -558,6 +558,11 @@ int line6_init_pcm(struct usb_line6 *line6, line6pcm->max_packet_size_out = usb_maxpacket(line6->usbdev, usb_sndisocpipe(line6->usbdev, ep_write), 1); + if (!line6pcm->max_packet_size_in || !line6pcm->max_packet_size_out) { + dev_err(line6pcm->line6->ifcdev, + "cannot get proper max packet size\n"); + return -EINVAL; + } spin_lock_init(&line6pcm->out.lock); spin_lock_init(&line6pcm->in.lock); diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 5d2fc5f58bfe..f4fd9548c529 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -753,7 +753,7 @@ static int snd_ni_control_init_val(struct usb_mixer_interface *mixer, return err; } - kctl->private_value |= (value << 24); + kctl->private_value |= ((unsigned int)value << 24); return 0; } @@ -914,7 +914,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer, if (err < 0) return err; - kctl->private_value |= value[0] << 24; + kctl->private_value |= (unsigned int)value[0] << 24; return 0; } diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h index fc446343ff41..7e3b87a77334 100644 --- a/tools/include/linux/bitops.h +++ b/tools/include/linux/bitops.h @@ -3,8 +3,6 @@ #include <asm/types.h> #include <linux/kernel.h> -#include <linux/compiler.h> - #ifndef __WORDSIZE #define __WORDSIZE (__SIZEOF_LONG__ * 8) #endif @@ -12,10 +10,9 @@ #ifndef BITS_PER_LONG # define BITS_PER_LONG __WORDSIZE #endif +#include <linux/bits.h> +#include <linux/compiler.h> -#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) -#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) -#define BITS_PER_BYTE 8 #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) #define BITS_TO_U64(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64)) #define BITS_TO_U32(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32)) diff --git a/tools/include/linux/bits.h b/tools/include/linux/bits.h new file mode 100644 index 000000000000..2b7b532c1d51 --- /dev/null +++ b/tools/include/linux/bits.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_BITS_H +#define __LINUX_BITS_H +#include <asm/bitsperlong.h> + +#define BIT(nr) (1UL << (nr)) +#define BIT_ULL(nr) (1ULL << (nr)) +#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) +#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) +#define BIT_ULL_MASK(nr) (1ULL << ((nr) % BITS_PER_LONG_LONG)) +#define BIT_ULL_WORD(nr) ((nr) / BITS_PER_LONG_LONG) +#define BITS_PER_BYTE 8 + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#define GENMASK(h, l) \ + (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (BITS_PER_LONG - 1 - (h)))) + +#define GENMASK_ULL(h, l) \ + (((~0ULL) - (1ULL << (l)) + 1) & \ + (~0ULL >> (BITS_PER_LONG_LONG - 1 - (h)))) + +#endif /* __LINUX_BITS_H */ diff --git a/tools/objtool/check.c b/tools/objtool/check.c index ae3446768181..95326c6a7a24 100644 --- a/tools/objtool/check.c +++ b/tools/objtool/check.c @@ -28,6 +28,8 @@ #include <linux/hashtable.h> #include <linux/kernel.h> +#define FAKE_JUMP_OFFSET -1 + struct alternative { struct list_head list; struct instruction *insn; @@ -498,7 +500,7 @@ static int add_jump_destinations(struct objtool_file *file) insn->type != INSN_JUMP_UNCONDITIONAL) continue; - if (insn->ignore) + if (insn->ignore || insn->offset == FAKE_JUMP_OFFSET) continue; rela = find_rela_by_dest_range(insn->sec, insn->offset, @@ -645,10 +647,10 @@ static int handle_group_alt(struct objtool_file *file, clear_insn_state(&fake_jump->state); fake_jump->sec = special_alt->new_sec; - fake_jump->offset = -1; + fake_jump->offset = FAKE_JUMP_OFFSET; fake_jump->type = INSN_JUMP_UNCONDITIONAL; fake_jump->jump_dest = list_next_entry(last_orig_insn, list); - fake_jump->ignore = true; + fake_jump->func = orig_insn->func; } if (!special_alt->new_len) { diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c index b9a95a1a8e69..d3d1452021d4 100644 --- a/tools/perf/arch/s390/util/machine.c +++ b/tools/perf/arch/s390/util/machine.c @@ -4,16 +4,19 @@ #include "util.h" #include "machine.h" #include "api/fs/fs.h" +#include "debug.h" int arch__fix_module_text_start(u64 *start, const char *name) { + u64 m_start = *start; char path[PATH_MAX]; snprintf(path, PATH_MAX, "module/%.*s/sections/.text", (int)strlen(name) - 2, name + 1); - - if (sysfs__read_ull(path, (unsigned long long *)start) < 0) - return -1; + if (sysfs__read_ull(path, (unsigned long long *)start) < 0) { + pr_debug2("Using module %s start:%#lx\n", path, m_start); + *start = m_start; + } return 0; } diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c index 3bdb2c78a21b..476e24cf97fa 100644 --- a/tools/perf/builtin-help.c +++ b/tools/perf/builtin-help.c @@ -186,7 +186,7 @@ static void add_man_viewer(const char *name) while (*p) p = &((*p)->next); *p = zalloc(sizeof(**p) + len + 1); - strncpy((*p)->name, name, len); + strcpy((*p)->name, name); } static int supported_man_viewer(const char *name, size_t len) diff --git a/tools/perf/check-headers.sh b/tools/perf/check-headers.sh index 83fe2202382e..ff38fc63bceb 100755 --- a/tools/perf/check-headers.sh +++ b/tools/perf/check-headers.sh @@ -4,6 +4,7 @@ HEADERS=' include/uapi/linux/fcntl.h include/uapi/linux/perf_event.h include/uapi/linux/stat.h +include/linux/bits.h include/linux/hash.h include/uapi/linux/hw_breakpoint.h arch/x86/include/asm/disabled-features.h diff --git a/tools/perf/ui/tui/helpline.c b/tools/perf/ui/tui/helpline.c index 88f5143a5981..3c97e27383a9 100644 --- a/tools/perf/ui/tui/helpline.c +++ b/tools/perf/ui/tui/helpline.c @@ -23,7 +23,7 @@ static void tui_helpline__push(const char *msg) SLsmg_set_color(0); SLsmg_write_nstring((char *)msg, SLtt_Screen_Cols); SLsmg_refresh(); - strncpy(ui_helpline__current, msg, sz)[sz - 1] = '\0'; + strlcpy(ui_helpline__current, msg, sz); } static int tui_helpline__show(const char *format, va_list ap) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 7123f4de32cc..226f4312b8f3 100644 --- a/tools/perf/util/data-convert-bt.c +++ b/tools/perf/util/data-convert-bt.c @@ -265,7 +265,7 @@ static int string_set_value(struct bt_ctf_field *field, const char *string) if (i > 0) strncpy(buffer, string, i); } - strncat(buffer + p, numstr, 4); + memcpy(buffer + p, numstr, 4); p += 3; } } diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index a11f6760cce8..de9b369d2d2e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c @@ -3027,7 +3027,7 @@ perf_event__synthesize_event_update_name(struct perf_tool *tool, if (ev == NULL) return -ENOMEM; - strncpy(ev->data, evsel->name, len); + strlcpy(ev->data, evsel->name, len + 1); err = process(tool, (union perf_event*) ev, NULL, NULL); free(ev); return err; diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index e72d370889f8..8b39e8086c2d 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h @@ -74,7 +74,6 @@ #include <sys/ttydefaults.h> #include <api/fs/tracing_path.h> #include <termios.h> -#include <linux/bitops.h> #include <termios.h> #include "strlist.h" diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh index 8ec76681605c..f25f72a75cf3 100755 --- a/tools/testing/selftests/netfilter/nft_nat.sh +++ b/tools/testing/selftests/netfilter/nft_nat.sh @@ -23,7 +23,11 @@ ip netns add ns0 ip netns add ns1 ip netns add ns2 -ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 +ip link add veth0 netns ns0 type veth peer name eth0 netns ns1 > /dev/null 2>&1 +if [ $? -ne 0 ];then + echo "SKIP: No virtual ethernet pair device support in kernel" + exit $ksft_skip +fi ip link add veth1 netns ns0 type veth peer name eth0 netns ns2 ip -net ns0 link set lo up diff --git a/tools/testing/selftests/timers/adjtick.c b/tools/testing/selftests/timers/adjtick.c index 9887fd538fec..91316ab4b041 100644 --- a/tools/testing/selftests/timers/adjtick.c +++ b/tools/testing/selftests/timers/adjtick.c @@ -147,6 +147,7 @@ int check_tick_adj(long tickval) eppm = get_ppm_drift(); printf("%lld usec, %lld ppm", systick + (systick * eppm / MILLION), eppm); + fflush(stdout); tx1.modes = 0; adjtimex(&tx1); diff --git a/tools/testing/selftests/timers/leapcrash.c b/tools/testing/selftests/timers/leapcrash.c index a1071bdbdeb7..a77c70b47495 100644 --- a/tools/testing/selftests/timers/leapcrash.c +++ b/tools/testing/selftests/timers/leapcrash.c @@ -114,6 +114,7 @@ int main(void) } clear_time_state(); printf("."); + fflush(stdout); } printf("[OK]\n"); return ksft_exit_pass(); diff --git a/tools/testing/selftests/timers/mqueue-lat.c b/tools/testing/selftests/timers/mqueue-lat.c index a2a3924d0b41..efdb62470052 100644 --- a/tools/testing/selftests/timers/mqueue-lat.c +++ b/tools/testing/selftests/timers/mqueue-lat.c @@ -113,6 +113,7 @@ int main(int argc, char **argv) int ret; printf("Mqueue latency : "); + fflush(stdout); ret = mqueue_lat_test(); if (ret < 0) { diff --git a/tools/testing/selftests/timers/nanosleep.c b/tools/testing/selftests/timers/nanosleep.c index ff942ff7c9b3..2e6e94c02a33 100644 --- a/tools/testing/selftests/timers/nanosleep.c +++ b/tools/testing/selftests/timers/nanosleep.c @@ -153,6 +153,7 @@ int main(int argc, char **argv) continue; printf("Nanosleep %-31s ", clockstring(clockid)); + fflush(stdout); length = 10; while (length <= (NSEC_PER_SEC * 10)) { diff --git a/tools/testing/selftests/timers/nsleep-lat.c b/tools/testing/selftests/timers/nsleep-lat.c index 2d7898fda0f1..ac06cf10a5c2 100644 --- a/tools/testing/selftests/timers/nsleep-lat.c +++ b/tools/testing/selftests/timers/nsleep-lat.c @@ -166,6 +166,7 @@ int main(int argc, char **argv) continue; printf("nsleep latency %-26s ", clockstring(clockid)); + fflush(stdout); length = 10; while (length <= (NSEC_PER_SEC * 10)) { diff --git a/tools/testing/selftests/timers/raw_skew.c b/tools/testing/selftests/timers/raw_skew.c index 0ab937a17ebb..4e631da7f956 100644 --- a/tools/testing/selftests/timers/raw_skew.c +++ b/tools/testing/selftests/timers/raw_skew.c @@ -124,6 +124,7 @@ int main(int argv, char **argc) printf("WARNING: ADJ_OFFSET in progress, this will cause inaccurate results\n"); printf("Estimating clock drift: "); + fflush(stdout); sleep(120); get_monotonic_and_raw(&mon, &raw); diff --git a/tools/testing/selftests/timers/set-tai.c b/tools/testing/selftests/timers/set-tai.c index dc88dbc8831f..3ae76ab483de 100644 --- a/tools/testing/selftests/timers/set-tai.c +++ b/tools/testing/selftests/timers/set-tai.c @@ -66,6 +66,7 @@ int main(int argc, char **argv) printf("tai offset started at %i\n", ret); printf("Checking tai offsets can be properly set: "); + fflush(stdout); for (i = 1; i <= 60; i++) { ret = set_tai(i); ret = get_tai(); diff --git a/tools/testing/selftests/timers/set-tz.c b/tools/testing/selftests/timers/set-tz.c index f4184928b16b..b038131c9682 100644 --- a/tools/testing/selftests/timers/set-tz.c +++ b/tools/testing/selftests/timers/set-tz.c @@ -76,6 +76,7 @@ int main(int argc, char **argv) printf("tz_minuteswest started at %i, dst at %i\n", min, dst); printf("Checking tz_minuteswest can be properly set: "); + fflush(stdout); for (i = -15*60; i < 15*60; i += 30) { ret = set_tz(i, dst); ret = get_tz_min(); @@ -87,6 +88,7 @@ int main(int argc, char **argv) printf("[OK]\n"); printf("Checking invalid tz_minuteswest values are caught: "); + fflush(stdout); if (!set_tz(-15*60-1, dst)) { printf("[FAILED] %i didn't return failure!\n", -15*60-1); diff --git a/tools/testing/selftests/timers/threadtest.c b/tools/testing/selftests/timers/threadtest.c index e632e116f05e..a4bf736dd842 100644 --- a/tools/testing/selftests/timers/threadtest.c +++ b/tools/testing/selftests/timers/threadtest.c @@ -175,6 +175,7 @@ int main(int argc, char **argv) strftime(buf, 255, "%a, %d %b %Y %T %z", localtime(&start)); printf("%s\n", buf); printf("Testing consistency with %i threads for %ld seconds: ", thread_count, runtime); + fflush(stdout); /* spawn */ for (i = 0; i < thread_count; i++) diff --git a/tools/testing/selftests/timers/valid-adjtimex.c b/tools/testing/selftests/timers/valid-adjtimex.c index 60fe3c569bd9..a747645d79f4 100644 --- a/tools/testing/selftests/timers/valid-adjtimex.c +++ b/tools/testing/selftests/timers/valid-adjtimex.c @@ -134,6 +134,7 @@ int validate_freq(void) /* Set the leap second insert flag */ printf("Testing ADJ_FREQ... "); + fflush(stdout); for (i = 0; i < NUM_FREQ_VALID; i++) { tx.modes = ADJ_FREQUENCY; tx.freq = valid_freq[i]; @@ -261,6 +262,7 @@ int set_bad_offset(long sec, long usec, int use_nano) int validate_set_offset(void) { printf("Testing ADJ_SETOFFSET... "); + fflush(stdout); /* Test valid values */ if (set_offset(NSEC_PER_SEC - 1, 1)) diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c index 1ebbf233de9a..6d64b2cb02ab 100644 --- a/virt/kvm/arm/vgic/vgic-its.c +++ b/virt/kvm/arm/vgic/vgic-its.c @@ -1466,6 +1466,7 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev) mutex_unlock(&its->its_lock); kfree(its); + kfree(kvm_dev);/* alloc by kvm_ioctl_create_device, free by .destroy */ } static int vgic_its_has_attr(struct kvm_device *dev, |