Merge "ARM: dts: msm: Delete property node for RB3 HW"
diff --git a/AndroidKernel.mk b/AndroidKernel.mk
index 790e713..1c2f92c 100644
--- a/AndroidKernel.mk
+++ b/AndroidKernel.mk
@@ -210,14 +210,31 @@
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 d769cd8..da7b543 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -37,7 +37,7 @@
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 67060d3..2f91abe 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -152,6 +152,9 @@
- QM215
compatible = "qcom, qm215"
+- QCM2150
+ compatible = "qcom, qcm2150"
+
- MDM9640
compatible = "qcom,mdm9640"
@@ -378,6 +381,7 @@
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/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 7454863..240bc5b 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -384,6 +384,9 @@
--> Sleep value (in ms)
- qcom,partial-update-enabled: Boolean used to enable partial
panel update for command mode panels.
+- qcom,partial-update-addr-offset: An array of two values indicate the panel
+ column, row address offset value.
+ Two default values are 0.
- qcom,mdss-dsi-horizontal-line-idle: List of width ranges (EC - SC) in pixels indicating
additional idle time in dsi clock cycles that is needed
to compensate for smaller line width.
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 0000000..aeed60f
--- /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 ee3723b..33b3871 100644
--- a/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt
+++ b/Documentation/devicetree/bindings/net/can/microchip,mcp251x.txt
@@ -4,6 +4,7 @@
- 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/devicetree/bindings/net/can/microchip,mcp25xxfd.txt b/Documentation/devicetree/bindings/net/can/microchip,mcp25xxfd.txt
new file mode 100644
index 0000000..716b0a1
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/microchip,mcp25xxfd.txt
@@ -0,0 +1,31 @@
+* Microchip MCP2517 stand-alone CAN controller device tree bindings
+
+Required properties:
+ - compatible: Should be one of the following:
+ - "microchip,mcp2517fd" for MCP2517fd.
+ - reg: SPI chip select.
+ - clocks: The clock feeding the CAN controller.
+ - interrupt-parent: The parent interrupt controller.
+ - interrupts: Should contain IRQ line for the CAN controller.
+ - gpio-controller: Marks the device node as a GPIO controller
+
+Optional properties:
+ - vdd-supply: Regulator that powers the CAN controller.
+ - xceiver-supply: Regulator that powers the CAN transceiver.
+ - microchip,clock_out_div = <0|1|2|4|10>: Clock output pin divider
+ 0 = Start of Frame output
+ default: 10
+ - microchip,clock_div2: bool: divide the internal clock by 2
+ - gpio_opendrain: bool: enable open-drain for all pins (except cantx)
+
+Example:
+ can0: can@1 {
+ compatible = "microchip,mcp2515";
+ reg = <1>;
+ clocks = <&clk24m>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <13 0x8>;
+ vdd-supply = <®5v0>;
+ xceiver-supply = <®5v0>;
+ gpio-controller;
+ };
diff --git a/Documentation/networking/ip-sysctl.txt b/Documentation/networking/ip-sysctl.txt
index c88a0a8..12d9a68 100644
--- a/Documentation/networking/ip-sysctl.txt
+++ b/Documentation/networking/ip-sysctl.txt
@@ -230,6 +230,14 @@
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
diff --git a/Makefile b/Makefile
index 5e75855..7118777 100755
--- a/Makefile
+++ b/Makefile
@@ -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, 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 @@
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 c7a081c..2de7577 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -23,7 +23,7 @@
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 ea022d4..21ec824 100644
--- a/arch/arc/include/asm/bug.h
+++ b/arch/arc/include/asm/bug.h
@@ -23,7 +23,8 @@
#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 d819de1..3ea4112 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -92,8 +92,11 @@
#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 @@
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 c927aa8..2fb0cd3 100644
--- a/arch/arc/kernel/traps.c
+++ b/arch/arc/kernel/traps.c
@@ -155,3 +155,11 @@
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 61fd1ce..6bb9f8e 100644
--- a/arch/arc/kernel/unwind.c
+++ b/arch/arc/kernel/unwind.c
@@ -185,11 +185,6 @@
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 @@
}
#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 a4dc881..3c88ccb 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -890,9 +890,11 @@
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 @@
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 @@
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 9cc83c5..e664c33 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 b13b0b2..8ccafdf 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 02378db..a2c7679 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 a885052..5834194 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 c5c05fd..200d908 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 2b6cb05..edc5dde 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 ff0ae9a..54f2ef6 100644
--- a/arch/arm/boot/dts/qcom/Makefile
+++ b/arch/arm/boot/dts/qcom/Makefile
@@ -3,7 +3,6 @@
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,18 @@
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-pcie-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 c2a447b..2eaca02 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts
+++ b/arch/arm/boot/dts/qcom/sa415m-ccard-pcie-ep.dts
@@ -31,6 +31,8 @@
&ipa_hw {
qcom,use-ipa-in-mhi-mode;
+ qcom,ipa-config-is-auto;
+ qcom,mhi-event-ring-id-limits = <7 11>; /* start and end */
};
&cnss_pcie {
diff --git a/arch/arm/boot/dts/qcom/sa415m-ccard-usb-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ccard-usb-ep.dts
index 1cf3a55..70e2849 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ccard-usb-ep.dts
+++ b/arch/arm/boot/dts/qcom/sa415m-ccard-usb-ep.dts
@@ -20,3 +20,8 @@
"qcom,sdxpoorwills", "qcom,ccard";
qcom,board-id = <25 2>, <25 0x102>;
};
+
+&ipa_hw {
+ qcom,ipa-config-is-auto;
+};
+
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 0000000..908eb87
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sa415m-cdp.dts
@@ -0,0 +1,36 @@
+/* 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>;
+};
+
+&smb138x {
+ status = "disabled";
+};
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 0000000..39ed5c6
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sa415m-mtp-256.dts
@@ -0,0 +1,34 @@
+/* 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>;
+};
+
+&smb138x {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp-pcie-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ttp-pcie-ep.dts
new file mode 100644
index 0000000..0cbc9e3
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp-pcie-ep.dts
@@ -0,0 +1,65 @@
+/* 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 "sa415m-ttp.dtsi"
+#include "sdxpoorwills-v2.dtsi"
+
+/ {
+ model = "Qualcomm Technologies, Inc. SA415M TTP PCIE-EP";
+ compatible = "qcom,sa415m-ttp",
+ "qcom,sdxpoorwills", "qcom,ttp";
+ qcom,board-id = <30 0x101>;
+};
+
+&mss_mem {
+ reg = <0x86400000 0x9300000>;
+};
+
+&usb {
+ /delete-property/ iommus;
+};
+
+&pcie_ep {
+ status = "okay";
+};
+
+&ipa_hw {
+ qcom,use-ipa-in-mhi-mode;
+ qcom,ipa-config-is-auto;
+ qcom,mhi-event-ring-id-limits = <7 11>; /* start and end */
+};
+
+&cnss_pcie {
+ status = "disabled";
+};
+
+&pcie0 {
+ status = "disabled";
+};
+
+&mhi_device {
+ status = "okay";
+};
+
+&restart_pshold {
+ qcom,force-warm-reboot;
+};
+
+&ipc_router_mhi_dev_xprt {
+ status = "okay";
+};
+
+&mhi_net_device {
+ status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts b/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts
index 802e8319..ffbc8de 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp-usb-ep.dts
@@ -29,3 +29,8 @@
&mss_mem {
reg = <0x86400000 0x9300000>;
};
+
+&ipa_hw {
+ qcom,ipa-config-is-auto;
+};
+
diff --git a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
index 27d4437..f918935 100644
--- a/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
+++ b/arch/arm/boot/dts/qcom/sa415m-ttp.dtsi
@@ -20,10 +20,17 @@
status = "okay";
};
+&sdhc_1 {
+ qcom,nonremovable;
+};
+
&usb {
status = "okay";
qcom,connector-type-uAB;
extcon = <0>, <0>, <0>, <&vbus_detect>;
+ dwc3@a600000 {
+ normal-eps-in-gsi-mode;
+ };
};
&soc {
@@ -46,8 +53,8 @@
};
cnss_pcie: qcom,cnss {
compatible = "qcom,cnss";
- reg = <0x10000000 0x10000000>,
- <0x20000000 0x10000>;
+ reg = <0xa0000000 0x10000000>,
+ <0xb0000000 0x10000>;
reg-names = "smmu_iova_base", "smmu_iova_ipa";
wlan-en-gpio = <&tlmm 52 0>;
@@ -84,6 +91,10 @@
};
};
+&smb138x {
+ status = "disabled";
+};
+
&i2c_4 {
status = "okay";
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 0000000..3a7b072
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sa415m-v2-cdp.dts
@@ -0,0 +1,37 @@
+/* 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>;
+};
+
+&smb138x {
+ status = "disabled";
+};
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 0000000..fe59e05
--- /dev/null
+++ b/arch/arm/boot/dts/qcom/sa415m-v2-mtp.dts
@@ -0,0 +1,39 @@
+/* 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>;
+};
+
+&smb138x {
+ status = "disabled";
+};
diff --git a/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi b/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi
index 2c2319f..934335f 100644
--- a/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi
+++ b/arch/arm/boot/dts/qcom/sdx-audio-lpass.dtsi
@@ -84,7 +84,7 @@
compress: qcom,msm-compress-dsp {
compatible = "qcom,msm-compress-dsp";
- qcom,adsp-version = "MDSP 1.2";
+ qcom,adsp-version = "MDSP 2.8";
};
qcom,msm-dai-stub {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index 09a6219..f441b3f 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -154,7 +154,7 @@
config {
pins = "gpio76", "gpio77";
drive-strength = <2>;
- bias-disable;
+ bias-pull-up;
};
};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
index 70dc3ae..f09e63d 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
@@ -25,7 +25,7 @@
regulator-name = "pmxpoorwills_s1_level";
qcom,set = <RPMH_REGULATOR_SET_ALL>;
regulator-min-microvolt =
- <RPMH_REGULATOR_LEVEL_MIN_SVS>;
+ <RPMH_REGULATOR_LEVEL_RETENTION>;
regulator-max-microvolt = <RPMH_REGULATOR_LEVEL_MAX>;
};
};
@@ -391,7 +391,7 @@
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-enable-ramp-delay = <100>;
- gpio = <&tlmm 96 GPIO_ACTIVE_HIGH>;
+ gpio = <&tlmm 83 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
@@ -401,7 +401,7 @@
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
regulator-enable-ramp-delay = <100>;
- gpio = <&tlmm 83 GPIO_ACTIVE_HIGH>;
+ gpio = <&tlmm 96 GPIO_ACTIVE_HIGH>;
enable-active-high;
};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index abbc8b5..7571661 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";
};
@@ -1390,6 +1389,7 @@
"eth_rgmii_clk", "eth_slave_ahb_clk";
qcom,phy-intr-redirect = <&tlmm 84 GPIO_ACTIVE_LOW>;
qcom,phy-reset = <&tlmm 85 GPIO_ACTIVE_LOW>;
+ qcom,phy-reset-delay-msecs = <10>;
vreg_rgmii-supply = <&vreg_rgmii>;
vreg_emac_phy-supply = <&vreg_emac_phy>;
vreg_rgmii_io_pads-supply = <&vreg_rgmii_io_pads>;
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index 5c68a44..8e386d3 100755
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -331,6 +331,11 @@
CONFIG_MSM_ISPIF=y
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_MDP3=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_SOUND=y
@@ -382,7 +387,6 @@
CONFIG_RTC_DRV_QPNP=y
CONFIG_DMADEVICES=y
CONFIG_QCOM_SPS_DMA=y
-CONFIG_SYNC_FILE=y
CONFIG_UIO=y
CONFIG_UIO_MSM_SHAREDMEM=y
CONFIG_STAGING=y
@@ -394,6 +398,7 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_REVID=y
CONFIG_USB_BAM=y
+CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig
old mode 100755
new mode 100644
index b903f85..5f69894
--- a/arch/arm/configs/msm8909_defconfig
+++ b/arch/arm/configs/msm8909_defconfig
@@ -355,6 +355,11 @@
CONFIG_QCOM_KGSL=y
CONFIG_FB=y
CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_MDP3=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
CONFIG_BACKLIGHT_LCD_SUPPORT=y
CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_LOGO=y
@@ -384,6 +389,8 @@
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
@@ -420,7 +427,6 @@
CONFIG_RTC_DRV_QPNP=y
CONFIG_DMADEVICES=y
CONFIG_QCOM_SPS_DMA=y
-CONFIG_SYNC_FILE=y
CONFIG_UIO=y
CONFIG_UIO_MSM_SHAREDMEM=y
CONFIG_STAGING=y
@@ -434,6 +440,7 @@
CONFIG_SPS_SUPPORT_NDP_BAM=y
CONFIG_QPNP_REVID=y
CONFIG_USB_BAM=y
+CONFIG_MSM_MDSS_PLL=y
CONFIG_REMOTE_SPINLOCK_MSM=y
CONFIG_MAILBOX=y
CONFIG_ARM_SMMU=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index 655d4db..15bd01d 100755
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -39,7 +39,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
@@ -90,7 +89,6 @@
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -98,6 +96,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -107,6 +106,7 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
@@ -219,6 +219,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -250,6 +251,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -275,6 +277,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -293,11 +296,13 @@
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
+CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -554,6 +559,7 @@
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 6e9f546..12254aa 100755
--- a/arch/arm/configs/msm8937_defconfig
+++ b/arch/arm/configs/msm8937_defconfig
@@ -40,7 +40,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -92,7 +91,6 @@
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -101,6 +99,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -110,6 +109,7 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
@@ -222,6 +222,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -254,6 +255,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -279,6 +281,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -297,11 +300,13 @@
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
+CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -565,6 +570,7 @@
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 6ab6c96..1c37757 100755
--- a/arch/arm/configs/msm8937go-perf_defconfig
+++ b/arch/arm/configs/msm8937go-perf_defconfig
@@ -40,7 +40,6 @@
CONFIG_KALLSYMS_ALL=y
# CONFIG_BASE_FULL is not set
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_SLUB_DEBUG is not set
# CONFIG_COMPAT_BRK is not set
@@ -90,7 +89,6 @@
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -98,6 +96,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -107,10 +106,12 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -216,6 +217,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -247,6 +249,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -271,6 +274,7 @@
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -289,11 +293,13 @@
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
+CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -356,7 +362,6 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1360_CHARGER_FG=y
@@ -454,6 +459,7 @@
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_SONY=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
@@ -548,6 +554,7 @@
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 41f11be..2e63db2d 100755
--- a/arch/arm/configs/msm8937go_defconfig
+++ b/arch/arm/configs/msm8937go_defconfig
@@ -41,7 +41,6 @@
CONFIG_KALLSYMS_ALL=y
# CONFIG_BASE_FULL is not set
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -92,7 +91,6 @@
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -101,6 +99,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -110,10 +109,12 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -219,6 +220,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -251,6 +253,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -275,6 +278,7 @@
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
CONFIG_DM_ANDROID_VERITY_AT_MOST_ONCE_DEFAULT_ENABLED=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -293,11 +297,13 @@
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
+CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -362,7 +368,6 @@
CONFIG_POWER_RESET=y
CONFIG_POWER_RESET_QCOM=y
CONFIG_QCOM_DLOAD_MODE=y
-CONFIG_POWER_SUPPLY=y
CONFIG_QPNP_FG=y
CONFIG_SMB135X_CHARGER=y
CONFIG_SMB1360_CHARGER_FG=y
@@ -461,6 +466,7 @@
CONFIG_HID_MAGICMOUSE=y
CONFIG_HID_MICROSOFT=y
CONFIG_HID_MULTITOUCH=y
+CONFIG_HID_SONY=y
CONFIG_USB_HIDDEV=y
CONFIG_USB=y
CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
@@ -557,6 +563,7 @@
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 d072b67..714cab1 100755
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -37,7 +37,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -85,7 +84,6 @@
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -93,6 +91,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -102,10 +101,12 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -211,6 +212,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -242,6 +244,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -265,6 +268,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -283,11 +287,13 @@
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
+CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -555,6 +561,7 @@
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 8ba9cce..0697744 100755
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -38,7 +38,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -88,7 +87,6 @@
CONFIG_NEON=y
CONFIG_KERNEL_MODE_NEON=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -97,6 +95,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -106,10 +105,12 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_NET_IPGRE_DEMUX=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -215,6 +216,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -247,6 +249,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -270,6 +273,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -288,11 +292,13 @@
CONFIG_PPP_MPPE=y
CONFIG_PPP_MULTILINK=y
CONFIG_PPPOE=y
+CONFIG_PPTP=y
CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -565,6 +571,7 @@
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 a517020..326cc4a 100644
--- a/arch/arm/configs/sa415m-perf_defconfig
+++ b/arch/arm/configs/sa415m-perf_defconfig
@@ -229,7 +229,7 @@
CONFIG_CLD_LL_CORE=y
CONFIG_CNSS_GENL=y
# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
@@ -414,6 +414,8 @@
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 e10d4ef..96b3cb9 100644
--- a/arch/arm/configs/sa415m_defconfig
+++ b/arch/arm/configs/sa415m_defconfig
@@ -230,7 +230,7 @@
CONFIG_CLD_LL_CORE=y
CONFIG_CNSS_GENL=y
# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
+CONFIG_INPUT_EVDEV=m
# CONFIG_INPUT_KEYBOARD is not set
# CONFIG_INPUT_MOUSE is not set
CONFIG_INPUT_MISC=y
@@ -445,6 +445,9 @@
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 d597ff0..a4d1631 100755
--- a/arch/arm/configs/sdm670-perf_defconfig
+++ b/arch/arm/configs/sdm670-perf_defconfig
@@ -99,9 +99,11 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -117,7 +119,6 @@
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -163,6 +164,7 @@
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
@@ -196,6 +198,7 @@
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
CONFIG_L2TP=y
CONFIG_L2TP_V3=y
CONFIG_L2TP_IP=y
@@ -465,6 +468,7 @@
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 83aaf9b..8d9d85b 100755
--- a/arch/arm/configs/sdm670_defconfig
+++ b/arch/arm/configs/sdm670_defconfig
@@ -102,9 +102,11 @@
CONFIG_IP_ROUTE_VERBOSE=y
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
CONFIG_INET_IPCOMP=y
+CONFIG_INET_UDP_DIAG=y
CONFIG_INET_DIAG_DESTROY=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_ROUTE_INFO=y
@@ -120,7 +122,6 @@
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -167,6 +168,7 @@
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
@@ -200,6 +202,7 @@
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
CONFIG_L2TP=y
CONFIG_L2TP_DEBUGFS=y
CONFIG_L2TP_V3=y
@@ -477,6 +480,7 @@
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 d4ebf56..1d85857 100644
--- a/arch/arm/include/asm/arch_timer.h
+++ b/arch/arm/include/asm/arch_timer.h
@@ -92,7 +92,14 @@
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 b74b174..b458e41 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 3d7351c..2fd0a26 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
old mode 100644
new mode 100755
index 9316300429..7ba363b
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -76,6 +76,10 @@
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 @@
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 8e4539f..3bdf0d5 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1479,6 +1479,8 @@
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 9a22d40..2477950 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -706,6 +706,9 @@
.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 81c935c..b406c12 100644
--- a/arch/arm/mach-exynos/suspend.c
+++ b/arch/arm/mach-exynos/suspend.c
@@ -500,8 +500,27 @@
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 edb888a..c6aa77d 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 @@
* 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 718981b..0aec48c 100644
--- a/arch/arm/mach-omap2/prm3xxx.c
+++ b/arch/arm/mach-omap2/prm3xxx.c
@@ -433,7 +433,7 @@
* 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 79214d5..3af02d2 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 @@
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 5157889..06956b0 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -351,7 +351,8 @@
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-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 @@
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 @@
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/apq8009-robot-som-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
index 8efa0c5..103ef7f 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-robot-som-refboard.dts
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2018-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
@@ -19,6 +19,7 @@
#include "apq8009-audio-external_codec.dtsi"
#include "msm8909-pm8916-camera.dtsi"
#include "msm8909-pm8916-camera-sensor-robot-som.dtsi"
+#include "dsi-panel-osd-disp-fwvga-video.dtsi"
/ {
model = "Qualcomm Technologies, Inc. APQ8009 Robot SOM refboard";
@@ -192,10 +193,6 @@
vin-supply = <&otg_vreg_5p0>;
};
- mdss_mdp: qcom,mdss_mdp@1a00000 {
- status = "disabled";
- };
-
bluetooth: bt_qca9379 {
compatible = "qca,qca9379";
qca,bt-reset-gpio = <&msm_gpio 47 0>; /* BT_EN */
@@ -372,3 +369,70 @@
&ext_codec {
status = "okay";
};
+
+&rpm_bus {
+ rpm-regulator-ldoa4 {
+ status = "okay";
+ pm8916_l4: regulator-l4 {
+ regulator-min-microvolt = <2050000>;
+ regulator-max-microvolt = <2050000>;
+ qcom,init-voltage = <2050000>;
+ regulator-always-on;
+ status = "okay";
+ };
+ };
+};
+
+&mdss_dsi0_pll {
+ status = "okay";
+};
+
+&mdss_mdp {
+ qcom,mdss-pref-prim-intf = "dsi";
+ status = "okay";
+};
+
+&dsi_osd_disp_fwvga_video {
+ qcom,mdss-dsi-pwm-gpio = <&pm8916_mpps 4 0>;
+};
+
+&pmx_mdss {
+ mdss_dsi_active: mdss_dsi_active {
+ mux {
+ pins = "gpio28", "gpio37";
+ };
+ };
+
+ mdss_dsi_suspend: mdss_dsi_suspend {
+ mux {
+ pins = "gpio28", "gpio37";
+ };
+ };
+};
+
+&mdss_dsi0 {
+ qcom,dsi-pref-prim-pan = <&dsi_osd_disp_fwvga_video>;
+
+ pinctrl-names = "mdss_default", "mdss_sleep";
+ pinctrl-0 = <&mdss_dsi_active &mdss_dsi_select_gpio>;
+ pinctrl-1 = <&mdss_dsi_suspend &mdss_dsi_select_gpio>;
+
+ qcom,platform-reset-gpio = <&msm_gpio 28 0>;
+ qcom,platform-bklight-en-gpio = <&msm_gpio 37 0>;
+
+ vdd-supply = <&pm8916_l17>;
+ vddio-supply = <&pm8916_l6>;
+ status = "okay";
+};
+
+&pm8916_mpps {
+ pinctrl-names = "default";
+ pinctrl-0 = <&ext_fep_wled_pwr_en_default>;
+ ext_fep_wled_pwr_en_default: ext_fep_wled_pwr_en_default {
+ pins = "mpp4"; /* MPP_4 */
+ function = "digital"; /* Digital */
+ output-high; /* Output */
+ power-source = <1>;
+ status = "okay";
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-osd-disp-fwvga-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-osd-disp-fwvga-video.dtsi
index 0967a50..5692a69 100644
--- a/arch/arm64/boot/dts/qcom/dsi-panel-osd-disp-fwvga-video.dtsi
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-osd-disp-fwvga-video.dtsi
@@ -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
@@ -28,7 +28,7 @@
qcom,mdss-dsi-h-sync-skew = <0>;
qcom,mdss-dsi-v-back-porch = <10>;
qcom,mdss-dsi-v-front-porch = <10>;
- qcom,mdss-dsi-v-pulse-width = <20>;
+ qcom,mdss-dsi-v-pulse-width = <5>;
qcom,mdss-dsi-h-left-border = <0>;
qcom,mdss-dsi-h-right-border = <0>;
qcom,mdss-dsi-v-top-border = <0>;
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-truly-rm69090-qvga-cmd.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-truly-rm69090-qvga-cmd.dtsi
new file mode 100644
index 0000000..4d74933
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-truly-rm69090-qvga-cmd.dtsi
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+
+&mdss_mdp {
+ dsi_truly_rm69090_qvga_cmd: qcom,mdss_dsi_truly_rm69090_qvga_cmd {
+ qcom,mdss-dsi-panel-name = "rm69090 qvga cmd mode dsi panel";
+ qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+ qcom,mdss-dsi-panel-type = "dsi_cmd_mode";
+ qcom,mdss-dsi-panel-destination = "display_1";
+ qcom,mdss-dsi-panel-framerate = <60>;
+ qcom,mdss-dsi-virtual-channel-id = <0>;
+ qcom,mdss-dsi-stream = <0>;
+ qcom,mdss-dsi-panel-width = <368>;
+ qcom,mdss-dsi-panel-height = <448>;
+ qcom,mdss-dsi-h-front-porch = <40>;
+ qcom,mdss-dsi-h-back-porch = <20>;
+ qcom,mdss-dsi-h-pulse-width = <2>;
+ qcom,mdss-dsi-h-sync-skew = <0>;
+ qcom,mdss-dsi-v-back-porch = <8>;
+ qcom,mdss-dsi-v-front-porch = <6>;
+ qcom,mdss-dsi-v-pulse-width = <2>;
+ qcom,mdss-dsi-h-left-border = <0>;
+ qcom,mdss-dsi-h-right-border = <0>;
+ qcom,mdss-dsi-v-top-border = <0>;
+ qcom,mdss-dsi-v-bottom-border = <0>;
+ qcom,mdss-dsi-bpp = <24>;
+ qcom,mdss-dsi-color-order = "rgb_swap_rgb";
+ qcom,mdss-dsi-underflow-color = <0xff>;
+ qcom,mdss-dsi-border-color = <0>;
+ qcom,mdss-dsi-pixel-packing = "tight";
+ qcom,mdss-dsi-pixel-alignment = <0>;
+ qcom,mdss-dsi-on-command = [
+ 15 01 00 00 00 00 02 FE 01
+ 15 01 00 00 00 00 02 6A 03
+ 15 01 00 00 00 00 02 FE 00
+ 15 01 00 00 00 00 02 35 00
+ 15 01 00 00 00 00 02 53 20
+ 15 01 00 00 00 00 02 51 80
+ 39 01 00 00 00 00 05 2A 00 10 01 7F
+ 39 01 00 00 00 00 05 2B 00 00 01 BF
+ 05 01 00 00 78 00 02 11 00
+ 05 01 00 00 40 00 02 29 00
+ ];
+ qcom,mdss-dsi-off-command = [
+ 05 01 00 00 28 00 02 28 00
+ 05 01 00 00 78 00 02 10 00
+ 15 01 00 00 00 00 02 4F 01
+ ];
+ qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-off-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-idle-on-command = [
+ 05 01 00 00 00 00 01 39 /* Idle-Mode On */
+ ];
+ qcom,mdss-dsi-idle-off-command = [
+ 15 01 00 00 00 00 02 FE 00
+ 15 01 00 00 00 00 02 53 20
+ 05 01 00 00 00 00 01 38 /* Idle-Mode Off */
+ ];
+ qcom,mdss-dsi-idle-on-command-state = "dsi_hs_mode";
+ qcom,mdss-dsi-idle-off-command-state = "dsi_lp_mode";
+ qcom,mdss-dsi-h-sync-pulse = <1>;
+ qcom,mdss-dsi-traffic-mode = "burst_mode";
+ qcom,mdss-dsi-lane-map = "lane_map_0123";
+ qcom,mdss-dsi-bllp-eof-power-mode;
+ qcom,mdss-dsi-bllp-power-mode;
+ qcom,mdss-dsi-lane-0-state;
+ qcom,mdss-dsi-te-pin-select = <1>;
+ qcom,mdss-dsi-te-dcs-command = <1>;
+ qcom,mdss-dsi-te-check-enable;
+ qcom,mdss-dsi-te-using-te-pin;
+ qcom,mdss-dsi-panel-timings = [7d 25 1d 00 37 33
+ 22 27 1e 03 04 00];
+ qcom,mdss-dsi-t-clk-post = <0x09>;
+ qcom,mdss-dsi-t-clk-pre = <0x2c>;
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <255>;
+ qcom,mdss-dsi-dma-trigger = "trigger_sw";
+ qcom,mdss-dsi-mdp-trigger = "none";
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
+ qcom,mdss-dsi-reset-sequence = <1 1>, <0 12>, <1 12>;
+ };
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
index 656385d..f7746c1 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -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
@@ -289,7 +289,7 @@
};
};
- pmx_mdss {
+ pmx_mdss: pmx_mdss {
mdss_dsi_active: mdss_dsi_active {
mux {
pins = "gpio25", "gpio37";
@@ -343,6 +343,20 @@
};
};
+ mdss_dsi_select_gpio: mdss_dsi_select_gpio {
+ mux {
+ pins = "gpio70";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio70";
+ drive-strength = <8>;
+ bias-pull-down;
+ output-low;
+ };
+ };
+
spi0 {
spi0_default: spi0_default {
mux {
diff --git a/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi
index 6d384fc..010694d 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/sdm429-qrd-spyro-evt-overlay.dts b/arch/arm64/boot/dts/qcom/qcm2150-qrd-overlay.dts
similarity index 81%
rename from arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
rename to arch/arm64/boot/dts/qcom/qcm2150-qrd-overlay.dts
index a90c4ba..d810150 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcm2150-qrd-overlay.dts
@@ -14,9 +14,9 @@
/dts-v1/;
/plugin/;
-#include "sdm429-qrd-spyro-evt.dtsi"
+#include "qcm2150-qrd.dtsi"
/ {
- model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro Overlay";
- qcom,board-id = <0xb 6>;
+ model = "QRD";
+ qcom,board-id = <0x01000b 4>;
};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dts
similarity index 69%
copy from arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
copy to arch/arm64/boot/dts/qcom/qcm2150-qrd.dts
index a90c4ba..5d1e1c5 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dts
@@ -12,11 +12,13 @@
*/
/dts-v1/;
-/plugin/;
-#include "sdm429-qrd-spyro-evt.dtsi"
+#include "qcm2150.dtsi"
+#include "qcm2150-qrd.dtsi"
/ {
- model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro Overlay";
- qcom,board-id = <0xb 6>;
+ 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/sdm429-qrd-spyro-evt-overlay.dts b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dtsi
similarity index 78%
copy from arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
copy to arch/arm64/boot/dts/qcom/qcm2150-qrd.dtsi
index a90c4ba..05af319 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcm2150-qrd.dtsi
@@ -11,12 +11,8 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-/plugin/;
-
-#include "sdm429-qrd-spyro-evt.dtsi"
+#include "qm215-qrd.dtsi"
/ {
- model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro Overlay";
- qcom,board-id = <0xb 6>;
+ model = "Qualcomm Technologies, Inc. QCM2150 QRD";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts b/arch/arm64/boot/dts/qcom/qcm2150.dts
similarity index 79%
copy from arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
copy to arch/arm64/boot/dts/qcom/qcm2150.dts
index a90c4ba..179d0ed 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcm2150.dts
@@ -12,11 +12,11 @@
*/
/dts-v1/;
-/plugin/;
-#include "sdm429-qrd-spyro-evt.dtsi"
+#include "qcm2150.dtsi"
/ {
- model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro Overlay";
- qcom,board-id = <0xb 6>;
+ model = "Qualcomm Technologies, Inc. QCM2150";
+ compatible = "qcom,qcm2150";
+ qcom,pmic-name = "PM8916";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts b/arch/arm64/boot/dts/qcom/qcm2150.dtsi
similarity index 71%
copy from arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
copy to arch/arm64/boot/dts/qcom/qcm2150.dtsi
index a90c4ba..eac04e1 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/qcm2150.dtsi
@@ -11,12 +11,13 @@
* GNU General Public License for more details.
*/
-/dts-v1/;
-/plugin/;
-
-#include "sdm429-qrd-spyro-evt.dtsi"
+#include "qm215.dtsi"
+#include "qm215-pm8916.dtsi"
+#include "qm215-audio.dtsi"
/ {
- model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro Overlay";
- qcom,board-id = <0xb 6>;
+ 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/sda845-svr.dtsi b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
index 2426b47..ece1392 100644
--- a/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda845-svr.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-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
@@ -80,7 +80,15 @@
qcom,disable-ctm;
};
+&ipa_hw {
+ status="disabled";
+};
+
&soc {
+ qcom,rmnet-ipa {
+ status="disabled";
+ };
+
qcom,qbt1000 {
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt.dts b/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt.dts
deleted file mode 100644
index c9d952d..0000000
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt.dts
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * 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 "sdm429.dtsi"
-#include "sdm429-qrd-spyro-evt.dtsi"
-
-/ {
- model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro";
- compatible = "qcom,sdm429-qrd", "qcom,sdm429", "qcom,qrd";
- qcom,board-id = <0xb 6>;
- qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
-};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt.dtsi b/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt.dtsi
deleted file mode 100644
index eaa844b..0000000
--- a/arch/arm64/boot/dts/qcom/sdm429-qrd-spyro-evt.dtsi
+++ /dev/null
@@ -1,667 +0,0 @@
-/*
- * 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 "sdm439-qrd.dtsi"
-#include "sdm429w-pm660.dtsi"
-
-&gpio_key_active {
- mux {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
- function = "gpio";
- };
-
- config {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
- drive-strength = <2>;
- bias-pull-up;
- };
-};
-
-&gpio_key_suspend {
- mux {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
- function = "gpio";
- };
-
- config {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
- drive-strength = <2>;
- bias-pull-up;
- };
-};
-
-&cdc_pdm_lines_act {
- mux {
- pins = "gpio68", "gpio73", "gpio74";
- function = "cdc_pdm0";
- };
-
- config {
- pins = "gpio68", "gpio73", "gpio74";
- drive-strength = <16>;
- };
-};
-
-&cdc_pdm_lines_sus {
- mux {
- pins = "gpio68", "gpio73", "gpio74";
- function = "cdc_pdm0";
- };
-
- config {
- pins = "gpio68", "gpio73", "gpio74";
- drive-strength = <2>;
- bias-disable;
- };
-};
-
-&cam_sensor_rear_standby {
- /* STANDBY */
- mux {
- /delete-property/ pins;
- pins = "gpio92";
- function = "gpio";
- };
-
- config {
- /delete-property/ pins;
- pins = "gpio92";
- bias-disable; /* No PULL */
- drive-strength = <2>; /* 2 MA */
- };
-};
-
-&cam_sensor_rear_standby_sleep {
- /* STANDBY */
- mux {
- /delete-property/ pins;
- pins = "gpio92";
- function = "gpio";
- };
-
- config {
- /delete-property/ pins;
- pins = "gpio92";
- bias-disable; /* No PULL */
- drive-strength = <2>; /* 2 MA */
- };
-};
-
-&cam_sensor_rear_vana {
- /* VANA */
- mux {
- /delete-property/ pins;
- pins = "gpio58";
- function = "gpio";
- };
-
- config {
- /delete-property/ pins;
- pins = "gpio58";
- bias-disable; /* No PULL */
- drive-strength = <2>; /* 2 MA */
- };
-};
-
-&cam_sensor_rear_vana_sleep {
- /* VANA */
- mux {
- /delete-property/ pins;
- pins = "gpio58";
- function = "gpio";
- };
-
- config {
- /delete-property/ pins;
- pins = "gpio58";
- bias-disable; /* No PULL */
- drive-strength = <2>; /* 2 MA */
- };
-};
-&mdss_dsi0 {
- qcom,dsi-pref-prim-pan = <&dsi_edo_rm67162_qvga_cmd>;
- pinctrl-names = "mdss_default", "mdss_sleep";
- pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
- pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
- qcom,platform-te-gpio = <&tlmm 24 0>;
- qcom,platform-reset-gpio = <&tlmm 60 0>;
- qcom,platform-enable-gpio = <&tlmm 69 0>;
-};
-
-&dsi_edo_rm67162_qvga_cmd {
- /delete-property/ qcom,mdss-dsi-panel-timings;
- qcom,mdss-dsi-panel-timings-phy-12nm = [06 05 01 0A 00 03 01 0F];
- qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_dcs";
- qcom,panel-supply-entries = <&dsi_pm660_panel_pwr_supply>;
-};
-&soc {
- /delete-node/ qcom,cci@1b0c000;
- cci: qcom,cci@1b0c000 {
- status = "ok";
- cell-index = <0>;
- compatible = "qcom,cci";
- reg = <0x1b0c000 0x4000>;
- #address-cells = <1>;
- #size-cells = <0>;
- reg-names = "cci";
- interrupts = <0 50 0>;
- interrupt-names = "cci";
- clocks = <&clock_gcc clk_gcc_camss_ispif_ahb_clk>,
- <&clock_gcc clk_cci_clk_src>,
- <&clock_gcc clk_gcc_camss_cci_ahb_clk>,
- <&clock_gcc clk_gcc_camss_cci_clk>,
- <&clock_gcc clk_gcc_camss_ahb_clk>,
- <&clock_gcc clk_gcc_camss_top_ahb_clk>;
- clock-names = "ispif_ahb_clk", "cci_src_clk",
- "cci_ahb_clk", "camss_cci_clk",
- "camss_ahb_clk", "camss_top_ahb_clk";
- qcom,clock-rates = <61540000 19200000 0 0 0 0>,
- <61540000 37500000 0 0 0 0>;
- pinctrl-names = "cci_default", "cci_suspend";
- pinctrl-0 = <&cci0_active &cci1_active>;
- pinctrl-1 = <&cci0_suspend &cci1_suspend>;
- gpios = <&tlmm 29 0>,
- <&tlmm 30 0>,
- <&tlmm 31 0>,
- <&tlmm 32 0>;
- qcom,gpio-tbl-num = <0 1 2 3>;
- qcom,gpio-tbl-flags = <1 1 1 1>;
- qcom,gpio-tbl-label = "CCI_I2C_DATA0",
- "CCI_I2C_CLK0",
- "CCI_I2C_DATA1",
- "CCI_I2C_CLK1";
- i2c_freq_100Khz: qcom,i2c_standard_mode {
- status = "disabled";
- };
- i2c_freq_400Khz: qcom,i2c_fast_mode {
- status = "disabled";
- };
- i2c_freq_custom: qcom,i2c_custom_mode {
- status = "disabled";
- };
-
- i2c_freq_1Mhz: qcom,i2c_fast_plus_mode {
- status = "disabled";
- };
- };
-};
-
-#include "sdm429w-camera-sensor-spyro.dtsi"
-
-&i2c_5 {
- status = "disabled";
-};
-
-&vol_up {
- gpios = <&tlmm 35 0x1>;
-};
-
-&gpio_keys {
- function_1: function_1 {
- label = "function_1";
- gpios = <&tlmm 127 0x1>;
- linux,input-type = <1>;
- linux,code = <116>;
- debounce-interval = <15>;
- linux,can-disable;
- gpio-key,wakeup;
- };
-
- function_2: function_2 {
- label = "function_2";
- gpios = <&tlmm 126 0x1>;
- linux,input-type = <1>;
- linux,code = <117>;
- debounce-interval = <15>;
- linux,can-disable;
- gpio-key,wakeup;
- };
-};
-
-&soc {
- /delete-node/ qcom,spm@b1d2000;
- qcom,spm@b1d2000 {
- compatible = "qcom,spm-v2";
- #address-cells = <1>;
- #size-cells = <1>;
- reg = <0xb1d2000 0x1000>;
- qcom,name = "system-cci";
- qcom,saw2-ver-reg = <0xfd0>;
- qcom,saw2-cfg = <0x14>;
- qcom,saw2-spm-dly= <0x3C102800>;
- qcom,saw2-spm-ctl = <0xe>;
- qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
- qcom,vctl-timeout-us = <500>;
- qcom,vctl-port = <0x0>;
- qcom,vctl-port-ub = <0x1>;
- qcom,pfm-port = <0x2>;
- };
-
-};
-
-
-&dsi_hx8399c_hd_vid {
- qcom,mdss-dsi-on-command = [
- 39 01 00 00 00 00 04
- b9 ff 83 99
- 39 01 00 00 00 00 02
- d2 88
- 39 01 00 00 00 00 0c
- b1 02 04 72 92 01
- 32 aa 11 11 52 57
- 39 01 00 00 00 00 10
- b2 00 80 80 cc 05 07 5a
- 11 10 10 00 1e 70 03 d4
- 39 01 00 00 00 00 2d
- b4 00 ff 59 59 01 ab 00
- 00 09 00 03 05 00 28 03
- 0b 0d 21 03 02 00 0c a3
- 80 59 59 02 ab 00 00 09
- 00 03 05 00 28 03 0b 0d
- 02 00 0c a3 01
- 39 01 00 00 05 00 22
- d3 00 0c 03 03 00 00 10
- 10 00 00 03 00 03 00 08
- 78 08 78 00 00 00 00 00
- 24 02 05 05 03 00 00 00
- 05 40
- 39 01 00 00 05 00 21
- d5 20 20 19 19 18 18 02
- 03 00 01 24 24 18 18 18
- 18 24 24 00 00 00 00 00
- 00 00 00 2f 2f 30 30 31
- 31
- 39 01 00 00 05 00 21
- d6 24 24 18 18 19 19 01
- 00 03 02 24 24 18 18 18
- 18 20 20 40 40 40 40 40
- 40 40 40 2f 2f 30 30 31
- 31
- 39 01 00 00 00 00 02
- bd 00
- 39 01 00 00 00 00 11
- d8 aa aa aa aa aa aa aa
- aa aa ba aa aa aa ba aa
- aa
- 39 01 00 00 00 00 02
- bd 01
- 39 01 00 00 00 00 11
- d8 00 00 00 00 00 00 00
- 00 82 ea aa aa 82 ea aa
- aa
- 39 01 00 00 00 00 02
- bd 02
- 39 01 00 00 00 00 09
- d8 ff ff c0 3f ff ff c0
- 3f
- 39 01 00 00 00 00 02
- bd 00
- 39 01 00 00 05 00 37
- e0 01 21 31 2d 66 6f 7b
- 75 7a 81 86 89 8c 90 95
- 97 9a a1 a2 aa 9e ad b0
- 5b 57 63 7a 01 21 31 2d
- 66 6f 7b 75 7a 81 86 89
- 8c 90 95 97 9a a1 a2 aa
- 9e ad b0 5b 57 63 7a
- 39 01 00 00 00 00 03
- b6 7e 7e
- 39 01 00 00 00 00 02
- cc 08
- 39 01 00 00 00 00 02
- 35 00
- 39 01 00 00 00 00 02
- dd 03
- 05 01 00 00 78 00 02 11 00
- 05 01 00 00 05 00 02 29 00];
- qcom,mdss-dsi-reset-sequence = <1 2>, <0 5>, <1 10>;
- };
-
-&firmware {
- android {
- compatible = "android,firmware";
- vbmeta {
- compatible = "android,vbmeta";
- parts = "vbmeta,boot,system,vendor,dtbo,recovery";
- };
- fstab {
- compatible = "android,fstab";
- vendor {
- compatible = "android,vendor";
- dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
- type = "ext4";
- mnt_flags = "ro,barrier=1,discard";
- fsmgr_flags = "wait,avb";
- status = "ok";
- };
- system {
- compatible = "android,system";
- dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
- type = "ext4";
- mnt_flags = "ro,barrier=1,discard";
- fsmgr_flags = "wait,avb";
- status = "ok";
- };
- };
- };
-};
-
-&i2c_4 {
- status = "ok";
-
- tsc@24 {
- compatible = "cy,cyttsp5_i2c_adapter";
- reg = <0x24>;
-
- interrupt-parent = <&tlmm>;
- interrupts = <65 0x2008>;
- cy,adapter_id = "cyttsp5_i2c_adapter";
- vcc_i2c-supply = <&L13A>;
- vdd-supply = <&L15A>;
- pinctrl-names = "pmx_ts_active", "pmx_ts_suspend",
- "pmx_ts_release";
- pinctrl-0 = <&ts_int_active &ts_reset_active>;
- pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
- pinctrl-2 = <&ts_release>;
-
- cy,core {
- cy,name = "cyttsp5_core";
- cy,irq_gpio = <65>;
- cy,rst_gpio = <64>;
- cy,hid_desc_register = <1>;
- cy,flags = <4>;
- cy,easy_wakeup_gesture = <1>;
- cy,btn_keys = <172 139 158 217 114 115 212 116>;
- cy,btn_keys-tag = <0>;
-
- cy,mt {
- cy,name = "cyttsp5_mt";
-
- cy,inp_dev_name = "cyttsp5_mt";
- cy,flags = <0x28>;
- cy,abs =
- <0x35 0 320 0 0
- 0x36 0 360 0 0
- 0x3a 0 255 0 0
- 0xffff 0 255 0 0
- 0x39 0 15 0 0
- 0x30 0 255 0 0
- 0x31 0 255 0 0
- 0x34 0xffffff81 127 0 0
- 0x37 0 1 0 0
- 0x3b 0 255 0 0>;
-
- cy,vkeys_x = <320>;
- cy,vkeys_y = <360>;
-
- cy,virtual_keys =
- <158 1360 90 160 180
- 139 1360 270 160 180
- 172 1360 450 160 180
- 217 1360 630 160 180>;
- };
-
- cy,btn {
- cy,name = "cyttsp5_btn";
-
- cy,inp_dev_name = "cyttsp5_btn";
- };
-
- cy,proximity {
- cy,name = "cyttsp5_proximity";
-
- cy,inp_dev_name = "cyttsp5_proximity";
- cy,abs = <0x19 0 1 0 0>;
- };
- };
- };
-
-};
-
-&tlmm {
- pmx_ts_int_active {
- ts_int_active: ts_int_active {
- mux {
- pins = "gpio65";
- function = "gpio";
- };
-
- config {
- pins = "gpio65";
- drive-strength = <8>;
- bias-pull-up;
- };
- };
- };
-
- pmx_ts_int_suspend {
- ts_int_suspend: ts_int_suspend {
- mux {
- pins = "gpio65";
- function = "gpio";
- };
-
- config {
- pins = "gpio65";
- drive-strength = <2>;
- bias-pull-down;
- };
- };
- };
-
- pmx_ts_reset_active {
- ts_reset_active: ts_reset_active {
- mux {
- pins = "gpio64";
- function = "gpio";
- };
-
- config {
- pins = "gpio64";
- drive-strength = <8>;
- bias-pull-up;
- };
- };
- };
-
- pmx_ts_reset_suspend {
- ts_reset_suspend: ts_reset_suspend {
- mux {
- pins = "gpio64";
- function = "gpio";
- };
-
- config {
- pins = "gpio64";
- drive-strength = <2>;
- bias-pull-down;
- };
- };
- };
-
- pmx_ts_release {
- ts_release: ts_release {
- mux {
- pins = "gpio65", "gpio64";
- function = "gpio";
- };
-
- config {
- pins = "gpio65", "gpio64";
- drive-strength = <2>;
- bias-pull-down;
- };
- };
- };
-
- smart_pa_int {
- pa_int_default: pa_int_default {
- mux {
- pins = "gpio73", "gpio73";
- function = "gpio";
- };
-
- config {
- pins = "gpio73", "gpio73";
- drive-strength = <4>;
- bias-disable;
- };
- };
- };
-
- smart_pa_rst {
- pa_rst_default: pa_rst_default {
- mux {
- pins = "gpio68", "gpio68";
- function = "gpio";
- };
-
- config {
- pins = "gpio68", "gpio68";
- drive-strength = <4>;
- bias-disable;
- };
- };
- };
-
-};
-
-&modem_mem {
- reg = <0x0 0x86800000 0x0 0x5000000>;
-};
-
-&adsp_fw_mem {
- reg = <0x0 0x8b800000 0x0 0x1400000>;
-};
-
-&wcnss_fw_mem {
- reg = <0x0 0x8cc00000 0x0 0x700000>;
-};
-
-
-&int_codec {
- compatible = "qcom,msm8952-dig-asoc-snd";
- status = "okay";
- qcom,model = "sdm429-qrd-snd-card";
- qcom,msm-ext-pa = "quaternary";
- /delete-property/ qcom,split-a2dp;
- asoc-wsa-codec-names;
- asoc-wsa-codec-prefixes;
- ext_pa_aw8896;
- qcom,audio-routing =
- "CDC_CONN", "MCLK",
- "QUAT_MI2S_RX", "DIGITAL_REGULATOR",
- "TX_I2S_CLK", "DIGITAL_REGULATOR",
- "DMIC1", "Digital Mic1",
- "DMIC2", "Digital Mic2";
- qcom,cdc-dmic-gpios = <&cdc_dmic_gpios>;
- qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
- qcom,msm-gpios =
- "quat_i2s",
- "dmic";
- qcom,pinctrl-names =
- "all_off",
- "quat_i2s_act",
- "dmic_act",
- "quat_i2s_dmic_act";
- pinctrl-names =
- "all_off",
- "quat_i2s_act",
- "dmic_act",
- "quat_i2s_dmic_act";
- pinctrl-0 = <&quat_mi2s_sleep &quat_mi2s_din_sleep
- &cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
- pinctrl-1 = <&quat_mi2s_active &quat_mi2s_din_active
- &cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
- pinctrl-2 = <&quat_mi2s_sleep &quat_mi2s_din_sleep
- &cdc_dmic0_clk_act &cdc_dmic0_data_act>;
- pinctrl-3 = <&quat_mi2s_active &quat_mi2s_din_active
- &cdc_dmic0_clk_act &cdc_dmic0_data_act>;
- /delete-property/qcom,cdc-us-euro-gpios;
- /delete-property/qcom,pri-mi2s-gpios;
- /delete-property/qcom,cdc-us-eu-gpios;
-
-
- asoc-codec = <&stub_codec>, <&msm_dig_codec>, <&ext_smart_pa>;
- asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec", "ext-smart-pa";
-};
-
-&soc {
- msm_dig_codec: msm_dig_codec {
- compatible = "qcom,msm-digital-codec";
- reg = <0xc0f0000 0x0>;
- qcom,no-analog-codec;
- cdc-vdd-digital-supply = <&pm660_l9>;
- qcom,cdc-vdd-digital-voltage = <1800000 1800000>;
- qcom,cdc-vdd-digital-current = <10000>;
- qcom,cdc-on-demand-supplies = "cdc-vdd-digital";
- };
-
- cdc_dmic_gpios: cdc_dmic_pinctrl {
- compatible = "qcom,msm-cdc-pinctrl";
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&cdc_dmic0_clk_act &cdc_dmic0_data_act>;
- pinctrl-1 = <&cdc_dmic0_clk_sus &cdc_dmic0_data_sus>;
- };
-
- cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
- compatible = "qcom,msm-cdc-pinctrl";
- pinctrl-names = "aud_active", "aud_sleep";
- pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
- pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
- };
-};
-
-&wsa881x_i2c_f {
- status = "disabled";
-};
-
-&wsa881x_i2c_45 {
- status = "disabled";
-};
-
-&wsa881x_analog_vi_gpio {
- status = "disabled";
-};
-
-&wsa881x_analog_clk_gpio {
- status = "disabled";
-};
-
-&wsa881x_analog_reset_gpio {
- status = "disabled";
-};
-
-&cdc_us_euro_sw {
- status = "disabled";
-};
-
-&cdc_pri_mi2s_gpios {
- status = "disabled";
-};
-
-&cdc_quin_mi2s_gpios {
- status = "disabled";
-};
-
-&i2c_2 {
- ext_smart_pa: aw8896_smartpa@34 {
- compatible = "awinic,aw8896_smartpa";
- reg = <0x34>;
- reset-gpio = <&tlmm 68 0>;
- irq-gpio = <&tlmm 73 0>;
- pinctrl-names = "default";
- pinctrl-0 = <&pa_int_default &pa_rst_default>;
- status = "okay";
- };
-};
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 5c15948..8d047ca 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 3207827..9014166 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-evt.dtsi
@@ -14,15 +14,48 @@
#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 {
+ sd_eldo_active: sd_eldo_active {
+ mux {
+ pins = "gpio91";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio91";
+ drive-strength = <2>;
+ bias-pull-up;
+ };
+ };
+ };
+
+ sd_eldo_suspend {
+ sd_eldo_suspend: sd_eldo_suspend {
+ mux {
+ pins = "gpio91";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio91";
+ drive-strength = <2>;
+ bias-disable;
+ };
+ };
+ };
+};
&gpio_key_active {
mux {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
+ pins = "gpio127", "gpio128", "gpio35", "gpio126";
function = "gpio";
};
config {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
+ pins = "gpio127", "gpio128", "gpio35", "gpio126";
drive-strength = <2>;
bias-pull-up;
};
@@ -30,18 +63,36 @@
&gpio_key_suspend {
mux {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
+ pins = "gpio127", "gpio128", "gpio35", "gpio126";
function = "gpio";
};
config {
- pins = "gpio91", "gpio127", "gpio128", "gpio35", "gpio126";
+ pins = "gpio127", "gpio128", "gpio35", "gpio126";
drive-strength = <2>;
bias-pull-up;
};
};
&soc {
+ /delete-node/ qcom,spm@b1d2000;
+ qcom,spm@b1d2000 {
+ compatible = "qcom,spm-v2";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ reg = <0xb1d2000 0x1000>;
+ qcom,name = "system-cci";
+ qcom,saw2-ver-reg = <0xfd0>;
+ qcom,saw2-cfg = <0x14>;
+ qcom,saw2-spm-dly= <0x3C102800>;
+ qcom,saw2-spm-ctl = <0xe>;
+ qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+ qcom,vctl-timeout-us = <500>;
+ qcom,vctl-port = <0x0>;
+ qcom,vctl-port-ub = <0x1>;
+ qcom,pfm-port = <0x2>;
+ };
+
gpio_keys: gpio_keys {
compatible = "gpio-keys";
label = "gpio-keys";
@@ -124,8 +175,10 @@
qcom,vdd-io-current-level = <200 22000>;
pinctrl-names = "active", "sleep";
- pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
- pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+ pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on
+ &sd_eldo_active>;
+ pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off
+ &sd_eldo_suspend>;
cd-gpios = <&tlmm 67 0x0>;
@@ -180,7 +233,7 @@
&secure_mem {
alignment = <0 0x400000>;
- size = <0 0x400000>;
+ size = <0 0x800000>;
status = "okay";
};
@@ -189,11 +242,11 @@
};
&adsp_fw_mem {
- reg = <0x0 0x8b800000 0x0 0x1400000>;
+ reg = <0x0 0x8b800000 0x0 0x1500000>;
};
&wcnss_fw_mem {
- reg = <0x0 0x8cc00000 0x0 0x700000>;
+ reg = <0x0 0x8cd00000 0x0 0x700000>;
};
&i2c_4 {
@@ -382,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/sdm429-spyro-qrd-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi
index 247d312..57cd8f0 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-mdss-panels.dtsi
@@ -12,6 +12,7 @@
*/
#include "dsi-panel-edo-rm67162-qvga-cmd.dtsi"
+#include "dsi-panel-truly-rm69090-qvga-cmd.dtsi"
&soc {
dsi_pm660_panel_pwr_supply: dsi_pm660_panel_pwr_supply {
@@ -83,3 +84,14 @@
qcom,partial-update-enabled;
qcom,panel-roi-alignment = <2 2 4 2 320 2>;
};
+
+&dsi_truly_rm69090_qvga_cmd {
+ /delete-property/ qcom,mdss-dsi-panel-timings;
+ qcom,mdss-dsi-panel-timings-phy-12nm = [04 04 01 08 00 03 01 0D];
+ qcom,panel-supply-entries = <&dsi_pm660_panel_pwr_supply>;
+ qcom,partial-update-enabled;
+ qcom,partial-update-addr-offset = <0x10 0>;
+ qcom,panel-roi-alignment = <2 2 4 2 20 2>;
+ qcom,esd-check-enabled;
+ qcom,mdss-dsi-panel-status-check-mode = "te_signal_check";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-wdp-overlay.dts b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-wdp-overlay.dts
index f70c458..26819ac 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-wdp-overlay.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-qrd-wdp-overlay.dts
@@ -20,7 +20,7 @@
model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro WDP Overlay";
compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd";
qcom,msm-id = <416 0x0>;
- qcom,board-id = <0x01000b 6>;
+ qcom,board-id = <0x01000b 7>;
qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
};
@@ -39,3 +39,64 @@
&sdhc_2 {
cd-gpios = <&tlmm 67 0x1>;
};
+
+&mdss_dsi {
+ vddio-supply = <&L12A>; /* 1.8v */
+};
+
+&mdss_dsi0_pll {
+ vddio-supply = <&L12A>; /* 1.8V */
+};
+
+&mdss_dsi1_pll {
+ vddio-supply = <&L12A>; /* 1.8V */
+};
+
+&mdss_dsi0 {
+ qcom,platform-enable-gpio = <&pm660_gpios 12 0>;
+ /delete-property/ vdd-supply;
+ qcom,dsi-pref-prim-pan = <&dsi_truly_rm69090_qvga_cmd>;
+};
+&dsi_pm660_panel_pwr_supply {
+ /delete-node/ qcom,panel-supply-entry@0;
+};
+
+&pm660_gpios {
+ gpio@cb00 {
+ status = "ok";
+ qcom,mode = <1>;
+ qcom,vin-sel = <0>;
+ qcom,src-sel = <0>;
+ qcom,master-en = <1>;
+ qcom,out-strength = <2>;
+ };
+};
+
+&i2c_4 {
+ status = "ok";
+
+ tsc@24 {
+ cy,core {
+ cy,mt {
+ cy,name = "cyttsp5_mt";
+
+ cy,inp_dev_name = "cyttsp5_mt";
+ cy,flags = <0x8>;
+ cy,abs =
+ <0x35 0 368 0 0
+ 0x36 0 448 0 0
+ 0x3a 0 255 0 0
+ 0xffff 0 255 0 0
+ 0x39 0 15 0 0
+ 0x30 0 255 0 0
+ 0x31 0 255 0 0
+ 0x34 0xffffff81 127 0 0
+ 0x37 0 1 0 0
+ 0x3b 0 255 0 0>;
+
+ };
+
+ };
+ };
+
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-spyro-wdp.dts b/arch/arm64/boot/dts/qcom/sdm429-spyro-wdp.dts
index dd12d18..b6eedaf 100644
--- a/arch/arm64/boot/dts/qcom/sdm429-spyro-wdp.dts
+++ b/arch/arm64/boot/dts/qcom/sdm429-spyro-wdp.dts
@@ -19,6 +19,6 @@
model = "Qualcomm Technologies, Inc. SDM429 QRD Spyro WDP";
compatible = "qcom,sdm429w-qrd", "qcom,sdm429w", "qcom,qrd";
qcom,msm-id = <416 0x0>;
- qcom,board-id = <0x01000b 6>;
+ qcom,board-id = <0x01000b 7>;
qcom,pmic-id = <0x0002001b 0x0 0x0 0x0>;
};
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 45756f7..c032db5 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-pm660.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi
index b432ce4..f6d85f4 100644
--- a/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm429w-pm660.dtsi
@@ -370,9 +370,10 @@
/* over-write the PM660 GPIO mappings for 429w */
&pm660_gpios {
- interrupts = <0x0 0xc3 0 IRQ_TYPE_NONE>;
- interrupt-names = "pm660_gpio4";
- qcom,gpios-disallowed = <1 2 3 5 6 7 8 9 10 11 12 13>;
+ interrupts = <0x0 0xc3 0 IRQ_TYPE_NONE>,
+ <0x0 0xcb 0 IRQ_TYPE_NONE>;
+ interrupt-names = "pm660_gpio4", "pm660_gpio12";
+ qcom,gpios-disallowed = <1 2 3 5 6 7 8 9 10 11 13>;
};
&pm660_vadc {
@@ -403,6 +404,8 @@
qcom,use-extcon;
qcom,pd-not-supported;
+ dpdm-supply = <&usb_otg>;
+
qcom,chgr@1000 {
reg = <0x1000 0x100>;
interrupts =
diff --git a/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm429w-regulator.dtsi
index 4b521b2..db76a24 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 2955610..2db4b60 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-rb3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-rb3.dtsi
@@ -290,6 +290,11 @@
&pmi8998_fg {
qcom,battery-data = <&mtp_batterydata>;
+ status = "disabled";
+};
+
+&bcl_sensor {
+ status = "disabled";
};
&smb1355_charger_0 {
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 24eb870..103334c 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-v2.1-rb3.dtsi
@@ -33,6 +33,33 @@
status = "ok";
};
+&pcie1 {
+ status = "disable";
+};
+
+&soc {
+ clk40M: can_clock {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <40000000>;
+ };
+};
+
+&qupv3_se0_spi {
+ status = "ok";
+ can@0 {
+ compatible = "microchip,mcp2517fd";
+ reg = <0>;
+ clocks = <&clk40M>;
+ interrupt-parent = <&tlmm>;
+ interrupts = <104 0>;
+ interrupt-names = "can_irq";
+ spi-max-frequency = <10000000>;
+ gpio-controller;
+ status = "okay";
+ };
+};
+
&qupv3_se3_i2c {
status = "disabled";
};
@@ -71,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";
};
@@ -223,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/boot/dts/qcom/sdw3100-apq8009w-wtp.dts b/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-wtp.dts
index 1f91311..e23d1a6 100644
--- a/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-wtp.dts
+++ b/arch/arm64/boot/dts/qcom/sdw3100-apq8009w-wtp.dts
@@ -26,7 +26,8 @@
qcom,msm-id = <265 0>,
<301 0>;
qcom,board-id = <8 0x10f>,
- <8 0x117>;
+ <8 0x117>,
+ <8 0x17>;
qcom,pmic-id = <0x0001001b 0x0 0x0 0x0>,
<0x0001011b 0x0 0x0 0x0>;
};
diff --git a/arch/arm64/configs/msm8937-perf_defconfig b/arch/arm64/configs/msm8937-perf_defconfig
index 7fde262..2ea4bd0 100755
--- a/arch/arm64/configs/msm8937-perf_defconfig
+++ b/arch/arm64/configs/msm8937-perf_defconfig
@@ -38,7 +38,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -80,7 +79,6 @@
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -97,6 +95,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -218,6 +217,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -249,6 +249,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -274,6 +275,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -298,6 +300,7 @@
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
diff --git a/arch/arm64/configs/msm8937_defconfig b/arch/arm64/configs/msm8937_defconfig
index 59f906a..c6312ed 100755
--- a/arch/arm64/configs/msm8937_defconfig
+++ b/arch/arm64/configs/msm8937_defconfig
@@ -39,7 +39,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -83,7 +82,6 @@
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -101,6 +99,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -223,6 +222,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -255,6 +255,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -280,6 +281,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -304,6 +306,7 @@
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
@@ -339,6 +342,7 @@
# CONFIG_SERIO_SERPORT is not set
# CONFIG_VT is not set
# CONFIG_LEGACY_PTYS is not set
+# CONFIG_DEVMEM is not set
# CONFIG_DEVKMEM is not set
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index b346f4e..4374ef3 100755
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -38,7 +38,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -79,7 +78,6 @@
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -96,6 +94,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -215,6 +214,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -248,6 +248,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -272,6 +273,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -295,6 +297,7 @@
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 2c1e89b..66ae8cf 100755
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -39,7 +39,6 @@
# CONFIG_RD_LZ4 is not set
CONFIG_KALLSYMS_ALL=y
CONFIG_BPF_SYSCALL=y
-# CONFIG_MEMBARRIER is not set
CONFIG_EMBEDDED=y
# CONFIG_COMPAT_BRK is not set
CONFIG_PROFILING=y
@@ -82,7 +81,6 @@
CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_COMPAT=y
-CONFIG_PM_AUTOSLEEP=y
CONFIG_PM_WAKELOCKS=y
CONFIG_PM_WAKELOCKS_LIMIT=0
# CONFIG_PM_WAKELOCKS_GC is not set
@@ -100,6 +98,7 @@
CONFIG_PACKET=y
CONFIG_UNIX=y
CONFIG_XFRM_USER=y
+CONFIG_XFRM_INTERFACE=y
CONFIG_XFRM_STATISTICS=y
CONFIG_NET_KEY=y
CONFIG_INET=y
@@ -220,6 +219,7 @@
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_HTB=y
CONFIG_NET_SCH_PRIO=y
+CONFIG_NET_SCH_INGRESS=y
CONFIG_NET_CLS_FW=y
CONFIG_NET_CLS_U32=y
CONFIG_CLS_U32_MARK=y
@@ -254,6 +254,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_HDCP_QSEECOM=y
@@ -278,6 +279,7 @@
CONFIG_DM_UEVENT=y
CONFIG_DM_VERITY=y
CONFIG_DM_VERITY_FEC=y
+CONFIG_DM_BOW=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=y
CONFIG_TUN=y
@@ -302,6 +304,7 @@
CONFIG_PPPOPNS=y
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_RTL8152=y
CONFIG_USB_USBNET=y
# CONFIG_WLAN_VENDOR_ADMTEK is not set
# CONFIG_WLAN_VENDOR_ATH is not set
diff --git a/arch/arm64/configs/sdm670-perf_defconfig b/arch/arm64/configs/sdm670-perf_defconfig
index d75479e..d233c67 100755
--- a/arch/arm64/configs/sdm670-perf_defconfig
+++ b/arch/arm64/configs/sdm670-perf_defconfig
@@ -104,6 +104,7 @@
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
@@ -125,7 +126,6 @@
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -172,6 +172,7 @@
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
@@ -205,6 +206,7 @@
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
CONFIG_L2TP=y
CONFIG_L2TP_V3=y
CONFIG_L2TP_IP=y
@@ -249,6 +251,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index 1eea891..25e3245 100755
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -109,6 +109,7 @@
CONFIG_IP_PNP=y
CONFIG_IP_PNP_DHCP=y
CONFIG_NET_IPGRE_DEMUX=y
+CONFIG_SYN_COOKIES=y
CONFIG_NET_IPVTI=y
CONFIG_INET_AH=y
CONFIG_INET_ESP=y
@@ -130,7 +131,6 @@
CONFIG_NF_CONNTRACK_SECMARK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CT_PROTO_DCCP=y
-CONFIG_NF_CT_PROTO_SCTP=y
CONFIG_NF_CT_PROTO_UDPLITE=y
CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
@@ -178,6 +178,7 @@
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
+# CONFIG_NETFILTER_XT_MATCH_SCTP is not set
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
CONFIG_NETFILTER_XT_MATCH_STATISTIC=y
@@ -211,6 +212,7 @@
CONFIG_IP6_NF_RAW=y
CONFIG_BRIDGE_NF_EBTABLES=y
CONFIG_BRIDGE_EBT_BROUTE=y
+CONFIG_IP_SCTP=y
CONFIG_L2TP=y
CONFIG_L2TP_DEBUGFS=y
CONFIG_L2TP_V3=y
@@ -258,6 +260,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 1ec275b..230ad65 100755
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -235,6 +235,8 @@
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=y
CONFIG_SOCKEV_NLMCAST=y
+CONFIG_CAN=y
+CONFIG_CAN_MCP25XXFD=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
@@ -250,6 +252,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 1a39bca..4225d8b 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -240,6 +240,8 @@
CONFIG_RMNET_DATA_FC=y
CONFIG_RMNET_DATA_DEBUG_PKT=y
CONFIG_SOCKEV_NLMCAST=y
+CONFIG_CAN=y
+CONFIG_CAN_MCP25XXFD=y
CONFIG_BT=y
CONFIG_MSM_BT_POWER=y
CONFIG_CFG80211=y
@@ -256,6 +258,7 @@
CONFIG_DMA_CMA=y
CONFIG_ZRAM=y
CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=16
CONFIG_BLK_DEV_RAM=y
CONFIG_BLK_DEV_RAM_SIZE=8192
CONFIG_QSEECOM=y
diff --git a/arch/arm64/crypto/sha256-core.S b/arch/arm64/crypto/sha256-core.S
deleted file mode 100644
index 3ce82cc..0000000
--- 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 bd0f59f..0000000
--- 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 cd63d71..7700bd7 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -443,6 +443,8 @@
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 @@
#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 3b79682..af0c14d 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -40,6 +40,7 @@
*/
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 2b9a637..f89263c 100644
--- a/arch/arm64/include/asm/vdso_datapage.h
+++ b/arch/arm64/include/asm/vdso_datapage.h
@@ -38,6 +38,7 @@
__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 61ae19e..b2debec 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -94,7 +94,7 @@
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 e137cea..82b4652 100644
--- a/arch/arm64/kernel/cpu_ops.c
+++ b/arch/arm64/kernel/cpu_ops.c
@@ -85,6 +85,7 @@
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
old mode 100644
new mode 100755
index f035ff6..22ef48f
--- a/arch/arm64/kernel/module.c
+++ b/arch/arm64/kernel/module.c
@@ -34,14 +34,18 @@
{
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 e8f759f..56956a1 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -217,6 +217,9 @@
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 2bd7426..a035df8 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -310,13 +310,14 @@
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 @@
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 04ca1d4..b202a2a 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -826,13 +826,18 @@
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 823616b..19067821 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 aa19b7a..476c7b4 100644
--- a/arch/ia64/mm/numa.c
+++ b/arch/ia64/mm/numa.c
@@ -49,6 +49,7 @@
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 ef9a2e4..21ddbf9 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 bb9940c..6cd2304 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -13,6 +13,7 @@
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 c7c31e2..26a058d 100644
--- a/arch/mips/ath79/setup.c
+++ b/arch/mips/ath79/setup.c
@@ -183,6 +183,12 @@
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 e081a26..cc2eb1b 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 5604db3..d79c68f 100644
--- a/arch/mips/include/asm/netlogic/xlr/fmn.h
+++ b/arch/mips/include/asm/netlogic/xlr/fmn.h
@@ -301,8 +301,6 @@
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 876442f..5be81f8 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 dbb9174..ec951dd 100644
--- a/arch/mips/kernel/uprobes.c
+++ b/arch/mips/kernel/uprobes.c
@@ -111,9 +111,6 @@
*/
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 7f2519c..15f7886 100644
--- a/arch/mips/math-emu/cp1emu.c
+++ b/arch/mips/math-emu/cp1emu.c
@@ -828,12 +828,12 @@
} 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 2da5649..3cc5b2e 100644
--- a/arch/mips/mm/tlbex.c
+++ b/arch/mips/mm/tlbex.c
@@ -386,6 +386,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 d80cd61..c3592b37 100644
--- a/arch/mips/pistachio/Platform
+++ b/arch/mips/pistachio/Platform
@@ -6,3 +6,4 @@
-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 933423f..b0db611 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 9d9f6f3..3da3e2b 100644
--- a/arch/powerpc/boot/addnote.c
+++ b/arch/powerpc/boot/addnote.c
@@ -223,7 +223,11 @@
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 5e12e19..defa553 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -271,6 +271,7 @@
#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 48e8f1f..b706759 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 b6952dd..73c3c12 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -811,6 +811,7 @@
#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 0a2b247..e840f94 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -374,12 +374,7 @@
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 @@
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 @@
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 ef27fbd..b1b2273 100644
--- a/arch/powerpc/kvm/book3s_rtas.c
+++ b/arch/powerpc/kvm/book3s_rtas.c
@@ -133,7 +133,7 @@
{
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 @@
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 @@
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 @@
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 @@
}
}
- mutex_unlock(&vcpu->kvm->lock);
+ mutex_unlock(&vcpu->kvm->arch.rtas_token_lock);
if (rc == 0) {
args.rets = orig_rets;
@@ -269,8 +269,6 @@
{
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 9cad2ed..31e9064 100644
--- a/arch/powerpc/mm/numa.c
+++ b/arch/powerpc/mm/numa.c
@@ -1574,6 +1574,9 @@
{
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 rc = 0;
+ if (!topology_updates_enabled)
+ return 0;
+
if (prrn_enabled) {
prrn_enabled = 0;
#ifdef CONFIG_SMP
@@ -1648,11 +1654,13 @@
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 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 7b1d172..83e5b25 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 e7d78f9..9f0810c 100644
--- a/arch/powerpc/net/bpf_jit_comp64.c
+++ b/arch/powerpc/net/bpf_jit_comp64.c
@@ -419,12 +419,12 @@
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 @@
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 @@
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 771edff..ba49ae6 100644
--- a/arch/powerpc/perf/core-book3s.c
+++ b/arch/powerpc/perf/core-book3s.c
@@ -1800,6 +1800,7 @@
int n;
int err;
struct cpu_hw_events *cpuhw;
+ u64 bhrb_filter;
if (!ppmu)
return -ENOENT;
@@ -1896,13 +1897,14 @@
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 ab830d1..5fbd9bd 100644
--- a/arch/powerpc/perf/power8-pmu.c
+++ b/arch/powerpc/perf/power8-pmu.c
@@ -29,6 +29,7 @@
#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 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 9abcd8f..c396d5e 100644
--- a/arch/powerpc/perf/power9-pmu.c
+++ b/arch/powerpc/perf/power9-pmu.c
@@ -30,6 +30,7 @@
#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 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 5811e78..1df70a7 100644
--- a/arch/s390/include/asm/facility.h
+++ b/arch/s390/include/asm/facility.h
@@ -61,6 +61,18 @@
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 @@
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 2032ab8..07f5719 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3288,21 +3288,28 @@
const struct kvm_memory_slot *new,
enum kvm_mr_change change)
{
- int rc;
+ int rc = 0;
- /* 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;
-
- 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 eaa8f8d..fa85cac0 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 71e7f77..84a80cd 100644
--- a/arch/sparc/kernel/perf_event.c
+++ b/arch/sparc/kernel/perf_event.c
@@ -889,6 +889,10 @@
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 fcf4d27..e09f7b4 100644
--- a/arch/sparc/mm/ultra.S
+++ b/arch/sparc/mm/ultra.S
@@ -586,7 +586,7 @@
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 @@
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 25c2366..040e3ef 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -56,7 +56,7 @@
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 93b170e..f20c83a 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -47,7 +47,7 @@
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 cb8178a2..e98e238 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -2867,7 +2867,7 @@
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 f26e26e..ad31c01 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -655,7 +655,7 @@
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 @@
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_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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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_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 cb13c05..9978ea4 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 @@
struct sigcontext_32 __user *sc)
{
unsigned int tmpflags, err = 0;
+ u16 gs, fs, es, ds;
void __user *buf;
u32 tmp;
@@ -78,16 +78,10 @@
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 @@
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 be6d054..52a65f1 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -766,8 +766,11 @@
{
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 16970c3..07a6c1f 100644
--- a/arch/x86/kernel/cpu/bugs.c
+++ b/arch/x86/kernel/cpu/bugs.c
@@ -829,6 +829,16 @@
}
/*
+ * 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 @@
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 d9ad49c..e348bee 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -673,20 +673,50 @@
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 bcd1b82..005e9a7 100644
--- a/arch/x86/kernel/irq_64.c
+++ b/arch/x86/kernel/irq_64.c
@@ -25,9 +25,18 @@
/*
* 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 @@
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 e497d37..8d20fb0 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 @@
{
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 b1a5d25..ca010df 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -129,16 +129,6 @@
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 @@
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 @@
{
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 @@
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 @@
{
#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 @@
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 9692a5e..b95693a 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 @@
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 @@
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 c863056..cf32533 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -1992,7 +1992,7 @@
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 5ab4a36..2729131 100644
--- a/arch/x86/kvm/pmu_intel.c
+++ b/arch/x86/kvm/pmu_intel.c
@@ -235,11 +235,14 @@
}
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 9338136..f7a7b98 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -1518,7 +1518,11 @@
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 1f32c4e..8b06700 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1109,7 +1109,7 @@
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 @@
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 @@
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 f7f8aa6..bc33d54 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -430,8 +430,6 @@
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 9bd1154..5f0e596 100644
--- a/arch/x86/pci/irq.c
+++ b/arch/x86/pci/irq.c
@@ -1117,6 +1117,8 @@
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 @@
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 @@
* 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 054e276..29dc59b 100644
--- a/arch/x86/power/cpu.c
+++ b/arch/x86/power/cpu.c
@@ -292,7 +292,17 @@
* 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 fef485b..6120046 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 @@
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 1c57054..c90a172 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -55,6 +55,9 @@
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 6107c03..edb108a 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -3227,6 +3227,7 @@
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 @@
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 @@
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 34454b0..ce006af 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -891,14 +891,13 @@
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 @@
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 35be49f..da1a987 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4355,9 +4355,12 @@
{ "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 574d08f..7637314 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -1388,6 +1388,10 @@
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 b90bbfe..272a83d 100644
--- a/drivers/bluetooth/bluetooth-power.c
+++ b/drivers/bluetooth/bluetooth-power.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2010, 2013-2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2010, 2013-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
@@ -613,6 +613,23 @@
return 0;
}
+static int get_bt_reset_gpio_value(void)
+{
+ int rc = 0;
+ int bt_reset_gpio = bt_power_pdata->bt_gpio_sys_rst;
+
+ rc = gpio_request(bt_reset_gpio, "bt_sys_rst_n");
+ if (rc) {
+ BT_PWR_ERR("unable to request gpio %d (%d)\n",
+ bt_reset_gpio, rc);
+ return rc;
+ }
+
+ rc = gpio_get_value(bt_reset_gpio);
+ gpio_free(bt_power_pdata->bt_gpio_sys_rst);
+ return rc;
+}
+
static int bt_power_probe(struct platform_device *pdev)
{
int ret = 0;
@@ -659,7 +676,8 @@
btpdev = pdev;
if (of_id) {
- if (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 dea48e1..df3469a 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -240,6 +240,8 @@
unsigned int *attrs;
uint32_t *crc;
uint64_t ctxid;
+ void *handle;
+ const void *ptr;
};
struct fastrpc_ctx_lst {
@@ -742,15 +744,14 @@
}
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 @@
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,34 +2450,51 @@
{
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)));
+ if (err == AEE_EUNSUPPORTED) {
+ remote_arg_t ra[1];
+
+ pr_warn("ADSPRPC:Failed to get security key with updated remote call, falling back to older method");
+ ra[0].buf.pv = (void *)&routargs;
+ ra[0].buf.len = sizeof(routargs);
+ ioctl.inv.sc = REMOTE_SCALARS_MAKE(7, 0, 1);
+ ioctl.inv.pra = ra;
+ VERIFY(err, 0 == (err = fastrpc_internal_invoke(fl,
+ FASTRPC_MODE_PARALLEL, 1, &ioctl)));
+ }
if (err)
goto bail;
+
desc.args[0] = TZ_PIL_AUTH_QDSP6_PROC;
desc.args[1] = phys;
desc.args[2] = size;
@@ -2883,11 +2902,13 @@
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/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 9c171ab..24fad76 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -1,5 +1,5 @@
/*
- * 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
@@ -125,6 +125,9 @@
} while (0)
#endif
+/* Fall back to older APIS in case API is not supported */
+#define AEE_EUNSUPPORTED 20
+
#define remote_arg64_t union remote_arg64
struct remote_buf64 {
diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c
index 57d6544..12c8bd9 100644
--- a/drivers/char/diag/diag_dci.c
+++ b/drivers/char/diag/diag_dci.c
@@ -726,29 +726,44 @@
return ((*event_mask_ptr & byte_mask) == byte_mask) ? 1 : 0;
}
-static int diag_dci_filter_commands(struct diag_pkt_header_t *header)
+static int diag_dci_filter_commands(struct diag_pkt_header_t *header,
+ int header_len)
{
if (!header)
return -ENOMEM;
- switch (header->cmd_code) {
- case 0x7d: /* Msg Mask Configuration */
- case 0x73: /* Log Mask Configuration */
- case 0x81: /* Event Mask Configuration */
- case 0x82: /* Event Mask Change */
- case 0x60: /* Event Mask Toggle */
- return 1;
+ if (header_len <= 0)
+ return -EIO;
+
+ if (header_len) {
+ switch (header->cmd_code) {
+ case 0x7d: /* Msg Mask Configuration */
+ case 0x73: /* Log Mask Configuration */
+ case 0x81: /* Event Mask Configuration */
+ case 0x82: /* Event Mask Change */
+ case 0x60: /* Event Mask Toggle */
+ DIAG_LOG(DIAG_DEBUG_DCI,
+ "diag: command not supported: %d\n",
+ header->cmd_code);
+ return 1;
+ }
}
- if (header->cmd_code == 0x4b && header->subsys_id == 0x12) {
- switch (header->subsys_cmd_code) {
- case 0x60: /* Extended Event Mask Config */
- case 0x61: /* Extended Msg Mask Config */
- case 0x62: /* Extended Log Mask Config */
- case 0x20C: /* Set current Preset ID */
- case 0x20D: /* Get current Preset ID */
- case 0x218: /* HDLC Disabled Command */
- return 1;
+ if (header_len >= (3*sizeof(uint8_t))) {
+ if (header->cmd_code == 0x4b && header->subsys_id == 0x12) {
+ switch (header->subsys_cmd_code) {
+ case 0x60: /* Extended Event Mask Config */
+ case 0x61: /* Extended Msg Mask Config */
+ case 0x62: /* Extended Log Mask Config */
+ case 0x20C: /* Set current Preset ID */
+ case 0x20D: /* Get current Preset ID */
+ case 0x218: /* HDLC Disabled Command */
+ DIAG_LOG(DIAG_DEBUG_DCI,
+ "diag: command not supported %d %d %d\n",
+ header->cmd_code, header->subsys_id,
+ header->subsys_cmd_code);
+ return 1;
+ }
}
}
@@ -1800,22 +1815,26 @@
static int diag_dci_process_apps_pkt(struct diag_pkt_header_t *pkt_header,
unsigned char *req_buf, int req_len,
- int tag)
+ int tag, int pkt_header_len)
{
- uint8_t cmd_code, subsys_id, i, goto_download = 0;
+ uint8_t cmd_code = 0, subsys_id = 0, i, goto_download = 0;
uint8_t header_len = sizeof(struct diag_dci_pkt_header_t);
- uint16_t ss_cmd_code;
+ uint16_t ss_cmd_code = 0;
uint32_t write_len = 0;
unsigned char *dest_buf = driver->apps_dci_buf;
unsigned char *payload_ptr = driver->apps_dci_buf + header_len;
struct diag_dci_pkt_header_t dci_header;
- if (!pkt_header || !req_buf || req_len <= 0 || tag < 0)
+ if (!pkt_header || !req_buf || req_len <= 0 || tag < 0 ||
+ pkt_header_len <= 0)
return -EIO;
- cmd_code = pkt_header->cmd_code;
- subsys_id = pkt_header->subsys_id;
- ss_cmd_code = pkt_header->subsys_cmd_code;
+ if (pkt_header_len >= (sizeof(uint8_t)))
+ cmd_code = pkt_header->cmd_code;
+ if (pkt_header_len >= (2 * sizeof(uint8_t)))
+ subsys_id = pkt_header->subsys_id;
+ if (pkt_header_len >= (3 * sizeof(uint8_t)))
+ ss_cmd_code = pkt_header->subsys_cmd_code;
if (cmd_code == DIAG_CMD_DOWNLOAD) {
*payload_ptr = DIAG_CMD_DOWNLOAD;
@@ -1935,7 +1954,7 @@
static int diag_process_dci_pkt_rsp(unsigned char *buf, int len)
{
int ret = DIAG_DCI_TABLE_ERR;
- int common_cmd = 0;
+ int common_cmd = 0, header_len = 0;
struct diag_pkt_header_t *header = NULL;
unsigned char *temp = buf;
unsigned char *req_buf = NULL;
@@ -1951,8 +1970,7 @@
if (!buf)
return -EIO;
- if (len < (sizeof(struct dci_pkt_req_t) +
- sizeof(struct diag_pkt_header_t)) ||
+ if (len < sizeof(struct dci_pkt_req_t) ||
len > DCI_REQ_BUF_SIZE) {
pr_err("diag: dci: Invalid length %d len in %s", len, __func__);
return -EIO;
@@ -1963,13 +1981,6 @@
read_len += sizeof(struct dci_pkt_req_t);
req_len -= sizeof(struct dci_pkt_req_t);
req_buf = temp; /* Start of the Request */
- header = (struct diag_pkt_header_t *)temp;
- read_len += sizeof(struct diag_pkt_header_t);
- if (read_len >= DCI_REQ_BUF_SIZE) {
- pr_err("diag: dci: In %s, invalid read_len: %d\n", __func__,
- read_len);
- return -EIO;
- }
mutex_lock(&driver->dci_mutex);
dci_entry = diag_dci_get_client_entry(req_hdr.client_id);
@@ -1980,11 +1991,40 @@
return DIAG_DCI_NO_REG;
}
+ header = (void *)temp;
+ header_len = len - sizeof(struct dci_pkt_req_t);
+ if (header_len <= 0) {
+ mutex_unlock(&driver->dci_mutex);
+ return -EIO;
+ }
+ if (header_len >= sizeof(uint8_t)) {
+ header->cmd_code = (uint16_t)(*(uint8_t *)temp);
+ read_len += sizeof(uint8_t);
+ }
+ if (header_len >= (2 * sizeof(uint8_t))) {
+ temp += sizeof(uint8_t);
+ header->subsys_id = (uint16_t)(*(uint8_t *)temp);
+ read_len += sizeof(uint8_t);
+ }
+ if (header_len == (3 * sizeof(uint8_t))) {
+ temp += sizeof(uint8_t);
+ header->subsys_cmd_code = (uint16_t)(*(uint8_t *)temp);
+ read_len += sizeof(uint8_t);
+ } else if (header_len >=
+ (2 * sizeof(uint8_t)) + sizeof(uint16_t)) {
+ temp += sizeof(uint8_t);
+ header->subsys_cmd_code = (uint16_t)(*(uint16_t *)temp);
+ read_len += sizeof(uint16_t);
+ }
+ if (read_len > DCI_REQ_BUF_SIZE) {
+ pr_err("diag: dci: In %s, invalid read_len: %d\n", __func__,
+ read_len);
+ mutex_unlock(&driver->dci_mutex);
+ return -EIO;
+ }
+
/* Check if the command is allowed on DCI */
- if (diag_dci_filter_commands(header)) {
- pr_debug("diag: command not supported %d %d %d",
- header->cmd_code, header->subsys_id,
- header->subsys_cmd_code);
+ if (diag_dci_filter_commands(header, header_len)) {
mutex_unlock(&driver->dci_mutex);
return DIAG_DCI_SEND_DATA_FAIL;
}
@@ -2038,14 +2078,23 @@
/* Check if it is a dedicated Apps command */
ret = diag_dci_process_apps_pkt(header, req_buf, req_len,
- req_entry->tag);
+ req_entry->tag, header_len);
if ((ret == DIAG_DCI_NO_ERROR && !common_cmd) || ret < 0)
return ret;
- reg_entry.cmd_code = header->cmd_code;
- reg_entry.subsys_id = header->subsys_id;
- reg_entry.cmd_code_hi = header->subsys_cmd_code;
- reg_entry.cmd_code_lo = header->subsys_cmd_code;
+ 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)))
+ reg_entry.subsys_id = header->subsys_id;
+ if (header_len >= (3 * sizeof(uint8_t))) {
+ reg_entry.cmd_code_hi = header->subsys_cmd_code;
+ reg_entry.cmd_code_lo = header->subsys_cmd_code;
+ }
mutex_lock(&driver->cmd_reg_mutex);
temp_entry = diag_cmd_search(®_entry, ALL_PROC);
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
index c6ec271..4335ad4 100644
--- a/drivers/char/diag/diag_masks.c
+++ b/drivers/char/diag/diag_masks.c
@@ -896,7 +896,8 @@
goto end;
if (mask_size + write_len > dest_len)
mask_size = dest_len - write_len;
- memcpy(dest_buf + write_len, src_buf + header_len, mask_size);
+ if (mask_size && src_len >= header_len + mask_size)
+ memcpy(dest_buf + write_len, src_buf + header_len, mask_size);
write_len += mask_size;
for (i = 0; i < NUM_MD_SESSIONS; i++) {
if (i == APPS_DATA)
@@ -1195,7 +1196,7 @@
int rsp_header_len = sizeof(struct diag_log_config_rsp_t);
uint32_t mask_size = 0;
struct diag_log_mask_t *log_item = NULL;
- struct diag_log_config_req_t *req;
+ struct diag_log_config_get_req_t *req;
struct diag_log_config_rsp_t rsp;
struct diag_mask_info *mask_info = NULL;
struct diag_md_session_t *info = NULL;
@@ -1205,7 +1206,7 @@
mask_info = (!info) ? &log_mask : info->log_mask;
if (!src_buf || !dest_buf || dest_len <= 0 || !mask_info ||
- src_len < sizeof(struct diag_log_config_req_t)) {
+ src_len < sizeof(struct diag_log_config_get_req_t)) {
pr_err("diag: Invalid input in %s, src_buf: %pK, src_len: %d, dest_buf: %pK, dest_len: %d, mask_info: %pK\n",
__func__, src_buf, src_len, dest_buf, dest_len,
mask_info);
@@ -1224,7 +1225,7 @@
return 0;
}
- req = (struct diag_log_config_req_t *)src_buf;
+ req = (struct diag_log_config_get_req_t *)src_buf;
read_len += req_header_len;
rsp.cmd_code = DIAG_CMD_LOG_CONFIG;
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
index a736ff2..5c76825 100644
--- a/drivers/char/diag/diag_masks.h
+++ b/drivers/char/diag/diag_masks.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2015, 2018-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
@@ -40,6 +40,13 @@
uint32_t *ptr;
};
+struct diag_log_config_get_req_t {
+ uint8_t cmd_code;
+ uint8_t padding[3];
+ uint32_t sub_cmd;
+ uint32_t equip_id;
+} __packed;
+
struct diag_log_config_req_t {
uint8_t cmd_code;
uint8_t padding[3];
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 560f0df..d99f984 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 @@
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 d7d7366..3451aba 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -496,7 +496,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
"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 @@
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 c42be06..128c2be 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 8c0017d..800ced0 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -75,7 +75,7 @@
/* 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 @@
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 39af05a..32b130c 100644
--- a/drivers/clk/rockchip/clk-rk3288.c
+++ b/drivers/clk/rockchip/clk-rk3288.c
@@ -826,6 +826,9 @@
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 @@
}
/*
+ * 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 63fdb79..bee305b 100644
--- a/drivers/clk/sunxi/clk-sun8i-bus-gates.c
+++ b/drivers/clk/sunxi/clk-sun8i-bus-gates.c
@@ -78,6 +78,10 @@
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 91cf857..863be43 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -334,7 +334,7 @@
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 08e8d50..fd33ddd 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1185,6 +1185,7 @@
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 38d1a82..32c9524 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -449,6 +449,8 @@
/* 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 35dd4d7..58c933f 100644
--- a/drivers/cpufreq/pasemi-cpufreq.c
+++ b/drivers/cpufreq/pasemi-cpufreq.c
@@ -146,6 +146,7 @@
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 ff44016..641f802 100644
--- a/drivers/cpufreq/pmac32-cpufreq.c
+++ b/drivers/cpufreq/pmac32-cpufreq.c
@@ -551,6 +551,7 @@
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 @@
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 5a4c5a6..2eaeebc 100644
--- a/drivers/cpufreq/ppc_cbe_cpufreq.c
+++ b/drivers/cpufreq/ppc_cbe_cpufreq.c
@@ -86,6 +86,7 @@
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 0de2f62..ec16ec2e 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-hash.c
@@ -250,7 +250,10 @@
}
} 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 463033b..5a24a48 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -2185,7 +2185,7 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 @@
.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 d9281a2..930a3f1 100644
--- a/drivers/crypto/vmx/aesp8-ppc.pl
+++ b/drivers/crypto/vmx/aesp8-ppc.pl
@@ -1318,7 +1318,7 @@
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 1c4b5b8..1bfe867 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 @@
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 @@
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 @@
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;
+ srclen);
+ dctx->bytes += srclen;
+ return 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;
- }
- 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 @@
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 @@
.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 b222dd7..12d9048 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1608,7 +1608,11 @@
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 1953e57..f17a4c7 100644
--- a/drivers/dma/idma64.c
+++ b/drivers/dma/idma64.c
@@ -589,7 +589,7 @@
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 @@
{
struct idma64_chip *chip;
struct device *dev = &pdev->dev;
+ struct device *sysdev = dev->parent;
struct resource *mem;
int ret;
@@ -645,11 +646,12 @@
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 6b81687..baa32e1 100644
--- a/drivers/dma/idma64.h
+++ b/drivers/dma/idma64.h
@@ -216,12 +216,14 @@
/**
* 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 b9c2972..84856ac 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -632,7 +632,7 @@
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 @@
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 6d7e3cd..57b375d 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -1020,6 +1020,7 @@
{
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 @@
_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 b10cbaa..e9e46a5 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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 56e6c4c..4c0b6df 100644
--- a/drivers/extcon/extcon-arizona.c
+++ b/drivers/extcon/extcon-arizona.c
@@ -1684,6 +1684,16 @@
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 7ec09ea..726d146 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
old mode 100644
new mode 100755
index d984332..1c963c4
--- 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 @@
#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 @@
__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 642fa03..768be77 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -689,6 +689,7 @@
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 75f30a0..0388821 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -296,6 +296,22 @@
}
}
+/*
+ * 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 @@
}
/* 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 @@
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 28341b3..84dea27 100644
--- a/drivers/gpu/drm/arm/hdlcd_crtc.c
+++ b/drivers/gpu/drm/arm/hdlcd_crtc.c
@@ -170,7 +170,8 @@
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 32ab5c3..1b2fae9 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -735,11 +735,11 @@
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 847ba40..246f818 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -522,6 +522,7 @@
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 ea733ab..d83be46 100644
--- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c
+++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c
@@ -609,6 +609,9 @@
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 63bde4e..e019ea2 100644
--- a/drivers/gpu/drm/gma500/intel_bios.c
+++ b/drivers/gpu/drm/gma500/intel_bios.c
@@ -436,6 +436,9 @@
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 b743727..d18e11d 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -538,6 +538,7 @@
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 1ea0e1f..54d878c 100644
--- a/drivers/gpu/drm/i915/intel_csr.c
+++ b/drivers/gpu/drm/i915/intel_csr.c
@@ -280,10 +280,17 @@
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 @@
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 @@
/* 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 @@
}
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 8dbba61..82114fe 100644
--- a/drivers/gpu/drm/imx/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3-crtc.c
@@ -76,14 +76,14 @@
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 eaa5a22..bdbf358 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -720,6 +720,8 @@
/* 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 92fc9bc..d023f64 100644
--- a/drivers/gpu/drm/msm/dp/dp_debug.c
+++ b/drivers/gpu/drm/msm/dp/dp_debug.c
@@ -192,6 +192,8 @@
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 @@
}
size -= 4;
+ if (size == 0)
+ goto bail;
dpcd_size = size / char_to_nib;
buf_t = buf + 4;
@@ -271,6 +275,7 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index d6e8fd3..9a0d973 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -1180,8 +1180,24 @@
else
ret = 0;
- if (sde_encoder_phys_cmd_is_master(phys_enc))
+ if (sde_encoder_phys_cmd_is_master(phys_enc)) {
+ /*
+ * Signaling the retire fence at ctl start timeout
+ * to allow the next commit and avoid device freeze.
+ * As ctl start timeout can occurs due to no read ptr,
+ * updating pending_rd_ptr_cnt here may not cover all
+ * cases. Hence signaling the retire fence.
+ */
+ if (atomic_add_unless(
+ &phys_enc->pending_retire_fence_cnt, -1, 0))
+ phys_enc->parent_ops.handle_frame_done(
+ phys_enc->parent,
+ phys_enc,
+ SDE_ENCODER_FRAME_EVENT_SIGNAL_RETIRE_FENCE);
+ atomic_add_unless(
+ &phys_enc->pending_ctlstart_cnt, -1, 0);
atomic_inc_return(&phys_enc->ctlstart_timeout);
+ }
}
return ret;
diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h
index a63c5ac..23b8f25 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 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 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 f0851d5..f89692c 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 @@
{
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 @@
}
}
+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 fc6b162..1be175a 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_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 4f197b1..ecacb22 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 @@
{
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 @@
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_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 807a2b6..ed50cc3 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 @@
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 @@
{
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 e1be14c..2fdb1b8 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 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 ca1caf4..8b6f8aa 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -935,12 +935,12 @@
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 4b556e6..6c30c24 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -1245,7 +1245,13 @@
}
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 9fe8eda..40c1e89 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -2493,7 +2493,8 @@
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 @@
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/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index b095b027..bff977d 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -302,6 +302,11 @@
PAGE_SIZE, 0, KGSL_MEMDESC_PRIVILEGED, "pagetable_desc");
if (ret)
return ret;
+
+ /* allocate a chunk of memory to create user profiling IB1s */
+ kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->profile_desc,
+ PAGE_SIZE, KGSL_MEMFLAGS_GPUREADONLY, 0, "profile_desc");
+
return kgsl_allocate_global(KGSL_DEVICE(adreno_dev), &rb->buffer_desc,
KGSL_RB_SIZE, KGSL_MEMFLAGS_GPUREADONLY,
0, "ringbuffer");
@@ -316,7 +321,7 @@
if (!adreno_is_a3xx(adreno_dev)) {
status = kgsl_allocate_global(device, &device->scratch,
- PAGE_SIZE, 0, 0, "scratch");
+ PAGE_SIZE, 0, KGSL_MEMDESC_RANDOM, "scratch");
if (status != 0)
return status;
}
@@ -347,7 +352,7 @@
kgsl_free_global(device, &rb->pagetable_desc);
kgsl_free_global(device, &rb->preemption_desc);
-
+ kgsl_free_global(device, &rb->profile_desc);
kgsl_free_global(device, &rb->buffer_desc);
kgsl_del_event_group(&rb->events);
memset(rb, 0, sizeof(struct adreno_ringbuffer));
@@ -840,6 +845,37 @@
return (unsigned int)(p - cmds);
}
+/* This is the maximum possible size for 64 bit targets */
+#define PROFILE_IB_DWORDS 4
+#define PROFILE_IB_SLOTS (PAGE_SIZE / (PROFILE_IB_DWORDS << 2))
+
+static int set_user_profiling(struct adreno_device *adreno_dev,
+ struct adreno_ringbuffer *rb, u32 *cmds, u64 gpuaddr)
+{
+ int dwords, index = 0;
+ u64 ib_gpuaddr;
+ u32 *ib;
+
+ if (!rb->profile_desc.hostptr)
+ return 0;
+
+ ib = ((u32 *) rb->profile_desc.hostptr) +
+ (rb->profile_index * PROFILE_IB_DWORDS);
+ ib_gpuaddr = rb->profile_desc.gpuaddr +
+ (rb->profile_index * (PROFILE_IB_DWORDS << 2));
+
+ dwords = _get_alwayson_counter(adreno_dev, ib, gpuaddr);
+
+ /* Make an indirect buffer for the request */
+ cmds[index++] = cp_mem_packet(adreno_dev, CP_INDIRECT_BUFFER_PFE, 2, 1);
+ index += cp_gpuaddr(adreno_dev, &cmds[index], ib_gpuaddr);
+ cmds[index++] = dwords;
+
+ rb->profile_index = (rb->profile_index + 1) % PROFILE_IB_SLOTS;
+
+ return index;
+}
+
/* adreno_rindbuffer_submitcmd - submit userspace IBs to the GPU */
int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev,
struct kgsl_drawobj_cmd *cmdobj,
@@ -940,14 +976,12 @@
!adreno_is_a3xx(adreno_dev) &&
(cmdobj->profiling_buf_entry != NULL)) {
user_profiling = true;
- dwords += 6;
/*
- * REG_TO_MEM packet on A5xx and above needs another ordinal.
- * Add 2 more dwords since we do profiling before and after.
+ * User side profiling uses two IB1s, one before with 4 dwords
+ * per INDIRECT_BUFFER_PFE call
*/
- if (!ADRENO_LEGACY_PM4(adreno_dev))
- dwords += 2;
+ dwords += 8;
/*
* we want to use an adreno_submit_time struct to get the
@@ -1006,11 +1040,11 @@
}
/*
- * Add cmds to read the GPU ticks at the start of command obj and
+ * Add IB1 to read the GPU ticks at the start of command obj and
* write it into the appropriate command obj profiling buffer offset
*/
if (user_profiling) {
- cmds += _get_alwayson_counter(adreno_dev, cmds,
+ cmds += set_user_profiling(adreno_dev, rb, cmds,
cmdobj->profiling_buffer_gpuaddr +
offsetof(struct kgsl_drawobj_profiling_buffer,
gpu_ticks_submitted));
@@ -1058,11 +1092,11 @@
}
/*
- * Add cmds to read the GPU ticks at the end of command obj and
+ * Add IB1 to read the GPU ticks at the end of command obj and
* write it into the appropriate command obj profiling buffer offset
*/
if (user_profiling) {
- cmds += _get_alwayson_counter(adreno_dev, cmds,
+ cmds += set_user_profiling(adreno_dev, rb, cmds,
cmdobj->profiling_buffer_gpuaddr +
offsetof(struct kgsl_drawobj_profiling_buffer,
gpu_ticks_retired));
diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h
index a4dc901..8e0c321 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.h
+++ b/drivers/gpu/msm/adreno_ringbuffer.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -135,6 +135,18 @@
unsigned long sched_timer;
enum adreno_dispatcher_starve_timer_states starve_timer_state;
spinlock_t preempt_lock;
+ /**
+ * @profile_desc: global memory to construct IB1s to do user side
+ * profiling
+ */
+ struct kgsl_memdesc profile_desc;
+ /**
+ * @profile_index: Pointer to the next "slot" in profile_desc for a user
+ * profiling IB1. This allows for PAGE_SIZE / 16 = 256 simultaneous
+ * commands per ringbuffer with user profiling enabled
+ * enough.
+ */
+ u32 profile_index;
};
/* Returns the current ringbuffer */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 2b83d44..66102af 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -3337,12 +3337,16 @@
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_phys_alloc *param = data;
struct kgsl_mem_entry *entry;
uint64_t flags;
int ret;
int id;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
if (ret)
return ret;
@@ -3422,9 +3426,13 @@
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_phys_free *param = data;
struct kgsl_mem_entry *entry;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
entry = kgsl_sharedmem_find_id_flags(process, param->id,
KGSL_MEMFLAGS_SPARSE_PHYS);
if (entry == NULL)
@@ -3454,10 +3462,14 @@
unsigned int cmd, void *data)
{
struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_virt_alloc *param = data;
struct kgsl_mem_entry *entry;
int ret;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
if (ret)
return ret;
@@ -3498,9 +3510,13 @@
unsigned int cmd, void *data)
{
struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_virt_free *param = data;
struct kgsl_mem_entry *entry = NULL;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
entry = kgsl_sharedmem_find_id_flags(process, param->id,
KGSL_MEMFLAGS_SPARSE_VIRT);
if (entry == NULL)
@@ -3847,6 +3863,7 @@
unsigned int cmd, void *data)
{
struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_device *device = dev_priv->device;
struct kgsl_sparse_bind *param = data;
struct kgsl_sparse_binding_object obj;
struct kgsl_mem_entry *virt_entry;
@@ -3855,6 +3872,9 @@
int ret = 0;
int i = 0;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
ptr = (void __user *) (uintptr_t) param->list;
if (param->size > sizeof(struct kgsl_sparse_binding_object) ||
@@ -3910,6 +3930,9 @@
long result;
unsigned int i = 0;
+ if (!(device->flags & KGSL_FLAG_SPARSE))
+ return -ENOTSUPP;
+
/* Make sure sparse and syncpoint count isn't too big */
if (param->numsparse > KGSL_MAX_SPARSE ||
param->numsyncs > KGSL_MAX_SYNCPOINTS)
@@ -4665,6 +4688,9 @@
/* Initialize logging first, so that failures below actually print. */
kgsl_device_debugfs_init(device);
+ /* Disable the sparse ioctl invocation as they are not used */
+ device->flags &= ~KGSL_FLAG_SPARSE;
+
status = kgsl_pwrctrl_init(device);
if (status)
goto error;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 1fa2717..8456be7 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -197,6 +197,8 @@
#define KGSL_MEMDESC_TZ_LOCKED BIT(7)
/* The memdesc is allocated through contiguous memory */
#define KGSL_MEMDESC_CONTIG BIT(8)
+/* For global buffers, randomly assign an address from the region */
+#define KGSL_MEMDESC_RANDOM BIT(9)
/**
* struct kgsl_memdesc - GPU memory object descriptor
@@ -313,7 +315,7 @@
void *priv;
struct list_head node;
unsigned int created;
- struct kthread_work work;
+ struct work_struct work;
int result;
struct kgsl_event_group *group;
};
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 6ae38a3..229e206 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2002,2007-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
@@ -66,6 +66,7 @@
};
#define KGSL_FLAG_WAKE_ON_TOUCH BIT(0)
+#define KGSL_FLAG_SPARSE BIT(1)
/*
* "list" of event types for ftrace symbolic magic
diff --git a/drivers/gpu/msm/kgsl_drawobj.c b/drivers/gpu/msm/kgsl_drawobj.c
index 40b49c3..1bfc905 100644
--- a/drivers/gpu/msm/kgsl_drawobj.c
+++ b/drivers/gpu/msm/kgsl_drawobj.c
@@ -598,13 +598,29 @@
return;
}
- cmdobj->profiling_buf_entry = entry;
- if (id != 0)
+ if (!id) {
+ cmdobj->profiling_buffer_gpuaddr = gpuaddr;
+ } else {
+ u64 off = offset + sizeof(struct kgsl_drawobj_profiling_buffer);
+
+ /*
+ * Make sure there is enough room in the object to store the
+ * entire profiling buffer object
+ */
+ if (off < offset || off >= entry->memdesc.size) {
+ dev_err(device->dev,
+ "ignore invalid profile offset ctxt %d id %d offset %lld gpuaddr %llx size %lld\n",
+ drawobj->context->id, id, offset, gpuaddr, size);
+ kgsl_mem_entry_put(entry);
+ return;
+ }
+
cmdobj->profiling_buffer_gpuaddr =
entry->memdesc.gpuaddr + offset;
- else
- cmdobj->profiling_buffer_gpuaddr = gpuaddr;
+ }
+
+ cmdobj->profiling_buf_entry = entry;
}
/**
diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c
index 759a966..47582da 100644
--- a/drivers/gpu/msm/kgsl_events.c
+++ b/drivers/gpu/msm/kgsl_events.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -32,7 +32,7 @@
{
list_del(&event->node);
event->result = result;
- kthread_queue_work(&kgsl_driver.worker, &event->work);
+ queue_work(device->events_wq, &event->work);
}
/**
@@ -42,7 +42,7 @@
* Each event callback has its own work struct and is run on a event specific
* workqeuue. This is the worker that queues up the event callback function.
*/
-static void _kgsl_event_worker(struct kthread_work *work)
+static void _kgsl_event_worker(struct work_struct *work)
{
struct kgsl_event *event = container_of(work, struct kgsl_event, work);
int id = KGSL_CONTEXT_ID(event->context);
@@ -286,7 +286,7 @@
event->created = jiffies;
event->group = group;
- kthread_init_work(&event->work, _kgsl_event_worker);
+ INIT_WORK(&event->work, _kgsl_event_worker);
trace_kgsl_register_event(KGSL_CONTEXT_ID(context), timestamp, func);
@@ -301,7 +301,7 @@
if (timestamp_cmp(retired, timestamp) >= 0) {
event->result = KGSL_EVENT_RETIRED;
- kthread_queue_work(&kgsl_driver.worker, &event->work);
+ queue_work(device->events_wq, &event->work);
spin_unlock(&group->lock);
return 0;
}
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index 87e1431..d023170 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -20,6 +20,7 @@
#include <linux/msm_kgsl.h>
#include <linux/ratelimit.h>
#include <linux/of_platform.h>
+#include <linux/random.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/secure_buffer.h>
#include <linux/compat.h>
@@ -93,15 +94,8 @@
*
* Here we define an array and a simple allocator to keep track of the currently
* active global entries. Each entry is assigned a unique address inside of a
- * MMU implementation specific "global" region. The addresses are assigned
- * sequentially and never re-used to avoid having to go back and reprogram
- * existing pagetables. The entire list of active entries are mapped and
- * unmapped into every new pagetable as it is created and destroyed.
- *
- * Because there are relatively few entries and they are defined at boot time we
- * don't need to go over the top to define a dynamic allocation scheme. It will
- * be less wasteful to pick a static number with a little bit of growth
- * potential.
+ * MMU implementation specific "global" region. We use a simple bitmap based
+ * allocator for the region to allow for both fixed and dynamic addressing.
*/
#define GLOBAL_PT_ENTRIES 32
@@ -111,10 +105,13 @@
char name[32];
};
+#define GLOBAL_MAP_PAGES (KGSL_IOMMU_GLOBAL_MEM_SIZE >> PAGE_SHIFT)
+
static struct global_pt_entry global_pt_entries[GLOBAL_PT_ENTRIES];
+static DECLARE_BITMAP(global_map, GLOBAL_MAP_PAGES);
+
static int secure_global_size;
static int global_pt_count;
-uint64_t global_pt_alloc;
static struct kgsl_memdesc gpu_qdss_desc;
static struct kgsl_memdesc gpu_qtimer_desc;
@@ -211,6 +208,12 @@
for (i = 0; i < global_pt_count; i++) {
if (global_pt_entries[i].memdesc == memdesc) {
+ u64 offset = memdesc->gpuaddr -
+ KGSL_IOMMU_GLOBAL_MEM_BASE(mmu);
+
+ bitmap_clear(global_map, offset >> PAGE_SHIFT,
+ kgsl_memdesc_footprint(memdesc) >> PAGE_SHIFT);
+
memdesc->gpuaddr = 0;
memdesc->priv &= ~KGSL_MEMDESC_GLOBAL;
global_pt_entries[i].memdesc = NULL;
@@ -222,19 +225,43 @@
static void kgsl_iommu_add_global(struct kgsl_mmu *mmu,
struct kgsl_memdesc *memdesc, const char *name)
{
+ u32 bit, start = 0;
+ u64 size = kgsl_memdesc_footprint(memdesc);
+
if (memdesc->gpuaddr != 0)
return;
- /*Check that we can fit the global allocations */
- if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES) ||
- WARN_ON((global_pt_alloc + memdesc->size) >=
- KGSL_IOMMU_GLOBAL_MEM_SIZE))
+ if (WARN_ON(global_pt_count >= GLOBAL_PT_ENTRIES))
return;
- memdesc->gpuaddr = KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + global_pt_alloc;
+ if (WARN_ON(size > KGSL_IOMMU_GLOBAL_MEM_SIZE))
+ return;
+
+ if (memdesc->priv & KGSL_MEMDESC_RANDOM) {
+ u32 range = GLOBAL_MAP_PAGES - (size >> PAGE_SHIFT);
+
+ start = get_random_int() % range;
+ }
+
+ while (start >= 0) {
+ bit = bitmap_find_next_zero_area(global_map, GLOBAL_MAP_PAGES,
+ start, size >> PAGE_SHIFT, 0);
+
+ if (bit < GLOBAL_MAP_PAGES)
+ break;
+
+ start--;
+ }
+
+ if (WARN_ON(start < 0))
+ return;
+
+ memdesc->gpuaddr =
+ KGSL_IOMMU_GLOBAL_MEM_BASE(mmu) + (bit << PAGE_SHIFT);
+
+ bitmap_set(global_map, bit, size >> PAGE_SHIFT);
memdesc->priv |= KGSL_MEMDESC_GLOBAL;
- global_pt_alloc += memdesc->size;
global_pt_entries[global_pt_count].memdesc = memdesc;
strlcpy(global_pt_entries[global_pt_count].name, name,
diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c
index 3198faf..38d9deb 100644
--- a/drivers/hid/hid-logitech-hidpp.c
+++ b/drivers/hid/hid-logitech-hidpp.c
@@ -449,13 +449,16 @@
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 @@
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 facd05c..e8c0898 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -96,17 +96,23 @@
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 @@
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 @@
"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 cb9fdd3..2b5b8c3 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -106,6 +106,13 @@
#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 @@
{
outb(0x02, sioaddr);
outb(0x02, sioaddr + 1);
+ release_region(sioaddr, 2);
}
/*
@@ -1220,7 +1228,11 @@
{
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 c00bad0..0d75bc7 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -1028,14 +1028,15 @@
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 @@
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 @@
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 086e706..772aac1 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -749,7 +749,7 @@
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 6bd2007..cbdb5c4 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -72,14 +72,19 @@
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 @@
u8 id, rev;
char *name;
unsigned short addr;
+ int err;
- superio_enter();
+ err = superio_enter();
+ if (err)
+ return err;
+
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 5d32318..d24df0c 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -73,16 +73,21 @@
/* 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 @@
{
u8 val;
unsigned short addr;
+ int err;
- superio_enter();
+ err = superio_enter();
+ if (err)
+ return err;
+
val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
/*
@@ -608,13 +617,14 @@
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 3a6bfa5..95d5e8e 100644
--- a/drivers/hwmon/vt1211.c
+++ b/drivers/hwmon/vt1211.c
@@ -226,15 +226,21 @@
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 @@
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 9d7be5a..6618db7 100644
--- a/drivers/i2c/busses/i2c-acorn.c
+++ b/drivers/i2c/busses/i2c-acorn.c
@@ -83,6 +83,7 @@
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 631169b..ad999a2 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 @@
{
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 @@
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 00e8e67..eaa312b 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -297,6 +297,7 @@
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 a1d072e..30f200a 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -62,7 +62,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 a3ae165..16180e6 100644
--- a/drivers/iio/common/ssp_sensors/ssp_iio.c
+++ b/drivers/iio/common/ssp_sensors/ssp_iio.c
@@ -80,7 +80,7 @@
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 3de7f44..86abba5 100644
--- a/drivers/iio/magnetometer/hmc5843_i2c.c
+++ b/drivers/iio/magnetometer/hmc5843_i2c.c
@@ -58,8 +58,13 @@
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 535f03a..79b2b70 100644
--- a/drivers/iio/magnetometer/hmc5843_spi.c
+++ b/drivers/iio/magnetometer/hmc5843_spi.c
@@ -58,6 +58,7 @@
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 @@
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 a2322b2..e5752352 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -455,6 +455,8 @@
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 d30b3b9..85db856 100644
--- a/drivers/infiniband/hw/hfi1/chip.c
+++ b/drivers/infiniband/hw/hfi1/chip.c
@@ -9620,6 +9620,7 @@
/* 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 9cbe52d..76e63c8 100644
--- a/drivers/infiniband/hw/hfi1/sdma.c
+++ b/drivers/infiniband/hw/hfi1/sdma.c
@@ -410,10 +410,7 @@
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 @@
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 @@
}
}
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 4c11116..098296a 100644
--- a/drivers/infiniband/hw/hfi1/user_sdma.c
+++ b/drivers/infiniband/hw/hfi1/user_sdma.c
@@ -260,7 +260,6 @@
struct list_head list;
struct user_sdma_request *req;
u16 flags;
- unsigned busycount;
u64 seqnum;
};
@@ -323,25 +322,22 @@
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 @@
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 d9c7175..15054a0 100644
--- a/drivers/infiniband/hw/hfi1/verbs.c
+++ b/drivers/infiniband/hw/hfi1/verbs.c
@@ -1344,8 +1344,6 @@
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 d8a5bad..837729d 100644
--- a/drivers/infiniband/hw/hfi1/verbs_txreq.c
+++ b/drivers/infiniband/hw/hfi1/verbs_txreq.c
@@ -100,7 +100,7 @@
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 31ded57..0bd58a0 100644
--- a/drivers/infiniband/hw/hfi1/verbs_txreq.h
+++ b/drivers/infiniband/hw/hfi1/verbs_txreq.h
@@ -71,6 +71,7 @@
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 @@
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 954f150..d6e1837 100644
--- a/drivers/infiniband/hw/qib/qib_verbs.c
+++ b/drivers/infiniband/hw/qib/qib_verbs.c
@@ -1568,8 +1568,6 @@
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 49d55a0..dbd4c0d 100644
--- a/drivers/infiniband/sw/rdmavt/mr.c
+++ b/drivers/infiniband/sw/rdmavt/mr.c
@@ -94,6 +94,8 @@
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 6500c3b..8b330b5 100644
--- a/drivers/infiniband/sw/rdmavt/qp.c
+++ b/drivers/infiniband/sw/rdmavt/qp.c
@@ -370,7 +370,8 @@
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 2165f3d..842c023 100644
--- a/drivers/input/keyboard/imx_keypad.c
+++ b/drivers/input/keyboard/imx_keypad.c
@@ -530,11 +530,12 @@
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 @@
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 @@
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 a306453..89d37d0 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -991,13 +991,31 @@
#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 38edf8f..15be3ee 100644
--- a/drivers/input/mouse/elantech.c
+++ b/drivers/input/mouse/elantech.c
@@ -1187,6 +1187,8 @@
"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 c36c31d..a63e08e 100644
--- a/drivers/input/sensors/smi130/smi130_acc.c
+++ b/drivers/input/sensors/smi130/smi130_acc.c
@@ -1604,6 +1604,7 @@
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 @@
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 @@
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 @@
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 @@
}
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 552d39c..fd9e87d 100644
--- a/drivers/input/sensors/smi130/smi130_gyro_driver.c
+++ b/drivers/input/sensors/smi130/smi130_gyro_driver.c
@@ -295,6 +295,7 @@
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 @@
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 @@
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 @@
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 @@
}
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 64cc510..f2b2bce 100644
--- a/drivers/input/touchscreen/cyttsp5/cyttsp5_core.c
+++ b/drivers/input/touchscreen/cyttsp5/cyttsp5_core.c
@@ -306,8 +306,12 @@
for (i = 0; i < cd->num_hid_reports; i++) {
report = cd->hid_reports[i];
- for (j = 0; j < report->num_fields; j++)
+ if (!report)
+ continue;
+ for (j = 0; j < report->num_fields; j++) {
kfree(report->fields[j]);
+ report->fields[j] = NULL;
+ }
kfree(report);
cd->hid_reports[i] = NULL;
}
@@ -3698,7 +3702,7 @@
rc = cyttsp5_hid_output_exit_easywake_state_(cd,
cd->easy_wakeup_gesture, &status);
if (rc || status == 0) {
- dev_err(cd->dev, "%s: failed, rc=%d, status=%d\n",
+ dev_dbg(cd->dev, "%s: failed, rc=%d, status=%d\n",
__func__, rc, status);
return -EBUSY;
}
@@ -3761,6 +3765,7 @@
/* 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)
@@ -4395,7 +4400,8 @@
if (!IS_DEEP_SLEEP_CONFIGURED(cd->easy_wakeup_gesture)) {
#ifdef CY_GES_WAKEUP
- return cyttsp5_core_wake_device_from_easy_wakeup_(cd);
+ if (!cyttsp5_core_wake_device_from_easy_wakeup_(cd))
+ return 0;
#endif
}
@@ -4633,7 +4639,7 @@
rc = cyttsp5_check_and_deassert_int(cd);
- if (reset || retry != CY_CORE_STARTUP_RETRY_COUNT) {
+ if (rc || retry != CY_CORE_STARTUP_RETRY_COUNT) {
/* reset hardware */
rc = cyttsp5_reset_and_wait(cd);
if (rc < 0) {
@@ -4773,12 +4779,11 @@
/* attention startup */
call_atten_cb(cd, CY_ATTEN_STARTUP, 0);
+ cyttsp5_start_wd_timer(cd);
exit:
if (!rc)
cd->startup_retry_count = 0;
- cyttsp5_start_wd_timer(cd);
-
if (!detected)
rc = -ENODEV;
@@ -4806,6 +4811,10 @@
rc = cyttsp5_startup_(cd, reset);
+ /* Wake the waiters for end of startup */
+ if (!rc)
+ wake_up(&cd->wait_q);
+
if (release_exclusive(cd, cd->dev) < 0)
/* Don't return fail code, mode is already changed. */
dev_err(cd->dev, "%s: fail to release exclusive\n", __func__);
@@ -4818,9 +4827,6 @@
cd->startup_state = STARTUP_NONE;
mutex_unlock(&cd->system_lock);
- /* Wake the waiters for end of startup */
- wake_up(&cd->wait_q);
-
return rc;
}
@@ -5759,6 +5765,8 @@
struct cyttsp5_core_commands *cyttsp5_get_commands(void)
{
+ if (!is_cyttsp5_probe_success)
+ return NULL;
return &_cyttsp5_core_commands;
}
EXPORT_SYMBOL_GPL(cyttsp5_get_commands);
@@ -5958,6 +5966,19 @@
}
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)
{
@@ -6001,12 +6022,7 @@
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;
@@ -6298,6 +6314,7 @@
/* 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 */
@@ -6436,12 +6453,13 @@
cyttsp5_btn_release(dev);
error_startup_mt:
cyttsp5_mt_release(dev);
+ cyttsp5_free_si_ptrs(cd);
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);
- cyttsp5_free_si_ptrs(cd);
remove_sysfs_interfaces(dev);
error_attr_create:
free_irq(cd->irq, cd);
@@ -6453,7 +6471,7 @@
cyttsp5_del_core(dev);
dev_set_drvdata(dev, NULL);
error_power:
- kfree(cd);
+ cyttsp5_power_init(cd, false);
error_alloc_data:
error_no_pdata:
dev_err(dev, "%s failed.\n", __func__);
@@ -6491,6 +6509,7 @@
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 9f3f586..c7dbafa 100644
--- a/drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c
+++ b/drivers/input/touchscreen/cyttsp5/cyttsp5_loader.c
@@ -751,7 +751,7 @@
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 e7b16db..9502c7a 100644
--- a/drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h
+++ b/drivers/input/touchscreen/cyttsp5/cyttsp5_regs.h
@@ -168,7 +168,7 @@
#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 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 28feb17..25cc6ae 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4119,9 +4119,7 @@
/* 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 @@
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 0390603..aa72907 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 @@
{
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 f96b8f2..d7c986f 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -394,7 +394,7 @@
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 @@
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 @@
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 dd344ee..ebacd21 100644
--- a/drivers/md/bcache/alloc.c
+++ b/drivers/md/bcache/alloc.c
@@ -322,10 +322,11 @@
* 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 646fe85..158eae1 100644
--- a/drivers/md/bcache/bset.c
+++ b/drivers/md/bcache/bset.c
@@ -823,12 +823,22 @@
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 ae96462..b935839 100644
--- a/drivers/md/bcache/bset.h
+++ b/drivers/md/bcache/bset.h
@@ -417,20 +417,26 @@
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 c76a017..6ee5370 100644
--- a/drivers/md/bcache/journal.c
+++ b/drivers/md/bcache/journal.c
@@ -309,6 +309,18 @@
}
}
+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 @@
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 8031bb2..298e45d 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1561,7 +1561,7 @@
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 @@
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 @@
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 @@
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 46b3227..f15f219 100644
--- a/drivers/md/dm-verity-target.c
+++ b/drivers/md/dm-verity-target.c
@@ -224,8 +224,8 @@
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 527ba28..bb65392 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7296,9 +7296,9 @@
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 @@
* 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 31f1610..59a4563 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -309,6 +309,9 @@
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 @@
}
/* 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 1f999e9..3554eea 100644
--- a/drivers/media/i2c/ov2659.c
+++ b/drivers/media/i2c/ov2659.c
@@ -1117,8 +1117,10 @@
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 e21b7e1..fc187c5 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -840,9 +840,16 @@
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 @@
done:
ov6650_s_power(&priv->subdev, 0);
+ if (!ret)
+ return 0;
+eclkput:
+ v4l2_clk_put(priv->clk);
+
return ret;
}
@@ -1035,18 +1047,9 @@
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 c889ec9..f5fc8bc 100644
--- a/drivers/media/pci/saa7146/hexium_gemini.c
+++ b/drivers/media/pci/saa7146/hexium_gemini.c
@@ -270,9 +270,8 @@
/* 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 c306a92..dc07ca3 100644
--- a/drivers/media/pci/saa7146/hexium_orion.c
+++ b/drivers/media/pci/saa7146/hexium_orion.c
@@ -232,9 +232,8 @@
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 b662504..717ee9a 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -1829,6 +1829,9 @@
/* 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_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 2695c54..8d454cb 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -2164,6 +2164,7 @@
}
CAM_DBG(CAM_ISP, "START CID SRC ... in ctx id:%d", ctx->ctx_index);
+ ctx->dual_ife_irq_mismatch_cnt = 0;
/* Start IFE root node: do nothing */
CAM_DBG(CAM_ISP, "Exit...(success)");
return 0;
@@ -2419,6 +2420,7 @@
memset(ctx->base, 0, sizeof(ctx->base));
/* release cdm handle */
+ ctx->dual_ife_irq_mismatch_cnt = 0;
cam_cdm_release(ctx->cdm_handle);
/* clean context */
@@ -3004,6 +3006,36 @@
}
}
+static void cam_ife_mgr_ctx_irq_dump(struct cam_ife_hw_mgr_ctx *ctx)
+{
+ struct cam_ife_hw_mgr_res *hw_mgr_res;
+ struct cam_hw_intf *hw_intf;
+ struct cam_isp_hw_get_cmd_update cmd_update;
+ int i = 0;
+
+ list_for_each_entry(hw_mgr_res, &ctx->res_list_ife_src, list) {
+ if (hw_mgr_res->res_type == CAM_IFE_HW_MGR_RES_UNINIT)
+ continue;
+ for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
+ if (!hw_mgr_res->hw_res[i])
+ continue;
+ switch (hw_mgr_res->hw_res[i]->res_id) {
+ case CAM_ISP_HW_VFE_IN_CAMIF:
+ hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
+ cmd_update.res = hw_mgr_res->hw_res[i];
+ cmd_update.cmd_type =
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP;
+ hw_intf->hw_ops.process_cmd(hw_intf->hw_priv,
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
+ &cmd_update, sizeof(cmd_update));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
{
int rc = 0;
@@ -3654,11 +3686,26 @@
(event_cnt[core_idx1] &&
(event_cnt[core_idx1] - event_cnt[core_idx0] > 1))) {
+ if (ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt > 10) {
+ rc = -1;
+ return rc;
+ }
+
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "One of the VFE cound not generate hw event %d",
+ "One of the VFE could not generate hw event %d",
hw_event_type);
- rc = -1;
- return rc;
+ if (event_cnt[core_idx0] >= 2) {
+ event_cnt[core_idx0]--;
+ ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt++;
+ }
+ if (event_cnt[core_idx1] >= 2) {
+ event_cnt[core_idx1]--;
+ ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt++;
+ }
+
+ if (ife_hw_mgr_ctx->dual_ife_irq_mismatch_cnt == 1)
+ cam_ife_mgr_ctx_irq_dump(ife_hw_mgr_ctx);
+ rc = 0;
}
CAM_DBG(CAM_ISP, "Only one core_index has given hw event %d",
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
index 9bfa34f..3a910b4 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.h
@@ -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
@@ -97,35 +97,38 @@
/**
* struct cam_vfe_hw_mgr_ctx - IFE HW manager Context object
*
- * @list: used by the ctx list.
- * @common: common acquired context data
- * @ctx_index: acquired context id.
- * @hw_mgr: IFE hw mgr which owns this context
- * @ctx_in_use: flag to tell whether context is active
- * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be
- * one.
- * @res_list_csid: CSID resource list
- * @res_list_ife_src: IFE input resource list
- * @res_list_ife_out: IFE output resoruces array
- * @free_res_list: Free resources list for the branch node
- * @res_pool: memory storage for the free resource list
- * @irq_status0_mask: irq_status0_mask for the context
- * @irq_status1_mask: irq_status1_mask for the context
- * @base device base index array contain the all IFE HW
- * instance associated with this context.
- * @num_base number of valid base data in the base array
- * @cdm_handle cdm hw acquire handle
- * @cdm_ops cdm util operation pointer for building
- * cdm commands
- * @cdm_cmd cdm base and length request pointer
- * @sof_cnt sof count value per core, used for dual VFE
- * @epoch_cnt epoch count value per core, used for dual VFE
- * @eof_cnt eof count value per core, used for dual VFE
- * @overflow_pending flat to specify the overflow is pending for the
- * context
- * @is_rdi_only_context flag to specify the context has only rdi resource
- * @config_done_complete indicator for configuration complete
- * @init_done indicate whether init hw is done
+ * @list: used by the ctx list.
+ * @common: common acquired context data
+ * @ctx_index: acquired context id.
+ * @hw_mgr: IFE hw mgr which owns this context
+ * @ctx_in_use: flag to tell whether context is active
+ * @res_list_ife_in: Starting resource(TPG,PHY0, PHY1...) Can only be
+ * one.
+ * @res_list_csid: CSID resource list
+ * @res_list_ife_src: IFE input resource list
+ * @res_list_ife_out: IFE output resoruces array
+ * @free_res_list: Free resources list for the branch node
+ * @res_pool: memory storage for the free resource list
+ * @irq_status0_mask: irq_status0_mask for the context
+ * @irq_status1_mask: irq_status1_mask for the context
+ * @base device base index array contain the all IFE HW
+ * instance associated with this context.
+ * @num_base number of valid base data in the base array
+ * @cdm_handle cdm hw acquire handle
+ * @cdm_ops cdm util operation pointer for building
+ * cdm commands
+ * @cdm_cmd cdm base and length request pointer
+ * @sof_cnt sof count value per core, used for dual VFE
+ * @epoch_cnt epoch count value per core, used for dual VFE
+ * @eof_cnt eof count value per core, used for dual VFE
+ * @overflow_pending flag to specify the overflow is pending for the
+ * context
+ * @is_rdi_only_context flag to specify the context has only rdi
+ * resource
+ * @config_done_complete indicator for configuration complete
+ * @init_done indicate whether init hw is done
+ * @dual_ife_irq_mismatch_cnt irq mismatch count value per core, used for
+ * dual VFE
*/
struct cam_ife_hw_mgr_ctx {
struct list_head list;
@@ -160,6 +163,7 @@
uint32_t is_rdi_only_context;
struct completion config_done_complete;
bool init_done;
+ uint32_t dual_ife_irq_mismatch_cnt;
};
/**
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
index 54aa4c2..2b814ac 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/include/cam_isp_hw.h
@@ -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
@@ -97,6 +97,7 @@
CAM_ISP_HW_CMD_GET_REG_DUMP,
CAM_ISP_HW_CMD_SOF_IRQ_DEBUG,
CAM_ISP_HW_CMD_SET_CAMIF_DEBUG,
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP,
CAM_ISP_HW_CMD_MAX,
};
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
index f6becfb..d8af627 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_core.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
@@ -696,6 +696,7 @@
case CAM_ISP_HW_CMD_CLOCK_UPDATE:
case CAM_ISP_HW_CMD_BW_UPDATE:
case CAM_ISP_HW_CMD_BW_CONTROL:
+ case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
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/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
index fc257ec..528eb6d 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_camif_ver2.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
@@ -378,6 +378,40 @@
return rc;
}
+static int cam_vfe_camif_irq_reg_dump(
+ struct cam_isp_resource_node *camif_res)
+{
+ struct cam_vfe_mux_camif_data *camif_priv;
+ struct cam_vfe_soc_private *soc_private;
+ int rc = 0;
+
+ if (!camif_res) {
+ CAM_ERR(CAM_ISP, "Error! Invalid input arguments\n");
+ return -EINVAL;
+ }
+
+ if ((camif_res->res_state == CAM_ISP_RESOURCE_STATE_RESERVED) ||
+ (camif_res->res_state == CAM_ISP_RESOURCE_STATE_AVAILABLE)) {
+ CAM_ERR(CAM_ISP, "Error! Invalid state\n");
+ return 0;
+ }
+
+ camif_priv = (struct cam_vfe_mux_camif_data *)camif_res->res_priv;
+ soc_private = camif_priv->soc_info->soc_private;
+
+ CAM_INFO(CAM_ISP,
+ "Core Id =%d Mask reg: offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ camif_priv->hw_intf->hw_idx,
+ 0x5c, cam_io_r_mb(camif_priv->mem_base + 0x5c),
+ 0x60, cam_io_r_mb(camif_priv->mem_base + 0x60));
+ CAM_INFO(CAM_ISP,
+ "Core Id =%d Status reg: offset 0x%x val 0x%x offset 0x%x val 0x%x",
+ camif_priv->hw_intf->hw_idx,
+ 0x6c, cam_io_r_mb(camif_priv->mem_base + 0x6c),
+ 0x70, cam_io_r_mb(camif_priv->mem_base + 0x70));
+ return rc;
+}
+
static int cam_vfe_camif_resource_stop(
struct cam_isp_resource_node *camif_res)
{
@@ -465,6 +499,9 @@
(struct cam_vfe_mux_camif_data *)rsrc_node->res_priv;
camif_priv->camif_debug = *((uint32_t *)cmd_args);
break;
+ case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
+ rc = cam_vfe_camif_irq_reg_dump(rsrc_node);
+ break;
default:
CAM_ERR(CAM_ISP,
"unsupported process command:%d", cmd_type);
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index 47a0438..7ec11e8 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.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
@@ -379,6 +379,19 @@
return -EINVAL;
}
+static int cam_vfe_get_irq_register_dump(
+ struct cam_vfe_top_ver2_priv *top_priv,
+ void *cmd_args, uint32_t arg_size)
+{
+ struct cam_isp_hw_get_cmd_update *cmd_update = cmd_args;
+
+ if (cmd_update->res->process_cmd)
+ cmd_update->res->process_cmd(cmd_update->res,
+ CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP, cmd_args, arg_size);
+
+ return 0;
+}
+
int cam_vfe_top_get_hw_caps(void *device_priv,
void *get_hw_cap_args, uint32_t arg_size)
{
@@ -657,6 +670,10 @@
case CAM_ISP_HW_CMD_BW_CONTROL:
rc = cam_vfe_top_bw_control(top_priv, cmd_args, arg_size);
break;
+ case CAM_ISP_HW_CMD_GET_IRQ_REGISTER_DUMP:
+ rc = cam_vfe_get_irq_register_dump(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/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
index 9628c81..dce58f3 100644
--- a/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_lrme/lrme_hw_mgr/lrme_hw/cam_lrme_hw_core.c
@@ -899,7 +899,7 @@
lrme_core->state = CAM_LRME_CORE_STATE_INIT;
} else {
CAM_ERR(CAM_LRME, "HW in wrong state %d", lrme_core->state);
- return -EINVAL;
+ rc = -EINVAL;
}
unlock:
@@ -951,7 +951,8 @@
if (lrme_core->req_submit != NULL) {
CAM_ERR(CAM_LRME, "req_submit is not NULL");
- return -EBUSY;
+ rc = -EBUSY;
+ goto error;
}
rc = cam_lrme_hw_util_submit_req(lrme_core, frame_req);
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 8c2853b..927e00b 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 @@
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 @@
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/cam_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 6797ba4..20976af 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -974,7 +974,7 @@
&eeprom_cap,
sizeof(struct cam_eeprom_query_cap_t))) {
CAM_ERR(CAM_EEPROM, "Failed Copy to User");
- return -EFAULT;
+ rc = -EFAULT;
goto release_mutex;
}
CAM_DBG(CAM_EEPROM, "eeprom_cap: ID: %d", eeprom_cap.slot_info);
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 576d5d6..e63c79a 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 @@
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 @@
} 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 @@
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_context.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
index 42f5a84..1f19f58 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.c
@@ -233,6 +233,28 @@
return rc;
}
+int cam_context_handle_crm_dump_req(struct cam_context *ctx,
+ struct cam_req_mgr_dump_info *dump)
+{
+ int rc = 0;
+
+ if (!ctx->state_machine) {
+ CAM_ERR(CAM_CORE, "Context is not ready");
+ return -EINVAL;
+ }
+ mutex_lock(&ctx->ctx_mutex);
+ if (ctx->state_machine[ctx->state].crm_ops.dump_req) {
+ rc = ctx->state_machine[ctx->state].crm_ops.dump_req(ctx,
+ dump);
+ } else {
+ CAM_ERR(CAM_CORE, "No crm dump req in dev %d, state %d",
+ ctx->dev_hdl, ctx->state);
+ }
+ mutex_unlock(&ctx->ctx_mutex);
+
+ return rc;
+}
+
int cam_context_dump_pf_info(struct cam_context *ctx, unsigned long iova,
uint32_t buf_info)
{
@@ -501,6 +523,33 @@
return rc;
}
+int cam_context_handle_dump_dev(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd)
+{
+ int rc = 0;
+
+ if (!ctx || !ctx->state_machine) {
+ CAM_ERR(CAM_CORE, "Context is not ready");
+ return -EINVAL;
+ }
+
+ if (!cmd) {
+ CAM_ERR(CAM_CORE, "Invalid stop device command payload");
+ return -EINVAL;
+ }
+
+ mutex_lock(&ctx->ctx_mutex);
+ if (ctx->state_machine[ctx->state].ioctl_ops.dump_dev)
+ rc = ctx->state_machine[ctx->state].ioctl_ops.dump_dev(
+ ctx, cmd);
+ else
+ CAM_WARN(CAM_CORE, "No dump device in dev %d, name %s state %d",
+ ctx->dev_hdl, ctx->dev_name, ctx->state);
+ mutex_unlock(&ctx->ctx_mutex);
+
+ return rc;
+}
+
int cam_context_init(struct cam_context *ctx,
const char *dev_name,
uint64_t dev_id,
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h
index 2d8c6e0..84a190a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context.h
@@ -92,6 +92,7 @@
* @flush_dev: Function pointer for flush device
* @acquire_hw: Function pointer for acquire hw
* @release_hw: Function pointer for release hw
+ * @dump_dev: Function pointer for dump dev
*
*/
struct cam_ctx_ioctl_ops {
@@ -109,6 +110,9 @@
struct cam_flush_dev_cmd *cmd);
int (*acquire_hw)(struct cam_context *ctx, void *args);
int (*release_hw)(struct cam_context *ctx, void *args);
+ int (*dump_dev)(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd);
+
};
/**
@@ -120,6 +124,7 @@
* @apply_req: Apply setting for the context
* @flush_req: Flush request to remove request ids
* @process_evt: Handle event notification from CRM.(optional)
+ * @dump_req: Dump information for the issue request
*
*/
struct cam_ctx_crm_ops {
@@ -135,6 +140,8 @@
struct cam_req_mgr_flush_request *flush);
int (*process_evt)(struct cam_context *ctx,
struct cam_req_mgr_link_evt_data *evt_data);
+ int (*dump_req)(struct cam_context *ctx,
+ struct cam_req_mgr_dump_info *dump);
};
@@ -305,6 +312,18 @@
struct cam_req_mgr_link_evt_data *process_evt);
/**
+ * cam_context_handle_crm_dump_req()
+ *
+ * @brief: Handle CRM dump request
+ *
+ * @ctx: Object pointer for cam_context
+ * @dump: Request to dump
+ *
+ */
+int cam_context_handle_crm_dump_req(struct cam_context *ctx,
+ struct cam_req_mgr_dump_info *dump);
+
+/**
* cam_context_dump_pf_info()
*
* @brief: Handle dump active request request command
@@ -413,6 +432,19 @@
int cam_context_handle_stop_dev(struct cam_context *ctx,
struct cam_start_stop_dev_cmd *cmd);
+
+/**
+ * cam_context_handle_dump_dev()
+ *
+ * @brief: Handle dump device command
+ *
+ * @ctx: Object pointer for cam_context
+ * @cmd: Dump device command payload
+ *
+ */
+int cam_context_handle_dump_dev(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd);
+
/**
* cam_context_deinit()
*
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
index 7600cbb..d7500a1 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.c
@@ -462,6 +462,17 @@
ctx->dev_name, ctx->ctx_id, req->request_id);
for (j = 0; j < req->num_in_map_entries; j++) {
+ rc = cam_sync_check_valid(
+ req->in_map_entries[j].sync_id);
+ if (rc) {
+ CAM_ERR(CAM_CTXT,
+ "invalid in map sync object %d",
+ req->in_map_entries[j].sync_id);
+ goto put_ref;
+ }
+ }
+
+ for (j = 0; j < req->num_in_map_entries; j++) {
cam_context_getref(ctx);
rc = cam_sync_register_callback(
cam_context_sync_callback,
@@ -482,7 +493,9 @@
ctx->dev_name, ctx->ctx_id,
req->request_id);
- goto put_ctx_ref;
+ cam_context_putref(ctx);
+ goto put_ref;
+
}
CAM_DBG(CAM_CTXT, "register in fence cb: %d ret = %d",
req->in_map_entries[j].sync_id, rc);
@@ -491,9 +504,6 @@
}
return rc;
-put_ctx_ref:
- for (--j; j >= 0; j--)
- cam_context_putref(ctx);
put_ref:
for (--i; i >= 0; i--) {
rc = cam_sync_put_obj_ref(req->out_map_entries[i].sync_id);
@@ -1029,3 +1039,43 @@
end:
return rc;
}
+
+int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd)
+{
+ int rc = 0;
+ struct cam_hw_dump_args dump_args;
+
+ if (!ctx || !cmd) {
+ CAM_ERR(CAM_CTXT, "Invalid input params %pK %pK", ctx, cmd);
+ return -EINVAL;
+ }
+ if (!ctx->hw_mgr_intf) {
+ CAM_ERR(CAM_CTXT, "[%s][%d] HW interface is not ready",
+ ctx->dev_name, ctx->ctx_id);
+ return -EFAULT;
+ }
+ memset(&dump_args, 0, sizeof(dump_args));
+ if (ctx->hw_mgr_intf->hw_dump) {
+ dump_args.ctxt_to_hw_map = ctx->ctxt_to_hw_map;
+ dump_args.buf_handle = cmd->buf_handle;
+ dump_args.offset = cmd->offset;
+ dump_args.request_id = cmd->issue_req_id;
+ rc = ctx->hw_mgr_intf->hw_dump(
+ ctx->hw_mgr_intf->hw_mgr_priv,
+ &dump_args);
+ if (rc) {
+ CAM_ERR(CAM_CTXT, "[%s][%d] handle[%u] failed",
+ ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
+ return rc;
+ }
+ CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %d",
+ ctx->dev_name, ctx->ctx_id,
+ dump_args.offset - cmd->offset);
+ /* Drivers update offest upto which the buffer is written*/
+ cmd->offset = dump_args.offset;
+ } else {
+ CAM_INFO(CAM_CTXT, "%s hw dump not registered", ctx->dev_name);
+ }
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h
index e1809b2..022641f 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_context_utils.h
@@ -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
@@ -36,5 +36,6 @@
int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
struct cam_packet *packet, unsigned long iova, uint32_t buf_info,
bool *mem_found);
-
+int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
+ struct cam_dump_req_cmd *cmd);
#endif /* _CAM_CONTEXT_UTILS_H_ */
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 6b7a900..19e3230 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,31 @@
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;
+};
+
+/**
+ * struct cam_hw_dump_args - Dump arguments
+ *
+ * @request_id: request_id
+ * @buf_handle: Buffer handle
+ * @offset: Buffer offset. This is updated by the drivers.
+ * @ctxt_to_hw_map: HW context from the acquire
+ */
+struct cam_hw_dump_args {
+ uint64_t request_id;
+ uint32_t buf_handle;
+ int32_t offset;
+ 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 +338,8 @@
* @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
+ * @hw_dump: Function pointer for HW dump
*
*/
struct cam_hw_mgr_intf {
@@ -333,6 +360,8 @@
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);
+ int (*hw_dump)(void *hw_priv, void *hw_dump_args);
};
#endif /* _CAM_HW_MGR_INTF_H_ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
index 2578fb9..322b7e6 100644
--- a/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
+++ b/drivers/media/platform/msm/camera_v3/cam_core/cam_node.c
@@ -330,6 +330,39 @@
return rc;
}
+static int __cam_node_handle_dump_dev(struct cam_node *node,
+ struct cam_dump_req_cmd *dump)
+{
+ struct cam_context *ctx = NULL;
+ int rc;
+
+ if (!dump)
+ return -EINVAL;
+
+ if (dump->dev_handle <= 0) {
+ CAM_ERR(CAM_CORE, "Invalid device handle for context");
+ return -EINVAL;
+ }
+
+ if (dump->session_handle <= 0) {
+ CAM_ERR(CAM_CORE, "Invalid session handle for context");
+ return -EINVAL;
+ }
+
+ ctx = (struct cam_context *)cam_get_device_priv(dump->dev_handle);
+ if (!ctx) {
+ CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+ dump->dev_handle);
+ return -EINVAL;
+ }
+
+ rc = cam_context_handle_dump_dev(ctx, dump);
+ if (rc)
+ CAM_ERR(CAM_CORE, "Flush failure for node %s", node->name);
+
+ return rc;
+}
+
static int __cam_node_handle_release_dev(struct cam_node *node,
struct cam_release_dev_cmd *release)
{
@@ -531,6 +564,25 @@
return cam_context_handle_crm_process_evt(ctx, evt_data);
}
+static int __cam_node_crm_dump_req(struct cam_req_mgr_dump_info *dump)
+{
+ struct cam_context *ctx = NULL;
+
+ if (!dump) {
+ CAM_ERR(CAM_CORE, "Invalid dump request payload");
+ return -EINVAL;
+ }
+
+ ctx = (struct cam_context *) cam_get_device_priv(dump->dev_hdl);
+ if (!ctx) {
+ CAM_ERR(CAM_CORE, "Can not get context for handle %d",
+ dump->dev_hdl);
+ return -EINVAL;
+ }
+
+ return cam_context_handle_crm_dump_req(ctx, dump);
+}
+
int cam_node_deinit(struct cam_node *node)
{
if (node)
@@ -586,6 +638,7 @@
node->crm_node_intf.link_setup = __cam_node_crm_link_setup;
node->crm_node_intf.flush_req = __cam_node_crm_flush_req;
node->crm_node_intf.process_evt = __cam_node_crm_process_evt;
+ node->crm_node_intf.dump_req = __cam_node_crm_dump_req;
mutex_init(&node->list_mutex);
INIT_LIST_HEAD(&node->free_ctx_list);
@@ -827,6 +880,28 @@
}
break;
}
+ case CAM_DUMP_REQ: {
+ struct cam_dump_req_cmd dump;
+
+ if (copy_from_user(&dump, u64_to_user_ptr(cmd->handle),
+ sizeof(dump))) {
+ rc = -EFAULT;
+ } else {
+ rc = __cam_node_handle_dump_dev(node, &dump);
+ if (rc) {
+ CAM_ERR(CAM_CORE,
+ "Dump device %s failed(rc = %d) ",
+ node->name, rc);
+ } else if (copy_to_user(u64_to_user_ptr(cmd->handle),
+ &dump, sizeof(dump))) {
+ CAM_ERR(CAM_CORE,
+ "Dump device %s copy_to_user fail",
+ node->name);
+ rc = -EFAULT;
+ }
+ }
+ break;
+ }
default:
CAM_ERR(CAM_CORE, "Unknown op code %d", cmd->op_code);
rc = -EINVAL;
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 4276b35..a68e207 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 @@
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 @@
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 @@
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]);
@@ -1234,6 +1244,13 @@
rc = cam_common_util_get_string_index(soc_private->client_name,
soc_private->num_clients, client_name, &client_indx);
+ if (rc) {
+ CAM_ERR(CAM_CPAS, "No match found for client %s",
+ client_name);
+ mutex_unlock(&cpas_hw->hw_mutex);
+ return rc;
+ }
+
mutex_lock(&cpas_core->client_mutex[client_indx]);
if (rc || !CAM_CPAS_CLIENT_VALID(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 719fb12..aaa435d 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 @@
(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 @@
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 0000000..734f378
--- /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 7b534a9..f285863 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_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 e13d7f2..4dbc8f1 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 @@
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 c94276c..f522f71 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 @@
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 cfc474a..03b93ac 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 @@
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 ae3d134..ae58b34 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 @@
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 57375c4..53c1c0f 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
@@ -38,18 +38,26 @@
static void __cam_isp_ctx_update_state_monitor_array(
struct cam_isp_context *ctx_isp,
- enum cam_isp_state_change_trigger trigger_type,
- uint32_t req_id)
+ enum cam_isp_hw_event_type hw_event,
+ enum cam_isp_ctx_activated_substate curr_state,
+ enum cam_isp_ctx_activated_substate next_state)
{
int iterator = 0;
iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head);
ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state =
- ctx_isp->substate_activated;
- ctx_isp->cam_isp_ctx_state_monitor[iterator].trigger =
- trigger_type;
- ctx_isp->cam_isp_ctx_state_monitor[iterator].req_id =
- req_id;
+ curr_state;
+ ctx_isp->cam_isp_ctx_state_monitor[iterator].next_state =
+ next_state;
+ ctx_isp->cam_isp_ctx_state_monitor[iterator].hw_event =
+ hw_event;
+ ctx_isp->cam_isp_ctx_state_monitor[iterator].last_reported_id =
+ ctx_isp->req_info.reported_req_id;
+ ctx_isp->cam_isp_ctx_state_monitor[iterator].last_applied_req_id =
+ ctx_isp->req_info.last_applied_req_id;
+ ctx_isp->cam_isp_ctx_state_monitor[iterator].frame_id =
+ ctx_isp->frame_id;
+
ctx_isp->cam_isp_ctx_state_monitor[iterator].evt_time_stamp =
jiffies_to_msecs(jiffies);
}
@@ -79,17 +87,17 @@
uint32_t evt_id)
{
switch (evt_id) {
- case CAM_ISP_STATE_CHANGE_TRIGGER_ERROR:
+ case CAM_ISP_HW_EVENT_ERROR:
return "ERROR";
- case CAM_ISP_STATE_CHANGE_TRIGGER_SOF:
+ case CAM_ISP_HW_EVENT_SOF:
return "SOF";
- case CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE:
+ case CAM_ISP_HW_EVENT_REG_UPDATE:
return "REG_UPDATE";
- case CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH:
+ case CAM_ISP_HW_EVENT_EPOCH:
return "EPOCH";
- case CAM_ISP_STATE_CHANGE_TRIGGER_EOF:
+ case CAM_ISP_HW_EVENT_EOF:
return "EOF";
- case CAM_ISP_STATE_CHANGE_TRIGGER_DONE:
+ case CAM_ISP_HW_EVENT_DONE:
return "DONE";
default:
return "CAM_ISP_EVENT_INVALID";
@@ -97,29 +105,58 @@
}
static void __cam_isp_ctx_dump_state_monitor_array(
- struct cam_isp_context *ctx_isp)
+ struct cam_isp_context *ctx_isp, bool log_rate_limit)
{
int i = 0;
uint64_t state_head = 0;
uint64_t index;
+ struct cam_isp_context_state_monitor *ctx_monitor;
state_head = atomic64_read(&ctx_isp->state_monitor_head);
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "Dumping state information for preceding requests");
+
+ ctx_monitor = ctx_isp->cam_isp_ctx_state_monitor;
+
+ if (log_rate_limit)
+ CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20,
+ "Dumping state information for preceding requests");
+ else
+ CAM_INFO(CAM_ISP,
+ "Dumping state information for preceding requests");
for (i = CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES - 1; i >= 0;
i--) {
index = (((state_head - i) +
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES) %
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES);
- CAM_ERR_RATE_LIMIT(CAM_ISP,
- "time[0x%llx] req_id[%u] state[%s] evt_type[%s]",
- ctx_isp->cam_isp_ctx_state_monitor[index].evt_time_stamp,
- ctx_isp->cam_isp_ctx_state_monitor[index].req_id,
- __cam_isp_ctx_substate_val_to_type(
- ctx_isp->cam_isp_ctx_state_monitor[index].curr_state),
- __cam_isp_hw_evt_val_to_type(
- ctx_isp->cam_isp_ctx_state_monitor[index].trigger));
+
+ if (log_rate_limit) {
+ CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20,
+ "time[%lld] last reported req_id[%lld] frame id[%lld] applied id[%lld] current state[%s] next state[%s] hw_event[%s]",
+ ctx_monitor[index].evt_time_stamp,
+ ctx_monitor[index].last_reported_id,
+ ctx_monitor[index].frame_id,
+ ctx_monitor[index].last_applied_req_id,
+ __cam_isp_ctx_substate_val_to_type(
+ ctx_monitor[index].curr_state),
+ __cam_isp_ctx_substate_val_to_type(
+ ctx_monitor[index].next_state),
+ __cam_isp_hw_evt_val_to_type(
+ ctx_monitor[index].hw_event));
+
+ } else {
+ CAM_INFO(CAM_ISP,
+ "time[%lld] last reported req_id[%lld] frame id[%lld] applied id[%lld] current state[%s] next state[%s] hw_event[%s]",
+ ctx_monitor[index].evt_time_stamp,
+ ctx_monitor[index].last_reported_id,
+ ctx_monitor[index].frame_id,
+ ctx_monitor[index].last_applied_req_id,
+ __cam_isp_ctx_substate_val_to_type(
+ ctx_monitor[index].curr_state),
+ __cam_isp_ctx_substate_val_to_type(
+ ctx_monitor[index].next_state),
+ __cam_isp_hw_evt_val_to_type(
+ ctx_monitor[index].hw_event));
+ }
}
}
@@ -403,7 +440,7 @@
struct cam_context *ctx = ctx_isp->base;
if (list_empty(&ctx->active_req_list)) {
- CAM_DBG(CAM_ISP, "Buf done with no active request!");
+ CAM_WARN(CAM_ISP, "Buf done with no active request!");
goto end;
}
@@ -415,6 +452,14 @@
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] ==
@@ -508,6 +553,10 @@
CAM_DBG(CAM_REQ,
"Move active request %lld to pending list(cnt = %d) [bubble recovery], ctx %u",
req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_HW_EVENT_DONE,
+ ctx_isp->substate_activated,
+ ctx_isp->substate_activated);
} else {
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->free_req_list);
@@ -515,32 +564,59 @@
CAM_DBG(CAM_REQ,
"Move active request %lld to free list(cnt = %d) [all fences done], ctx %u",
req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);
+ ctx_isp->req_info.last_bufdone_req_id = req->request_id;
+ ctx_isp->req_info.last_bufdone_time_stamp =
+ jiffies_to_msecs(jiffies);
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp,
+ CAM_ISP_HW_EVENT_DONE,
+ ctx_isp->substate_activated,
+ 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:
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
- ctx_isp->base->req_list->request_id);
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,
@@ -548,6 +624,8 @@
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;
}
@@ -556,6 +634,7 @@
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;
@@ -565,9 +644,9 @@
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,
@@ -575,21 +654,64 @@
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;
}
@@ -599,7 +721,8 @@
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");
@@ -624,13 +747,22 @@
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;
}
@@ -658,6 +790,7 @@
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",
@@ -665,9 +798,12 @@
}
list_for_each_entry(req, &ctx->active_req_list, list) {
- if (req->request_id > ctx_isp->reported_req_id) {
+ if (req->request_id >
+ ctx_isp->req_info.reported_req_id) {
request_id = req->request_id;
- ctx_isp->reported_req_id = request_id;
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
break;
}
}
@@ -675,6 +811,17 @@
if (ctx_isp->substate_activated == CAM_ISP_CTX_ACTIVATED_BUBBLE)
request_id = 0;
+ if (request_id && ctx_isp->req_info.reported_req_id &&
+ ((request_id - ctx_isp->req_info.reported_req_id) >
+ 1)){
+ CAM_INFO(CAM_ISP,
+ "ctx:%d curr req id: %lld last reported id:%lld",
+ ctx->ctx_id, request_id,
+ ctx_isp->req_info.reported_req_id);
+
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
+ }
+
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
} else {
@@ -742,8 +889,15 @@
ctx_isp->frame_id++;
ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
ctx_isp->boot_timestamp = sof_event_data->boot_time;
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
+
+ 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);
@@ -755,8 +909,9 @@
{
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");
@@ -778,11 +933,17 @@
CAM_ERR(CAM_ISP,
"receive rup in unexpected state");
}
- if (req != NULL) {
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
- req->request_id);
- }
+
+ 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;
}
@@ -791,16 +952,18 @@
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)) {
/*
* If no wait req in epoch, this is an error case.
* The recovery is to go back to sof state
*/
- CAM_ERR(CAM_ISP, "No wait request");
+ CAM_ERR(CAM_ISP, "Ctx:%d No wait request", ctx->ctx_id);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
/* Send SOF event as empty frame*/
@@ -815,7 +978,9 @@
req_isp = (struct cam_isp_ctx_req *)req->req_priv;
req_isp->bubble_detected = true;
- CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
+ CAM_INFO(CAM_ISP, "ctx:%d Report Bubble flag %d req id:%lld",
+ ctx->ctx_id, req_isp->bubble_report, req->request_id);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
if (req_isp->bubble_report && ctx->ctx_crm_intf &&
ctx->ctx_crm_intf->notify_err) {
struct cam_req_mgr_error_notify notify;
@@ -842,9 +1007,11 @@
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->active_req_list);
- if (req->request_id > ctx_isp->reported_req_id) {
+ if (req->request_id > ctx_isp->req_info.reported_req_id) {
request_id = req->request_id;
- ctx_isp->reported_req_id = request_id;
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
}
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_ERROR);
@@ -853,15 +1020,16 @@
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
end:
- if (request_id == 0) {
- req = list_last_entry(&ctx->active_req_list,
- struct cam_ctx_request, list);
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id);
- } else {
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, request_id);
- }
+
+ 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;
}
@@ -884,7 +1052,6 @@
int rc = 0;
struct cam_context *ctx = ctx_isp->base;
struct cam_isp_hw_sof_event_data *sof_event_data = evt_data;
- struct cam_ctx_request *req;
if (!evt_data) {
CAM_ERR(CAM_ISP, "in valid sof event data");
@@ -895,17 +1062,19 @@
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
CAM_DBG(CAM_ISP, "Still need to wait for the buf done");
- req = list_last_entry(&ctx->active_req_list,
- struct cam_ctx_request, list);
- if (req)
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
- ctx->req_list->request_id);
CAM_DBG(CAM_ISP, "next substate %d",
ctx_isp->substate_activated);
@@ -952,7 +1121,8 @@
* If no pending req in epoch, this is an error case.
* Just go back to the bubble state.
*/
- CAM_ERR(CAM_ISP, "No pending request.");
+ CAM_ERR(CAM_ISP, "ctx:%d No pending request.", ctx->ctx_id);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
@@ -964,6 +1134,9 @@
list);
req_isp = (struct cam_isp_ctx_req *)req->req_priv;
req_isp->bubble_detected = true;
+ CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld",
+ ctx->ctx_id, req_isp->bubble_report, req->request_id);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
if (req_isp->bubble_report && ctx->ctx_crm_intf &&
ctx->ctx_crm_intf->notify_err) {
@@ -992,9 +1165,11 @@
list_add_tail(&req->list, &ctx->active_req_list);
if (!req_isp->bubble_report) {
- if (req->request_id > ctx_isp->reported_req_id) {
+ if (req->request_id > ctx_isp->req_info.reported_req_id) {
request_id = req->request_id;
- ctx_isp->reported_req_id = request_id;
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_ERROR);
} else
@@ -1007,11 +1182,7 @@
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
- req = list_last_entry(&ctx->active_req_list, struct cam_ctx_request,
- list);
- if (req)
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH, req->request_id);
+
return 0;
}
@@ -1023,9 +1194,7 @@
(struct cam_isp_hw_done_event_data *) evt_data;
rc = __cam_isp_ctx_handle_buf_done_in_activated_state(ctx_isp, done, 1);
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
- ctx_isp->base->req_list->request_id);
+
return rc;
}
@@ -1083,9 +1252,6 @@
if (error_event_data->enable_reg_dump)
cam_isp_ctx_dump_req(req_isp);
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_ERROR, req_to_dump->request_id);
-
list_for_each_entry_safe(req, req_temp,
&ctx->active_req_list, list) {
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
@@ -1176,14 +1342,15 @@
end:
do {
if (list_empty(&ctx->pending_req_list)) {
- error_request_id = ctx_isp->last_applied_req_id + 1;
+ error_request_id =
+ ctx_isp->req_info.last_applied_req_id + 1;
req_isp = NULL;
break;
}
req = list_first_entry(&ctx->pending_req_list,
struct cam_ctx_request, list);
req_isp = (struct cam_isp_ctx_req *) req->req_priv;
- error_request_id = ctx_isp->last_applied_req_id;
+ error_request_id = ctx_isp->req_info.last_applied_req_id;
if (req_isp->bubble_report) {
req_to_report = req;
@@ -1201,7 +1368,8 @@
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->free_req_list);
- } while (req->request_id < ctx_isp->last_applied_req_id);
+ } while (req->request_id <
+ ctx_isp->req_info.last_applied_req_id);
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_err) {
notify.link_hdl = ctx->link_hdl;
@@ -1240,8 +1408,8 @@
V4L_EVENT_CAM_REQ_MGR_EVENT))
CAM_ERR(CAM_ISP,
"Error in notifying the error time for req id:%lld ctx %u",
- ctx_isp->last_applied_req_id,
- ctx->ctx_id);
+ ctx_isp->req_info.last_applied_req_id,
+ ctx->ctx_id);
}
ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_HW_ERROR;
} else {
@@ -1278,8 +1446,7 @@
ctx_isp->frame_id++;
ctx_isp->sof_timestamp_val = sof_event_data->timestamp;
ctx_isp->boot_timestamp = sof_event_data->boot_time;
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_SOF, req->request_id);
+
CAM_DBG(CAM_ISP, "frame id: %lld time stamp:0x%llx",
ctx_isp->frame_id, ctx_isp->sof_timestamp_val);
@@ -1293,6 +1460,7 @@
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",
@@ -1300,9 +1468,12 @@
}
list_for_each_entry(req, &ctx->active_req_list, list) {
- if (req->request_id > ctx_isp->reported_req_id) {
+ if (req->request_id >
+ ctx_isp->req_info.reported_req_id) {
request_id = req->request_id;
- ctx_isp->reported_req_id = request_id;
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
break;
}
}
@@ -1343,8 +1514,10 @@
CAM_DBG(CAM_ISP, "No request, move to SOF");
ctx_isp->substate_activated =
CAM_ISP_CTX_ACTIVATED_SOF;
- if (ctx_isp->reported_req_id < curr_req_id) {
- ctx_isp->reported_req_id = curr_req_id;
+ if (ctx_isp->req_info.reported_req_id < curr_req_id) {
+ ctx_isp->req_info.reported_req_id = curr_req_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
__cam_isp_ctx_send_sof_timestamp(ctx_isp,
curr_req_id,
CAM_REQ_MGR_SOF_EVENT_SUCCESS);
@@ -1379,7 +1552,7 @@
{
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) {
@@ -1402,11 +1575,10 @@
CAM_ERR(CAM_ISP,
"receive rup in unexpected state");
}
- if (req != NULL) {
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
- req->request_id);
- }
+
+ if (req_isp && req_isp->hw_update_data.fps)
+ ctx_isp->fps = req_isp->hw_update_data.fps;
+
end:
return rc;
}
@@ -1417,7 +1589,7 @@
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;
@@ -1440,6 +1612,9 @@
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.
@@ -1451,9 +1626,12 @@
if (ctx->ctx_crm_intf && ctx->ctx_crm_intf->notify_trigger &&
ctx_isp->active_req_cnt <= 2) {
list_for_each_entry(req, &ctx->active_req_list, list) {
- if (req->request_id > ctx_isp->reported_req_id) {
+ if (req->request_id >
+ ctx_isp->req_info.reported_req_id) {
request_id = req->request_id;
- ctx_isp->reported_req_id = request_id;
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
break;
}
}
@@ -1466,6 +1644,7 @@
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",
@@ -1478,11 +1657,7 @@
CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
- if (req != NULL && !rc) {
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
- req->request_id);
- }
+
return rc;
}
@@ -1729,19 +1904,19 @@
} else {
spin_lock_bh(&ctx->lock);
ctx_isp->substate_activated = next_state;
- ctx_isp->last_applied_req_id = apply->request_id;
+ ctx_isp->req_info.last_applied_req_id =
+ apply->request_id;
+ ctx_isp->req_info.last_applied_time_stamp =
+ jiffies_to_msecs(jiffies);
list_del_init(&req->list);
list_add_tail(&req->list, &ctx->wait_req_list);
CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld",
- next_state, ctx_isp->last_applied_req_id);
+ next_state,
+ ctx_isp->req_info.last_applied_req_id);
spin_unlock_bh(&ctx->lock);
}
end:
- if (ctx_isp != NULL) {
- __cam_isp_ctx_update_state_monitor_array(ctx_isp,
- CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
- ctx->req_list->request_id);
- }
+
return rc;
}
@@ -1863,21 +2038,92 @@
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);
+
+ if (!list_empty(&ctx->active_req_list)) {
+ CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20,
+ "ctx:%d last applied id:%lld, reported req id:%lld, buf done id:%lld",
+ ctx->ctx_id,
+ ctx_isp->req_info.last_applied_req_id,
+ ctx_isp->req_info.reported_req_id,
+ ctx_isp->req_info.last_bufdone_req_id);
+ CAM_INFO_RATE_LIMIT_CUSTOM(CAM_ISP, 5, 20,
+ "current time:%u last apply time:%lld, reported req time:%lld, buf done time:%lld",
+ jiffies_to_msecs(jiffies),
+ ctx_isp->req_info.last_applied_time_stamp,
+ ctx_isp->req_info.last_reported_id_time_stamp,
+ ctx_isp->req_info.last_bufdone_time_stamp);
+
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
+ }
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;
}
@@ -2041,6 +2287,7 @@
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",
@@ -2133,8 +2380,10 @@
list);
req_isp = (struct cam_isp_ctx_req *)req->req_priv;
req_isp->bubble_detected = true;
+ CAM_INFO(CAM_ISP, "Ctx:%d Report Bubble flag %d req id:%lld",
+ ctx->ctx_id, req_isp->bubble_report, req->request_id);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
- CAM_DBG(CAM_ISP, "Report Bubble flag %d", req_isp->bubble_report);
if (req_isp->bubble_report && ctx->ctx_crm_intf &&
ctx->ctx_crm_intf->notify_err) {
struct cam_req_mgr_error_notify notify;
@@ -2161,9 +2410,11 @@
req->request_id, ctx_isp->active_req_cnt);
if (!req_isp->bubble_report) {
- if (req->request_id > ctx_isp->reported_req_id) {
+ if (req->request_id > ctx_isp->req_info.reported_req_id) {
request_id = req->request_id;
- ctx_isp->reported_req_id = request_id;
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ jiffies_to_msecs(jiffies);
__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
CAM_REQ_MGR_SOF_EVENT_ERROR);
} else
@@ -2228,6 +2479,7 @@
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",
@@ -2257,7 +2509,7 @@
{
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;
@@ -2298,6 +2550,7 @@
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",
@@ -2305,8 +2558,14 @@
} else {
CAM_ERR(CAM_ISP, "Can not notify SOF to CRM");
}
- if (request_id)
- ctx_isp->reported_req_id = request_id;
+ if (request_id) {
+ ctx_isp->req_info.reported_req_id = request_id;
+ ctx_isp->req_info.last_reported_id_time_stamp =
+ 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);
@@ -2481,9 +2740,14 @@
ctx->last_flush_req = 0;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
- ctx_isp->reported_req_id = 0;
ctx_isp->hw_acquired = false;
ctx_isp->init_received = false;
+ ctx_isp->req_info.reported_req_id = 0;
+ ctx_isp->req_info.last_applied_req_id = 0;
+ ctx_isp->req_info.last_bufdone_req_id = 0;
+ 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;
/*
* Ideally, we should never have any active request here.
@@ -2538,11 +2802,16 @@
ctx->last_flush_req = 0;
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
- ctx_isp->reported_req_id = 0;
ctx_isp->hw_acquired = false;
ctx_isp->init_received = false;
ctx_isp->rdi_only_context = false;
ctx_isp->split_acquire = false;
+ ctx_isp->req_info.reported_req_id = 0;
+ ctx_isp->req_info.last_applied_req_id = 0;
+ ctx_isp->req_info.last_bufdone_req_id = 0;
+ 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;
/*
* Ideally, we should never have any active request here.
@@ -2573,7 +2842,7 @@
{
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;
@@ -2662,6 +2931,7 @@
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;
@@ -2718,6 +2988,7 @@
CAM_ERR(CAM_ISP, "Recevied Update in wrong state");
}
}
+
if (rc)
goto put_ref;
@@ -3169,7 +3440,7 @@
atomic_set(&ctx_isp->process_bubble, 0);
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
- ctx_isp->reported_req_id = 0;
+ ctx_isp->req_info.reported_req_id = 0;
ctx_isp->substate_activated = ctx_isp->rdi_only_context ?
CAM_ISP_CTX_ACTIVATED_APPLIED :
(req_isp->num_fence_map_out) ? CAM_ISP_CTX_ACTIVATED_EPOCH :
@@ -3301,7 +3572,15 @@
}
ctx_isp->frame_id = 0;
ctx_isp->active_req_cnt = 0;
- ctx_isp->reported_req_id = 0;
+ ctx_isp->req_info.reported_req_id = 0;
+ ctx_isp->req_info.last_applied_req_id = 0;
+ ctx_isp->req_info.last_bufdone_req_id = 0;
+ 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);
CAM_DBG(CAM_ISP, "Stop device success next state %d on ctx %u",
@@ -3478,8 +3757,9 @@
rc = ctx_ops->crm_ops.apply_req(ctx, apply);
} else {
CAM_ERR_RATE_LIMIT(CAM_ISP,
- "No handle function in activated substate %d",
- ctx_isp->substate_activated);
+ "Ctx:%d No handle function in activated substate %d",
+ ctx->ctx_id, ctx_isp->substate_activated);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
rc = -EFAULT;
}
@@ -3490,8 +3770,6 @@
return rc;
}
-
-
static int __cam_isp_ctx_handle_irq_in_activated(void *context,
uint32_t evt_id, void *evt_data)
{
@@ -3500,22 +3778,27 @@
struct cam_context *ctx = (struct cam_context *)context;
struct cam_isp_context *ctx_isp =
(struct cam_isp_context *)ctx->ctx_priv;
+ enum cam_isp_ctx_activated_substate curr_state;
spin_lock(&ctx->lock);
trace_cam_isp_activated_irq(ctx, ctx_isp->substate_activated, evt_id,
__cam_isp_ctx_get_event_ts(evt_id, evt_data));
+ curr_state = ctx_isp->substate_activated;
CAM_DBG(CAM_ISP, "Enter: State %d, Substate %d, evt id %d",
ctx->state, ctx_isp->substate_activated, evt_id);
irq_ops = &ctx_isp->substate_machine_irq[ctx_isp->substate_activated];
if (irq_ops->irq_ops[evt_id]) {
rc = irq_ops->irq_ops[evt_id](ctx_isp, evt_data);
} else {
- CAM_DBG(CAM_ISP, "No handle function for substate %d",
- ctx_isp->substate_activated);
- __cam_isp_ctx_dump_state_monitor_array(ctx_isp);
+ CAM_INFO(CAM_ISP, "Ctx:%d No handle function for substate %d",
+ ctx->ctx_id, ctx_isp->substate_activated);
+ __cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
}
+ if (evt_id != CAM_ISP_HW_EVENT_DONE)
+ __cam_isp_ctx_update_state_monitor_array(ctx_isp, evt_id,
+ curr_state, ctx_isp->substate_activated);
CAM_DBG(CAM_ISP, "Exit: State %d Substate %d",
ctx->state, ctx_isp->substate_activated);
@@ -3677,7 +3960,13 @@
ctx->base = ctx_base;
ctx->frame_id = 0;
ctx->active_req_cnt = 0;
- ctx->reported_req_id = 0;
+ ctx->req_info.reported_req_id = 0;
+ ctx->req_info.last_applied_req_id = 0;
+ ctx->req_info.last_bufdone_req_id = 0;
+ ctx->req_info.last_applied_time_stamp = 0;
+ ctx->req_info.last_bufdone_time_stamp = 0;
+ ctx->req_info.last_reported_id_time_stamp = 0;
+
ctx->hw_ctx = NULL;
ctx->substate_activated = CAM_ISP_CTX_ACTIVATED_SOF;
ctx->substate_machine = cam_isp_ctx_activated_state_machine;
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 4954f20..cb73252 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
@@ -62,20 +67,6 @@
};
/**
- * enum cam_isp_state_change_trigger - Different types of ISP events
- *
- */
-enum cam_isp_state_change_trigger {
- CAM_ISP_STATE_CHANGE_TRIGGER_ERROR,
- CAM_ISP_STATE_CHANGE_TRIGGER_SOF,
- CAM_ISP_STATE_CHANGE_TRIGGER_REG_UPDATE,
- CAM_ISP_STATE_CHANGE_TRIGGER_EPOCH,
- CAM_ISP_STATE_CHANGE_TRIGGER_EOF,
- CAM_ISP_STATE_CHANGE_TRIGGER_DONE,
- CAM_ISP_STATE_CHANGE_TRIGGER_MAX
-};
-
-/**
* struct cam_isp_ctx_irq_ops - Function table for handling IRQ callbacks
*
* @irq_ops: Array of handle function pointers.
@@ -125,20 +116,47 @@
* debug purposes
*
*@curr_state: Current sub state that received req
- *@req_type: Event type of incoming req
- *@req_id: Request id
- *@evt_time_stamp Current time stamp
+ *@next_state: Next sub state that received req
+ *@hw_event: Hw Event type of incoming req
+ *@last_reported_id: Last_reported_id to userspace
+ *@last_applied_req_id Last applied request id to hardware
+ *@frame_id: Current Frame id
+ *@evt_time_stamp Current time stamp of this event logged
*
*/
struct cam_isp_context_state_monitor {
enum cam_isp_ctx_activated_substate curr_state;
- enum cam_isp_state_change_trigger trigger;
- uint32_t req_id;
+ enum cam_isp_ctx_activated_substate next_state;
+ enum cam_isp_hw_event_type hw_event;
+ int64_t last_reported_id;
+ int64_t last_applied_req_id;
int64_t frame_id;
uint64_t evt_time_stamp;
};
/**
+ * struct cam_isp_context_req_id_info - ISP context request id
+ * information for last applied, reported and bufdone.
+ *
+ *@last_applied_req_id: Last applied request id
+ *@last_bufdone_req_id: Last bufdone request id
+ *@reported_req_id: Last reported request id to userspace
+ *@last_applied_time_stamp: Last applied request time stamp information
+ *@last_bufdone_time_stamp Last bufdone request time stamp information
+ *@last_reported_id_time_stamp: Last reported request time stamp information
+ *
+ */
+
+struct cam_isp_context_req_id_info {
+ int64_t last_applied_req_id;
+ int64_t last_bufdone_req_id;
+ int64_t reported_req_id;
+ int64_t last_applied_time_stamp;
+ int64_t last_bufdone_time_stamp;
+ int64_t last_reported_id_time_stamp;
+
+};
+/**
* struct cam_isp_context - ISP context object
*
* @base: Common context object pointer
@@ -152,19 +170,24 @@
* @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
- * @reported_req_id: Last reported request id
* @subscribe_event: The irq event mask that CRM subscribes to, IFE
* will invoke CRM cb at those event.
- * @last_applied_req_id: Last applied request id
* @state_monitor_head: Write index to the state monitoring array
+ * @req_info Request id information about last applied,
+ * reported and buf done
* @cam_isp_ctx_state_monitor: State monitoring array
* @rdi_only_context: Get context type information.
* true, if context is rdi only context
* @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 {
@@ -181,18 +204,22 @@
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;
- int64_t reported_req_id;
uint32_t subscribe_event;
- int64_t last_applied_req_id;
atomic64_t state_monitor_head;
struct cam_isp_context_state_monitor cam_isp_ctx_state_monitor[
CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES];
+ struct cam_isp_context_req_id_info req_info;
bool rdi_only_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 fe3d2f1..91e1e74 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 @@
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 @@
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 @@
&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 @@
"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 @@
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 @@
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 @@
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)
{
@@ -2637,7 +2769,7 @@
/* Stop the master CSID path first */
cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
- master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+ master_base_idx, csid_halt_type);
/* stop rest of the CSID paths */
for (i = 0; i < ctx->num_base; i++) {
@@ -2647,7 +2779,7 @@
ctx->base[i].idx, i, master_base_idx);
cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
- ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+ ctx->base[i].idx, csid_halt_type);
}
CAM_DBG(CAM_ISP, "Stopping master CID idx %d", master_base_idx);
@@ -2925,6 +3057,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0b3c387..21f67ba 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
@@ -467,6 +467,7 @@
int32_t hdl;
int mmu_hdl;
bool mode, is_buf_secure;
+ uint64_t req_id;
io_cfg = (struct cam_buf_io_cfg *) ((uint8_t *)
&prepare->packet->payload +
@@ -475,6 +476,7 @@
num_in_buf = 0;
io_cfg_used_bytes = 0;
prepare->pf_data->packet = prepare->packet;
+ req_id = prepare->packet->header.request_id;
/* Max one hw entries required for each base */
if (prepare->num_hw_update_entries + 1 >=
@@ -489,7 +491,7 @@
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);
@@ -616,12 +618,37 @@
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;
}
+ if (j == 0) {
+ rc = cam_packet_validate_plane_size(
+ &io_cfg[i],
+ plane_id,
+ size);
+ if (rc) {
+ CAM_ERR(CAM_ISP,
+ "Invalid buffer size, port 0x%x plane %d req_id %llu format %d memh 0x%x",
+ io_cfg[i].resource_type,
+ plane_id,
+ req_id,
+ io_cfg[i].format,
+ io_cfg[i].mem_handle[plane_id]);
+ return -EINVAL;
+ }
+ }
+
/* need to update with offset */
io_addr[plane_id] +=
io_cfg[i].offsets[plane_id];
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 096e0f1..1ab9361 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 @@
* @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_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 @@
* @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 @@
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 25bdc51d..719bbe7 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_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 0000000..2051292
--- /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 0000000..0ec7672
--- /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 0000000..058a4e9
--- /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 0000000..058c242
--- /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 0000000..1a4e145
--- /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 0000000..b2ebeaf
--- /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 576e8cb..6254b97 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 @@
.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 42f0f29..ed2857b 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 @@
.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 8a78fe0..d430cee 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 @@
.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 5610f6d..7541d06 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_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 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 6;
break;
case CAM_FORMAT_MIPI_RAW_8:
switch (out_format) {
@@ -111,6 +113,7 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 8;
break;
case CAM_FORMAT_MIPI_RAW_10:
switch (out_format) {
@@ -126,6 +129,7 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 10;
break;
case CAM_FORMAT_MIPI_RAW_12:
switch (out_format) {
@@ -140,6 +144,7 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 12;
break;
case CAM_FORMAT_MIPI_RAW_14:
switch (out_format) {
@@ -154,6 +159,7 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 14;
break;
case CAM_FORMAT_MIPI_RAW_16:
switch (out_format) {
@@ -168,6 +174,7 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 16;
break;
case CAM_FORMAT_MIPI_RAW_20:
switch (out_format) {
@@ -182,6 +189,7 @@
rc = -EINVAL;
break;
}
+ *in_bpp = 20;
break;
case CAM_FORMAT_DPCM_10_6_10:
*decode_fmt = 0x7;
@@ -467,6 +475,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
+ /* 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 @@
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 @@
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 @@
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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;
- return 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;
+
+ /* 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 600deb2..f2173f1 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 @@
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 @@
* @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 @@
* @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 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 @@
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 0c45bd1..8d34020 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 @@
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 @@
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 b230147..d90030d 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 @@
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 9d6bcb7..3bcedc9 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_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 a26c112..162ddad 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 @@
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 @@
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 4e9a975..a70f0bb 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 @@
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 @@
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 @@
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 @@
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 b0ac94b..9d03cba 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 @@
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 @@
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 f7b42d5..1a3a7cb 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 @@
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_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
index 52907cd..225f859 100644
--- a/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_jpeg/jpeg_hw/jpeg_enc_hw/jpeg_enc_core.c
@@ -91,6 +91,9 @@
CAM_ERR(CAM_JPEG, "soc enable is failed %d", rc);
goto soc_failed;
}
+ spin_lock(&jpeg_enc_dev->hw_lock);
+ jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_UP;
+ spin_unlock(&jpeg_enc_dev->hw_lock);
mutex_unlock(&core_info->core_mutex);
@@ -140,6 +143,9 @@
return -EFAULT;
}
+ spin_lock(&jpeg_enc_dev->hw_lock);
+ jpeg_enc_dev->hw_state = CAM_HW_STATE_POWER_DOWN;
+ spin_unlock(&jpeg_enc_dev->hw_lock);
rc = cam_jpeg_enc_disable_soc_resources(soc_info);
if (rc)
CAM_ERR(CAM_JPEG, "soc disable failed %d", rc);
@@ -173,12 +179,19 @@
hw_info = core_info->jpeg_enc_hw_info;
mem_base = soc_info->reg_map[0].mem_base;
+ spin_lock(&jpeg_enc_dev->hw_lock);
+ if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_ERR(CAM_JPEG, "JPEG HW is in off state");
+ spin_unlock(&jpeg_enc_dev->hw_lock);
+ return -EINVAL;
+ }
irq_status = cam_io_r_mb(mem_base +
core_info->jpeg_enc_hw_info->reg_offset.int_status);
cam_io_w_mb(irq_status,
soc_info->reg_map[0].mem_base +
core_info->jpeg_enc_hw_info->reg_offset.int_clr);
+ spin_unlock(&jpeg_enc_dev->hw_lock);
CAM_DBG(CAM_JPEG, "irq_num %d irq_status = %x , core_state %d",
irq_num, irq_status, core_info->core_state);
@@ -268,6 +281,12 @@
mutex_lock(&core_info->core_mutex);
spin_lock(&jpeg_enc_dev->hw_lock);
+ if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_ERR(CAM_JPEG, "JPEG HW is in off state");
+ spin_unlock(&jpeg_enc_dev->hw_lock);
+ mutex_unlock(&core_info->core_mutex);
+ return -EINVAL;
+ }
if (core_info->core_state == CAM_JPEG_ENC_CORE_RESETTING) {
CAM_ERR(CAM_JPEG, "alrady resetting");
spin_unlock(&jpeg_enc_dev->hw_lock);
@@ -319,10 +338,18 @@
hw_info = core_info->jpeg_enc_hw_info;
mem_base = soc_info->reg_map[0].mem_base;
- if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) {
- CAM_ERR(CAM_JPEG, "Error not ready");
+ spin_lock(&jpeg_enc_dev->hw_lock);
+ if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_ERR(CAM_JPEG, "JPEG HW is in off state");
+ spin_unlock(&jpeg_enc_dev->hw_lock);
return -EINVAL;
}
+ if (core_info->core_state != CAM_JPEG_ENC_CORE_READY) {
+ CAM_ERR(CAM_JPEG, "Error not ready");
+ spin_unlock(&jpeg_enc_dev->hw_lock);
+ return -EINVAL;
+ }
+ spin_unlock(&jpeg_enc_dev->hw_lock);
cam_io_w_mb(hw_info->reg_val.hw_cmd_start,
mem_base + hw_info->reg_offset.hw_cmd);
@@ -352,6 +379,12 @@
mutex_lock(&core_info->core_mutex);
spin_lock(&jpeg_enc_dev->hw_lock);
+ if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) {
+ CAM_ERR(CAM_JPEG, "JPEG HW is in off state");
+ spin_unlock(&jpeg_enc_dev->hw_lock);
+ mutex_unlock(&core_info->core_mutex);
+ return -EINVAL;
+ }
if (core_info->core_state == CAM_JPEG_ENC_CORE_ABORTING) {
CAM_ERR(CAM_JPEG, "alrady stopping");
spin_unlock(&jpeg_enc_dev->hw_lock);
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 c8e2a02..4d10ea6 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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_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 @@
}
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 @@
__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 @@
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 @@
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 @@
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;
@@ -3303,9 +3454,73 @@
}
+int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req)
+{
+ int rc = 0;
+ struct cam_req_mgr_core_link *link = NULL;
+ struct cam_req_mgr_core_session *session = NULL;
+ struct cam_req_mgr_dump_info info;
+ struct cam_req_mgr_connected_device *device = NULL;
+ int i;
+
+ if (!dump_req) {
+ CAM_ERR(CAM_CRM, "dump req is NULL");
+ rc = -EFAULT;
+ goto end;
+ }
+
+ mutex_lock(&g_crm_core_dev->crm_lock);
+ /* session hdl's priv data is cam session struct */
+ session = (struct cam_req_mgr_core_session *)
+ cam_get_device_priv(dump_req->session_handle);
+ if (!session) {
+ CAM_ERR(CAM_CRM, "Invalid session %x",
+ dump_req->session_handle);
+ rc = -EINVAL;
+ goto end;
+ }
+ if (session->num_links <= 0) {
+ CAM_WARN(CAM_CRM, "No active links in session %x",
+ dump_req->session_handle);
+ goto end;
+ }
+
+ link = (struct cam_req_mgr_core_link *)
+ cam_get_device_priv(dump_req->link_hdl);
+ if (!link) {
+ CAM_DBG(CAM_CRM, "link ptr NULL %x", dump_req->link_hdl);
+ rc = -EINVAL;
+ goto end;
+ }
+ info.offset = dump_req->offset;
+ for (i = 0; i < link->num_devs; i++) {
+ device = &link->l_dev[i];
+ info.link_hdl = dump_req->link_hdl;
+ info.dev_hdl = device->dev_hdl;
+ info.req_id = dump_req->issue_req_id;
+ info.buf_handle = dump_req->buf_handle;
+ if (device->ops && device->ops->dump_req) {
+ rc = device->ops->dump_req(&info);
+ if (rc) {
+ CAM_ERR(CAM_REQ, "Fail dump req %lld dev %d",
+ info.req_id,
+ device->dev_hdl);
+ }
+ }
+ }
+ dump_req->offset = info.offset;
+ CAM_INFO(CAM_REQ, "req %lld, offset %u",
+ dump_req->issue_req_id, dump_req->offset);
+end:
+ mutex_unlock(&g_crm_core_dev->crm_lock);
+ return 0;
+
+}
+
int cam_req_mgr_core_device_init(void)
{
int i;
+
CAM_DBG(CAM_CRM, "Enter g_crm_core_dev %pK", g_crm_core_dev);
if (g_crm_core_dev) {
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 05fe086..679b2cf 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
@@ -53,6 +56,7 @@
CRM_WORKQ_TASK_NOTIFY_FREEZE,
CRM_WORKQ_TASK_SCHED_REQ,
CRM_WORKQ_TASK_FLUSH_REQ,
+ CRM_WORKQ_TASK_DUMP_REQ,
CRM_WORKQ_TASK_INVALID,
};
@@ -321,7 +325,10 @@
* 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 +356,8 @@
bool initial_skip;
bool in_msync_mode;
int64_t initial_sync_req;
+ uint64_t sof_timestamp;
+ uint64_t prev_sof_timestamp;
};
/**
@@ -477,4 +486,11 @@
*/
int cam_req_mgr_link_control(struct cam_req_mgr_link_control *control);
+/**
+ * cam_req_mgr_dump_request()
+ * @brief: Dumps the request information
+ * @dump_req: Dump request
+ */
+int cam_req_mgr_dump_request(struct cam_dump_req_cmd *dump_req);
+
#endif
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c
index 31607ac..5d4d9fc 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_dev.c
@@ -473,6 +473,31 @@
rc = -EINVAL;
}
break;
+
+ case CAM_REQ_MGR_REQUEST_DUMP: {
+ struct cam_dump_req_cmd cmd;
+
+ if (k_ioctl->size != sizeof(cmd))
+ return -EINVAL;
+
+ if (copy_from_user(&cmd,
+ u64_to_user_ptr(k_ioctl->handle),
+ sizeof(struct cam_dump_req_cmd))) {
+ rc = -EFAULT;
+ break;
+ }
+
+ rc = cam_req_mgr_dump_request(&cmd);
+ if (!rc)
+ if (copy_to_user(
+ u64_to_user_ptr(k_ioctl->handle),
+ &cmd, sizeof(struct cam_dump_req_cmd))) {
+ rc = -EFAULT;
+ break;
+ }
+ }
+ break;
+
default:
return -ENOIOCTLCMD;
}
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 1d1df45..3327418 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
@@ -26,6 +26,7 @@
struct cam_req_mgr_apply_request;
struct cam_req_mgr_flush_request;
struct cam_req_mgr_link_evt_data;
+struct cam_req_mgr_dump_info;
#define SKIP_NEXT_FRAME 0x100
@@ -52,6 +53,7 @@
* @cam_req_mgr_apply_req : CRM asks device to apply certain request id.
* @cam_req_mgr_flush_req : Flush or cancel request
* cam_req_mgr_process_evt : generic events
+ * cam_req_mgr_dump_req : dump request
*/
typedef int (*cam_req_mgr_get_dev_info) (struct cam_req_mgr_device_info *);
typedef int (*cam_req_mgr_link_setup)(
@@ -59,6 +61,7 @@
typedef int (*cam_req_mgr_apply_req)(struct cam_req_mgr_apply_request *);
typedef int (*cam_req_mgr_flush_req)(struct cam_req_mgr_flush_request *);
typedef int (*cam_req_mgr_process_evt)(struct cam_req_mgr_link_evt_data *);
+typedef int (*cam_req_mgr_dump_req)(struct cam_req_mgr_dump_info *);
/**
* @brief : cam_req_mgr_crm_cb - func table
@@ -81,6 +84,7 @@
* @apply_req : payload to apply request id on a device linked
* @flush_req : payload to flush request
* @process_evt : payload to generic event
+ * @dump_req : payload to dump request
*/
struct cam_req_mgr_kmd_ops {
cam_req_mgr_get_dev_info get_dev_info;
@@ -88,6 +92,7 @@
cam_req_mgr_apply_req apply_req;
cam_req_mgr_flush_req flush_req;
cam_req_mgr_process_evt process_evt;
+ cam_req_mgr_dump_req dump_req;
};
/**
@@ -201,12 +206,14 @@
* @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;
};
/**
@@ -336,4 +343,25 @@
int32_t link_hdl;
struct cam_req_mgr_req_queue *in_q;
};
+
+/**
+ * struct cam_req_mgr_dump_info
+ * @req_id : request id to cancel
+ * @link_hdl : link identifier
+ * @dev_hdl : device handle for cross check
+ * @buf_handle : buf handle
+ * @offset : offset of buffere
+ * @error_type : error type
+ *
+ */
+struct cam_req_mgr_dump_info {
+ uint64_t req_id;
+ int32_t link_hdl;
+ int32_t dev_hdl;
+ uint32_t buf_handle;
+ int32_t offset;
+ int32_t error_type;
+};
+
+
#endif
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c
index d531fdc..feee331 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.c
@@ -52,7 +52,7 @@
hdl_tbl = hdl_tbl_local;
spin_unlock_bh(&hdl_tbl_lock);
- bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES) * sizeof(long);
+ bitmap_size = BITS_TO_LONGS(CAM_REQ_MGR_MAX_HANDLES_V2) * sizeof(long);
hdl_tbl->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
if (!hdl_tbl->bitmap) {
rc = -ENOMEM;
@@ -99,7 +99,7 @@
return -EINVAL;
}
- for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++) {
+ for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++) {
if (hdl_tbl->hdl[i].state == HDL_ACTIVE) {
CAM_ERR(CAM_CRM, "Dev handle = %x session_handle = %x",
hdl_tbl->hdl[i].hdl_value,
@@ -108,7 +108,7 @@
clear_bit(i, hdl_tbl->bitmap);
}
}
- bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES);
+ bitmap_zero(hdl_tbl->bitmap, CAM_REQ_MGR_MAX_HANDLES_V2);
spin_unlock_bh(&hdl_tbl_lock);
return 0;
@@ -120,7 +120,7 @@
idx = find_first_zero_bit(hdl_tbl->bitmap, hdl_tbl->bits);
- if (idx >= CAM_REQ_MGR_MAX_HANDLES || idx < 0)
+ if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2 || idx < 0)
return -ENOSR;
set_bit(idx, hdl_tbl->bitmap);
@@ -132,7 +132,7 @@
{
int i;
- for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES; i++)
+ for (i = 0; i < CAM_REQ_MGR_MAX_HANDLES_V2; i++)
CAM_INFO(CAM_CRM, "session_hdl=%x hdl_value=%x\n"
"type=%d state=%d dev_id=%lld",
hdl_tbl->hdl[i].session_hdl,
@@ -226,7 +226,7 @@
}
idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
- if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
+ if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) {
CAM_ERR_RATE_LIMIT(CAM_CRM, "Invalid idx");
goto device_priv_fail;
}
@@ -270,7 +270,7 @@
}
idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
- if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
+ if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) {
CAM_ERR(CAM_CRM, "Invalid idx");
goto device_ops_fail;
}
@@ -313,7 +313,7 @@
}
idx = CAM_REQ_MGR_GET_HDL_IDX(dev_hdl);
- if (idx >= CAM_REQ_MGR_MAX_HANDLES) {
+ if (idx >= CAM_REQ_MGR_MAX_HANDLES_V2) {
CAM_ERR(CAM_CRM, "Invalid idx %d", idx);
goto destroy_hdl_fail;
}
diff --git a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h
index 50d6f30..5d9b6c07a 100644
--- a/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_req_mgr/cam_req_mgr_util.h
@@ -62,7 +62,7 @@
* @bits: size of bit map in bits
*/
struct cam_req_mgr_util_hdl_tbl {
- struct handle hdl[CAM_REQ_MGR_MAX_HANDLES];
+ struct handle hdl[CAM_REQ_MGR_MAX_HANDLES_V2];
void *bitmap;
size_t bits;
};
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 0181a4d..f66d86c 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 @@
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 8074ecd..b860559 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 @@
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 @@
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 @@
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 @@
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 @@
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_sensor_module/cam_eeprom/cam_eeprom_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
index 06d6bd4..bcd3823 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_eeprom/cam_eeprom_core.c
@@ -1016,7 +1016,7 @@
&eeprom_cap,
sizeof(struct cam_eeprom_query_cap_t))) {
CAM_ERR(CAM_EEPROM, "Failed Copy to User");
- return -EFAULT;
+ rc = -EFAULT;
goto release_mutex;
}
CAM_DBG(CAM_EEPROM, "eeprom_cap: ID: %d", eeprom_cap.slot_info);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
index a2a738d..94bc611 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -927,6 +927,16 @@
}
break;
case CAM_CONFIG_DEV: {
+ if (s_ctrl->sensor_state < CAM_SENSOR_ACQUIRE) {
+ rc = -EINVAL;
+ CAM_ERR(CAM_SENSOR,
+ "sensor_id:[0x%x] not acquired to configure [%d] ",
+ s_ctrl->sensordata->slave_info.sensor_id,
+ s_ctrl->sensor_state
+ );
+ goto release_mutex;
+ }
+
rc = cam_sensor_i2c_pkt_parse(s_ctrl, arg);
if (rc < 0) {
CAM_ERR(CAM_SENSOR, "Failed i2c pkt parse: %d", rc);
diff --git a/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c b/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c
index 626473f..77a7204 100644
--- a/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c
+++ b/drivers/media/platform/msm/camera_v3/cam_smmu/cam_smmu_api.c
@@ -191,7 +191,7 @@
static struct dentry *smmu_dentry;
-static bool smmu_fatal_flag;
+static bool smmu_fatal_flag = true;
static enum dma_data_direction cam_smmu_translate_dir(
enum cam_smmu_map_dir dir);
diff --git a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
index d4487ef..93d39e3 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
+++ b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync.c
@@ -288,6 +288,7 @@
int rc;
long idx = 0;
bool bit;
+ int i = 0;
if (!sync_obj || !merged_obj) {
CAM_ERR(CAM_SYNC, "Invalid pointer(s)");
@@ -305,6 +306,14 @@
return -EINVAL;
}
+ for (i = 0; i < num_objs; i++) {
+ rc = cam_sync_check_valid(sync_obj[i]);
+ if (rc) {
+ CAM_ERR(CAM_SYNC, "Sync_obj[%d] %d valid check fail",
+ i, sync_obj[i]);
+ return rc;
+ }
+ }
do {
idx = find_first_zero_bit(sync_dev->bitmap, CAM_SYNC_MAX_OBJS);
if (idx >= CAM_SYNC_MAX_OBJS)
@@ -376,6 +385,29 @@
return cam_sync_deinit_object(sync_dev->sync_table, sync_obj);
}
+int cam_sync_check_valid(int32_t sync_obj)
+{
+ struct sync_table_row *row = NULL;
+
+ if (sync_obj >= CAM_SYNC_MAX_OBJS || sync_obj <= 0)
+ return -EINVAL;
+
+ row = sync_dev->sync_table + sync_obj;
+
+ if (!test_bit(sync_obj, sync_dev->bitmap)) {
+ CAM_ERR(CAM_SYNC, "Error: Released sync obj received %d",
+ sync_obj);
+ return -EINVAL;
+ }
+
+ if (row->state == CAM_SYNC_STATE_INVALID) {
+ CAM_ERR(CAM_SYNC,
+ "Error: accessing an uninitialized sync obj = %d",
+ sync_obj);
+ return -EINVAL;
+ }
+ return 0;
+}
int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms)
{
unsigned long timeleft;
diff --git a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_api.h b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_api.h
index c735d51..f2f67cb 100644
--- a/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_api.h
+++ b/drivers/media/platform/msm/camera_v3/cam_sync/cam_sync_api.h
@@ -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
@@ -147,5 +147,14 @@
*/
int cam_sync_wait(int32_t sync_obj, uint64_t timeout_ms);
+/**
+ * @brief: Check if sync object is valid
+ *
+ * @param sync_obj: int referencing the sync object to be checked
+ *
+ * @return 0 upon success, -EINVAL if sync object is in bad state or arguments
+ * are invalid
+ */
+int cam_sync_check_valid(int32_t sync_obj);
#endif /* __CAM_SYNC_API_H__ */
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c
index bba12cf..fd113ae 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.c
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.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
@@ -55,3 +55,22 @@
return wr_idx;
}
+
+uint64_t cam_common_util_get_time_diff(struct timeval *t1, struct timeval *t2)
+{
+ uint64_t diff = 0;
+
+ diff = (t1->tv_sec - t2->tv_sec) * 1000000 +
+ (t1->tv_usec - t2->tv_usec);
+ return diff;
+}
+
+void cam_common_util_get_curr_timestamp(struct timeval *time_stamp)
+{
+ struct timespec ts;
+
+ get_monotonic_boottime(&ts);
+ time_stamp->tv_sec = ts.tv_sec;
+ time_stamp->tv_usec = ts.tv_nsec/1000;
+}
+
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h
index 47d441f..136eaf0 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_common_util.h
@@ -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
@@ -52,4 +52,26 @@
uint32_t cam_common_util_remove_duplicate_arr(int32_t *array,
uint32_t num);
+/**
+ * cam_common_util_get_time_diff()
+ *
+ * @brief Get the time difference between 2 timestamps in usecs
+ *
+ * @t1: Pointer to the later time
+ * @t2: Pointer to the prev time
+ *
+ * @return: differnce in usecs
+ */
+uint64_t cam_common_util_get_time_diff(struct timeval *t1, struct timeval *t2);
+
+/**
+ * cam_comomon_util_get_curr_timestamp()
+ *
+ * @brief Get the current timestamp
+ *
+ * @time_stamp: Pointer to the time
+ *
+ * @return: void
+ */
+void cam_common_util_get_curr_timestamp(struct timeval *time_stamp);
#endif /* _CAM_COMMON_UTIL_H_ */
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 0f910c9..185e060 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 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 @@
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 @@
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 @@
((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;
}
@@ -353,3 +393,115 @@
return rc;
}
+
+int32_t cam_packet_validate_plane_size(
+ struct cam_buf_io_cfg *io_cfg,
+ int plane_index,
+ size_t size)
+{
+ int rc = 0;
+ uint32_t kmd_plane_size = 0;
+ uint32_t plane_stride = 0;
+ uint32_t slice_height = 0;
+ uint32_t metadata_size = 0;
+ uint32_t format = io_cfg->format;
+ uint32_t plane_pixel_size = 0;
+
+ if (plane_index < CAM_PACKET_MAX_PLANES) {
+ plane_stride = io_cfg->planes[plane_index].plane_stride;
+ slice_height = io_cfg->planes[plane_index].slice_height;
+ }
+
+ if (!(plane_stride && slice_height)) {
+ CAM_ERR(CAM_ISP,
+ "Invalid values from UMD stride %d, slice height %d",
+ plane_stride,
+ slice_height);
+ return -EINVAL;
+ }
+
+ switch (format) {
+ case CAM_FORMAT_MIPI_RAW_6:
+ case CAM_FORMAT_MIPI_RAW_8:
+ kmd_plane_size = ((plane_stride * slice_height) + 16 - 1)
+ / 16 * 16;
+ break;
+ case CAM_FORMAT_MIPI_RAW_10:
+ if (plane_stride % 4 == 0)
+ kmd_plane_size = ((plane_stride * slice_height)
+ + 16 - 1) / 16 * 16;
+ break;
+ case CAM_FORMAT_MIPI_RAW_12:
+ if (plane_stride % 2 == 0)
+ kmd_plane_size = ((plane_stride * slice_height)
+ + 16 - 1) / 16 * 16;
+ break;
+ case CAM_FORMAT_MIPI_RAW_14:
+ if (plane_stride % 4 == 0)
+ kmd_plane_size = plane_stride * slice_height * 7 / 4;
+ break;
+ case CAM_FORMAT_PLAIN16_8:
+ case CAM_FORMAT_PLAIN16_10:
+ case CAM_FORMAT_PLAIN16_12:
+ case CAM_FORMAT_PLAIN16_14:
+ case CAM_FORMAT_PLAIN16_16:
+ case CAM_FORMAT_PLAIN64:
+ kmd_plane_size = plane_stride * slice_height;
+ break;
+ case CAM_FORMAT_NV21:
+ case CAM_FORMAT_NV12:
+ if (plane_index < CAM_PACKET_MAX_PLANES)
+ kmd_plane_size = plane_stride * slice_height;
+ break;
+ case CAM_FORMAT_PD10:
+ if (plane_index < CAM_PACKET_MAX_PLANES)
+ kmd_plane_size = plane_stride * slice_height;
+ break;
+ case CAM_FORMAT_UBWC_NV12:
+ case CAM_FORMAT_UBWC_NV12_4R:
+ case CAM_FORMAT_UBWC_TP10:
+ metadata_size = io_cfg->planes[plane_index].meta_size;
+ plane_pixel_size = ((plane_stride * slice_height) +
+ (4096 - 1)) & ~((uint32_t) 4096 - 1);
+ kmd_plane_size = metadata_size + plane_pixel_size;
+ break;
+ case CAM_FORMAT_UBWC_P010:
+ case CAM_FORMAT_PLAIN32_20:
+ case CAM_FORMAT_TP10:
+ case CAM_FORMAT_YUV422:
+ case CAM_FORMAT_PD8:
+ case CAM_FORMAT_PLAIN128:
+ case CAM_FORMAT_ARGB:
+ case CAM_FORMAT_ARGB_10:
+ case CAM_FORMAT_ARGB_12:
+ case CAM_FORMAT_ARGB_14:
+ case CAM_FORMAT_MIPI_RAW_16:
+ case CAM_FORMAT_MIPI_RAW_20:
+ case CAM_FORMAT_QTI_RAW_8:
+ case CAM_FORMAT_QTI_RAW_10:
+ case CAM_FORMAT_QTI_RAW_12:
+ case CAM_FORMAT_QTI_RAW_14:
+ case CAM_FORMAT_PLAIN8:
+ case CAM_FORMAT_PLAIN8_SWAP:
+ case CAM_FORMAT_PLAIN8_10:
+ case CAM_FORMAT_PLAIN8_10_SWAP:
+ kmd_plane_size = plane_stride * slice_height;
+ break;
+ default:
+ kmd_plane_size = plane_stride * slice_height;
+ break;
+ }
+ if (!kmd_plane_size ||
+ kmd_plane_size > (size - io_cfg->offsets[plane_index])) {
+ CAM_ERR(CAM_ISP,
+ "kmd size: %d umd size: %zu width: %d height: %d stride: %d sliceheight: %d ",
+ kmd_plane_size,
+ size,
+ io_cfg->planes[plane_index].width,
+ io_cfg->planes[plane_index].height,
+ plane_stride,
+ slice_height);
+ return -EINVAL;
+ }
+ return rc;
+}
diff --git a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
index 33c07ad..e49968e 100644
--- a/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
+++ b/drivers/media/platform/msm/camera_v3/cam_utils/cam_packet_util.h
@@ -135,4 +135,20 @@
struct cam_cmd_buf_desc *cmd_buf,
cam_packet_generic_blob_handler blob_handler_cb, void *user_data);
+/**
+ * cam_packet_validate_plane_size()
+ *
+ * @brief: Utility function to calculate and validate size of buffer
+ * required for a format.
+ * @io_cfg: Contains IO config info
+ * @plane_index Plane index for which size is to be calculated
+ *
+ * @return: Size of buffer
+ *
+ */
+int32_t cam_packet_validate_plane_size(
+ struct cam_buf_io_cfg *io_cfg,
+ int plane_index,
+ size_t size);
+
#endif /* _CAM_PACKET_UTIL_H_ */
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index bde3110..6c2eebef 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -370,6 +370,12 @@
"hal_process_session_init_done: bad_pkt_size\n");
return -E2BIG;
}
+ if (pkt->size < sizeof(struct hfi_msg_event_notify_packet) - sizeof(u32)
+ + sizeof(struct hfi_msg_release_buffer_ref_event_packet)) {
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, pkt->size);
+ return -E2BIG;
+ }
data = (struct hfi_msg_release_buffer_ref_event_packet *)
pkt->rg_ext_event_data;
@@ -1558,15 +1564,13 @@
struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL;
+ u32 is_sync_frame;
dprintk(VIDC_DBG, "RECEIVED: SESSION_ETB_DONE[%#x]\n", pkt->session_id);
if (!pkt || pkt->size <
- sizeof(struct hfi_msg_session_empty_buffer_done_packet)) {
- dprintk(VIDC_ERR,
- "hal_process_session_etb_done: bad_pkt_size\n");
- return -E2BIG;
- }
+ sizeof(struct hfi_msg_session_empty_buffer_done_packet))
+ goto bad_packet_size;
data_done.device_id = device_id;
data_done.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -1586,8 +1590,13 @@
data_done.input_done.extra_data_buffer = pkt->extra_data_buffer;
data_done.input_done.status =
hfi_map_err_status(pkt->error_type);
- hfi_picture_type = (struct hfi_picture_type *)&pkt->rgData[0];
- if (hfi_picture_type->is_sync_frame) {
+ is_sync_frame = pkt->rgData[0];
+ if (is_sync_frame == 1) {
+ if (pkt->size <
+ sizeof(struct hfi_msg_session_empty_buffer_done_packet)
+ + sizeof(struct hfi_picture_type))
+ goto bad_packet_size;
+ hfi_picture_type = (struct hfi_picture_type *)&pkt->rgData[1];
if (hfi_picture_type->picture_type)
data_done.input_done.flags =
hfi_picture_type->picture_type;
@@ -1604,6 +1613,10 @@
info->response.data = data_done;
return 0;
+bad_packet_size:
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, pkt ? pkt->size : 0);
+ return -E2BIG;
}
static int hfi_process_session_ftb_done(
@@ -1838,8 +1851,7 @@
cmd_done.size = sizeof(struct msm_vidc_cb_cmd_done);
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
cmd_done.status = hfi_map_err_status(pkt->error_type);
- cmd_done.data.buffer_info =
- *(struct hal_buffer_info *)pkt->rg_buffer_info;
+ cmd_done.data.buffer_info.buffer_addr = *pkt->rg_buffer_info;
cmd_done.size = sizeof(struct hal_buffer_info);
info->response_type = HAL_SESSION_RELEASE_BUFFER_DONE;
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi.h b/drivers/media/platform/msm/vidc/vidc_hfi.h
index 0cfe693..949eb0d 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi.h
@@ -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
@@ -601,7 +601,7 @@
u32 extra_data_buffer;
u32 flags;
struct hfi_frame_cr_stats_type ubwc_cr_stats;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_msg_session_fill_buffer_done_compressed_packet {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index 733cbb9..f66d6c9 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -655,7 +655,6 @@
};
struct hfi_picture_type {
- u32 is_sync_frame;
u32 picture_type;
};
diff --git a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
index abf2ef1..654d9fa 100644
--- a/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc_3x/hfi_response_handler.c
@@ -287,6 +287,12 @@
"hal_process_session_init_done: bad_pkt_size\n");
return -E2BIG;
}
+ if (pkt->size < sizeof(struct hfi_msg_event_notify_packet) - sizeof(u32)
+ + sizeof(struct hfi_msg_release_buffer_ref_event_packet)) {
+ dprintk(VIDC_ERR,
+ "hfi_msg_release_buffer_ref_event: bad_pkt_size\n");
+ return -E2BIG;
+ }
data = (struct hfi_msg_release_buffer_ref_event_packet *)
pkt->rg_ext_event_data;
@@ -1540,15 +1546,13 @@
struct hfi_msg_session_empty_buffer_done_packet *pkt = _pkt;
struct msm_vidc_cb_data_done data_done = {0};
struct hfi_picture_type *hfi_picture_type = NULL;
+ u32 is_sync_frame;
dprintk(VIDC_DBG, "RECEIVED: SESSION_ETB_DONE[%#x]\n", pkt->session_id);
if (!pkt || pkt->size <
- sizeof(struct hfi_msg_session_empty_buffer_done_packet)) {
- dprintk(VIDC_ERR,
- "hal_process_session_etb_done: bad_pkt_size\n");
- return -E2BIG;
- }
+ sizeof(struct hfi_msg_session_empty_buffer_done_packet))
+ goto bad_packet_size;
data_done.device_id = device_id;
data_done.session_id = (void *)(uintptr_t)pkt->session_id;
@@ -1563,8 +1567,13 @@
(ion_phys_addr_t)pkt->extra_data_buffer;
data_done.input_done.status =
hfi_map_err_status(pkt->error_type);
- hfi_picture_type = (struct hfi_picture_type *)&pkt->rgData[0];
- if (hfi_picture_type->is_sync_frame) {
+ is_sync_frame = pkt->rgData[0];
+ if (is_sync_frame == 1) {
+ if (pkt->size <
+ sizeof(struct hfi_msg_session_empty_buffer_done_packet)
+ + sizeof(struct hfi_picture_type))
+ goto bad_packet_size;
+ hfi_picture_type = (struct hfi_picture_type *)&pkt->rgData[1];
if (hfi_picture_type->picture_type)
data_done.input_done.flags =
hfi_picture_type->picture_type;
@@ -1583,6 +1592,10 @@
};
return 0;
+bad_packet_size:
+ dprintk(VIDC_ERR, "%s: bad_pkt_size: %d\n",
+ __func__, pkt ? pkt->size : 0);
+ return -E2BIG;
}
static int hfi_process_session_ftb_done(
@@ -1823,8 +1836,7 @@
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
cmd_done.status = hfi_map_err_status(pkt->error_type);
if (pkt->rg_buffer_info) {
- cmd_done.data.buffer_info =
- *(struct hal_buffer_info *)pkt->rg_buffer_info;
+ cmd_done.data.buffer_info.buffer_addr = *pkt->rg_buffer_info;
cmd_done.size = sizeof(struct hal_buffer_info);
} else {
dprintk(VIDC_ERR, "invalid payload in rel_buff_done\n");
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
index be3b992..d7e2154 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vidc_common.c
@@ -347,7 +347,7 @@
* ----------------|----------------------|------------------------|
*/
- if (is_realtime_session(inst) &&
+ if (!is_realtime_session(inst) &&
(quirks & LOAD_CALC_IGNORE_NON_REALTIME_LOAD)) {
if (!inst->prop.fps) {
dprintk(VIDC_INFO, "instance:%pK fps = 0\n", inst);
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi.h
index d0fd493..903603b 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2016, 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2016, 2018-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
@@ -662,7 +662,7 @@
u32 input_tag;
u32 packet_buffer;
u32 extra_data_buffer;
- u32 rgData[0];
+ u32 rgData[1];
};
struct hfi_msg_session_fill_buffer_done_compressed_packet {
diff --git a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
index c09cf84c..16c390a 100644
--- a/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc_3x/vidc_hfi_helper.h
@@ -701,7 +701,6 @@
};
struct hfi_picture_type {
- u32 is_sync_frame;
u32 picture_type;
};
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 25d4fd4..a72982d 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -984,7 +984,7 @@
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 642b89c..c1457cf 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -494,7 +494,8 @@
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 @@
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 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 85dd9a8..48eeb5a 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -764,6 +764,9 @@
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 @@
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 @@
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 @@
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 d793c63..05e7edb 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -1248,8 +1248,7 @@
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 60bf5f0..a5efcd4 100644
--- a/drivers/media/usb/go7007/go7007-fw.c
+++ b/drivers/media/usb/go7007/go7007-fw.c
@@ -1499,8 +1499,8 @@
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 1eb4f7b..ff48964 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -670,6 +670,8 @@
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 a82a00d..8086999 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 18b41b9..73889d6 100644
--- a/drivers/media/usb/siano/smsusb.c
+++ b/drivers/media/usb/siano/smsusb.c
@@ -402,6 +402,7 @@
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 @@
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 @@
/* 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 f4e2ee7..24487d5 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -868,7 +868,7 @@
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 9ae687b..de8aef0 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2052,7 +2052,22 @@
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 19ac8bc..22dd8c0 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -273,6 +273,9 @@
{
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 9d167c9..e153276 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -131,12 +131,12 @@
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 4aeba9b..ec37cfe 100644
--- a/drivers/mfd/tps65912-spi.c
+++ b/drivers/mfd/tps65912-spi.c
@@ -27,6 +27,7 @@
{ .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 dd19f17..2b8c479 100644
--- a/drivers/mfd/twl6040.c
+++ b/drivers/mfd/twl6040.c
@@ -322,8 +322,19 @@
}
}
+ /*
+ * 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 c0012ca..74923ff 100644
--- a/drivers/misc/genwqe/card_dev.c
+++ b/drivers/misc/genwqe/card_dev.c
@@ -782,6 +782,8 @@
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 466a9b7..b642b4fd7 100644
--- a/drivers/misc/genwqe/card_utils.c
+++ b/drivers/misc/genwqe/card_utils.c
@@ -582,6 +582,10 @@
/* 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 2290845..01e0fa7 100644
--- a/drivers/misc/kgdbts.c
+++ b/drivers/misc/kgdbts.c
@@ -1133,7 +1133,7 @@
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 @@
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 1fcafc1..7c5321f 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -1497,20 +1497,17 @@
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;
@@ -2679,7 +2676,8 @@
if (!IS_ERR_OR_NULL(data->client.ihandle)) {
ion_unmap_kernel(qseecom.ion_clnt, data->client.ihandle);
ion_free(qseecom.ion_clnt, data->client.ihandle);
- data->client.ihandle = NULL;
+ memset((void *)&data->client,
+ 0, sizeof(struct qseecom_client_handle));
}
return ret;
}
@@ -3437,6 +3435,33 @@
return 0;
}
+static int __boundary_checks_offset_64(struct qseecom_send_modfd_cmd_req *req,
+ struct qseecom_send_modfd_listener_resp *lstnr_resp,
+ struct qseecom_dev_handle *data, int i)
+{
+
+ if ((data->type != QSEECOM_LISTENER_SERVICE) &&
+ (req->ifd_data[i].fd > 0)) {
+ if ((req->cmd_req_len < sizeof(uint64_t)) ||
+ (req->ifd_data[i].cmd_buf_offset >
+ req->cmd_req_len - sizeof(uint64_t))) {
+ pr_err("Invalid offset (req len) 0x%x\n",
+ req->ifd_data[i].cmd_buf_offset);
+ return -EINVAL;
+ }
+ } else if ((data->type == QSEECOM_LISTENER_SERVICE) &&
+ (lstnr_resp->ifd_data[i].fd > 0)) {
+ if ((lstnr_resp->resp_len < sizeof(uint64_t)) ||
+ (lstnr_resp->ifd_data[i].cmd_buf_offset >
+ lstnr_resp->resp_len - sizeof(uint64_t))) {
+ pr_err("Invalid offset (lstnr resp len) 0x%x\n",
+ lstnr_resp->ifd_data[i].cmd_buf_offset);
+ return -EINVAL;
+ }
+ }
+ return 0;
+}
+
static int __qseecom_update_cmd_buf(void *msg, bool cleanup,
struct qseecom_dev_handle *data)
{
@@ -3796,7 +3821,8 @@
if (sg_ptr->nents == 1) {
uint64_t *update_64bit;
- if (__boundary_checks_offset(req, lstnr_resp, data, i))
+ if (__boundary_checks_offset_64(req, lstnr_resp,
+ data, i))
goto err;
/* 64bit app uses 64bit address */
update_64bit = (uint64_t *) field;
@@ -7537,6 +7563,13 @@
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 f866a4ba..b9da2c6 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 @@
/* 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 @@
* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 344973a..917e18a 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 @@
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 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 @@
* 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 @@
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 b5f3a7f..0fc5859 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 adc9c0c..4493c29 100644
--- a/drivers/mmc/core/pwrseq_emmc.c
+++ b/drivers/mmc/core/pwrseq_emmc.c
@@ -30,19 +30,14 @@
#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 @@
{
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 @@
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 088b3c7..0e70922 100644
--- a/drivers/mmc/core/sd.c
+++ b/drivers/mmc/core/sd.c
@@ -220,6 +220,14 @@
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 6224ad3..c2df68e 100644
--- a/drivers/mmc/host/mmc_spi.c
+++ b/drivers/mmc/host/mmc_spi.c
@@ -819,6 +819,10 @@
}
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 a51d636..6f11cd95 100644
--- a/drivers/mmc/host/sdhci-of-esdhc.c
+++ b/drivers/mmc/host/sdhci-of-esdhc.c
@@ -636,6 +636,11 @@
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 9316972..fd01138 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4241,12 +4241,12 @@
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 47f43bd..baef09b 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 2e33f37..5cd8a56 100644
--- a/drivers/net/can/spi/Kconfig
+++ b/drivers/net/can/spi/Kconfig
@@ -2,10 +2,11 @@
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
@@ -13,4 +14,10 @@
depends on SPI
---help---
Unified driver for QTI CAN controllers.
+
+config CAN_MCP25XXFD
+ tristate "Microchip MCP25xxFD SPI CAN controllers"
+ depends on HAS_DMA
+ ---help---
+ Driver for the Microchip MCP25XXFD SPI FD-CAN controller family.
endmenu
diff --git a/drivers/net/can/spi/Makefile b/drivers/net/can/spi/Makefile
index 64ba861..bbb4343 100644
--- a/drivers/net/can/spi/Makefile
+++ b/drivers/net/can/spi/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
obj-$(CONFIG_QTI_CAN) += qti-can.o
+obj-$(CONFIG_CAN_MCP25XXFD) += mcp25xxfd.o
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index f3f05fe..d8c448b 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 @@
enum mcp251x_model {
CAN_MCP251X_MCP2510 = 0x2510,
CAN_MCP251X_MCP2515 = 0x2515,
+ CAN_MCP251X_MCP25625 = 0x25625,
};
struct mcp251x_priv {
@@ -280,7 +281,6 @@
}
MCP251X_IS(2510);
-MCP251X_IS(2515);
static void mcp251x_clean(struct net_device *net)
{
@@ -640,7 +640,7 @@
/* 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 @@
/* 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 @@
/* 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 @@
.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 @@
.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_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/mcp25xxfd.c b/drivers/net/can/spi/mcp25xxfd.c
new file mode 100644
index 0000000..12cdf44
--- /dev/null
+++ b/drivers/net/can/spi/mcp25xxfd.c
@@ -0,0 +1,4513 @@
+/*
+ * CAN bus driver for Microchip 25XXFD CAN Controller with SPI Interface
+ *
+ * Copyright 2017 Martin Sperl <kernel@xxxxxxxxxxxxxxxx>
+ *
+ * SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+ *
+ * Based on Microchip MCP251x CAN controller driver written by
+ * David Vrabel, Copyright 2006 Arcom Control Systems Ltd.
+ *
+ */
+
+#include <linux/can/core.h>
+#include <linux/can/dev.h>
+#include <linux/can/led.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/freezer.h>
+#include <linux/gpio/driver.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/sort.h>
+#include <linux/spi/spi.h>
+#include <linux/uaccess.h>
+#include <linux/regulator/consumer.h>
+
+#define DEVICE_NAME "mcp25xxfd"
+
+/* device description and rational:
+ *
+ * the mcp25xxfd is a CanFD controller that also supports can2.0 only
+ * modes.
+ * It is connected via spi to the host and requires at minimum a single
+ * irq line in addition to the SPI lines - it is not mentioned explicitly
+ * in the documentation but in principle SPI 3-wire should be possible.
+ *
+ * The clock connected is typically 4MHz, 20MHz or 40MHz.
+ * For the 4MHz clock the controller contains 10x PLL circuitry.
+ *
+ * The controller itself has 2KB or ECC-SRAM for data.
+ * It also has 32 FIFOs (of up to 32 CAN-frames).
+ * There are 4 Fifo types which can get configured:
+ * * TEF - Transmission Event Fifo - which consumes FIFO 0
+ * even if it is not configured
+ * * Tansmission Queue - for up to 32 Frames.
+ * this queue reorders CAN frames to get transmitted following the
+ * typical CAN dominant/recessive rules on the can bus itself.
+ * This FIFO is optional.
+ * * TX FIFO: generic TX fifos that can contain arbitrary data
+ * and which come with a configurable priority for transmission
+ * It is also possible to have the Controller automatically trigger
+ * a transfer when a Filter Rule for a RTR frame matches.
+ * Each of these fifos in principle can get configured for distinct
+ * dlc sizes (8 thru 64 bytes)
+ * * RX FIFO: generic RX fifo which is filled via filter-rules.
+ * Each of these fifos in principle can get configured for distinct
+ * dlc sizes (8 thru 64 bytes)
+ * Unfortunately there is no filter rule that would allow triggering
+ * on different frame sizes, so for all practical purposes the
+ * RX fifos have to be of the same size (unless one wants to experience
+ * lost data).
+ * When a Can Frame is transmitted fromthe TX Queue or an individual
+ * TX FIFO then a small TEF Frame can get added to the TEF FIFO queue
+ * to log the Transmission of the frame - this includes ID, Flags
+ * (including a custom identifier/index) .
+ *
+ * The controller provides an optional free running counter with a divider
+ * for timestamping of RX frames as well as for TEF entries.
+ *
+ * Driver Implementation details and rational:
+ * * The whole driver has been designed to give best performance
+ * and as little packet loss as possible with 1MHZ Can frames with DLC=0
+ * on small/slow devices like the Raspberry Pi 1
+ * * This means that some optimizations for full duplex communication
+ * have been implemented to avoid CPU introduced latencies
+ * (especially for spi_write_then_read cases) - this only applies to
+ * 4 wire SPI busses.
+ * * Due to the fact that the TXQ does reorder Can-Frames we do not make
+ * use of it to avoid unexpected behaviour (say when running a
+ * firmware upgrade via Can)
+ * * this means we use individual TX-fifos with a given priority and
+ * we have to wait until all the TX fifos have been transmitted before
+ * we can restart the networking queue to avoid reordering the frames on
+ * the Can bus itself.
+ * Still we can transmit a transmit only Duty-cycle of 66% to 90% on the
+ * Can bus (at 1MHz).
+ * The scaling factors here are:
+ * * Can bus speed - lower Speeds increase Duty-cycle
+ * * SPI Clock Rate - higher speeds increase duty-cycle
+ * * CPU speed + SPI implementation - reduces latencies between transfers
+ * * There is a module parameter that allows the modification of the
+ * number of tx_fifos, which is by default 7.
+ * * The driver offers some module parameters that allow to control the use
+ * of some optimizations (prefer reading more data than necessary instead
+ * of multiple SPI transfers - the idea here is that this way we may
+ * allow the SPI-controller to use DMA instead of programmed IO to
+ * limit latencies/number of interrupts)
+ * When we have to read multiple RX frames in CanFD mode:
+ * * we allow reading all 64 bytes of payload even if DLC <=8
+ * this mode is used in Can2.0 only mode by default and can not get
+ * disabled (SRAM Reads have to be a multiple of 4 bytes anyway)
+ * * Releasing/freeing the RX queue requires writing of 1 byte per fifo.
+ * unfortunately these 32-bit registers are not ajacent to each other,
+ * so that for 2 consecutive RX Frames instead of writing 1 byte per
+ * fifo (with protocol overhead of 2 bytes - so a total of 6 bytes in
+ * 2 transfers) we transmit 13 bytes (with a protocol overhead of 2 -
+ * so a total of 15 bytes)
+ * This optimization is only enabled by a module parameter.
+ * * we use TEF + time stamping to record the transmitted frames
+ * including their timestamp - we use this to order TX and RX frames
+ * when submitting them to the network stack.
+ * * due to the inability to "filter" based on DLC sizes we have to use
+ * a common FIFO size. This is 8 bytes for Can2.0 and 64 bytes for CanFD.
+ * * the driver tries to detect the Controller only by reading registers,
+ * but there are circumstances (e.g. after a crashed driver) where we
+ * have to "blindly" configure the clock rate to get the controller to
+ * respond correctly.
+ * * There is one situation where the controller will require a full POR
+ * (total power off) to recover from a bad Clock configuration.
+ * This happens when the wrong clock is configured in the device tree
+ * (say 4MHz are configured, while 20 or 40MHz are used)
+ * in such a situation the driver tries to enable the PLL, which will
+ * never synchronize and the controller becomes unresponsive to further
+ * spi requests until a POR.
+ */
+
+#define MCP25XXFD_OST_DELAY_MS 3
+#define MCP25XXFD_MIN_CLOCK_FREQUENCY 1000000
+#define MCP25XXFD_MAX_CLOCK_FREQUENCY 40000000
+#define MCP25XXFD_PLL_MULTIPLIER 10
+#define MCP25XXFD_AUTO_PLL_MAX_CLOCK_FREQUENCY \
+ (MCP25XXFD_MAX_CLOCK_FREQUENCY / MCP25XXFD_PLL_MULTIPLIER)
+#define MCP25XXFD_SCLK_DIVIDER 2
+
+#define MCP25XXFD_OSC_POLLING_JIFFIES (HZ / 2)
+
+#define TX_ECHO_SKB_MAX 32
+
+#define INSTRUCTION_RESET 0x0000
+#define INSTRUCTION_READ 0x3000
+#define INSTRUCTION_WRITE 0x2000
+#define INSTRUCTION_READ_CRC 0xB000
+#define INSTRUCTION_WRITE_CRC 0xA000
+#define INSTRUCTION_WRITE_SAVE 0xC000
+
+#define ADDRESS_MASK 0x0fff
+
+#define MCP25XXFD_SFR_BASE(x) (0xE00 + (x))
+#define MCP25XXFD_OSC MCP25XXFD_SFR_BASE(0x00)
+# define MCP25XXFD_OSC_PLLEN BIT(0)
+# define MCP25XXFD_OSC_OSCDIS BIT(2)
+# define MCP25XXFD_OSC_SCLKDIV BIT(4)
+# define MCP25XXFD_OSC_CLKODIV_BITS 2
+# define MCP25XXFD_OSC_CLKODIV_SHIFT 5
+# define MCP25XXFD_OSC_CLKODIV_MASK \
+ GENMASK(MCP25XXFD_OSC_CLKODIV_SHIFT \
+ + MCP25XXFD_OSC_CLKODIV_BITS - 1, \
+ MCP25XXFD_OSC_CLKODIV_SHIFT)
+# define MCP25XXFD_OSC_CLKODIV_10 3
+# define MCP25XXFD_OSC_CLKODIV_4 2
+# define MCP25XXFD_OSC_CLKODIV_2 1
+# define MCP25XXFD_OSC_CLKODIV_1 0
+# define MCP25XXFD_OSC_PLLRDY BIT(8)
+# define MCP25XXFD_OSC_OSCRDY BIT(10)
+# define MCP25XXFD_OSC_SCLKRDY BIT(12)
+#define MCP25XXFD_IOCON MCP25XXFD_SFR_BASE(0x04)
+# define MCP25XXFD_IOCON_TRIS0 BIT(0)
+# define MCP25XXFD_IOCON_TRIS1 BIT(1)
+# define MCP25XXFD_IOCON_XSTBYEN BIT(6)
+# define MCP25XXFD_IOCON_LAT0 BIT(8)
+# define MCP25XXFD_IOCON_LAT1 BIT(9)
+# define MCP25XXFD_IOCON_GPIO0 BIT(16)
+# define MCP25XXFD_IOCON_GPIO1 BIT(17)
+# define MCP25XXFD_IOCON_PM0 BIT(24)
+# define MCP25XXFD_IOCON_PM1 BIT(25)
+# define MCP25XXFD_IOCON_TXCANOD BIT(28)
+# define MCP25XXFD_IOCON_SOF BIT(29)
+# define MCP25XXFD_IOCON_INTOD BIT(29)
+#define MCP25XXFD_CRC MCP25XXFD_SFR_BASE(0x08)
+# define MCP25XXFD_CRC_MASK GENMASK(15, 0)
+# define MCP25XXFD_CRC_CRCERRIE BIT(16)
+# define MCP25XXFD_CRC_FERRIE BIT(17)
+# define MCP25XXFD_CRC_CRCERRIF BIT(24)
+# define MCP25XXFD_CRC_FERRIF BIT(25)
+#define MCP25XXFD_ECCCON MCP25XXFD_SFR_BASE(0x0C)
+# define MCP25XXFD_ECCCON_ECCEN BIT(0)
+# define MCP25XXFD_ECCCON_SECIE BIT(1)
+# define MCP25XXFD_ECCCON_DEDIE BIT(2)
+# define MCP25XXFD_ECCCON_PARITY_BITS 6
+# define MCP25XXFD_ECCCON_PARITY_SHIFT 8
+# define MCP25XXFD_ECCCON_PARITY_MASK \
+ GENMASK(MCP25XXFD_ECCCON_PARITY_SHIFT \
+ + MCP25XXFD_ECCCON_PARITY_BITS - 1, \
+ MCP25XXFD_ECCCON_PARITY_SHIFT)
+#define MCP25XXFD_ECCSTAT MCP25XXFD_SFR_BASE(0x10)
+# define MCP25XXFD_ECCSTAT_SECIF BIT(1)
+# define MCP25XXFD_ECCSTAT_DEDIF BIT(2)
+# define MCP25XXFD_ECCSTAT_ERRADDR_SHIFT 8
+# define MCP25XXFD_ECCSTAT_ERRADDR_MASK \
+ GENMASK(MCP25XXFD_ECCSTAT_ERRADDR_SHIFT + 11, \
+ MCP25XXFD_ECCSTAT_ERRADDR_SHIFT)
+
+#define CAN_SFR_BASE(x) (0x000 + (x))
+#define CAN_CON CAN_SFR_BASE(0x00)
+# define CAN_CON_DNCNT_BITS 5
+# define CAN_CON_DNCNT_SHIFT 0
+# define CAN_CON_DNCNT_MASK \
+ GENMASK(CAN_CON_DNCNT_SHIFT + CAN_CON_DNCNT_BITS - 1, \
+ CAN_CON_DNCNT_SHIFT)
+# define CAN_CON_ISOCRCEN BIT(5)
+# define CAN_CON_PXEDIS BIT(6)
+# define CAN_CON_WAKFIL BIT(8)
+# define CAN_CON_WFT_BITS 2
+# define CAN_CON_WFT_SHIFT 9
+# define CAN_CON_WFT_MASK \
+ GENMASK(CAN_CON_WFT_SHIFT + CAN_CON_WFT_BITS - 1, \
+ CAN_CON_WFT_SHIFT)
+# define CAN_CON_BUSY BIT(11)
+# define CAN_CON_BRSDIS BIT(12)
+# define CAN_CON_RTXAT BIT(16)
+# define CAN_CON_ESIGM BIT(17)
+# define CAN_CON_SERR2LOM BIT(18)
+# define CAN_CON_STEF BIT(19)
+# define CAN_CON_TXQEN BIT(20)
+# define CAN_CON_OPMODE_BITS 3
+# define CAN_CON_OPMOD_SHIFT 21
+# define CAN_CON_OPMOD_MASK \
+ GENMASK(CAN_CON_OPMOD_SHIFT + CAN_CON_OPMODE_BITS - 1, \
+ CAN_CON_OPMOD_SHIFT)
+# define CAN_CON_REQOP_BITS 3
+# define CAN_CON_REQOP_SHIFT 24
+# define CAN_CON_REQOP_MASK \
+ GENMASK(CAN_CON_REQOP_SHIFT + CAN_CON_REQOP_BITS - 1, \
+ CAN_CON_REQOP_SHIFT)
+# define CAN_CON_MODE_MIXED 0
+# define CAN_CON_MODE_SLEEP 1
+# define CAN_CON_MODE_INTERNAL_LOOPBACK 2
+# define CAN_CON_MODE_LISTENONLY 3
+# define CAN_CON_MODE_CONFIG 4
+# define CAN_CON_MODE_EXTERNAL_LOOPBACK 5
+# define CAN_CON_MODE_CAN2_0 6
+# define CAN_CON_MODE_RESTRICTED 7
+# define CAN_CON_ABAT BIT(27)
+# define CAN_CON_TXBWS_BITS 3
+# define CAN_CON_TXBWS_SHIFT 28
+# define CAN_CON_TXBWS_MASK \
+ GENMASK(CAN_CON_TXBWS_SHIFT + CAN_CON_TXBWS_BITS - 1, \
+ CAN_CON_TXBWS_SHIFT)
+# define CAN_CON_DEFAULT \
+ (CAN_CON_ISOCRCEN | \
+ CAN_CON_PXEDIS | \
+ CAN_CON_WAKFIL | \
+ (3 << CAN_CON_WFT_SHIFT) | \
+ CAN_CON_STEF | \
+ CAN_CON_TXQEN | \
+ (CAN_CON_MODE_CONFIG << CAN_CON_OPMOD_SHIFT) | \
+ (CAN_CON_MODE_CONFIG << CAN_CON_REQOP_SHIFT))
+# define CAN_CON_DEFAULT_MASK \
+ (CAN_CON_DNCNT_MASK | \
+ CAN_CON_ISOCRCEN | \
+ CAN_CON_PXEDIS | \
+ CAN_CON_WAKFIL | \
+ CAN_CON_WFT_MASK | \
+ CAN_CON_BRSDIS | \
+ CAN_CON_RTXAT | \
+ CAN_CON_ESIGM | \
+ CAN_CON_SERR2LOM | \
+ CAN_CON_STEF | \
+ CAN_CON_TXQEN | \
+ CAN_CON_OPMOD_MASK | \
+ CAN_CON_REQOP_MASK | \
+ CAN_CON_ABAT | \
+ CAN_CON_TXBWS_MASK)
+#define CAN_NBTCFG CAN_SFR_BASE(0x04)
+# define CAN_NBTCFG_SJW_BITS 7
+# define CAN_NBTCFG_SJW_SHIFT 0
+# define CAN_NBTCFG_SJW_MASK \
+ GENMASK(CAN_NBTCFG_SJW_SHIFT + CAN_NBTCFG_SJW_BITS - 1, \
+ CAN_NBTCFG_SJW_SHIFT)
+# define CAN_NBTCFG_TSEG2_BITS 7
+# define CAN_NBTCFG_TSEG2_SHIFT 8
+# define CAN_NBTCFG_TSEG2_MASK \
+ GENMASK(CAN_NBTCFG_TSEG2_SHIFT + CAN_NBTCFG_TSEG2_BITS - 1, \
+ CAN_NBTCFG_TSEG2_SHIFT)
+# define CAN_NBTCFG_TSEG1_BITS 8
+# define CAN_NBTCFG_TSEG1_SHIFT 16
+# define CAN_NBTCFG_TSEG1_MASK \
+ GENMASK(CAN_NBTCFG_TSEG1_SHIFT + CAN_NBTCFG_TSEG1_BITS - 1, \
+ CAN_NBTCFG_TSEG1_SHIFT)
+# define CAN_NBTCFG_BRP_BITS 8
+# define CAN_NBTCFG_BRP_SHIFT 24
+# define CAN_NBTCFG_BRP_MASK \
+ GENMASK(CAN_NBTCFG_BRP_SHIFT + CAN_NBTCFG_BRP_BITS - 1, \
+ CAN_NBTCFG_BRP_SHIFT)
+#define CAN_DBTCFG CAN_SFR_BASE(0x08)
+# define CAN_DBTCFG_SJW_BITS 4
+# define CAN_DBTCFG_SJW_SHIFT 0
+# define CAN_DBTCFG_SJW_MASK \
+ GENMASK(CAN_DBTCFG_SJW_SHIFT + CAN_DBTCFG_SJW_BITS - 1, \
+ CAN_DBTCFG_SJW_SHIFT)
+# define CAN_DBTCFG_TSEG2_BITS 4
+# define CAN_DBTCFG_TSEG2_SHIFT 8
+# define CAN_DBTCFG_TSEG2_MASK \
+ GENMASK(CAN_DBTCFG_TSEG2_SHIFT + CAN_DBTCFG_TSEG2_BITS - 1, \
+ CAN_DBTCFG_TSEG2_SHIFT)
+# define CAN_DBTCFG_TSEG1_BITS 5
+# define CAN_DBTCFG_TSEG1_SHIFT 16
+# define CAN_DBTCFG_TSEG1_MASK \
+ GENMASK(CAN_DBTCFG_TSEG1_SHIFT + CAN_DBTCFG_TSEG1_BITS - 1, \
+ CAN_DBTCFG_TSEG1_SHIFT)
+# define CAN_DBTCFG_BRP_BITS 8
+# define CAN_DBTCFG_BRP_SHIFT 24
+# define CAN_DBTCFG_BRP_MASK \
+ GENMASK(CAN_DBTCFG_BRP_SHIFT + CAN_DBTCFG_BRP_BITS - 1, \
+ CAN_DBTCFG_BRP_SHIFT)
+#define CAN_TDC CAN_SFR_BASE(0x0C)
+# define CAN_TDC_TDCV_BITS 5
+# define CAN_TDC_TDCV_SHIFT 0
+# define CAN_TDC_TDCV_MASK \
+ GENMASK(CAN_TDC_TDCV_SHIFT + CAN_TDC_TDCV_BITS - 1, \
+ CAN_TDC_TDCV_SHIFT)
+# define CAN_TDC_TDCO_BITS 5
+# define CAN_TDC_TDCO_SHIFT 8
+# define CAN_TDC_TDCO_MASK \
+ GENMASK(CAN_TDC_TDCO_SHIFT + CAN_TDC_TDCO_BITS - 1, \
+ CAN_TDC_TDCO_SHIFT)
+# define CAN_TDC_TDCMOD_BITS 2
+# define CAN_TDC_TDCMOD_SHIFT 16
+# define CAN_TDC_TDCMOD_MASK \
+ GENMASK(CAN_TDC_TDCMOD_SHIFT + CAN_TDC_TDCMOD_BITS - 1, \
+ CAN_TDC_TDCMOD_SHIFT)
+# define CAN_TDC_TDCMOD_DISABLED 0
+# define CAN_TDC_TDCMOD_MANUAL 1
+# define CAN_TDC_TDCMOD_AUTO 2
+# define CAN_TDC_SID11EN BIT(24)
+# define CAN_TDC_EDGFLTEN BIT(25)
+#define CAN_TBC CAN_SFR_BASE(0x10)
+#define CAN_TSCON CAN_SFR_BASE(0x14)
+# define CAN_TSCON_TBCPRE_BITS 10
+# define CAN_TSCON_TBCPRE_SHIFT 0
+# define CAN_TSCON_TBCPRE_MASK \
+ GENMASK(CAN_TSCON_TBCPRE_SHIFT + CAN_TSCON_TBCPRE_BITS - 1, \
+ CAN_TSCON_TBCPRE_SHIFT)
+# define CAN_TSCON_TBCEN BIT(16)
+# define CAN_TSCON_TSEOF BIT(17)
+# define CAN_TSCON_TSRES BIT(18)
+#define CAN_VEC CAN_SFR_BASE(0x18)
+# define CAN_VEC_ICODE_BITS 7
+# define CAN_VEC_ICODE_SHIFT 0
+# define CAN_VEC_ICODE_MASK \
+ GENMASK(CAN_VEC_ICODE_SHIFT + CAN_VEC_ICODE_BITS - 1, \
+ CAN_VEC_ICODE_SHIFT)
+# define CAN_VEC_FILHIT_BITS 5
+# define CAN_VEC_FILHIT_SHIFT 8
+# define CAN_VEC_FILHIT_MASK \
+ GENMASK(CAN_VEC_FILHIT_SHIFT + CAN_VEC_FILHIT_BITS - 1, \
+ CAN_VEC_FILHIT_SHIFT)
+# define CAN_VEC_TXCODE_BITS 7
+# define CAN_VEC_TXCODE_SHIFT 16
+# define CAN_VEC_TXCODE_MASK \
+ GENMASK(CAN_VEC_TXCODE_SHIFT + CAN_VEC_TXCODE_BITS - 1, \
+ CAN_VEC_TXCODE_SHIFT)
+# define CAN_VEC_RXCODE_BITS 7
+# define CAN_VEC_RXCODE_SHIFT 24
+# define CAN_VEC_RXCODE_MASK \
+ GENMASK(CAN_VEC_RXCODE_SHIFT + CAN_VEC_RXCODE_BITS - 1, \
+ CAN_VEC_RXCODE_SHIFT)
+#define CAN_INT CAN_SFR_BASE(0x1C)
+# define CAN_INT_IF_SHIFT 0
+# define CAN_INT_TXIF BIT(0)
+# define CAN_INT_RXIF BIT(1)
+# define CAN_INT_TBCIF BIT(2)
+# define CAN_INT_MODIF BIT(3)
+# define CAN_INT_TEFIF BIT(4)
+# define CAN_INT_ECCIF BIT(8)
+# define CAN_INT_SPICRCIF BIT(9)
+# define CAN_INT_TXATIF BIT(10)
+# define CAN_INT_RXOVIF BIT(11)
+# define CAN_INT_SERRIF BIT(12)
+# define CAN_INT_CERRIF BIT(13)
+# define CAN_INT_WAKIF BIT(14)
+# define CAN_INT_IVMIF BIT(15)
+# define CAN_INT_IF_MASK \
+ (CAN_INT_TXIF | \
+ CAN_INT_RXIF | \
+ CAN_INT_TBCIF | \
+ CAN_INT_MODIF | \
+ CAN_INT_TEFIF | \
+ CAN_INT_ECCIF | \
+ CAN_INT_SPICRCIF | \
+ CAN_INT_TXATIF | \
+ CAN_INT_RXOVIF | \
+ CAN_INT_CERRIF | \
+ CAN_INT_SERRIF | \
+ CAN_INT_WAKEIF | \
+ CAN_INT_IVMIF)
+# define CAN_INT_IE_SHIFT 16
+# define CAN_INT_TXIE (CAN_INT_TXIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_RXIE (CAN_INT_RXIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_TBCIE (CAN_INT_TBCIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_MODIE (CAN_INT_MODIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_TEFIE (CAN_INT_TEFIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_ECCIE (CAN_INT_ECCIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_SPICRCIE \
+ (CAN_INT_SPICRCIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_TXATIE (CAN_INT_TXATIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_RXOVIE (CAN_INT_RXOVIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_CERRIE (CAN_INT_CERRIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_SERRIE (CAN_INT_SERRIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_WAKIE (CAN_INT_WAKIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_IVMIE (CAN_INT_IVMIF << CAN_INT_IE_SHIFT)
+# define CAN_INT_IE_MASK \
+ (CAN_INT_TXIE | \
+ CAN_INT_RXIE | \
+ CAN_INT_TBCIE | \
+ CAN_INT_MODIE | \
+ CAN_INT_TEFIE | \
+ CAN_INT_ECCIE | \
+ CAN_INT_SPICRCIE | \
+ CAN_INT_TXATIE | \
+ CAN_INT_RXOVIE | \
+ CAN_INT_CERRIE | \
+ CAN_INT_SERRIE | \
+ CAN_INT_WAKEIE | \
+ CAN_INT_IVMIE)
+#define CAN_RXIF CAN_SFR_BASE(0x20)
+#define CAN_TXIF CAN_SFR_BASE(0x24)
+#define CAN_RXOVIF CAN_SFR_BASE(0x28)
+#define CAN_TXATIF CAN_SFR_BASE(0x2C)
+#define CAN_TXREQ CAN_SFR_BASE(0x30)
+#define CAN_TREC CAN_SFR_BASE(0x34)
+# define CAN_TREC_REC_BITS 8
+# define CAN_TREC_REC_SHIFT 0
+# define CAN_TREC_REC_MASK \
+ GENMASK(CAN_TREC_REC_SHIFT + CAN_TREC_REC_BITS - 1, \
+ CAN_TREC_REC_SHIFT)
+# define CAN_TREC_TEC_BITS 8
+# define CAN_TREC_TEC_SHIFT 8
+# define CAN_TREC_TEC_MASK \
+ GENMASK(CAN_TREC_TEC_SHIFT + CAN_TREC_TEC_BITS - 1, \
+ CAN_TREC_TEC_SHIFT)
+# define CAN_TREC_EWARN BIT(16)
+# define CAN_TREC_RXWARN BIT(17)
+# define CAN_TREC_TXWARN BIT(18)
+# define CAN_TREC_RXBP BIT(19)
+# define CAN_TREC_TXBP BIT(20)
+# define CAN_TREC_TXBO BIT(21)
+#define CAN_BDIAG0 CAN_SFR_BASE(0x38)
+# define CAN_BDIAG0_NRERRCNT_BITS 8
+# define CAN_BDIAG0_NRERRCNT_SHIFT 0
+# define CAN_BDIAG0_NRERRCNT_MASK \
+ GENMASK(CAN_BDIAG0_NRERRCNT_SHIFT + CAN_BDIAG0_NRERRCNT_BITS - 1, \
+ CAN_BDIAG0_NRERRCNT_SHIFT)
+# define CAN_BDIAG0_NTERRCNT_BITS 8
+# define CAN_BDIAG0_NTERRCNT_SHIFT 8
+# define CAN_BDIAG0_NTERRCNT_MASK \
+ GENMASK(CAN_BDIAG0_NTERRCNT_SHIFT + CAN_BDIAG0_NTERRCNT_BITS - 1, \
+ CAN_BDIAG0_NTERRCNT_SHIFT)
+# define CAN_BDIAG0_DRERRCNT_BITS 8
+# define CAN_BDIAG0_DRERRCNT_SHIFT 16
+# define CAN_BDIAG0_DRERRCNT_MASK \
+ GENMASK(CAN_BDIAG0_DRERRCNT_SHIFT + CAN_BDIAG0_DRERRCNT_BITS - 1, \
+ CAN_BDIAG0_DRERRCNT_SHIFT)
+# define CAN_BDIAG0_DTERRCNT_BITS 8
+# define CAN_BDIAG0_DTERRCNT_SHIFT 24
+# define CAN_BDIAG0_DTERRCNT_MASK \
+ GENMASK(CAN_BDIAG0_DTERRCNT_SHIFT + CAN_BDIAG0_DTERRCNT_BITS - 1, \
+ CAN_BDIAG0_DTERRCNT_SHIFT)
+#define CAN_BDIAG1 CAN_SFR_BASE(0x3C)
+# define CAN_BDIAG1_EFMSGCNT_BITS 16
+# define CAN_BDIAG1_EFMSGCNT_SHIFT 0
+# define CAN_BDIAG1_EFMSGCNT_MASK \
+ GENMASK(CAN_BDIAG1_EFMSGCNT_SHIFT + CAN_BDIAG1_EFMSGCNT_BITS - 1, \
+ CAN_BDIAG1_EFMSGCNT_SHIFT)
+# define CAN_BDIAG1_NBIT0ERR BIT(16)
+# define CAN_BDIAG1_NBIT1ERR BIT(17)
+# define CAN_BDIAG1_NACKERR BIT(18)
+# define CAN_BDIAG1_NSTUFERR BIT(19)
+# define CAN_BDIAG1_NFORMERR BIT(20)
+# define CAN_BDIAG1_NCRCERR BIT(21)
+# define CAN_BDIAG1_TXBOERR BIT(23)
+# define CAN_BDIAG1_DBIT0ERR BIT(24)
+# define CAN_BDIAG1_DBIT1ERR BIT(25)
+# define CAN_BDIAG1_DFORMERR BIT(27)
+# define CAN_BDIAG1_DSTUFERR BIT(28)
+# define CAN_BDIAG1_DCRCERR BIT(29)
+# define CAN_BDIAG1_ESI BIT(30)
+# define CAN_BDIAG1_DLCMM BIT(31)
+#define CAN_TEFCON CAN_SFR_BASE(0x40)
+# define CAN_TEFCON_TEFNEIE BIT(0)
+# define CAN_TEFCON_TEFHIE BIT(1)
+# define CAN_TEFCON_TEFFIE BIT(2)
+# define CAN_TEFCON_TEFOVIE BIT(3)
+# define CAN_TEFCON_TEFTSEN BIT(5)
+# define CAN_TEFCON_UINC BIT(8)
+# define CAN_TEFCON_FRESET BIT(10)
+# define CAN_TEFCON_FSIZE_BITS 5
+# define CAN_TEFCON_FSIZE_SHIFT 24
+# define CAN_TEFCON_FSIZE_MASK \
+ GENMASK(CAN_TEFCON_FSIZE_SHIFT + CAN_TEFCON_FSIZE_BITS - 1, \
+ CAN_TEFCON_FSIZE_SHIFT)
+#define CAN_TEFSTA CAN_SFR_BASE(0x44)
+# define CAN_TEFSTA_TEFNEIF BIT(0)
+# define CAN_TEFSTA_TEFHIF BIT(1)
+# define CAN_TEFSTA_TEFFIF BIT(2)
+# define CAN_TEFSTA_TEVOVIF BIT(3)
+#define CAN_TEFUA CAN_SFR_BASE(0x48)
+#define CAN_RESERVED CAN_SFR_BASE(0x4C)
+#define CAN_TXQCON CAN_SFR_BASE(0x50)
+# define CAN_TXQCON_TXQNIE BIT(0)
+# define CAN_TXQCON_TXQEIE BIT(2)
+# define CAN_TXQCON_TXATIE BIT(4)
+# define CAN_TXQCON_TXEN BIT(7)
+# define CAN_TXQCON_UINC BIT(8)
+# define CAN_TXQCON_TXREQ BIT(9)
+# define CAN_TXQCON_FRESET BIT(10)
+# define CAN_TXQCON_TXPRI_BITS 5
+# define CAN_TXQCON_TXPRI_SHIFT 16
+# define CAN_TXQCON_TXPRI_MASK \
+ GENMASK(CAN_TXQCON_TXPRI_SHIFT + CAN_TXQCON_TXPRI_BITS - 1, \
+ CAN_TXQCON_TXPRI_SHIFT)
+# define CAN_TXQCON_TXAT_BITS 2
+# define CAN_TXQCON_TXAT_SHIFT 21
+# define CAN_TXQCON_TXAT_MASK \
+ GENMASK(CAN_TXQCON_TXAT_SHIFT + CAN_TXQCON_TXAT_BITS - 1, \
+ CAN_TXQCON_TXAT_SHIFT)
+# define CAN_TXQCON_FSIZE_BITS 5
+# define CAN_TXQCON_FSIZE_SHIFT 24
+# define CAN_TXQCON_FSIZE_MASK \
+ GENMASK(CAN_TXQCON_FSIZE_SHIFT + CAN_TXQCON_FSIZE_BITS - 1, \
+ CAN_TXQCON_FSIZE_SHIFT)
+# define CAN_TXQCON_PLSIZE_BITS 3
+# define CAN_TXQCON_PLSIZE_SHIFT 29
+# define CAN_TXQCON_PLSIZE_MASK \
+ GENMASK(CAN_TXQCON_PLSIZE_SHIFT + CAN_TXQCON_PLSIZE_BITS - 1, \
+ CAN_TXQCON_PLSIZE_SHIFT)
+# define CAN_TXQCON_PLSIZE_8 0
+# define CAN_TXQCON_PLSIZE_12 1
+# define CAN_TXQCON_PLSIZE_16 2
+# define CAN_TXQCON_PLSIZE_20 3
+# define CAN_TXQCON_PLSIZE_24 4
+# define CAN_TXQCON_PLSIZE_32 5
+# define CAN_TXQCON_PLSIZE_48 6
+# define CAN_TXQCON_PLSIZE_64 7
+
+#define CAN_TXQSTA CAN_SFR_BASE(0x54)
+# define CAN_TXQSTA_TXQNIF BIT(0)
+# define CAN_TXQSTA_TXQEIF BIT(2)
+# define CAN_TXQSTA_TXATIF BIT(4)
+# define CAN_TXQSTA_TXERR BIT(5)
+# define CAN_TXQSTA_TXLARB BIT(6)
+# define CAN_TXQSTA_TXABT BIT(7)
+# define CAN_TXQSTA_TXQCI_BITS 5
+# define CAN_TXQSTA_TXQCI_SHIFT 8
+# define CAN_TXQSTA_TXQCI_MASK \
+ GENMASK(CAN_TXQSTA_TXQCI_SHIFT + CAN_TXQSTA_TXQCI_BITS - 1, \
+ CAN_TXQSTA_TXQCI_SHIFT)
+
+#define CAN_TXQUA CAN_SFR_BASE(0x58)
+#define CAN_FIFOCON(x) CAN_SFR_BASE(0x5C + 12 * ((x) - 1))
+#define CAN_FIFOCON_TFNRFNIE BIT(0)
+#define CAN_FIFOCON_TFHRFHIE BIT(1)
+#define CAN_FIFOCON_TFERFFIE BIT(2)
+#define CAN_FIFOCON_RXOVIE BIT(3)
+#define CAN_FIFOCON_TXATIE BIT(4)
+#define CAN_FIFOCON_RXTSEN BIT(5)
+#define CAN_FIFOCON_RTREN BIT(6)
+#define CAN_FIFOCON_TXEN BIT(7)
+#define CAN_FIFOCON_UINC BIT(8)
+#define CAN_FIFOCON_TXREQ BIT(9)
+#define CAN_FIFOCON_FRESET BIT(10)
+# define CAN_FIFOCON_TXPRI_BITS 5
+# define CAN_FIFOCON_TXPRI_SHIFT 16
+# define CAN_FIFOCON_TXPRI_MASK \
+ GENMASK(CAN_FIFOCON_TXPRI_SHIFT + CAN_FIFOCON_TXPRI_BITS - 1, \
+ CAN_FIFOCON_TXPRI_SHIFT)
+# define CAN_FIFOCON_TXAT_BITS 2
+# define CAN_FIFOCON_TXAT_SHIFT 21
+# define CAN_FIFOCON_TXAT_MASK \
+ GENMASK(CAN_FIFOCON_TXAT_SHIFT + CAN_FIFOCON_TXAT_BITS - 1, \
+ CAN_FIFOCON_TXAT_SHIFT)
+# define CAN_FIFOCON_TXAT_ONE_SHOT 0
+# define CAN_FIFOCON_TXAT_THREE_SHOT 1
+# define CAN_FIFOCON_TXAT_UNLIMITED 2
+# define CAN_FIFOCON_FSIZE_BITS 5
+# define CAN_FIFOCON_FSIZE_SHIFT 24
+# define CAN_FIFOCON_FSIZE_MASK \
+ GENMASK(CAN_FIFOCON_FSIZE_SHIFT + CAN_FIFOCON_FSIZE_BITS - 1, \
+ CAN_FIFOCON_FSIZE_SHIFT)
+# define CAN_FIFOCON_PLSIZE_BITS 3
+# define CAN_FIFOCON_PLSIZE_SHIFT 29
+# define CAN_FIFOCON_PLSIZE_MASK \
+ GENMASK(CAN_FIFOCON_PLSIZE_SHIFT + CAN_FIFOCON_PLSIZE_BITS - 1, \
+ CAN_FIFOCON_PLSIZE_SHIFT)
+#define CAN_FIFOSTA(x) CAN_SFR_BASE(0x60 + 12 * ((x) - 1))
+# define CAN_FIFOSTA_TFNRFNIF BIT(0)
+# define CAN_FIFOSTA_TFHRFHIF BIT(1)
+# define CAN_FIFOSTA_TFERFFIF BIT(2)
+# define CAN_FIFOSTA_RXOVIF BIT(3)
+# define CAN_FIFOSTA_TXATIF BIT(4)
+# define CAN_FIFOSTA_TXERR BIT(5)
+# define CAN_FIFOSTA_TXLARB BIT(6)
+# define CAN_FIFOSTA_TXABT BIT(7)
+# define CAN_FIFOSTA_FIFOCI_BITS 5
+# define CAN_FIFOSTA_FIFOCI_SHIFT 8
+# define CAN_FIFOSTA_FIFOCI_MASK \
+ GENMASK(CAN_FIFOSTA_FIFOCI_SHIFT + CAN_FIFOSTA_FIFOCI_BITS - 1, \
+ CAN_FIFOSTA_FIFOCI_SHIFT)
+#define CAN_FIFOUA(x) CAN_SFR_BASE(0x64 + 12 * ((x) - 1))
+#define CAN_FLTCON(x) CAN_SFR_BASE(0x1D0 + ((x) & 0x1c))
+# define CAN_FILCON_SHIFT(x) (((x) & 3) * 8)
+# define CAN_FILCON_BITS(x) CAN_FILCON_BITS_
+# define CAN_FILCON_BITS_ 4
+ /* avoid macro reuse warning, so do not use GENMASK as above */
+# define CAN_FILCON_MASK(x) \
+ (GENMASK(CAN_FILCON_BITS_ - 1, 0) << CAN_FILCON_SHIFT(x))
+# define CAN_FIFOCON_FLTEN(x) BIT(7 + CAN_FILCON_SHIFT(x))
+#define CAN_FLTOBJ(x) CAN_SFR_BASE(0x1F0 + 8 * (x))
+# define CAN_FILOBJ_SID_BITS 11
+# define CAN_FILOBJ_SID_SHIFT 0
+# define CAN_FILOBJ_SID_MASK \
+ GENMASK(CAN_FILOBJ_SID_SHIFT + CAN_FILOBJ_SID_BITS - 1, \
+ CAN_FILOBJ_SID_SHIFT)
+# define CAN_FILOBJ_EID_BITS 18
+# define CAN_FILOBJ_EID_SHIFT 12
+# define CAN_FILOBJ_EID_MASK \
+ GENMASK(CAN_FILOBJ_EID_SHIFT + CAN_FILOBJ_EID_BITS - 1, \
+ CAN_FILOBJ_EID_SHIFT)
+# define CAN_FILOBJ_SID11 BIT(29)
+# define CAN_FILOBJ_EXIDE BIT(30)
+#define CAN_FLTMASK(x) CAN_SFR_BASE(0x1F4 + 8 * (x))
+# define CAN_FILMASK_MSID_BITS 11
+# define CAN_FILMASK_MSID_SHIFT 0
+# define CAN_FILMASK_MSID_MASK \
+ GENMASK(CAN_FILMASK_MSID_SHIFT + CAN_FILMASK_MSID_BITS - 1, \
+ CAN_FILMASK_MSID_SHIFT)
+# define CAN_FILMASK_MEID_BITS 18
+# define CAN_FILMASK_MEID_SHIFT 12
+# define CAN_FILMASK_MEID_MASK \
+ GENMASK(CAN_FILMASK_MEID_SHIFT + CAN_FILMASK_MEID_BITS - 1, \
+ CAN_FILMASK_MEID_SHIFT)
+# define CAN_FILMASK_MSID11 BIT(29)
+# define CAN_FILMASK_MIDE BIT(30)
+
+#define CAN_OBJ_ID_SID_BITS 11
+#define CAN_OBJ_ID_SID_SHIFT 0
+#define CAN_OBJ_ID_SID_MASK \
+ GENMASK(CAN_OBJ_ID_SID_SHIFT + CAN_OBJ_ID_SID_BITS - 1, \
+ CAN_OBJ_ID_SID_SHIFT)
+#define CAN_OBJ_ID_EID_BITS 18
+#define CAN_OBJ_ID_EID_SHIFT 11
+#define CAN_OBJ_ID_EID_MASK \
+ GENMASK(CAN_OBJ_ID_EID_SHIFT + CAN_OBJ_ID_EID_BITS - 1, \
+ CAN_OBJ_ID_EID_SHIFT)
+#define CAN_OBJ_ID_SID_BIT11 BIT(29)
+
+#define CAN_OBJ_FLAGS_DLC_BITS 4
+#define CAN_OBJ_FLAGS_DLC_SHIFT 0
+#define CAN_OBJ_FLAGS_DLC_MASK \
+ GENMASK(CAN_OBJ_FLAGS_DLC_SHIFT + CAN_OBJ_FLAGS_DLC_BITS - 1, \
+ CAN_OBJ_FLAGS_DLC_SHIFT)
+#define CAN_OBJ_FLAGS_IDE BIT(4)
+#define CAN_OBJ_FLAGS_RTR BIT(5)
+#define CAN_OBJ_FLAGS_BRS BIT(6)
+#define CAN_OBJ_FLAGS_FDF BIT(7)
+#define CAN_OBJ_FLAGS_ESI BIT(8)
+#define CAN_OBJ_FLAGS_SEQ_BITS 7
+#define CAN_OBJ_FLAGS_SEQ_SHIFT 9
+#define CAN_OBJ_FLAGS_SEQ_MASK \
+ GENMASK(CAN_OBJ_FLAGS_SEQ_SHIFT + CAN_OBJ_FLAGS_SEQ_BITS - 1, \
+ CAN_OBJ_FLAGS_SEQ_SHIFT)
+#define CAN_OBJ_FLAGS_FILHIT_BITS 11
+#define CAN_OBJ_FLAGS_FILHIT_SHIFT 5
+#define CAN_OBJ_FLAGS_FILHIT_MASK \
+ GENMASK(CAN_FLAGS_FILHIT_SHIFT + CAN_FLAGS_FILHIT_BITS - 1, \
+ CAN_FLAGS_FILHIT_SHIFT)
+
+#define CAN_OBJ_FLAGS_CUSTOM_ISTEF BIT(31)
+
+#define MCP25XXFD_BUFFER_TXRX_SIZE 2048
+
+static const char * const mcp25xxfd_mode_names[] = {
+ [CAN_CON_MODE_MIXED] = "can2.0+canfd",
+ [CAN_CON_MODE_SLEEP] = "sleep",
+ [CAN_CON_MODE_INTERNAL_LOOPBACK] = "internal loopback",
+ [CAN_CON_MODE_LISTENONLY] = "listen only",
+ [CAN_CON_MODE_CONFIG] = "config",
+ [CAN_CON_MODE_EXTERNAL_LOOPBACK] = "external loopback",
+ [CAN_CON_MODE_CAN2_0] = "can2.0",
+ [CAN_CON_MODE_RESTRICTED] = "restricted"
+};
+
+struct mcp25xxfd_obj {
+ u32 id;
+ u32 flags;
+};
+
+struct mcp25xxfd_obj_tx {
+ struct mcp25xxfd_obj header;
+ u32 data[];
+};
+
+static void mcp25xxfd_obj_to_le(struct mcp25xxfd_obj *obj)
+{
+ obj->id = cpu_to_le32(obj->id);
+ obj->flags = cpu_to_le32(obj->flags);
+}
+
+struct mcp25xxfd_obj_ts {
+ u32 id;
+ u32 flags;
+ u32 ts;
+};
+
+struct mcp25xxfd_obj_tef {
+ struct mcp25xxfd_obj_ts header;
+};
+
+struct mcp25xxfd_obj_rx {
+ struct mcp25xxfd_obj_ts header;
+ u8 data[];
+};
+
+static void mcp25xxfd_obj_ts_from_le(struct mcp25xxfd_obj_ts *obj)
+{
+ obj->id = le32_to_cpu(obj->id);
+ obj->flags = le32_to_cpu(obj->flags);
+ obj->ts = le32_to_cpu(obj->ts);
+}
+
+#define FIFO_DATA(x) (0x400 + (x))
+#define FIFO_DATA_SIZE 0x800
+
+static const struct can_bittiming_const mcp25xxfd_nominal_bittiming_const = {
+ .name = DEVICE_NAME,
+ .tseg1_min = 2,
+ .tseg1_max = BIT(CAN_NBTCFG_TSEG1_BITS),
+ .tseg2_min = 1,
+ .tseg2_max = BIT(CAN_NBTCFG_TSEG2_BITS),
+ .sjw_max = BIT(CAN_NBTCFG_SJW_BITS),
+ .brp_min = 1,
+ .brp_max = BIT(CAN_NBTCFG_BRP_BITS),
+ .brp_inc = 1,
+};
+
+static const struct can_bittiming_const mcp25xxfd_data_bittiming_const = {
+ .name = DEVICE_NAME,
+ .tseg1_min = 1,
+ .tseg1_max = BIT(CAN_DBTCFG_TSEG1_BITS),
+ .tseg2_min = 1,
+ .tseg2_max = BIT(CAN_DBTCFG_TSEG2_BITS),
+ .sjw_max = BIT(CAN_DBTCFG_SJW_BITS),
+ .brp_min = 1,
+ .brp_max = BIT(CAN_DBTCFG_BRP_BITS),
+ .brp_inc = 1,
+};
+
+enum mcp25xxfd_model {
+ CAN_MCP2517FD = 0x2517,
+};
+
+enum mcp25xxfd_gpio_mode {
+ gpio_mode_int = 0,
+ gpio_mode_standby = MCP25XXFD_IOCON_XSTBYEN,
+ gpio_mode_out_low = MCP25XXFD_IOCON_PM0,
+ gpio_mode_out_high = MCP25XXFD_IOCON_PM0 | MCP25XXFD_IOCON_LAT0,
+ gpio_mode_in = MCP25XXFD_IOCON_PM0 | MCP25XXFD_IOCON_TRIS0
+};
+
+struct mcp25xxfd_trigger_tx_message {
+ struct spi_message msg;
+ struct spi_transfer fill_xfer;
+ struct spi_transfer trigger_xfer;
+ int fifo;
+ char fill_cmd[2];
+ char fill_obj[sizeof(struct mcp25xxfd_obj_tx)];
+ char fill_data[64];
+ char trigger_cmd[2];
+ char trigger_data;
+};
+
+struct mcp25xxfd_read_fifo_info {
+ struct mcp25xxfd_obj_ts *rxb[32];
+ int rx_count;
+};
+
+struct mcp25xxfd_priv {
+ struct can_priv can;
+ struct net_device *net;
+ struct spi_device *spi;
+ struct regulator *power;
+ struct regulator *transceiver;
+ struct clk *clk;
+
+ struct mutex clk_user_lock; /* lock for enabling/disabling the clock */
+ int clk_user_mask;
+#define MCP25XXFD_CLK_USER_CAN BIT(0)
+#define MCP25XXFD_CLK_USER_GPIO0 BIT(1)
+#define MCP25XXFD_CLK_USER_GPIO1 BIT(2)
+
+ struct dentry *debugfs_dir;
+
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio;
+#endif
+
+ /* the actual model of the mcp25xxfd */
+ enum mcp25xxfd_model model;
+
+ struct {
+ /* clock configuration */
+ bool clock_pll;
+ bool clock_div2;
+ int clock_odiv;
+
+ /* GPIO configuration */
+ bool gpio_opendrain;
+ } config;
+
+ /* the distinct spi_speeds to use for spi communication */
+ u32 spi_setup_speed_hz;
+ u32 spi_speed_hz;
+
+ /* fifo info */
+ struct {
+ /* define payload size and mode */
+ int payload_size;
+ u32 payload_mode;
+
+ /* TEF addresses - start, end and current */
+ u32 tef_fifos;
+ u32 tef_address_start;
+ u32 tef_address_end;
+ u32 tef_address;
+
+ /* address in mcp25xxfd-Fifo RAM of each fifo */
+ u32 fifo_address[32];
+
+ /* infos on tx-fifos */
+ u32 tx_fifos;
+ u32 tx_fifo_start;
+ u32 tx_fifo_mask; /* bitmask of which fifo is a tx fifo */
+ u32 tx_submitted_mask;
+ u32 tx_pending_mask;
+ u32 tx_pending_mask_in_irq;
+ u32 tx_processed_mask;
+
+ /* info on rx_fifos */
+ u32 rx_fifos;
+ u32 rx_fifo_depth;
+ u32 rx_fifo_start;
+ u32 rx_fifo_mask; /* bitmask of which fifo is a rx fifo */
+
+ /* memory image of FIFO RAM on mcp25xxfd */
+ u8 fifo_data[MCP25XXFD_BUFFER_TXRX_SIZE];
+
+ } fifos;
+
+ /* structure with active fifos that need to get fed to the system */
+ struct mcp25xxfd_read_fifo_info queued_fifos;
+
+ /* statistics */
+ struct {
+ /* number of calls to the irq handler */
+ u64 irq_calls;
+ /* number of loops inside the irq handler */
+ u64 irq_loops;
+
+ /* interrupt handler state and statistics */
+ u32 irq_state;
+#define IRQ_STATE_NEVER_RUN 0
+#define IRQ_STATE_RUNNING 1
+#define IRQ_STATE_HANDLED 2
+ /* stats on number of rx overflows */
+ u64 rx_overflow;
+ /* statistics of FIFO usage */
+ u64 fifo_usage[32];
+
+ /* message abort counter */
+ u64 rx_mab;
+ u64 tx_mab;
+
+ /* message counter fd */
+ u64 rx_fd_count;
+ u64 tx_fd_count;
+
+ /* message counter fd bit rate switch */
+ u64 rx_brs_count;
+ u64 tx_brs_count;
+
+ /* interrupt counter */
+ u64 int_ivm_count;
+ u64 int_wake_count;
+ u64 int_cerr_count;
+ u64 int_serr_count;
+ u64 int_rxov_count;
+ u64 int_txat_count;
+ u64 int_spicrc_count;
+ u64 int_ecc_count;
+ u64 int_tef_count;
+ u64 int_mod_count;
+ u64 int_tbc_count;
+ u64 int_rx_count;
+ u64 int_tx_count;
+
+ /* dlc statistics */
+ u64 rx_dlc_usage[16];
+ u64 tx_dlc_usage[16];
+ } stats;
+
+ /* the current status of the mcp25xxfd */
+ struct {
+ u32 intf;
+ /* ASSERT(CAN_INT + 4 == CAN_RXIF) */
+ u32 rxif;
+ /* ASSERT(CAN_RXIF + 4 == CAN_TXIF) */
+ u32 txif;
+ /* ASSERT(CAN_TXIF + 4 == CAN_RXOVIF) */
+ u32 rxovif;
+ /* ASSERT(CAN_RXOVIF + 4 == CAN_TXATIF) */
+ u32 txatif;
+ /* ASSERT(CAN_TXATIF + 4 == CAN_TXREQ) */
+ u32 txreq;
+ /* ASSERT(CAN_TXREQ + 4 == CAN_TREC) */
+ u32 trec;
+ /* ASSERT(CAN_TREC + 4 == CAN_BDIAG0) */
+ u32 bdiag0;
+ /* ASSERT(CAN_BDIAG0 + 4 == CAN_BDIAG1) */
+ u32 bdiag1;
+ } status;
+
+ /* configuration registers */
+ struct {
+ u32 osc;
+ u32 ecccon;
+ u32 con;
+ u32 iocon;
+ u32 tdc;
+ u32 tscon;
+ u32 tefcon;
+ u32 nbtcfg;
+ u32 dbtcfg;
+ } regs;
+
+ /* interrupt handler signaling */
+ int force_quit;
+ int after_suspend;
+#define AFTER_SUSPEND_UP 1
+#define AFTER_SUSPEND_DOWN 2
+#define AFTER_SUSPEND_POWER 4
+#define AFTER_SUSPEND_RESTART 8
+ int restart_tx;
+
+ /* interrupt flags during irq handling */
+ u32 bdiag1_clear_mask;
+ u32 bdiag1_clear_value;
+
+ /* composit error id and dataduring irq handling */
+ u32 can_err_id;
+ u32 can_err_data[8];
+
+ /* the current mode */
+ u32 active_can_mode;
+ u32 new_state;
+
+ /* status of the tx_queue enabled/disabled */
+ u32 tx_queue_status;
+#define TX_QUEUE_STATUS_INIT 0
+#define TX_QUEUE_STATUS_RUNNING 1
+#define TX_QUEUE_STATUS_NEEDS_START 2
+#define TX_QUEUE_STATUS_STOPPED 3
+
+ /* spi-tx/rx buffers for efficient transfers
+ * used during setup and irq
+ */
+ struct mutex spi_rxtx_lock;
+ u8 spi_tx[MCP25XXFD_BUFFER_TXRX_SIZE];
+ u8 spi_rx[MCP25XXFD_BUFFER_TXRX_SIZE];
+
+ /* structure for transmit fifo spi_messages */
+ struct mcp25xxfd_trigger_tx_message *spi_transmit_fifos;
+};
+
+/* module parameters */
+bool use_bulk_release_fifos;
+module_param(use_bulk_release_fifos, bool, 0664);
+MODULE_PARM_DESC(use_bulk_release_fifos,
+ "Use code that favours longer spi transfers over multiple transfers");
+bool use_complete_fdfifo_read;
+module_param(use_complete_fdfifo_read, bool, 0664);
+MODULE_PARM_DESC(use_complete_fdfifo_read,
+ "Use code that favours longer spi transfers over multiple transfers for fd can");
+unsigned int tx_fifos;
+module_param(tx_fifos, uint, 0664);
+MODULE_PARM_DESC(tx_fifos,
+ "Number of tx-fifos to configure\n");
+unsigned int bw_sharing_log2bits;
+module_param(bw_sharing_log2bits, uint, 0664);
+MODULE_PARM_DESC(bw_sharing_log2bits,
+ "Delay between 2 transmissions in number of arbitration bit times\n");
+bool three_shot;
+module_param(three_shot, bool, 0664);
+MODULE_PARM_DESC(three_shot,
+ "Use 3 shots when one-shot is requested");
+
+/* spi sync helper */
+
+/* wrapper arround spi_sync, that sets speed_hz */
+static int mcp25xxfd_sync_transfer(struct spi_device *spi,
+ struct spi_transfer *xfer,
+ unsigned int xfers,
+ int speed_hz)
+{
+ int i;
+
+ for (i = 0; i < xfers; i++)
+ xfer[i].speed_hz = speed_hz;
+
+ return spi_sync_transfer(spi, xfer, xfers);
+}
+
+/* an optimization of spi_write_then_read that merges the transfers */
+static int mcp25xxfd_write_then_read(struct spi_device *spi,
+ const void *tx_buf,
+ unsigned int tx_len,
+ void *rx_buf,
+ unsigned int rx_len,
+ int speed_hz)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct spi_transfer xfer[2];
+ u8 single_reg_data_tx[6];
+ u8 single_reg_data_rx[6];
+ int ret;
+
+ memset(xfer, 0, sizeof(xfer));
+
+ /* when using a halfduplex controller or to big for buffer */
+ if ((spi->master->flags & SPI_MASTER_HALF_DUPLEX) ||
+ (tx_len + rx_len > sizeof(priv->spi_tx))) {
+ xfer[0].tx_buf = tx_buf;
+ xfer[0].len = tx_len;
+
+ xfer[1].rx_buf = rx_buf;
+ xfer[1].len = rx_len;
+
+ return mcp25xxfd_sync_transfer(spi, xfer, 2, speed_hz);
+ }
+
+ /* full duplex optimization */
+ xfer[0].len = tx_len + rx_len;
+ if (xfer[0].len > sizeof(single_reg_data_tx)) {
+ mutex_lock(&priv->spi_rxtx_lock);
+ xfer[0].tx_buf = priv->spi_tx;
+ xfer[0].rx_buf = priv->spi_rx;
+ } else {
+ xfer[0].tx_buf = single_reg_data_tx;
+ xfer[0].rx_buf = single_reg_data_rx;
+ }
+
+ /* copy and clean */
+ memcpy((u8 *)xfer[0].tx_buf, tx_buf, tx_len);
+ memset((u8 *)xfer[0].tx_buf + tx_len, 0, rx_len);
+
+ ret = mcp25xxfd_sync_transfer(spi, xfer, 1, speed_hz);
+ if (!ret)
+ memcpy(rx_buf, xfer[0].rx_buf + tx_len, rx_len);
+
+ if (xfer[0].len > sizeof(single_reg_data_tx))
+ mutex_unlock(&priv->spi_rxtx_lock);
+
+ return ret;
+}
+
+/* simple spi_write wrapper with speed_hz */
+static int mcp25xxfd_write(struct spi_device *spi,
+ const void *tx_buf,
+ unsigned int tx_len,
+ int speed_hz)
+{
+ struct spi_transfer xfer;
+
+ memset(&xfer, 0, sizeof(xfer));
+ xfer.tx_buf = tx_buf;
+ xfer.len = tx_len;
+
+ return mcp25xxfd_sync_transfer(spi, &xfer, 1, speed_hz);
+}
+
+/* spi_sync wrapper similar to spi_write_then_read that optimizes transfers */
+static int mcp25xxfd_write_then_write(struct spi_device *spi,
+ const void *tx_buf,
+ unsigned int tx_len,
+ const void *tx2_buf,
+ unsigned int tx2_len,
+ int speed_hz)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct spi_transfer xfer;
+ u8 single_reg_data[6];
+ int ret;
+
+ if (tx_len + tx2_len > MCP25XXFD_BUFFER_TXRX_SIZE)
+ return -EINVAL;
+
+ memset(&xfer, 0, sizeof(xfer));
+
+ xfer.len = tx_len + tx2_len;
+ if (xfer.len > sizeof(single_reg_data)) {
+ mutex_lock(&priv->spi_rxtx_lock);
+ xfer.tx_buf = priv->spi_tx;
+ } else {
+ xfer.tx_buf = single_reg_data;
+ }
+
+ memcpy((u8 *)xfer.tx_buf, tx_buf, tx_len);
+ memcpy((u8 *)xfer.tx_buf + tx_len, tx2_buf, tx2_len);
+
+ ret = mcp25xxfd_sync_transfer(spi, &xfer, 1, speed_hz);
+
+ if (xfer.len > sizeof(single_reg_data))
+ mutex_unlock(&priv->spi_rxtx_lock);
+
+ return ret;
+}
+
+/* mcp25xxfd spi command/protocol helper */
+
+static void mcp25xxfd_calc_cmd_addr(u16 cmd, u16 addr, u8 *data)
+{
+ cmd = cmd | (addr & ADDRESS_MASK);
+
+ data[0] = (cmd >> 8) & 0xff;
+ data[1] = (cmd >> 0) & 0xff;
+}
+
+static int mcp25xxfd_cmd_reset(struct spi_device *spi, u32 speed_hz)
+{
+ u8 cmd[2];
+
+ mcp25xxfd_calc_cmd_addr(INSTRUCTION_RESET, 0, cmd);
+
+ /* write the reset command */
+ return mcp25xxfd_write(spi, cmd, 2, speed_hz);
+}
+
+/* read multiple bytes, transform some registers */
+static int mcp25xxfd_cmd_readn(struct spi_device *spi, u32 reg,
+ void *data, int n, u32 speed_hz)
+{
+ u8 cmd[2];
+ int ret;
+
+ mcp25xxfd_calc_cmd_addr(INSTRUCTION_READ, reg, cmd);
+
+ ret = mcp25xxfd_write_then_read(spi, &cmd, 2, data, n, speed_hz);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mcp25xxfd_convert_to_cpu(u32 *data, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ data[i] = le32_to_cpu(data[i]);
+
+ return 0;
+}
+
+static int mcp25xxfd_first_byte(u32 mask)
+{
+ return (mask & 0x0000ffff) ?
+ ((mask & 0x000000ff) ? 0 : 1) :
+ ((mask & 0x00ff0000) ? 2 : 3);
+}
+
+static int mcp25xxfd_last_byte(u32 mask)
+{
+ return (mask & 0xffff0000) ?
+ ((mask & 0xff000000) ? 3 : 2) :
+ ((mask & 0x0000ff00) ? 1 : 0);
+}
+
+/* read a register, but we are only interrested in a few bytes */
+static int mcp25xxfd_cmd_read_mask(struct spi_device *spi, u32 reg,
+ u32 *data, u32 mask, u32 speed_hz)
+{
+ int first_byte, last_byte, len_byte;
+ int ret;
+
+ /* check that at least one bit is set */
+ if (!mask)
+ return -EINVAL;
+
+ /* calculate first and last byte used */
+ first_byte = mcp25xxfd_first_byte(mask);
+ last_byte = mcp25xxfd_last_byte(mask);
+ len_byte = last_byte - first_byte + 1;
+
+ /* do a partial read */
+ *data = 0;
+ ret = mcp25xxfd_cmd_readn(spi, reg + first_byte,
+ ((void *)data + first_byte), len_byte,
+ speed_hz);
+ if (ret)
+ return ret;
+
+ return mcp25xxfd_convert_to_cpu(data, 1);
+}
+
+static int mcp25xxfd_cmd_read(struct spi_device *spi, u32 reg, u32 *data,
+ u32 speed_hz)
+{
+ return mcp25xxfd_cmd_read_mask(spi, reg, data, -1, speed_hz);
+}
+
+/* read a register, but we are only interrested in a few bytes */
+static int mcp25xxfd_cmd_write_mask(struct spi_device *spi, u32 reg,
+ u32 data, u32 mask, u32 speed_hz)
+{
+ int first_byte, last_byte, len_byte;
+ u8 cmd[2];
+
+ /* check that at least one bit is set */
+ if (!mask)
+ return -EINVAL;
+
+ /* calculate first and last byte used */
+ first_byte = mcp25xxfd_first_byte(mask);
+ last_byte = mcp25xxfd_last_byte(mask);
+ len_byte = last_byte - first_byte + 1;
+
+ /* prepare buffer */
+ mcp25xxfd_calc_cmd_addr(INSTRUCTION_WRITE, reg + first_byte, cmd);
+ data = cpu_to_le32(data);
+
+ return mcp25xxfd_write_then_write(spi,
+ cmd, sizeof(cmd),
+ ((void *)&data + first_byte),
+ len_byte,
+ speed_hz);
+}
+
+static int mcp25xxfd_cmd_write(struct spi_device *spi, u32 reg, u32 data,
+ u32 speed_hz)
+{
+ return mcp25xxfd_cmd_write_mask(spi, reg, data, -1, speed_hz);
+}
+
+static int mcp25xxfd_cmd_writen(struct spi_device *spi, u32 reg,
+ void *data, int n, u32 speed_hz)
+{
+ u8 cmd[2];
+ int ret;
+
+ mcp25xxfd_calc_cmd_addr(INSTRUCTION_WRITE, reg, cmd);
+
+ ret = mcp25xxfd_write_then_write(spi, &cmd, 2, data, n, speed_hz);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mcp25xxfd_clean_sram(struct spi_device *spi, u32 speed_hz)
+{
+ u8 buffer[256];
+ int i;
+ int ret;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ for (i = 0; i < FIFO_DATA_SIZE; i += sizeof(buffer)) {
+ ret = mcp25xxfd_cmd_writen(spi, FIFO_DATA(i),
+ buffer, sizeof(buffer),
+ speed_hz);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* mcp25xxfd opmode helper functions */
+
+static int mcp25xxfd_get_opmode(struct spi_device *spi,
+ int *mode,
+ int speed_hz)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int ret;
+
+ /* read the mode */
+ ret = mcp25xxfd_cmd_read_mask(spi,
+ CAN_CON,
+ &priv->regs.con,
+ CAN_CON_OPMOD_MASK,
+ speed_hz);
+ if (ret)
+ return ret;
+ /* calculate the mode */
+ *mode = (priv->regs.con & CAN_CON_OPMOD_MASK) >>
+ CAN_CON_OPMOD_SHIFT;
+
+ /* and assign to active mode as well */
+ priv->active_can_mode = *mode;
+
+ return 0;
+}
+
+static int mcp25xxfd_set_opmode(struct spi_device *spi, int mode,
+ int speed_hz)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 val = priv->regs.con & ~CAN_CON_REQOP_MASK;
+
+ /* regs.con also contains the effective register */
+ priv->regs.con = val |
+ (mode << CAN_CON_REQOP_SHIFT) |
+ (mode << CAN_CON_OPMOD_SHIFT);
+ priv->active_can_mode = mode;
+
+ /* if the opmode is sleep then the oscilator will be disabled
+ * and also not ready
+ */
+ if (mode == CAN_CON_MODE_SLEEP) {
+ priv->regs.osc &= ~(MCP25XXFD_OSC_OSCRDY |
+ MCP25XXFD_OSC_PLLRDY |
+ MCP25XXFD_OSC_SCLKRDY);
+ priv->regs.osc |= MCP25XXFD_OSC_OSCDIS;
+ }
+
+ /* but only write the relevant section */
+ return mcp25xxfd_cmd_write_mask(spi, CAN_CON,
+ priv->regs.con,
+ CAN_CON_REQOP_MASK,
+ speed_hz);
+}
+
+static int mcp25xxfd_set_normal_opmode(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int mode;
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
+ mode = CAN_CON_MODE_EXTERNAL_LOOPBACK;
+ else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
+ mode = CAN_CON_MODE_LISTENONLY;
+ else if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
+ mode = CAN_CON_MODE_MIXED;
+ else
+ mode = CAN_CON_MODE_CAN2_0;
+
+ return mcp25xxfd_set_opmode(spi, mode, priv->spi_setup_speed_hz);
+}
+
+/* clock helper */
+static int mcp25xxfd_wake_from_sleep(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 waitfor = MCP25XXFD_OSC_OSCRDY;
+ u32 mask = waitfor | MCP25XXFD_OSC_OSCDIS;
+ unsigned long timeout;
+ int ret;
+
+ /* write clock with OSCDIS cleared*/
+ priv->regs.osc &= ~MCP25XXFD_OSC_OSCDIS;
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_OSC,
+ priv->regs.osc,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* wait for synced pll/osc/sclk */
+ timeout = jiffies + MCP25XXFD_OSC_POLLING_JIFFIES;
+ while (time_before_eq(jiffies, timeout)) {
+ ret = mcp25xxfd_cmd_read(spi, MCP25XXFD_OSC,
+ &priv->regs.osc,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ if ((priv->regs.osc & mask) == waitfor) {
+ priv->active_can_mode = CAN_CON_MODE_CONFIG;
+ return 0;
+ }
+ /* wait some time */
+ msleep(100);
+ }
+
+ dev_err(&spi->dev,
+ "Clock did not enable within the timeout period\n");
+ return -ETIMEDOUT;
+}
+
+static int mcp25xxfd_hw_check_clock(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 val;
+ int ret;
+
+ /* read the osc register and check if it matches
+ * what we have on record
+ */
+ ret = mcp25xxfd_cmd_read(spi, MCP25XXFD_OSC,
+ &val,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ if (val == priv->regs.osc)
+ return 0;
+
+ /* ignore all those ready bits on second try */
+ if ((val & 0xff) == (priv->regs.osc & 0xff)) {
+ dev_info(&spi->dev,
+ "The oscillator register value %08x does not match what we expect: %08x - it is still reasonable, but please investigate\n",
+ val, priv->regs.osc);
+ return 0;
+ }
+
+ dev_err(&spi->dev,
+ "The oscillator register value %08x does not match what we expect: %08x\n",
+ val, priv->regs.osc);
+
+ return -ENODEV;
+}
+
+static int mcp25xxfd_start_clock(struct spi_device *spi, int requestor_mask)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int ret = 0;
+
+ mutex_lock(&priv->clk_user_lock);
+
+ priv->clk_user_mask |= requestor_mask;
+
+ if (priv->clk_user_mask != requestor_mask)
+ goto out;
+
+ /* check that the controller clock register
+ * is what it is supposed to be
+ */
+ ret = mcp25xxfd_hw_check_clock(spi);
+ if (ret) {
+ dev_err(&spi->dev,
+ "Controller clock register in unexpected state");
+ goto out;
+ }
+
+ /* and we start the clock */
+ if (!IS_ERR(priv->clk))
+ ret = clk_prepare_enable(priv->clk);
+
+ /* we wake from sleep */
+ if (priv->active_can_mode == CAN_CON_MODE_SLEEP)
+ ret = mcp25xxfd_wake_from_sleep(spi);
+
+out:
+ mutex_unlock(&priv->clk_user_lock);
+
+ return ret;
+}
+
+static int mcp25xxfd_stop_clock(struct spi_device *spi, int requestor_mask)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ mutex_lock(&priv->clk_user_lock);
+
+ priv->clk_user_mask &= ~requestor_mask;
+
+ if (!priv->clk_user_mask)
+ goto out;
+
+ /* put us into sleep mode */
+ mcp25xxfd_set_opmode(spi, CAN_CON_MODE_SLEEP,
+ priv->spi_setup_speed_hz);
+
+ /* and we stop the clock */
+ if (!IS_ERR(priv->clk))
+ clk_disable_unprepare(priv->clk);
+
+out:
+ mutex_unlock(&priv->clk_user_lock);
+
+ return 0;
+}
+
+/* mcp25xxfd GPIO helper functions */
+#ifdef CONFIG_GPIOLIB
+
+enum mcp25xxfd_gpio_pins {
+ MCP25XXFD_GPIO_GPIO0 = 0,
+ MCP25XXFD_GPIO_GPIO1 = 1,
+};
+
+static int mcp25xxfd_gpio_request(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ int clock_requestor = offset ?
+ MCP25XXFD_CLK_USER_GPIO1 : MCP25XXFD_CLK_USER_GPIO0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ mcp25xxfd_start_clock(priv->spi, clock_requestor);
+
+ return 0;
+}
+
+static void mcp25xxfd_gpio_free(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ int clock_requestor = offset ?
+ MCP25XXFD_CLK_USER_GPIO1 : MCP25XXFD_CLK_USER_GPIO0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return;
+
+ mcp25xxfd_stop_clock(priv->spi, clock_requestor);
+}
+
+static int mcp25xxfd_gpio_get(struct gpio_chip *chip, unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask = (offset) ? MCP25XXFD_IOCON_GPIO1 : MCP25XXFD_IOCON_GPIO0;
+ int ret;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* read the relevant gpio Latch */
+ ret = mcp25xxfd_cmd_read_mask(priv->spi, MCP25XXFD_IOCON,
+ &priv->regs.iocon, mask,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* return the match */
+ return priv->regs.iocon & mask;
+}
+
+static void mcp25xxfd_gpio_set(struct gpio_chip *chip, unsigned int offset,
+ int value)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask = (offset) ? MCP25XXFD_IOCON_LAT1 : MCP25XXFD_IOCON_LAT0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return;
+
+ /* update in memory representation with the corresponding value */
+ if (value)
+ priv->regs.iocon |= mask;
+ else
+ priv->regs.iocon &= ~mask;
+
+ mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_IOCON,
+ priv->regs.iocon, mask,
+ priv->spi_setup_speed_hz);
+}
+
+static int mcp25xxfd_gpio_direction_input(struct gpio_chip *chip,
+ unsigned int offset)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask_tri = (offset) ?
+ MCP25XXFD_IOCON_TRIS1 : MCP25XXFD_IOCON_TRIS0;
+ u32 mask_stby = (offset) ?
+ 0 : MCP25XXFD_IOCON_XSTBYEN;
+ u32 mask_pm = (offset) ?
+ MCP25XXFD_IOCON_PM1 : MCP25XXFD_IOCON_PM0;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* set the mask */
+ priv->regs.iocon |= mask_tri | mask_pm;
+
+ /* clear stby */
+ priv->regs.iocon &= ~mask_stby;
+
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_IOCON,
+ priv->regs.iocon,
+ mask_tri | mask_stby | mask_pm,
+ priv->spi_setup_speed_hz);
+}
+
+static int mcp25xxfd_gpio_direction_output(struct gpio_chip *chip,
+ unsigned int offset, int value)
+{
+ struct mcp25xxfd_priv *priv = gpiochip_get_data(chip);
+ u32 mask_tri = (offset) ?
+ MCP25XXFD_IOCON_TRIS1 : MCP25XXFD_IOCON_TRIS0;
+ u32 mask_lat = (offset) ?
+ MCP25XXFD_IOCON_LAT1 : MCP25XXFD_IOCON_LAT0;
+ u32 mask_pm = (offset) ?
+ MCP25XXFD_IOCON_PM1 : MCP25XXFD_IOCON_PM0;
+ u32 mask_stby = (offset) ?
+ 0 : MCP25XXFD_IOCON_XSTBYEN;
+
+ /* only handle gpio 0/1 */
+ if (offset > 1)
+ return -EINVAL;
+
+ /* clear the tristate bit and also clear stby */
+ priv->regs.iocon &= ~(mask_tri | mask_stby);
+
+ /* set GPIO mode */
+ priv->regs.iocon |= mask_pm;
+
+ /* set the value */
+ if (value)
+ priv->regs.iocon |= mask_lat;
+ else
+ priv->regs.iocon &= ~mask_lat;
+
+ return mcp25xxfd_cmd_write_mask(priv->spi, MCP25XXFD_IOCON,
+ priv->regs.iocon,
+ mask_tri | mask_lat |
+ mask_pm | mask_stby,
+ priv->spi_setup_speed_hz);
+}
+
+static int mcp25xxfd_gpio_setup(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* gpiochip only handles GPIO0 and GPIO1 */
+ priv->gpio.owner = THIS_MODULE;
+ priv->gpio.parent = &spi->dev;
+ priv->gpio.label = dev_name(&spi->dev);
+ priv->gpio.direction_input = mcp25xxfd_gpio_direction_input;
+ priv->gpio.get = mcp25xxfd_gpio_get;
+ priv->gpio.direction_output = mcp25xxfd_gpio_direction_output;
+ priv->gpio.set = mcp25xxfd_gpio_set;
+ priv->gpio.request = mcp25xxfd_gpio_request;
+ priv->gpio.free = mcp25xxfd_gpio_free;
+ priv->gpio.base = -1;
+ priv->gpio.ngpio = 2;
+ priv->gpio.can_sleep = 1;
+
+ return devm_gpiochip_add_data(&spi->dev, &priv->gpio, priv);
+}
+
+#else
+
+static int mcp25xxfd_gpio_setup(struct spi_device *spi)
+{
+ return 0;
+}
+
+#endif
+
+/* ideally these would be defined in uapi/linux/can.h */
+#define CAN_EFF_SID_SHIFT (CAN_EFF_ID_BITS - CAN_SFF_ID_BITS)
+#define CAN_EFF_SID_BITS CAN_SFF_ID_BITS
+#define CAN_EFF_SID_MASK \
+ GENMASK(CAN_EFF_SID_SHIFT + CAN_EFF_SID_BITS - 1, \
+ CAN_EFF_SID_SHIFT)
+#define CAN_EFF_EID_SHIFT 0
+#define CAN_EFF_EID_BITS CAN_EFF_SID_SHIFT
+#define CAN_EFF_EID_MASK \
+ GENMASK(CAN_EFF_EID_SHIFT + CAN_EFF_EID_BITS - 1, \
+ CAN_EFF_EID_SHIFT)
+
+static void mcp25xxfd_canid_to_mcpid(u32 can_id, u32 *id, u32 *flags)
+{
+ if (can_id & CAN_EFF_FLAG) {
+ int sid = (can_id & CAN_EFF_SID_MASK) >> CAN_EFF_SID_SHIFT;
+ int eid = (can_id & CAN_EFF_EID_MASK) >> CAN_EFF_EID_SHIFT;
+ *id = (eid << CAN_OBJ_ID_EID_SHIFT) |
+ (sid << CAN_OBJ_ID_SID_SHIFT);
+ *flags = CAN_OBJ_FLAGS_IDE;
+ } else {
+ *id = can_id & CAN_SFF_MASK;
+ *flags = 0;
+ }
+
+ *flags |= (can_id & CAN_RTR_FLAG) ? CAN_OBJ_FLAGS_RTR : 0;
+}
+
+static void mcp25xxfd_mcpid_to_canid(u32 mcpid, u32 mcpflags, u32 *id)
+{
+ u32 sid = (mcpid & CAN_OBJ_ID_SID_MASK) >> CAN_OBJ_ID_SID_SHIFT;
+ u32 eid = (mcpid & CAN_OBJ_ID_EID_MASK) >> CAN_OBJ_ID_EID_SHIFT;
+
+ if (mcpflags & CAN_OBJ_FLAGS_IDE) {
+ *id = (eid << CAN_EFF_EID_SHIFT) |
+ (sid << CAN_EFF_SID_SHIFT) |
+ CAN_EFF_FLAG;
+ } else {
+ *id = sid;
+ }
+
+ *id |= (mcpflags & CAN_OBJ_FLAGS_RTR) ? CAN_RTR_FLAG : 0;
+}
+
+static void __mcp25xxfd_stop_queue(struct net_device *net,
+ unsigned int id)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+
+ if (priv->tx_queue_status >= TX_QUEUE_STATUS_STOPPED)
+ dev_warn(&priv->spi->dev,
+ "tx-queue is already stopped by: %i\n",
+ priv->tx_queue_status);
+
+ priv->tx_queue_status = id ? id : TX_QUEUE_STATUS_STOPPED;
+ netif_stop_queue(priv->net);
+}
+
+/* helper to identify who is stopping the queue by line number */
+#define mcp25xxfd_stop_queue(spi) \
+ __mcp25xxfd_stop_queue(spi, __LINE__)
+
+static void mcp25xxfd_wake_queue(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* nothing should be left pending /in flight now... */
+ priv->fifos.tx_pending_mask = 0;
+ priv->fifos.tx_submitted_mask = 0;
+ priv->fifos.tx_processed_mask = 0;
+ priv->tx_queue_status = TX_QUEUE_STATUS_RUNNING;
+
+ /* wake queue now */
+ netif_wake_queue(priv->net);
+}
+
+/* CAN transmit related*/
+
+static void mcp25xxfd_mark_tx_pending(void *context)
+{
+ struct mcp25xxfd_trigger_tx_message *txm = context;
+ struct spi_device *spi = txm->msg.spi;
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* only here or in the irq handler this value is changed,
+ * so there is no race condition and it does not require locking
+ * serialization happens via spi_pump_message
+ */
+ priv->fifos.tx_pending_mask |= BIT(txm->fifo);
+}
+
+static int mcp25xxfd_fill_spi_transmit_fifos(struct mcp25xxfd_priv *priv)
+{
+ struct mcp25xxfd_trigger_tx_message *txm;
+ int i, fifo;
+ const u32 trigger = CAN_FIFOCON_TXREQ | CAN_FIFOCON_UINC;
+ const int first_byte = mcp25xxfd_first_byte(trigger);
+ u32 fifo_address;
+
+ priv->spi_transmit_fifos = kcalloc(priv->fifos.tx_fifos,
+ sizeof(*priv->spi_transmit_fifos),
+ GFP_KERNEL | GFP_DMA);
+ if (!priv->spi_transmit_fifos)
+ return -ENOMEM;
+
+ for (i = 0; i < priv->fifos.tx_fifos; i++) {
+ fifo = priv->fifos.tx_fifo_start + i;
+ txm = &priv->spi_transmit_fifos[i];
+ fifo_address = priv->fifos.fifo_address[fifo];
+ /* prepare the message */
+ spi_message_init(&txm->msg);
+ txm->msg.complete = mcp25xxfd_mark_tx_pending;
+ txm->msg.context = txm;
+ txm->fifo = fifo;
+ /* the payload itself */
+ txm->fill_xfer.speed_hz = priv->spi_speed_hz;
+ txm->fill_xfer.tx_buf = txm->fill_cmd;
+ txm->fill_xfer.len = 2;
+ txm->fill_xfer.cs_change = true;
+ mcp25xxfd_calc_cmd_addr(INSTRUCTION_WRITE,
+ FIFO_DATA(fifo_address),
+ txm->fill_cmd);
+ spi_message_add_tail(&txm->fill_xfer, &txm->msg);
+ /* the trigger command */
+ txm->trigger_xfer.speed_hz = priv->spi_speed_hz;
+ txm->trigger_xfer.tx_buf = txm->trigger_cmd;
+ txm->trigger_xfer.len = 3;
+ mcp25xxfd_calc_cmd_addr(INSTRUCTION_WRITE,
+ CAN_FIFOCON(fifo) + first_byte,
+ txm->trigger_cmd);
+ txm->trigger_data = trigger >> (8 * first_byte);
+ spi_message_add_tail(&txm->trigger_xfer, &txm->msg);
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_transmit_message_common(struct spi_device *spi,
+ int fifo,
+ struct mcp25xxfd_obj_tx *obj,
+ int len,
+ u8 *data)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_trigger_tx_message *txm =
+ &priv->spi_transmit_fifos[fifo - priv->fifos.tx_fifo_start];
+ int ret;
+
+ /* add fifo as seq */
+ obj->header.flags |= fifo << CAN_OBJ_FLAGS_SEQ_SHIFT;
+
+ /* transform to le32 */
+ mcp25xxfd_obj_to_le(&obj->header);
+
+ /* fill in details */
+ memcpy(txm->fill_obj, obj, sizeof(struct mcp25xxfd_obj_tx));
+ memset(txm->fill_data, 0, priv->fifos.payload_size);
+ memcpy(txm->fill_data, data, len);
+
+ /* transfers to FIFO RAM has to be multiple of 4 */
+ txm->fill_xfer.len =
+ 2 + sizeof(struct mcp25xxfd_obj_tx) + ALIGN(len, 4);
+
+ /* and transmit asyncroniously */
+ ret = spi_async(spi, &txm->msg);
+ if (ret)
+ return NETDEV_TX_BUSY;
+
+ return NETDEV_TX_OK;
+}
+
+static int mcp25xxfd_transmit_fdmessage(struct spi_device *spi, int fifo,
+ struct canfd_frame *frame)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_obj_tx obj;
+ int dlc = can_len2dlc(frame->len);
+ u32 flags;
+
+ frame->len = can_dlc2len(dlc);
+
+ mcp25xxfd_canid_to_mcpid(frame->can_id, &obj.header.id, &flags);
+
+ flags |= dlc << CAN_OBJ_FLAGS_DLC_SHIFT;
+ flags |= (frame->can_id & CAN_EFF_FLAG) ? CAN_OBJ_FLAGS_IDE : 0;
+ flags |= (frame->can_id & CAN_RTR_FLAG) ? CAN_OBJ_FLAGS_RTR : 0;
+ if (frame->flags & CANFD_BRS) {
+ flags |= CAN_OBJ_FLAGS_BRS;
+ priv->stats.tx_brs_count++;
+ }
+ flags |= (frame->flags & CANFD_ESI) ? CAN_OBJ_FLAGS_ESI : 0;
+ flags |= CAN_OBJ_FLAGS_FDF;
+
+ priv->stats.tx_fd_count++;
+ priv->stats.tx_dlc_usage[dlc]++;
+
+ obj.header.flags = flags;
+
+ return mcp25xxfd_transmit_message_common(spi, fifo, &obj,
+ frame->len, frame->data);
+}
+
+static int mcp25xxfd_transmit_message(struct spi_device *spi, int fifo,
+ struct can_frame *frame)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_obj_tx obj;
+ u32 flags;
+
+ if (frame->can_dlc > 8)
+ frame->can_dlc = 8;
+
+ priv->stats.tx_dlc_usage[frame->can_dlc]++;
+
+ mcp25xxfd_canid_to_mcpid(frame->can_id, &obj.header.id, &flags);
+
+ flags |= frame->can_dlc << CAN_OBJ_FLAGS_DLC_SHIFT;
+ flags |= (frame->can_id & CAN_EFF_FLAG) ? CAN_OBJ_FLAGS_IDE : 0;
+ flags |= (frame->can_id & CAN_RTR_FLAG) ? CAN_OBJ_FLAGS_RTR : 0;
+
+ obj.header.flags = flags;
+
+ return mcp25xxfd_transmit_message_common(spi, fifo, &obj,
+ frame->can_dlc, frame->data);
+}
+
+static bool mcp25xxfd_is_last_txfifo(struct spi_device *spi,
+ int fifo)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ return (fifo ==
+ (priv->fifos.tx_fifo_start + priv->fifos.tx_fifos - 1));
+}
+
+static netdev_tx_t mcp25xxfd_start_xmit(struct sk_buff *skb,
+ struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ struct spi_device *spi = priv->spi;
+ u32 pending_mask;
+ int fifo;
+ int ret;
+
+ if (can_dropped_invalid_skb(net, skb))
+ return NETDEV_TX_OK;
+
+ if (priv->can.state == CAN_STATE_BUS_OFF) {
+ mcp25xxfd_stop_queue(priv->net);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* get effective mask */
+ pending_mask = priv->fifos.tx_pending_mask |
+ priv->fifos.tx_submitted_mask;
+
+ /* decide on fifo to assign */
+ if (pending_mask)
+ fifo = fls(pending_mask);
+ else
+ fifo = priv->fifos.tx_fifo_start;
+
+ /* handle error - this should not happen... */
+ if (fifo >= priv->fifos.tx_fifo_start + priv->fifos.tx_fifos) {
+ dev_err(&spi->dev,
+ "reached tx-fifo %i, which is not valid\n",
+ fifo);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* if we are the last one, then stop the queue */
+ if (mcp25xxfd_is_last_txfifo(spi, fifo))
+ mcp25xxfd_stop_queue(priv->net);
+
+ /* mark as submitted */
+ priv->fifos.tx_submitted_mask |= BIT(fifo);
+ priv->stats.fifo_usage[fifo]++;
+
+ /* now process it for real */
+ if (can_is_canfd_skb(skb))
+ ret = mcp25xxfd_transmit_fdmessage(spi, fifo,
+ (struct canfd_frame *)
+ skb->data);
+ else
+ ret = mcp25xxfd_transmit_message(spi, fifo,
+ (struct can_frame *)
+ skb->data);
+
+ /* keep it for reference until the message really got transmitted */
+ if (ret == NETDEV_TX_OK)
+ can_put_echo_skb(skb, priv->net, fifo);
+
+ return ret;
+}
+
+/* CAN RX Related */
+
+static int mcp25xxfd_can_transform_rx_fd(struct spi_device *spi,
+ struct mcp25xxfd_obj_rx *rx)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct canfd_frame *frame;
+ struct sk_buff *skb;
+ u32 flags = rx->header.flags;
+ int dlc;
+
+ /* allocate the skb buffer */
+ skb = alloc_canfd_skb(priv->net, &frame);
+ if (!skb) {
+ dev_err(&spi->dev, "cannot allocate RX skb\n");
+ priv->net->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ mcp25xxfd_mcpid_to_canid(rx->header.id, flags, &frame->can_id);
+ frame->flags |= (flags & CAN_OBJ_FLAGS_BRS) ? CANFD_BRS : 0;
+ frame->flags |= (flags & CAN_OBJ_FLAGS_ESI) ? CANFD_ESI : 0;
+
+ dlc = (flags & CAN_OBJ_FLAGS_DLC_MASK) >> CAN_OBJ_FLAGS_DLC_SHIFT;
+ frame->len = can_dlc2len(dlc);
+
+ memcpy(frame->data, rx->data, frame->len);
+
+ priv->stats.rx_fd_count++;
+ priv->net->stats.rx_packets++;
+ priv->net->stats.rx_bytes += frame->len;
+ if (rx->header.flags & CAN_OBJ_FLAGS_BRS)
+ priv->stats.rx_brs_count++;
+ priv->stats.rx_dlc_usage[dlc]++;
+
+ can_led_event(priv->net, CAN_LED_EVENT_RX);
+
+ netif_rx_ni(skb);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_transform_rx_normal(struct spi_device *spi,
+ struct mcp25xxfd_obj_rx *rx)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct sk_buff *skb;
+ struct can_frame *frame;
+ u32 flags = rx->header.flags;
+ int len;
+ int dlc;
+
+ /* allocate the skb buffer */
+ skb = alloc_can_skb(priv->net, &frame);
+ if (!skb) {
+ dev_err(&spi->dev, "cannot allocate RX skb\n");
+ priv->net->stats.rx_dropped++;
+ return -ENOMEM;
+ }
+
+ mcp25xxfd_mcpid_to_canid(rx->header.id, flags, &frame->can_id);
+
+ dlc = (flags & CAN_OBJ_FLAGS_DLC_MASK) >> CAN_OBJ_FLAGS_DLC_SHIFT;
+ frame->can_dlc = dlc;
+
+ len = can_dlc2len(frame->can_dlc);
+
+ memcpy(frame->data, rx->data, len);
+
+ priv->net->stats.rx_packets++;
+ priv->net->stats.rx_bytes += len;
+ priv->stats.rx_dlc_usage[dlc]++;
+
+ can_led_event(priv->net, CAN_LED_EVENT_RX);
+
+ netif_rx_ni(skb);
+
+ return 0;
+}
+
+static int mcp25xxfd_process_queued_rx(struct spi_device *spi,
+ struct mcp25xxfd_obj_ts *obj)
+{
+ struct mcp25xxfd_obj_rx *rx = container_of(obj,
+ struct mcp25xxfd_obj_rx,
+ header);
+
+ if (obj->flags & CAN_OBJ_FLAGS_FDF)
+ return mcp25xxfd_can_transform_rx_fd(spi, rx);
+ else
+ return mcp25xxfd_can_transform_rx_normal(spi, rx);
+}
+
+static int mcp25xxfd_normal_release_fifos(struct spi_device *spi,
+ int start, int end)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int ret;
+
+ /* release each fifo in a separate transfer */
+ for (; start < end ; start++) {
+ ret = mcp25xxfd_cmd_write_mask(spi, CAN_FIFOCON(start),
+ CAN_FIFOCON_UINC,
+ CAN_FIFOCON_UINC,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* unfortunately the CAN_FIFOCON are not directly consecutive
+ * so the optimization of "clearing all in one spi_transfer"
+ * would produce an overhead of 11 unnecessary bytes/fifo
+ * - transferring 14 (2 cmd + 12 data) bytes
+ * instead of just 3 (2 + 1).
+ * On some slower systems this may still be beneficial,
+ * but it is not good enough for the generic case.
+ * On a Raspberry Pi CM the timings for clearing 3 fifos
+ * (at 12.5MHz SPI clock speed) are:
+ * * normal:
+ * * 3 spi transfers
+ * * 9 bytes total
+ * * 36.74us from first CS low to last CS high
+ * * individual CS: 9.14us, 5.74us and 5.16us
+ * * 77.02us from CS up of fifo transfer to last release CS up
+ * * bulk:
+ * * 1 spi transfer
+ * * 27 bytes total
+ * * 29.06us CS Low
+ * * 78.28us from CS up of fifo transfer to last release CS up
+ * this obviously varies with SPI_clock speed
+ * - the slower the clock the less efficient the optimization.
+ * similarly the faster the CPU (and bigger the code cache) the
+ * less effcient the optimization - the above case is border line.
+ */
+
+#define FIFOCON_SPACING (CAN_FIFOCON(1) - CAN_FIFOCON(0))
+#define FIFOCON_SPACINGW (FIFOCON_SPACING / sizeof(u32))
+
+static int mcp25xxfd_bulk_release_fifos(struct spi_device *spi,
+ int start, int end)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int i;
+ int ret;
+
+ /* calculate start address and length */
+ int fifos = end - start;
+ int first_byte = mcp25xxfd_first_byte(CAN_FIFOCON_UINC);
+ int addr = CAN_FIFOCON(start);
+ int len = 1 + (fifos - 1) * FIFOCON_SPACING;
+
+ /* the worsted case buffer */
+ u32 buf[32 * FIFOCON_SPACINGW], base;
+
+ base = (priv->fifos.payload_mode << CAN_FIFOCON_PLSIZE_SHIFT) |
+ ((priv->fifos.rx_fifo_depth - 1) << CAN_FIFOCON_FSIZE_SHIFT) |
+ CAN_FIFOCON_RXTSEN | /* RX timestamps */
+ CAN_FIFOCON_UINC |
+ CAN_FIFOCON_TFERFFIE | /* FIFO Full */
+ CAN_FIFOCON_TFHRFHIE | /* FIFO Half Full*/
+ CAN_FIFOCON_TFNRFNIE; /* FIFO not empty */
+
+ memset(buf, 0, sizeof(buf));
+ for (i = 0; i < end - start ; i++) {
+ if (i == priv->fifos.rx_fifos - 1)
+ base |= CAN_FIFOCON_RXOVIE;
+ buf[FIFOCON_SPACINGW * i] = cpu_to_le32(base);
+ }
+
+ ret = mcp25xxfd_cmd_writen(spi, addr + first_byte,
+ (u8 *)buf + first_byte,
+ len,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+/* queued FIFO handling for release to system */
+
+static void mcp25xxfd_clear_queued_fifos(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* prepare rfi - mostly used for sorting */
+ priv->queued_fifos.rx_count = 0;
+}
+
+static void mcp25xxfd_addto_queued_fifos(struct spi_device *spi,
+ struct mcp25xxfd_obj_ts *obj)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_read_fifo_info *rfi = &priv->queued_fifos;
+
+ /* timestamps must ignore the highest byte, so we shift it,
+ * so that it still compares correctly
+ */
+ obj->ts <<= 8;
+
+ /* add pointer to queued array-list */
+ rfi->rxb[rfi->rx_count] = obj;
+ rfi->rx_count++;
+}
+
+static int mcp25xxfd_process_queued_tef(struct spi_device *spi,
+ struct mcp25xxfd_obj_ts *obj)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_obj_tef *tef = container_of(obj,
+ struct mcp25xxfd_obj_tef,
+ header);
+ int dlc = (obj->flags & CAN_OBJ_FLAGS_DLC_MASK)
+ >> CAN_OBJ_FLAGS_DLC_SHIFT;
+ int fifo = (tef->header.flags & CAN_OBJ_FLAGS_SEQ_MASK) >>
+ CAN_OBJ_FLAGS_SEQ_SHIFT;
+
+ /* update counters */
+ priv->net->stats.tx_packets++;
+ priv->net->stats.tx_bytes += can_dlc2len(dlc);
+ if (obj->flags & CAN_OBJ_FLAGS_FDF)
+ priv->stats.tx_fd_count++;
+ if (obj->flags & CAN_OBJ_FLAGS_BRS)
+ priv->stats.tx_brs_count++;
+ priv->stats.tx_dlc_usage[dlc]++;
+
+ /* release it */
+ can_get_echo_skb(priv->net, fifo);
+
+ can_led_event(priv->net, CAN_LED_EVENT_TX);
+
+ return 0;
+}
+
+static int mcp25xxfd_compare_obj_ts(const void *a, const void *b)
+{
+ const struct mcp25xxfd_obj_ts * const *rxa = a;
+ const struct mcp25xxfd_obj_ts * const *rxb = b;
+ /* using signed here to handle rollover correctly */
+ s32 ats = (*rxa)->ts;
+ s32 bts = (*rxb)->ts;
+
+ if (ats < bts)
+ return -EINVAL;
+ if (ats > bts)
+ return 1;
+ return 0;
+}
+
+static int mcp25xxfd_process_queued_fifos(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_read_fifo_info *rfi = &priv->queued_fifos;
+ int i;
+ int ret;
+
+ /* sort the fifos (rx and TEF) by receive timestamp */
+ sort(rfi->rxb, rfi->rx_count, sizeof(struct mcp25xxfd_obj_ts *),
+ mcp25xxfd_compare_obj_ts, NULL);
+
+ /* process the recived fifos */
+ for (i = 0; i < rfi->rx_count ; i++) {
+ if (rfi->rxb[i]->flags & CAN_OBJ_FLAGS_CUSTOM_ISTEF)
+ ret = mcp25xxfd_process_queued_tef(spi, rfi->rxb[i]);
+ else
+ ret = mcp25xxfd_process_queued_rx(spi, rfi->rxb[i]);
+ if (ret)
+ return ret;
+ }
+
+ /* clear queued fifos */
+ mcp25xxfd_clear_queued_fifos(spi);
+
+ return 0;
+}
+
+static int mcp25xxfd_transform_rx(struct spi_device *spi,
+ struct mcp25xxfd_obj_rx *rx)
+{
+ int dlc;
+
+ /* transform the data to system byte order */
+ mcp25xxfd_obj_ts_from_le(&rx->header);
+
+ /* add the object to the list */
+ mcp25xxfd_addto_queued_fifos(spi, &rx->header);
+
+ /* calc length and return it */
+ dlc = (rx->header.flags & CAN_OBJ_FLAGS_DLC_MASK)
+ >> CAN_OBJ_FLAGS_DLC_SHIFT;
+ return can_dlc2len(dlc);
+}
+
+/* read_fifo implementations
+ *
+ * read_fifos is a simple implementation, that:
+ * * loops all fifos
+ * * read header + some data-bytes (8)
+ * * read rest of data-bytes bytes
+ * * release fifo
+ * for 3 can frames dlc<=8 to read here we have:
+ * * 6 spi transfers
+ * * 75 bytes (= 3 * (2 + 12 + 8) bytes + 3 * 3 bytes)
+ * for 3 canfd frames dlc>8 to read here we have:
+ * * 9 spi transfers
+ * * 81 (= 3 * (2 + 12 + 8 + 2) bytes + 3 * 3 bytes) + 3 * extra payload
+ * this only transfers the required size of bytes on the spi bus.
+ *
+ * bulk_read_fifos is an optimization that is most practical for
+ * Can2.0 busses, but may also be practical for CanFD busses that
+ * have a high average payload data size.
+ *
+ * It will read all of the fifo data in a single spi_transfer:
+ * * read all fifos in one go (as long as these are ajacent to each other)
+ * * loop all fifos
+ * * release fifo
+ * for 3 can2.0 frames to read here we have:
+ * * 4 spi transfers
+ * * 71 bytes (= 2 + 3 * (12 + 8) bytes + 3 * 3 bytes)
+ * for 3 canfd frames to read here we have:
+ * * 4 spi transfers
+ * * 230 bytes (= 2 + 3 * (12 + 64) bytes)
+ * obviously this reads way too many bytes for framesizes <=32 bytes,
+ * but it avoids the overhead on the CPU side and may even trigger
+ * DMA transfers due to the high byte count, which release CPU cycles.
+ *
+ * This optimization will also be efficient for cases where a high
+ * percentage of canFD frames has a dlc-size > 8.
+ * This mode is used for Can2.0 configured busses.
+ *
+ * For now this option can get forced for CanFD via a module parameter.
+ * In the future there may be some heuristics that could trigger a usage
+ * of this mode as well in some circumstances.
+ *
+ * Note: there is a second optimization for release fifo as well,
+ * but it is not as efficient as this optimization for the
+ * non-CanFD case - see mcp25xxfd_bulk_release_fifos
+ */
+
+static int mcp25xxfd_read_fifos(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int fifo_header_size = sizeof(struct mcp25xxfd_obj_rx);
+ int fifo_min_payload_size = 8;
+ int fifo_min_size = fifo_header_size + fifo_min_payload_size;
+ int fifo_max_payload_size =
+ ((priv->can.ctrlmode & CAN_CTRLMODE_FD) ? 64 : 8);
+ u32 mask = priv->status.rxif;
+ struct mcp25xxfd_obj_rx *rx;
+ int i, len;
+ int ret;
+ u32 fifo_address;
+ u8 *data;
+
+ /* read all the "open" segments in big chunks */
+ for (i = priv->fifos.rx_fifo_start + priv->fifos.rx_fifos - 1;
+ i >= priv->fifos.rx_fifo_start;
+ i--) {
+ if (!(mask & BIT(i)))
+ continue;
+ /* the fifo to fill */
+ rx = (struct mcp25xxfd_obj_rx *)
+ (priv->fifos.fifo_data + priv->fifos.fifo_address[i]);
+ /* read the minimal payload */
+ fifo_address = priv->fifos.fifo_address[i];
+ ret = mcp25xxfd_cmd_readn(spi,
+ FIFO_DATA(fifo_address),
+ rx,
+ fifo_min_size,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+ /* process fifo stats and get length */
+ len = min_t(int, mcp25xxfd_transform_rx(spi, rx),
+ fifo_max_payload_size);
+
+ /* read extra payload if needed */
+ if (len > fifo_min_payload_size) {
+ data = &rx->data[fifo_min_payload_size];
+ ret = mcp25xxfd_cmd_readn(spi,
+ FIFO_DATA(fifo_address +
+ fifo_min_size),
+ data,
+ len - fifo_min_payload_size,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+ }
+ /* release fifo */
+ ret = mcp25xxfd_normal_release_fifos(spi, i, i + 1);
+ if (ret)
+ return ret;
+ /* increment fifo_usage */
+ priv->stats.fifo_usage[i]++;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_bulk_read_fifo_range(struct spi_device *spi,
+ int start, int end)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ const int fifo_header_size = sizeof(struct mcp25xxfd_obj_rx);
+ const int fifo_max_payload_size = priv->fifos.payload_size;
+ const int fifo_max_size = fifo_header_size + fifo_max_payload_size;
+ struct mcp25xxfd_obj_rx *rx;
+ int i;
+ int ret;
+
+ /* now we got start and end, so read the range */
+ ret = mcp25xxfd_cmd_readn(spi,
+ FIFO_DATA(priv->fifos.fifo_address[start]),
+ priv->fifos.fifo_data +
+ priv->fifos.fifo_address[start],
+ (end - start) * fifo_max_size,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ /* clear all the fifos in range */
+ if (use_bulk_release_fifos)
+ ret = mcp25xxfd_bulk_release_fifos(spi, start, end);
+ else
+ ret = mcp25xxfd_normal_release_fifos(spi, start, end);
+ if (ret)
+ return ret;
+
+ /* preprocess data */
+ for (i = start; i < end ; i++) {
+ /* store the fifo to process */
+ rx = (struct mcp25xxfd_obj_rx *)
+ (priv->fifos.fifo_data + priv->fifos.fifo_address[i]);
+ /* process fifo stats */
+ mcp25xxfd_transform_rx(spi, rx);
+ /* increment usage */
+ priv->stats.fifo_usage[i]++;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_bulk_read_fifos(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 mask = priv->status.rxif;
+ int i, start, end;
+ int ret;
+
+ /* find blocks of set bits top down */
+ for (i = priv->fifos.rx_fifo_start + priv->fifos.rx_fifos - 1;
+ mask && (i >= priv->fifos.rx_fifo_start);
+ i--) {
+ /* if the bit is 0 then continue loop to find a 1 */
+ if ((mask & BIT(i)) == 0)
+ continue;
+
+ /* so we found a non-0 bit - this is start and end */
+ start = i;
+ end = i;
+
+ /* find the first bit set */
+ for (; mask & BIT(i); i--) {
+ mask &= ~BIT(i);
+ start = i;
+ }
+
+ /* now process that range */
+ ret = mcp25xxfd_bulk_read_fifo_range(spi, start, end + 1);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_rxif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 mask = priv->status.rxif;
+ int ret;
+
+ if (!mask)
+ return 0;
+
+ /* read all the fifos - for non-fd case use bulk read optimization */
+ if (((priv->can.ctrlmode & CAN_CTRLMODE_FD) == 0) ||
+ use_complete_fdfifo_read)
+ ret = mcp25xxfd_bulk_read_fifos(spi);
+ else
+ ret = mcp25xxfd_read_fifos(spi);
+
+ return 0;
+}
+
+static void mcp25xxfd_mark_tx_processed(struct spi_device *spi,
+ int fifo)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* set mask */
+ priv->fifos.tx_processed_mask |= BIT(fifo);
+
+ /* check if we should reenable the TX-queue */
+ if (mcp25xxfd_is_last_txfifo(spi, fifo))
+ priv->tx_queue_status = TX_QUEUE_STATUS_NEEDS_START;
+}
+
+static int mcp25xxfd_can_ist_handle_tefif_handle_single(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct mcp25xxfd_obj_tef *tef;
+ int fifo;
+ int ret;
+
+ /* calc address in address space */
+ tef = (struct mcp25xxfd_obj_tef *)(priv->fifos.fifo_data +
+ priv->fifos.tef_address);
+
+ /* read all the object data */
+ ret = mcp25xxfd_cmd_readn(spi,
+ FIFO_DATA(priv->fifos.tef_address),
+ tef,
+ /* we do not read the last byte of the ts
+ * to avoid MAB issiues
+ */
+ sizeof(*tef) - 1,
+ priv->spi_speed_hz);
+ /* increment the counter to read next */
+ ret = mcp25xxfd_cmd_write_mask(spi,
+ CAN_TEFCON,
+ CAN_TEFCON_UINC,
+ CAN_TEFCON_UINC,
+ priv->spi_speed_hz);
+
+ /* transform the data to system byte order */
+ mcp25xxfd_obj_ts_from_le(&tef->header);
+
+ fifo = (tef->header.flags & CAN_OBJ_FLAGS_SEQ_MASK) >>
+ CAN_OBJ_FLAGS_SEQ_SHIFT;
+
+ /* submit to queue */
+ tef->header.flags |= CAN_OBJ_FLAGS_CUSTOM_ISTEF;
+ mcp25xxfd_addto_queued_fifos(spi, &tef->header);
+
+ /* increment tef_address with rollover */
+ priv->fifos.tef_address += sizeof(*tef);
+ if (priv->fifos.tef_address > priv->fifos.tef_address_end)
+ priv->fifos.tef_address =
+ priv->fifos.tef_address_start;
+
+ /* and mark as processed right now */
+ mcp25xxfd_mark_tx_processed(spi, fifo);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_tefif_conservative(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 val[2];
+ int ret;
+
+ while (1) {
+ /* get the current TEFSTA and TEFUA */
+ ret = mcp25xxfd_cmd_readn(priv->spi,
+ CAN_TEFSTA,
+ val,
+ 8,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+ mcp25xxfd_convert_to_cpu(val, 2);
+
+ /* check for interrupt flags */
+ if (!(val[0] & CAN_TEFSTA_TEFNEIF))
+ return 0;
+
+ if (priv->fifos.tef_address != val[1]) {
+ dev_err(&spi->dev,
+ "TEF Address mismatch - read: %04x calculated: %04x\n",
+ val[1], priv->fifos.tef_address);
+ priv->fifos.tef_address = val[1];
+ }
+
+ ret = mcp25xxfd_can_ist_handle_tefif_handle_single(spi);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_tefif_count(struct spi_device *spi,
+ int count)
+{
+ int i;
+ int ret;
+
+ /* now clear TEF for each */
+ /* TODO: optimize for BULK reads, as we (hopefully) know COUNT */
+ for (i = 0; i < count; i++) {
+ /* handle a single TEF */
+ ret = mcp25xxfd_can_ist_handle_tefif_handle_single(spi);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_tefif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 pending = priv->fifos.tx_pending_mask_in_irq &
+ (~priv->fifos.tx_processed_mask);
+ int count;
+
+ /* calculate the number of fifos that have been processed */
+ count = hweight_long(pending);
+ count -= hweight_long(priv->status.txreq & pending);
+
+ /* in case of unexpected results handle "safely" */
+ if (count <= 0)
+ return mcp25xxfd_can_ist_handle_tefif_conservative(spi);
+
+ return mcp25xxfd_can_ist_handle_tefif_count(spi, count);
+}
+
+static int mcp25xxfd_can_ist_handle_txatif_fifo(struct spi_device *spi,
+ int fifo)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 val;
+ int ret;
+
+ /* read fifo status */
+ ret = mcp25xxfd_cmd_read(spi,
+ CAN_FIFOSTA(fifo),
+ &val,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ /* clear the relevant interrupt flags */
+ ret = mcp25xxfd_cmd_write_mask(spi,
+ CAN_FIFOSTA(fifo),
+ 0,
+ CAN_FIFOSTA_TXABT |
+ CAN_FIFOSTA_TXLARB |
+ CAN_FIFOSTA_TXERR |
+ CAN_FIFOSTA_TXATIF,
+ priv->spi_speed_hz);
+
+ /* for specific cases we could trigger a retransmit
+ * instead of an abort.
+ */
+
+ /* and we release it from the echo_skb buffer
+ * NOTE: this is one place where packet delivery will not
+ * be ordered, as we do not have any timing information
+ * when this occurred
+ */
+ can_get_echo_skb(priv->net, fifo);
+
+ /* but we need to run a bit of cleanup */
+ priv->status.txif &= ~BIT(fifo);
+ priv->net->stats.tx_aborted_errors++;
+
+ /* mark the fifo as processed */
+ mcp25xxfd_mark_tx_processed(spi, fifo);
+
+ /* handle all the known cases accordingly - ignoring FIFO full */
+ val &= CAN_FIFOSTA_TXABT |
+ CAN_FIFOSTA_TXLARB |
+ CAN_FIFOSTA_TXERR;
+ switch (val) {
+ case CAN_FIFOSTA_TXERR:
+ break;
+ default:
+ dev_warn_ratelimited(&spi->dev,
+ "Unknown TX-Fifo abort condition: %08x - stopping tx-queue\n",
+ val);
+ break;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_txatif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int i, fifo;
+ int ret;
+
+ /* process all the fifos with that flag set */
+ for (i = 0, fifo = priv->fifos.tx_fifo_start;
+ i < priv->fifos.tx_fifos; i++, fifo++) {
+ if (priv->status.txatif & BIT(fifo)) {
+ ret = mcp25xxfd_can_ist_handle_txatif_fifo(spi, fifo);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static void mcp25xxfd_error_skb(struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ struct sk_buff *skb;
+ struct can_frame *frame;
+
+ skb = alloc_can_err_skb(net, &frame);
+ if (skb) {
+ frame->can_id = priv->can_err_id;
+ memcpy(frame->data, priv->can_err_data, 8);
+ netif_rx_ni(skb);
+ } else {
+ netdev_err(net, "cannot allocate error skb\n");
+ }
+}
+
+static int mcp25xxfd_can_ist_handle_rxovif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 mask = priv->status.rxovif;
+ int i;
+ int ret;
+
+ /* clear all fifos that have an overflow bit set */
+ for (i = 0; i < 32; i++) {
+ if (mask & BIT(i)) {
+ ret = mcp25xxfd_cmd_write_mask(spi,
+ CAN_FIFOSTA(i),
+ 0,
+ CAN_FIFOSTA_RXOVIF,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+ /* update statistics */
+ priv->net->stats.rx_over_errors++;
+ priv->net->stats.rx_errors++;
+ priv->stats.rx_overflow++;
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_modif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int omode = priv->active_can_mode;
+ int mode;
+ int ret;
+
+ /* Note that this irq does not get triggered in all situations
+ * for example SERRIF will move to RESTICTED or LISTENONLY
+ * but MODIF will not be raised!
+ */
+
+ /* get the mode */
+ ret = mcp25xxfd_get_opmode(spi, &mode, priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ /* if we are restricted, then return to "normal" mode */
+ if (mode == CAN_CON_MODE_RESTRICTED)
+ return mcp25xxfd_set_normal_opmode(spi);
+
+ /* the controller itself will transition to sleep, so we ignore it */
+ if (mode == CAN_CON_MODE_SLEEP)
+ return 0;
+
+ /* switches to the same mode as before are also ignored
+ * - this typically happens if the driver is shortly
+ * switching to a different mode and then returning to the
+ * original mode
+ */
+ if (mode == omode)
+ return 0;
+
+ /* these we need to handle correctly, so warn and give context */
+ dev_warn(&spi->dev,
+ "Controller unexpectedly switched from mode %s(%u) to %s(%u)\n",
+ mcp25xxfd_mode_names[omode], omode,
+ mcp25xxfd_mode_names[mode], mode);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_cerrif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* in principle we could also delay reading bdiag registers
+ * until we get here - it would add some extra delay in the
+ * error case, but be slightly faster in the "normal" case.
+ * slightly faster would be saving 8 bytes of spi transfer.
+ */
+
+ dev_err_ratelimited(&spi->dev, "CAN Bus error\n");
+ priv->can_err_id |= CAN_ERR_BUSERROR;
+
+ if (priv->status.bdiag1 &
+ (CAN_BDIAG1_DBIT0ERR | CAN_BDIAG1_NBIT0ERR)) {
+ priv->can_err_id |= CAN_ERR_BUSERROR;
+ priv->can_err_data[2] |= CAN_ERR_PROT_BIT0;
+ priv->bdiag1_clear_mask |= CAN_BDIAG1_DBIT0ERR |
+ CAN_BDIAG1_NBIT0ERR;
+ }
+ if (priv->status.bdiag1 &
+ (CAN_BDIAG1_DBIT1ERR | CAN_BDIAG1_NBIT1ERR)) {
+ priv->can_err_id |= CAN_ERR_BUSERROR;
+ priv->can_err_data[2] |= CAN_ERR_PROT_BIT1;
+ priv->bdiag1_clear_mask |= CAN_BDIAG1_DBIT1ERR |
+ CAN_BDIAG1_NBIT1ERR;
+ }
+ if (priv->status.bdiag1 &
+ (CAN_BDIAG1_DSTUFERR | CAN_BDIAG1_NSTUFERR)) {
+ priv->can_err_id |= CAN_ERR_BUSERROR;
+ priv->can_err_data[2] |= CAN_ERR_PROT_STUFF;
+ priv->bdiag1_clear_mask |= CAN_BDIAG1_DSTUFERR |
+ CAN_BDIAG1_NSTUFERR;
+ }
+ if (priv->status.bdiag1 &
+ (CAN_BDIAG1_DFORMERR | CAN_BDIAG1_NFORMERR)) {
+ priv->can_err_id |= CAN_ERR_BUSERROR;
+ priv->can_err_data[2] |= CAN_ERR_PROT_FORM;
+ priv->bdiag1_clear_mask |= CAN_BDIAG1_DFORMERR |
+ CAN_BDIAG1_NFORMERR;
+ }
+ if (priv->status.bdiag1 & CAN_BDIAG1_NACKERR) {
+ priv->can_err_id |= CAN_ERR_ACK;
+ priv->bdiag1_clear_mask |= CAN_BDIAG1_NACKERR;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_eccif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int ret;
+ u32 val;
+ u32 addr;
+
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_UNSPEC;
+
+ /* read ECC status register */
+ ret = mcp25xxfd_cmd_read(spi, MCP25XXFD_ECCSTAT, &val,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ addr = (val & MCP25XXFD_ECCSTAT_ERRADDR_MASK) >>
+ MCP25XXFD_ECCSTAT_ERRADDR_SHIFT;
+
+ dev_err_ratelimited(&spi->dev,
+ "ECC %s bit error at %03x\n",
+ (val & MCP25XXFD_ECCSTAT_DEDIF) ?
+ "double" : "single",
+ addr);
+
+ return mcp25xxfd_cmd_write(spi, MCP25XXFD_ECCSTAT, 0,
+ priv->spi_speed_hz);
+}
+
+static int mcp25xxfd_can_ist_handle_serrif_txmab(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ priv->net->stats.tx_fifo_errors++;
+ priv->net->stats.tx_errors++;
+ priv->stats.tx_mab++;
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_serrif_rxmab(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ priv->net->stats.rx_dropped++;
+ priv->net->stats.rx_errors++;
+ priv->stats.rx_mab++;
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_serrif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 clear;
+ int ret;
+
+ /* clear some interrupts immediately,
+ * so that we get notified if they happen again
+ */
+ clear = CAN_INT_SERRIF | CAN_INT_MODIF | CAN_INT_IVMIF;
+ ret = mcp25xxfd_cmd_write_mask(spi, CAN_INT,
+ priv->status.intf & (~clear),
+ clear,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ /* Errors here are:
+ * * Bus Bandwidth Error: when a RX Message Assembly Buffer
+ * is still full when the next message has already arrived
+ * the recived message shall be ignored
+ * * TX MAB Underflow: when a TX Message is invalid
+ * due to ECC errors or TXMAB underflow
+ * in this situatioon the system will transition to
+ * Restricted or Listen Only mode
+ */
+
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_UNSPEC;
+
+ /* a mode change + invalid message would indicate
+ * TX MAB Underflow
+ */
+ if ((priv->status.intf & CAN_INT_MODIF) &&
+ (priv->status.intf & CAN_INT_IVMIF)) {
+ return mcp25xxfd_can_ist_handle_serrif_txmab(spi);
+ }
+
+ /* for RX there is only the RXIF an indicator
+ * - surprizingly RX-MAB does not change mode or anything
+ */
+ if (priv->status.intf & CAN_INT_RXIF)
+ return mcp25xxfd_can_ist_handle_serrif_rxmab(spi);
+
+ /* the final case */
+ dev_warn_ratelimited(&spi->dev,
+ "unidentified system error - intf = %08x\n",
+ priv->status.intf);
+
+ return 0;
+}
+
+static int mcp25xxfd_can_ist_handle_ivmif(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* if we have a systemerror as well, then ignore it */
+ if (priv->status.intf & CAN_INT_SERRIF)
+ return 0;
+
+ /* otherwise it is an RX issue, so account for it here */
+ priv->can_err_id |= CAN_ERR_PROT;
+ priv->can_err_data[2] |= CAN_ERR_PROT_FORM;
+ priv->net->stats.rx_frame_errors++;
+ priv->net->stats.rx_errors++;
+
+ return 0;
+}
+
+static int mcp25xxfd_disable_interrupts(struct spi_device *spi,
+ u32 speed_hz)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ priv->status.intf = 0;
+ return mcp25xxfd_cmd_write(spi, CAN_INT, 0, speed_hz);
+}
+
+static int mcp25xxfd_enable_interrupts(struct spi_device *spi,
+ u32 speed_hz)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ priv->status.intf = CAN_INT_TEFIE |
+ CAN_INT_RXIE |
+ CAN_INT_MODIE |
+ CAN_INT_SERRIE |
+ CAN_INT_IVMIE |
+ CAN_INT_CERRIE |
+ CAN_INT_RXOVIE |
+ CAN_INT_ECCIE;
+ return mcp25xxfd_cmd_write(spi, CAN_INT,
+ priv->status.intf,
+ speed_hz);
+}
+
+static int mcp25xxfd_hw_wake(struct spi_device *spi)
+{
+ return mcp25xxfd_start_clock(spi, MCP25XXFD_CLK_USER_CAN);
+}
+
+static void mcp25xxfd_hw_sleep(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ /* disable interrupts */
+ mcp25xxfd_disable_interrupts(spi, priv->spi_setup_speed_hz);
+
+ /* stop the clocks */
+ mcp25xxfd_stop_clock(spi, MCP25XXFD_CLK_USER_CAN);
+}
+
+static int mcp25xxfd_can_ist_handle_status(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ const u32 clear_irq = CAN_INT_TBCIF |
+ CAN_INT_MODIF |
+ CAN_INT_SERRIF |
+ CAN_INT_CERRIF |
+ CAN_INT_WAKIF |
+ CAN_INT_IVMIF;
+ int ret;
+
+ /* clear all the interrupts asap */
+ ret = mcp25xxfd_cmd_write_mask(spi, CAN_INT,
+ priv->status.intf & (~clear_irq),
+ clear_irq,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ /* interrupt clearing info */
+ priv->bdiag1_clear_value = 0;
+ priv->bdiag1_clear_mask = 0;
+ priv->can_err_id = 0;
+ memset(priv->can_err_data, 0, 8);
+
+ /* state changes */
+ priv->new_state = priv->can.state;
+
+ /* clear queued fifos */
+ mcp25xxfd_clear_queued_fifos(spi);
+
+ /* system error interrupt needs to get handled first
+ * to get us out of restricted mode
+ */
+ if (priv->status.intf & CAN_INT_SERRIF) {
+ priv->stats.int_serr_count++;
+ ret = mcp25xxfd_can_ist_handle_serrif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* mode change interrupt */
+ if (priv->status.intf & CAN_INT_MODIF) {
+ priv->stats.int_mod_count++;
+ ret = mcp25xxfd_can_ist_handle_modif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* handle the rx */
+ if (priv->status.intf & CAN_INT_RXIF) {
+ priv->stats.int_rx_count++;
+ ret = mcp25xxfd_can_ist_handle_rxif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* handle aborted TX FIFOs */
+ if (priv->status.txatif) {
+ priv->stats.int_txat_count++;
+ ret = mcp25xxfd_can_ist_handle_txatif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* handle the tef */
+ if (priv->status.intf & CAN_INT_TEFIF) {
+ priv->stats.int_tef_count++;
+ ret = mcp25xxfd_can_ist_handle_tefif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* process the queued fifos */
+ ret = mcp25xxfd_process_queued_fifos(spi);
+
+ /* handle error interrupt flags */
+ if (priv->status.rxovif) {
+ priv->stats.int_rxov_count++;
+ ret = mcp25xxfd_can_ist_handle_rxovif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* sram ECC error interrupt */
+ if (priv->status.intf & CAN_INT_ECCIF) {
+ priv->stats.int_ecc_count++;
+ ret = mcp25xxfd_can_ist_handle_eccif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* message format interrupt */
+ if (priv->status.intf & CAN_INT_IVMIF) {
+ priv->stats.int_ivm_count++;
+ ret = mcp25xxfd_can_ist_handle_ivmif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* handle bus errors in more detail */
+ if (priv->status.intf & CAN_INT_CERRIF) {
+ priv->stats.int_cerr_count++;
+ ret = mcp25xxfd_can_ist_handle_cerrif(spi);
+ if (ret)
+ return ret;
+ }
+
+ /* Error counter handling */
+ if (priv->status.trec & CAN_TREC_TXWARN) {
+ priv->new_state = CAN_STATE_ERROR_WARNING;
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_TX_WARNING;
+ }
+ if (priv->status.trec & CAN_TREC_RXWARN) {
+ priv->new_state = CAN_STATE_ERROR_WARNING;
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_RX_WARNING;
+ }
+ if (priv->status.trec & CAN_TREC_TXBP) {
+ priv->new_state = CAN_STATE_ERROR_PASSIVE;
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+ }
+ if (priv->status.trec & CAN_TREC_RXBP) {
+ priv->new_state = CAN_STATE_ERROR_PASSIVE;
+ priv->can_err_id |= CAN_ERR_CRTL;
+ priv->can_err_data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+ }
+ if (priv->status.trec & CAN_TREC_TXBO) {
+ priv->new_state = CAN_STATE_BUS_OFF;
+ priv->can_err_id |= CAN_ERR_BUSOFF;
+ }
+
+ /* based on the last state state check the new state */
+ switch (priv->can.state) {
+ case CAN_STATE_ERROR_ACTIVE:
+ if (priv->new_state >= CAN_STATE_ERROR_WARNING &&
+ priv->new_state <= CAN_STATE_BUS_OFF)
+ priv->can.can_stats.error_warning++;
+ /* fallthrough */
+ case CAN_STATE_ERROR_WARNING:
+ if (priv->new_state >= CAN_STATE_ERROR_PASSIVE &&
+ priv->new_state <= CAN_STATE_BUS_OFF)
+ priv->can.can_stats.error_passive++;
+ break;
+ default:
+ break;
+ }
+ priv->can.state = priv->new_state;
+
+ /* and send error packet */
+ if (priv->can_err_id)
+ mcp25xxfd_error_skb(priv->net);
+
+ /* handle BUS OFF */
+ if (priv->can.state == CAN_STATE_BUS_OFF) {
+ if (priv->can.restart_ms == 0) {
+ mcp25xxfd_stop_queue(priv->net);
+ priv->force_quit = 1;
+ priv->can.can_stats.bus_off++;
+ can_bus_off(priv->net);
+ mcp25xxfd_hw_sleep(spi);
+ }
+ } else {
+ /* restart the tx queue if needed */
+ if (priv->fifos.tx_processed_mask == priv->fifos.tx_fifo_mask)
+ mcp25xxfd_wake_queue(spi);
+ }
+
+ /* clear bdiag flags */
+ if (priv->bdiag1_clear_mask) {
+ ret = mcp25xxfd_cmd_write_mask(spi,
+ CAN_BDIAG1,
+ priv->bdiag1_clear_value,
+ priv->bdiag1_clear_mask,
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static irqreturn_t mcp25xxfd_can_ist(int irq, void *dev_id)
+{
+ struct mcp25xxfd_priv *priv = dev_id;
+ struct spi_device *spi = priv->spi;
+ int ret;
+
+ priv->stats.irq_calls++;
+ priv->stats.irq_state = IRQ_STATE_RUNNING;
+
+ while (!priv->force_quit) {
+ /* count irq loops */
+ priv->stats.irq_loops++;
+
+ /* copy pending to in_irq - any
+ * updates that happen asyncronously
+ * are not taken into account here
+ */
+ priv->fifos.tx_pending_mask_in_irq =
+ priv->fifos.tx_pending_mask;
+
+ /* read interrupt status flags */
+ ret = mcp25xxfd_cmd_readn(spi, CAN_INT,
+ &priv->status,
+ sizeof(priv->status),
+ priv->spi_speed_hz);
+ if (ret)
+ return ret;
+
+ /* only act if the mask is applied */
+ if ((priv->status.intf &
+ (priv->status.intf >> CAN_INT_IE_SHIFT)) == 0)
+ break;
+
+ /* handle the status */
+ ret = mcp25xxfd_can_ist_handle_status(spi);
+ if (ret)
+ return ret;
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mcp25xxfd_get_berr_counter(const struct net_device *net,
+ struct can_berr_counter *bec)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+
+ bec->txerr = (priv->status.trec & CAN_TREC_TEC_MASK) >>
+ CAN_TREC_TEC_SHIFT;
+ bec->rxerr = (priv->status.trec & CAN_TREC_REC_MASK) >>
+ CAN_TREC_REC_SHIFT;
+
+ return 0;
+}
+
+static int mcp25xxfd_power_enable(struct regulator *reg, int enable)
+{
+ return 0;
+}
+
+static int mcp25xxfd_do_set_mode(struct net_device *net, enum can_mode mode)
+{
+ switch (mode) {
+ case CAN_MODE_START:
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int mcp25xxfd_do_set_nominal_bittiming(struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ struct spi_device *spi = priv->spi;
+
+ int sjw = bt->sjw;
+ int pseg2 = bt->phase_seg2;
+ int pseg1 = bt->phase_seg1;
+ int propseg = bt->prop_seg;
+ int brp = bt->brp;
+
+ int tseg1 = propseg + pseg1;
+ int tseg2 = pseg2;
+
+ /* calculate nominal bit timing */
+ priv->regs.nbtcfg = ((sjw - 1) << CAN_NBTCFG_SJW_SHIFT) |
+ ((tseg2 - 1) << CAN_NBTCFG_TSEG2_SHIFT) |
+ ((tseg1 - 1) << CAN_NBTCFG_TSEG1_SHIFT) |
+ ((brp - 1) << CAN_NBTCFG_BRP_SHIFT);
+
+ return mcp25xxfd_cmd_write(spi, CAN_NBTCFG,
+ priv->regs.nbtcfg,
+ priv->spi_setup_speed_hz);
+}
+
+static int mcp25xxfd_do_set_data_bittiming(struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ struct can_bittiming *bt = &priv->can.data_bittiming;
+ struct spi_device *spi = priv->spi;
+
+ int sjw = bt->sjw;
+ int pseg2 = bt->phase_seg2;
+ int pseg1 = bt->phase_seg1;
+ int propseg = bt->prop_seg;
+ int brp = bt->brp;
+
+ int tseg1 = propseg + pseg1;
+ int tseg2 = pseg2;
+
+ int ret;
+
+ /* set up Transmitter delay compensation */
+ if (!priv->regs.tdc)
+ priv->regs.tdc = CAN_TDC_EDGFLTEN |
+ (CAN_TDC_TDCMOD_AUTO << CAN_TDC_TDCMOD_SHIFT);
+ ret = mcp25xxfd_cmd_write(spi, CAN_TDC, priv->regs.tdc,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* calculate nominal bit timing */
+ priv->regs.dbtcfg = ((sjw - 1) << CAN_DBTCFG_SJW_SHIFT) |
+ ((tseg2 - 1) << CAN_DBTCFG_TSEG2_SHIFT) |
+ ((tseg1 - 1) << CAN_DBTCFG_TSEG1_SHIFT) |
+ ((brp - 1) << CAN_DBTCFG_BRP_SHIFT);
+
+ return mcp25xxfd_cmd_write(spi, CAN_DBTCFG,
+ priv->regs.dbtcfg,
+ priv->spi_setup_speed_hz);
+}
+
+static int mcp25xxfd_hw_probe(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int ret;
+
+ /* Wait for oscillator startup timer after power up */
+ msleep(MCP25XXFD_OST_DELAY_MS);
+
+ /* send a "blind" reset, hoping we are in Config mode */
+ mcp25xxfd_cmd_reset(spi, priv->spi_setup_speed_hz);
+
+ /* Wait for oscillator startup again */
+ msleep(MCP25XXFD_OST_DELAY_MS);
+
+ /* check clock register that the clock is ready or disabled */
+ ret = mcp25xxfd_cmd_read(spi, MCP25XXFD_OSC,
+ &priv->regs.osc,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* there can only be one... */
+ switch (priv->regs.osc &
+ (MCP25XXFD_OSC_OSCRDY | MCP25XXFD_OSC_OSCDIS)) {
+ case MCP25XXFD_OSC_OSCRDY: /* either the clock is ready */
+ break;
+ case MCP25XXFD_OSC_OSCDIS: /* or the clock is disabled */
+ /* wakeup sleeping system */
+ ret = mcp25xxfd_wake_from_sleep(spi);
+ if (ret)
+ return ret;
+ /* send a reset, hoping we are now in Config mode */
+ mcp25xxfd_cmd_reset(spi, priv->spi_setup_speed_hz);
+
+ /* Wait for oscillator startup again */
+ msleep(MCP25XXFD_OST_DELAY_MS);
+ break;
+ default:
+ /* otherwise there is no valid device (or in strange state)
+ *
+ * if PLL is enabled but not ready, then there may be
+ * something "fishy"
+ * this happened during driver development
+ * (enabling pll, when when on wrong clock), so best warn
+ * about such a possibility
+ */
+ if ((priv->regs.osc &
+ (MCP25XXFD_OSC_PLLEN | MCP25XXFD_OSC_PLLRDY))
+ == MCP25XXFD_OSC_PLLEN)
+ dev_err(&spi->dev,
+ "mcp25xxfd may be in a strange state - a power disconnect may be required\n");
+
+ return -ENODEV;
+ }
+
+ /* check if we are in config mode already*/
+
+ /* read CON register and match */
+ ret = mcp25xxfd_cmd_read(spi, CAN_CON,
+ &priv->regs.con,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* apply mask and check */
+ if ((priv->regs.con & CAN_CON_DEFAULT_MASK) == CAN_CON_DEFAULT) {
+ priv->active_can_mode = CAN_CON_MODE_CONFIG;
+ return 0;
+ }
+
+ /* as per datasheet a reset only works in Config Mode
+ * so as we have in principle no knowledge of the current
+ * mode that the controller is in we have no safe way
+ * to detect the device correctly
+ * hence we need to "blindly" put the controller into
+ * config mode.
+ * on the "save" side, the OSC reg has to be valid already,
+ * so there is a chance we got the controller...
+ */
+
+ /* blindly force it into config mode */
+ priv->regs.con = CAN_CON_DEFAULT;
+ priv->active_can_mode = CAN_CON_MODE_CONFIG;
+ ret = mcp25xxfd_cmd_write(spi, CAN_CON, CAN_CON_DEFAULT,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* delay some time */
+ msleep(MCP25XXFD_OST_DELAY_MS);
+
+ /* reset can controller */
+ mcp25xxfd_cmd_reset(spi, priv->spi_setup_speed_hz);
+
+ /* delay some time */
+ msleep(MCP25XXFD_OST_DELAY_MS);
+
+ /* read CON register and match a final time */
+ ret = mcp25xxfd_cmd_read(spi, CAN_CON,
+ &priv->regs.con,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* apply mask and check */
+ if ((priv->regs.con & CAN_CON_DEFAULT_MASK) != CAN_CON_DEFAULT)
+ return -ENODEV;
+
+ /* just in case: disable interrupts on controller */
+ return mcp25xxfd_disable_interrupts(spi,
+ priv->spi_setup_speed_hz);
+}
+
+static int mcp25xxfd_setup_osc(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ int val = ((priv->config.clock_pll) ? MCP25XXFD_OSC_PLLEN : 0)
+ | ((priv->config.clock_div2) ? MCP25XXFD_OSC_SCLKDIV : 0);
+ int waitfor = ((priv->config.clock_pll) ? MCP25XXFD_OSC_PLLRDY : 0)
+ | ((priv->config.clock_div2) ? MCP25XXFD_OSC_SCLKRDY : 0)
+ | MCP25XXFD_OSC_OSCRDY;
+ int ret;
+ unsigned long timeout;
+
+ /* manage clock_out divider */
+ switch (priv->config.clock_odiv) {
+ case 10:
+ val |= (MCP25XXFD_OSC_CLKODIV_10)
+ << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 4:
+ val |= (MCP25XXFD_OSC_CLKODIV_4)
+ << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 2:
+ val |= (MCP25XXFD_OSC_CLKODIV_2)
+ << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 1:
+ val |= (MCP25XXFD_OSC_CLKODIV_1)
+ << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ case 0:
+ /* this means implicitly SOF output */
+ val |= (MCP25XXFD_OSC_CLKODIV_10)
+ << MCP25XXFD_OSC_CLKODIV_SHIFT;
+ break;
+ default:
+ dev_err(&spi->dev,
+ "Unsupported output clock divider %i\n",
+ priv->config.clock_odiv);
+ return -EINVAL;
+ }
+
+ /* write clock */
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_OSC, val,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* wait for synced pll/osc/sclk */
+ timeout = jiffies + MCP25XXFD_OSC_POLLING_JIFFIES;
+ while (time_before_eq(jiffies, timeout)) {
+ ret = mcp25xxfd_cmd_read(spi, MCP25XXFD_OSC,
+ &priv->regs.osc,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ if ((priv->regs.osc & waitfor) == waitfor)
+ return 0;
+ }
+
+ dev_err(&spi->dev,
+ "Clock did not lock within the timeout period\n");
+
+ /* we timed out */
+ return -ENODEV;
+}
+
+static int mcp25xxfd_setup_fifo(struct net_device *net,
+ struct mcp25xxfd_priv *priv,
+ struct spi_device *spi)
+{
+ u32 val, available_memory, tx_memory_used;
+ int ret;
+ int i, fifo;
+
+ /* clear all filter */
+ for (i = 0; i < 32; i++) {
+ ret = mcp25xxfd_cmd_write(spi, CAN_FLTOBJ(i), 0,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_cmd_write(spi, CAN_FLTMASK(i), 0,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ ret = mcp25xxfd_cmd_write_mask(spi, CAN_FLTCON(i), 0,
+ CAN_FILCON_MASK(i),
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ }
+
+ /* decide on TEF, tx and rx FIFOS */
+ switch (net->mtu) {
+ case CAN_MTU:
+ /* note: if we have INT1 connected to a GPIO
+ * then we could handle this differently and more
+ * efficiently
+ */
+
+ /* mtu is 8 */
+ priv->fifos.payload_size = 8;
+ priv->fifos.payload_mode = CAN_TXQCON_PLSIZE_8;
+
+ /* 7 tx fifos starting at fifo 1 */
+ priv->fifos.tx_fifos = 7;
+
+ /* 24 rx fifos with 1 buffers/fifo */
+ priv->fifos.rx_fifo_depth = 1;
+
+ break;
+ case CANFD_MTU:
+ /* wish there was a way to have hw filters
+ * that can separate based on length ...
+ */
+ /* MTU is 64 */
+ priv->fifos.payload_size = 64;
+ priv->fifos.payload_mode = CAN_TXQCON_PLSIZE_64;
+
+ /* 7 tx fifos */
+ priv->fifos.tx_fifos = 7;
+
+ /* 19 rx fifos with 1 buffer/fifo */
+ priv->fifos.rx_fifo_depth = 1;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* if defined as a module modify the number of tx_fifos */
+ if (tx_fifos) {
+ dev_info(&spi->dev,
+ "Using %i tx-fifos as per module parameter\n",
+ tx_fifos);
+ priv->fifos.tx_fifos = tx_fifos;
+ }
+
+ /* check range - we need 1 RX-fifo and one tef-fifo, hence 30 */
+ if (priv->fifos.tx_fifos > 30) {
+ dev_err(&spi->dev,
+ "There is an absolute maximum of 30 tx-fifos\n");
+ return -EINVAL;
+ }
+
+ tx_memory_used = priv->fifos.tx_fifos *
+ (sizeof(struct mcp25xxfd_obj_tef) +
+ sizeof(struct mcp25xxfd_obj_tx) +
+ priv->fifos.payload_size);
+ /* check that we are not exceeding memory limits with 1 RX buffer */
+ if (tx_memory_used + (sizeof(struct mcp25xxfd_obj_rx) +
+ priv->fifos.payload_size) > MCP25XXFD_BUFFER_TXRX_SIZE) {
+ dev_err(&spi->dev,
+ "Configured %i tx-fifos exceeds available memory already\n",
+ priv->fifos.tx_fifos);
+ return -EINVAL;
+ }
+
+ /* calculate possible amount of RX fifos */
+ available_memory = MCP25XXFD_BUFFER_TXRX_SIZE - tx_memory_used;
+
+ priv->fifos.rx_fifos = available_memory /
+ (sizeof(struct mcp25xxfd_obj_rx) +
+ priv->fifos.payload_size) /
+ priv->fifos.rx_fifo_depth;
+
+ /* we only support 31 FIFOS in total (TEF = FIFO0),
+ * so modify rx accordingly
+ */
+ if (priv->fifos.tx_fifos + priv->fifos.rx_fifos > 31)
+ priv->fifos.rx_fifos = 31 - priv->fifos.tx_fifos;
+
+ /* calculate effective memory used */
+ available_memory -= priv->fifos.rx_fifos *
+ (sizeof(struct mcp25xxfd_obj_rx) +
+ priv->fifos.payload_size) *
+ priv->fifos.rx_fifo_depth;
+
+ /* calcluate tef size */
+ priv->fifos.tef_fifos = priv->fifos.tx_fifos;
+ fifo = available_memory / sizeof(struct mcp25xxfd_obj_tef);
+ if (fifo > 0) {
+ priv->fifos.tef_fifos += fifo;
+ if (priv->fifos.tef_fifos > 32)
+ priv->fifos.tef_fifos = 32;
+ }
+
+ /* calculate rx/tx fifo start */
+ priv->fifos.rx_fifo_start = 1;
+ priv->fifos.tx_fifo_start =
+ priv->fifos.rx_fifo_start + priv->fifos.rx_fifos;
+
+ /* set up TEF SIZE to the number of tx_fifos and IRQ */
+ priv->regs.tefcon = CAN_TEFCON_FRESET |
+ CAN_TEFCON_TEFNEIE |
+ CAN_TEFCON_TEFTSEN |
+ ((priv->fifos.tef_fifos - 1) << CAN_TEFCON_FSIZE_SHIFT);
+
+ ret = mcp25xxfd_cmd_write(spi, CAN_TEFCON,
+ priv->regs.tefcon,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* set up tx fifos */
+ val = CAN_FIFOCON_TXEN |
+ CAN_FIFOCON_TXATIE | /* show up txatie flags in txatif reg */
+ CAN_FIFOCON_FRESET | /* reset FIFO */
+ (priv->fifos.payload_mode << CAN_FIFOCON_PLSIZE_SHIFT) |
+ (0 << CAN_FIFOCON_FSIZE_SHIFT); /* 1 FIFO only */
+
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ if (three_shot)
+ val |= CAN_FIFOCON_TXAT_THREE_SHOT <<
+ CAN_FIFOCON_TXAT_SHIFT;
+ else
+ val |= CAN_FIFOCON_TXAT_ONE_SHOT <<
+ CAN_FIFOCON_TXAT_SHIFT;
+ else
+ val |= CAN_FIFOCON_TXAT_UNLIMITED <<
+ CAN_FIFOCON_TXAT_SHIFT;
+
+ for (i = 0; i < priv->fifos.tx_fifos; i++) {
+ fifo = priv->fifos.tx_fifo_start + i;
+ ret = mcp25xxfd_cmd_write(spi, CAN_FIFOCON(fifo),
+ /* the prioriy needs to be inverted
+ * we need to run from lowest to
+ * highest to avoid MAB errors
+ */
+ val | ((31 - fifo) <<
+ CAN_FIFOCON_TXPRI_SHIFT),
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ priv->fifos.tx_fifo_mask |= BIT(fifo);
+ }
+
+ /* now set up RX FIFO */
+ for (i = 0,
+ fifo = priv->fifos.rx_fifo_start + priv->fifos.rx_fifos - 1;
+ i < priv->fifos.rx_fifos; i++, fifo--) {
+ /* prepare the fifo itself */
+ ret = mcp25xxfd_cmd_write(spi, CAN_FIFOCON(fifo),
+ (priv->fifos.payload_mode <<
+ CAN_FIFOCON_PLSIZE_SHIFT) |
+ ((priv->fifos.rx_fifo_depth - 1) <<
+ CAN_FIFOCON_FSIZE_SHIFT) |
+ /* RX timestamps: */
+ CAN_FIFOCON_RXTSEN |
+ /* reset FIFO: */
+ CAN_FIFOCON_FRESET |
+ /* FIFO Full: */
+ CAN_FIFOCON_TFERFFIE |
+ /* FIFO Half Full: */
+ CAN_FIFOCON_TFHRFHIE |
+ /* FIFO not empty: */
+ CAN_FIFOCON_TFNRFNIE |
+ /* on last fifo add overflow flag: */
+ ((i == priv->fifos.rx_fifos - 1) ?
+ CAN_FIFOCON_RXOVIE : 0),
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ /* prepare the rx filter config: filter i directs to fifo
+ * FLTMSK and FLTOBJ are 0 already, so they match everything
+ */
+ ret = mcp25xxfd_cmd_write_mask(spi, CAN_FLTCON(i),
+ CAN_FIFOCON_FLTEN(i) |
+ (fifo << CAN_FILCON_SHIFT(i)),
+ CAN_FIFOCON_FLTEN(i) |
+ CAN_FILCON_MASK(i),
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ priv->fifos.rx_fifo_mask |= BIT(fifo);
+ }
+
+ /* we need to move out of CONFIG mode shortly to get the addresses */
+ ret = mcp25xxfd_set_opmode(spi, CAN_CON_MODE_INTERNAL_LOOPBACK,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* for the TEF fifo */
+ ret = mcp25xxfd_cmd_read(spi, CAN_TEFUA, &val,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ priv->fifos.tef_address = val;
+ priv->fifos.tef_address_start = val;
+ priv->fifos.tef_address_end = priv->fifos.tef_address_start +
+ priv->fifos.tef_fifos * sizeof(struct mcp25xxfd_obj_tef) -
+ 1;
+
+ /* get all the relevant addresses for the transmit fifos */
+ for (i = 0; i < priv->fifos.tx_fifos; i++) {
+ fifo = priv->fifos.tx_fifo_start + i;
+ ret = mcp25xxfd_cmd_read(spi, CAN_FIFOUA(fifo),
+ &val, priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ priv->fifos.fifo_address[fifo] = val;
+ }
+
+ /* and prepare the spi_messages */
+ ret = mcp25xxfd_fill_spi_transmit_fifos(priv);
+ if (ret)
+ return ret;
+
+ /* get all the relevant addresses for the rx fifos */
+ for (i = 0; i < priv->fifos.rx_fifos; i++) {
+ fifo = priv->fifos.rx_fifo_start + i;
+ ret = mcp25xxfd_cmd_read(spi, CAN_FIFOUA(fifo),
+ &val, priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ priv->fifos.fifo_address[fifo] = val;
+ }
+
+ /* now get back into config mode */
+ ret = mcp25xxfd_set_opmode(spi, CAN_CON_MODE_CONFIG,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int mcp25xxfd_setup(struct net_device *net,
+ struct mcp25xxfd_priv *priv,
+ struct spi_device *spi)
+{
+ int ret;
+
+ /* set up pll/clock if required */
+ ret = mcp25xxfd_setup_osc(spi);
+ if (ret)
+ return ret;
+
+ /* set up RAM ECC */
+ priv->regs.ecccon = MCP25XXFD_ECCCON_ECCEN |
+ MCP25XXFD_ECCCON_SECIE |
+ MCP25XXFD_ECCCON_DEDIE;
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_ECCCON,
+ priv->regs.ecccon,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* clean SRAM now that we have ECC enabled
+ * only this case it is clear that all RAM cels have
+ * valid ECC bits
+ */
+ ret = mcp25xxfd_clean_sram(spi, priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* time stamp control register - 1ns resolution, but disabled */
+ ret = mcp25xxfd_cmd_write(spi, CAN_TBC, 0,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ priv->regs.tscon = CAN_TSCON_TBCEN |
+ ((priv->can.clock.freq / 1000000)
+ << CAN_TSCON_TBCPRE_SHIFT);
+ ret = mcp25xxfd_cmd_write(spi, CAN_TSCON,
+ priv->regs.tscon,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* setup value of con_register */
+ priv->regs.con = CAN_CON_STEF /* enable TEF */;
+
+ /* transmission bandwidth sharing bits */
+ if (bw_sharing_log2bits > 12)
+ bw_sharing_log2bits = 12;
+ priv->regs.con |= bw_sharing_log2bits << CAN_CON_TXBWS_SHIFT;
+ /* non iso FD mode */
+ if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO))
+ priv->regs.con |= CAN_CON_ISOCRCEN;
+ /* one shot */
+ if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
+ priv->regs.con |= CAN_CON_RTXAT;
+
+ /* and put us into default mode = CONFIG */
+ priv->regs.con |= (CAN_CON_MODE_CONFIG << CAN_CON_REQOP_SHIFT) |
+ (CAN_CON_MODE_CONFIG << CAN_CON_OPMOD_SHIFT);
+ /* apply it now - later we will only switch opsmodes... */
+ ret = mcp25xxfd_cmd_write(spi, CAN_CON,
+ priv->regs.con,
+ priv->spi_setup_speed_hz);
+
+ /* setup fifos - this also puts the system into sleep mode */
+ return mcp25xxfd_setup_fifo(net, priv, spi);
+}
+
+static int mcp25xxfd_open(struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ struct spi_device *spi = priv->spi;
+ int ret;
+
+ //pr_err("mcp25xxfd_open start\n");
+ ret = open_candev(net);
+ if (ret) {
+ dev_err(&spi->dev, "unable to set initial baudrate!\n");
+ return ret;
+ }
+
+ mcp25xxfd_gpio_direction_output(&priv->gpio, 0, 0);
+
+ mcp25xxfd_power_enable(priv->transceiver, 1);
+
+ priv->force_quit = 0;
+
+ /* clear those statistics */
+ memset(&priv->stats, 0, sizeof(priv->stats));
+
+ ret = request_threaded_irq(spi->irq, NULL,
+ mcp25xxfd_can_ist,
+ IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+ DEVICE_NAME, priv);
+ if (ret) {
+ dev_err(&spi->dev, "failed to acquire irq %d - %i\n",
+ spi->irq, ret);
+ mcp25xxfd_power_enable(priv->transceiver, 0);
+ close_candev(net);
+ return ret;
+ }
+
+ /* wake from sleep if necessary */
+ ret = mcp25xxfd_hw_wake(spi);
+ if (ret)
+ goto open_clean;
+
+ ret = mcp25xxfd_setup(net, priv, spi);
+ if (ret)
+ goto open_clean;
+
+ mcp25xxfd_do_set_nominal_bittiming(net);
+ mcp25xxfd_do_set_data_bittiming(net);
+
+ ret = mcp25xxfd_set_normal_opmode(spi);
+ if (ret)
+ goto open_clean;
+ /* setting up default state */
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ /* only now enable the interrupt on the controller */
+ ret = mcp25xxfd_enable_interrupts(spi,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ goto open_clean;
+
+ can_led_event(net, CAN_LED_EVENT_OPEN);
+
+ priv->tx_queue_status = TX_QUEUE_STATUS_RUNNING;
+ netif_wake_queue(net);
+
+ return 0;
+
+open_clean:
+ mcp25xxfd_disable_interrupts(spi, priv->spi_setup_speed_hz);
+ free_irq(spi->irq, priv);
+ mcp25xxfd_hw_sleep(spi);
+ mcp25xxfd_power_enable(priv->transceiver, 0);
+ close_candev(net);
+
+ return ret;
+}
+
+static void mcp25xxfd_clean(struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ int i;
+
+ for (i = 0; i < priv->fifos.tx_fifos; i++) {
+ if (priv->fifos.tx_pending_mask & BIT(i)) {
+ can_free_echo_skb(priv->net, 0);
+ priv->net->stats.tx_errors++;
+ }
+ }
+
+ priv->fifos.tx_pending_mask = 0;
+}
+
+static int mcp25xxfd_stop(struct net_device *net)
+{
+ struct mcp25xxfd_priv *priv = netdev_priv(net);
+ struct spi_device *spi = priv->spi;
+
+ close_candev(net);
+ mcp25xxfd_gpio_direction_output(&priv->gpio, 0, 1);
+ kfree(priv->spi_transmit_fifos);
+ priv->spi_transmit_fifos = NULL;
+
+ priv->force_quit = 1;
+ free_irq(spi->irq, priv);
+
+ /* Disable and clear pending interrupts */
+ mcp25xxfd_disable_interrupts(spi, priv->spi_setup_speed_hz);
+
+ mcp25xxfd_clean(net);
+
+ mcp25xxfd_hw_sleep(spi);
+
+ mcp25xxfd_power_enable(priv->transceiver, 0);
+
+ priv->can.state = CAN_STATE_STOPPED;
+
+ can_led_event(net, CAN_LED_EVENT_STOP);
+
+ return 0;
+}
+
+static const struct net_device_ops mcp25xxfd_netdev_ops = {
+ .ndo_open = mcp25xxfd_open,
+ .ndo_stop = mcp25xxfd_stop,
+ .ndo_start_xmit = mcp25xxfd_start_xmit,
+ .ndo_change_mtu = can_change_mtu,
+};
+
+static const struct of_device_id mcp25xxfd_of_match[] = {
+ {
+ .compatible = "microchip,mcp2517fd",
+ .data = (void *)CAN_MCP2517FD,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, mcp25xxfd_of_match);
+
+static const struct spi_device_id mcp25xxfd_id_table[] = {
+ {
+ .name = "mcp2517fd",
+ .driver_data = (kernel_ulong_t)CAN_MCP2517FD,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, mcp25xxfd_id_table);
+
+static int mcp25xxfd_dump_regs(struct seq_file *file, void *offset)
+{
+ struct spi_device *spi = file->private;
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ u32 data[CAN_TXQUA - CAN_CON + 4];
+ int i;
+ int count;
+ int ret;
+
+ count = (CAN_TXQUA - CAN_CON) / 4 + 1;
+ ret = mcp25xxfd_cmd_readn(spi, CAN_CON, data, 4 * count,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ mcp25xxfd_convert_to_cpu((u32 *)data, 4 * count);
+
+ for (i = 0; i < count; i++) {
+ seq_printf(file, "Reg 0x%03x = 0x%08x\n",
+ CAN_CON + 4 * i,
+ ((u32 *)data)[i]);
+ }
+
+ count = (MCP25XXFD_ECCSTAT - MCP25XXFD_OSC) / 4 + 1;
+ ret = mcp25xxfd_cmd_readn(spi, MCP25XXFD_OSC, data, 4 * count,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+ mcp25xxfd_convert_to_cpu((u32 *)data, 4 * count);
+
+ for (i = 0; i < count; i++) {
+ seq_printf(file, "Reg 0x%03x = 0x%08x\n",
+ MCP25XXFD_OSC + 4 * i,
+ ((u32 *)data)[i]);
+ }
+
+ return 0;
+}
+
+#if defined(CONFIG_DEBUG_FS)
+static void mcp25xxfd_debugfs_add(struct mcp25xxfd_priv *priv)
+{
+ struct dentry *root, *fifousage, *fifoaddr, *rx, *tx, *status,
+ *regs, *stats, *rxdlc, *txdlc;
+ char name[32];
+ int i;
+
+ /* create the net device name */
+ snprintf(name, sizeof(name), DEVICE_NAME "-%s", priv->net->name);
+ priv->debugfs_dir = debugfs_create_dir(name, NULL);
+ root = priv->debugfs_dir;
+
+ rx = debugfs_create_dir("rx", root);
+ tx = debugfs_create_dir("tx", root);
+ fifoaddr = debugfs_create_dir("fifo_address", root);
+ status = debugfs_create_dir("status", root);
+ regs = debugfs_create_dir("regs", root);
+ stats = debugfs_create_dir("stats", root);
+ fifousage = debugfs_create_dir("fifo_usage", stats);
+ rxdlc = debugfs_create_dir("rx_dlc_usage", stats);
+ txdlc = debugfs_create_dir("tx_dlc_usage", stats);
+
+ /* add spi speed info */
+ debugfs_create_u32("spi_setup_speed_hz", 0444, root,
+ &priv->spi_setup_speed_hz);
+ debugfs_create_u32("spi_speed_hz", 0444, root,
+ &priv->spi_speed_hz);
+
+ /* add irq state info */
+ debugfs_create_u32("irq_state", 0444, root, &priv->stats.irq_state);
+
+ /* for the clock user mask */
+ debugfs_create_u32("clk_user_mask", 0444, root, &priv->clk_user_mask);
+
+ /* add fd statistics */
+ debugfs_create_u64("rx_fd_frames", 0444, stats,
+ &priv->stats.rx_fd_count);
+ debugfs_create_u64("tx_fd_frames", 0444, stats,
+ &priv->stats.tx_fd_count);
+ debugfs_create_u64("rx_brs_frames", 0444, stats,
+ &priv->stats.rx_brs_count);
+ debugfs_create_u64("tx_brs_frames", 0444, stats,
+ &priv->stats.tx_brs_count);
+
+ /* export the status structure */
+ debugfs_create_x32("intf", 0444, status, &priv->status.intf);
+ debugfs_create_x32("rx_if", 0444, status, &priv->status.rxif);
+ debugfs_create_x32("tx_if", 0444, status, &priv->status.txif);
+ debugfs_create_x32("rx_ovif", 0444, status, &priv->status.rxovif);
+ debugfs_create_x32("tx_atif", 0444, status, &priv->status.txatif);
+ debugfs_create_x32("tx_req", 0444, status, &priv->status.txreq);
+ debugfs_create_x32("trec", 0444, status, &priv->status.trec);
+ debugfs_create_x32("bdiag0", 0444, status, &priv->status.bdiag0);
+ debugfs_create_x32("bdiag1", 0444, status, &priv->status.bdiag1);
+
+ /* some configuration registers */
+ debugfs_create_x32("con", 0444, regs, &priv->regs.con);
+ debugfs_create_x32("ecccon", 0444, regs, &priv->regs.ecccon);
+ debugfs_create_x32("osc", 0444, regs, &priv->regs.osc);
+ debugfs_create_x32("iocon", 0444, regs, &priv->regs.iocon);
+ debugfs_create_x32("tdc", 0774, regs, &priv->regs.tdc);
+ debugfs_create_x32("tscon", 0444, regs, &priv->regs.tscon);
+ debugfs_create_x32("nbtcfg", 0444, regs, &priv->regs.nbtcfg);
+ debugfs_create_x32("dbtcfg", 0444, regs, &priv->regs.dbtcfg);
+
+ /* information on fifos */
+ debugfs_create_u32("fifo_start", 0444, rx,
+ &priv->fifos.rx_fifo_start);
+ debugfs_create_u32("fifo_count", 0444, rx,
+ &priv->fifos.rx_fifos);
+ debugfs_create_x32("fifo_mask", 0444, rx,
+ &priv->fifos.rx_fifo_mask);
+ debugfs_create_u64("rx_overflow", 0444, rx,
+ &priv->stats.rx_overflow);
+ debugfs_create_u64("rx_mab", 0444, stats,
+ &priv->stats.rx_mab);
+
+ debugfs_create_u32("fifo_start", 0444, tx,
+ &priv->fifos.tx_fifo_start);
+ debugfs_create_u32("fifo_count", 0444, tx,
+ &priv->fifos.tx_fifos);
+ debugfs_create_x32("fifo_mask", 0444, tx,
+ &priv->fifos.tx_fifo_mask);
+ debugfs_create_x32("fifo_pending", 0444, tx,
+ &priv->fifos.tx_pending_mask);
+ debugfs_create_x32("fifo_submitted", 0444, tx,
+ &priv->fifos.tx_submitted_mask);
+ debugfs_create_x32("fifo_processed", 0444, tx,
+ &priv->fifos.tx_processed_mask);
+ debugfs_create_u32("queue_status", 0444, tx,
+ &priv->tx_queue_status);
+ debugfs_create_u64("tx_mab", 0444, stats,
+ &priv->stats.tx_mab);
+
+ debugfs_create_u32("tef_count", 0444, tx,
+ &priv->fifos.tef_fifos);
+
+ debugfs_create_u32("fifo_max_payload_size", 0444, root,
+ &priv->fifos.payload_size);
+
+ /* interrupt statistics */
+ debugfs_create_u64("int", 0444, stats,
+ &priv->stats.irq_calls);
+ debugfs_create_u64("int_loops", 0444, stats,
+ &priv->stats.irq_loops);
+ debugfs_create_u64("int_ivm", 0444, stats,
+ &priv->stats.int_ivm_count);
+ debugfs_create_u64("int_wake", 0444, stats,
+ &priv->stats.int_wake_count);
+ debugfs_create_u64("int_cerr", 0444, stats,
+ &priv->stats.int_cerr_count);
+ debugfs_create_u64("int_serr", 0444, stats,
+ &priv->stats.int_serr_count);
+ debugfs_create_u64("int_rxov", 0444, stats,
+ &priv->stats.int_rxov_count);
+ debugfs_create_u64("int_txat", 0444, stats,
+ &priv->stats.int_txat_count);
+ debugfs_create_u64("int_spicrc", 0444, stats,
+ &priv->stats.int_spicrc_count);
+ debugfs_create_u64("int_ecc", 0444, stats,
+ &priv->stats.int_ecc_count);
+ debugfs_create_u64("int_tef", 0444, stats,
+ &priv->stats.int_tef_count);
+ debugfs_create_u64("int_mod", 0444, stats,
+ &priv->stats.int_mod_count);
+ debugfs_create_u64("int_tbc", 0444, stats,
+ &priv->stats.int_tbc_count);
+ debugfs_create_u64("int_rx", 0444, stats,
+ &priv->stats.int_rx_count);
+ debugfs_create_u64("int_tx", 0444, stats,
+ &priv->stats.int_tx_count);
+
+ /* dlc statistics */
+ for (i = 0; i < 16; i++) {
+ snprintf(name, sizeof(name), "%02i", i);
+ debugfs_create_u64(name, 0444, rxdlc,
+ &priv->stats.rx_dlc_usage[i]);
+ debugfs_create_u64(name, 0444, txdlc,
+ &priv->stats.tx_dlc_usage[i]);
+ }
+
+ /* statistics on fifo buffer usage and address */
+ for (i = 1; i < 32; i++) {
+ snprintf(name, sizeof(name), "%02i", i);
+ debugfs_create_u64(name, 0444, fifousage,
+ &priv->stats.fifo_usage[i]);
+ debugfs_create_u32(name, 0444, fifoaddr,
+ &priv->fifos.fifo_address[i]);
+ }
+
+ /* dump the controller registers themselves */
+ debugfs_create_devm_seqfile(&priv->spi->dev, "reg_dump",
+ root, mcp25xxfd_dump_regs);
+}
+
+static void mcp25xxfd_debugfs_remove(struct mcp25xxfd_priv *priv)
+{
+ debugfs_remove_recursive(priv->debugfs_dir);
+}
+
+#else
+static void mcp25xxfd_debugfs_add(struct mcp25xxfd_priv *priv)
+{
+ return 0;
+}
+
+static void mcp25xxfd_debugfs_remove(struct mcp25xxfd_priv *priv)
+{
+}
+#endif
+
+#ifdef CONFIG_OF_DYNAMIC
+int mcp25xxfd_of_parse(struct mcp25xxfd_priv *priv)
+{
+ struct spi_device *spi = priv->spi;
+ const struct device_node *np = spi->dev.of_node;
+ u32 val;
+ int ret;
+
+ priv->config.clock_div2 =
+ of_property_read_bool(np, "microchip,clock-div2");
+
+ ret = of_property_read_u32_index(np, "microchip,clock-out-div",
+ 0, &val);
+ if (!ret) {
+ switch (val) {
+ case 0:
+ case 1:
+ case 2:
+ case 4:
+ case 10:
+ priv->config.clock_odiv = val;
+ break;
+ default:
+ dev_err(&spi->dev,
+ "Invalid value in device tree for microchip,clock_out_div: %u - valid values: 0, 1, 2, 4, 10\n",
+ val);
+ return -EINVAL;
+ }
+ }
+
+ priv->config.gpio_opendrain =
+ of_property_read_bool(np, "gpio-open-drain");
+
+ return 0;
+}
+#else
+int mcp25xxfd_of_parse(struct mcp25xxfd_priv *priv)
+{
+ return 0;
+}
+#endif
+
+static int mcp25xxfd_can_probe(struct spi_device *spi)
+{
+ const struct of_device_id *of_id =
+ of_match_device(mcp25xxfd_of_match, &spi->dev);
+ struct net_device *net;
+ struct mcp25xxfd_priv *priv;
+ struct clk *clk;
+ int ret, freq;
+
+ /* as irq_create_fwspec_mapping() can return 0, check for it */
+ if (spi->irq <= 0) {
+ dev_err(&spi->dev, "no valid irq line defined: irq = %i\n",
+ spi->irq);
+ return -EINVAL;
+ }
+
+ clk = devm_clk_get(&spi->dev, NULL);
+ if (IS_ERR(clk)) {
+ dev_err(&spi->dev,
+ "Can't get Clock source\n");
+ return PTR_ERR(clk);
+ }
+ freq = clk_get_rate(clk);
+ if (freq < MCP25XXFD_MIN_CLOCK_FREQUENCY ||
+ freq > MCP25XXFD_MAX_CLOCK_FREQUENCY) {
+ dev_err(&spi->dev,
+ "Clock frequency %i is not in range [%i:%i]\n",
+ freq,
+ MCP25XXFD_MIN_CLOCK_FREQUENCY,
+ MCP25XXFD_MAX_CLOCK_FREQUENCY);
+ return -ERANGE;
+ }
+
+ /* Allocate can/net device */
+ net = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX);
+ if (!net)
+ return -ENOMEM;
+
+ net->netdev_ops = &mcp25xxfd_netdev_ops;
+ net->flags |= IFF_ECHO;
+
+ priv = netdev_priv(net);
+ priv->can.bittiming_const = &mcp25xxfd_nominal_bittiming_const;
+ priv->can.do_set_bittiming = &mcp25xxfd_do_set_nominal_bittiming;
+ priv->can.data_bittiming_const = &mcp25xxfd_data_bittiming_const;
+ priv->can.do_set_data_bittiming = &mcp25xxfd_do_set_data_bittiming;
+ priv->can.do_set_mode = mcp25xxfd_do_set_mode;
+ priv->can.do_get_berr_counter = mcp25xxfd_get_berr_counter;
+
+ priv->can.ctrlmode_supported =
+ CAN_CTRLMODE_FD |
+ CAN_CTRLMODE_LOOPBACK |
+ CAN_CTRLMODE_LISTENONLY |
+ CAN_CTRLMODE_BERR_REPORTING |
+ CAN_CTRLMODE_FD_NON_ISO |
+ CAN_CTRLMODE_ONE_SHOT;
+
+ if (of_id)
+ priv->model = (enum mcp25xxfd_model)of_id->data;
+ else
+ priv->model = spi_get_device_id(spi)->driver_data;
+
+ spi_set_drvdata(spi, priv);
+ priv->spi = spi;
+ priv->net = net;
+ priv->clk = clk;
+
+ priv->clk_user_mask = MCP25XXFD_CLK_USER_CAN;
+
+ mutex_init(&priv->clk_user_lock);
+ mutex_init(&priv->spi_rxtx_lock);
+
+ /* enable the clock and mark as enabled */
+ priv->clk_user_mask = MCP25XXFD_CLK_USER_CAN;
+ ret = clk_prepare_enable(clk);
+ if (ret)
+ goto out_free;
+
+ /* Setup GPIO controller */
+ ret = mcp25xxfd_gpio_setup(spi);
+ if (ret)
+ goto out_clk;
+
+ /* all by default as push/pull */
+ priv->config.gpio_opendrain = false;
+
+ /* do not use the SCK clock divider of 2 */
+ priv->config.clock_div2 = false;
+
+ /* clock output is divided by 10 */
+ priv->config.clock_odiv = 10;
+
+ /* as a first guess we assume we are in CAN_CON_MODE_SLEEP
+ * this is how we leave the controller when removing ourselves
+ */
+ priv->active_can_mode = CAN_CON_MODE_SLEEP;
+
+ /* if we have a clock that is smaller then 4MHz, then enable the pll */
+ priv->config.clock_pll =
+ (freq <= MCP25XXFD_AUTO_PLL_MAX_CLOCK_FREQUENCY);
+
+ /* check in device tree for overrrides */
+ ret = mcp25xxfd_of_parse(priv);
+ if (ret)
+ return ret;
+
+ /* decide on real can clock rate */
+ priv->can.clock.freq = freq;
+ if (priv->config.clock_pll) {
+ priv->can.clock.freq *= MCP25XXFD_PLL_MULTIPLIER;
+ if (priv->can.clock.freq > MCP25XXFD_MAX_CLOCK_FREQUENCY) {
+ dev_err(&spi->dev,
+ "PLL clock frequency %i would exceed limit\n",
+ priv->can.clock.freq
+ );
+ return -EINVAL;
+ }
+ }
+ if (priv->config.clock_div2)
+ priv->can.clock.freq /= MCP25XXFD_SCLK_DIVIDER;
+
+ /* calclculate the clock frequencies to use */
+ priv->spi_setup_speed_hz = freq / 2;
+ priv->spi_speed_hz = priv->can.clock.freq / 2;
+ if (priv->config.clock_div2) {
+ priv->spi_setup_speed_hz /= MCP25XXFD_SCLK_DIVIDER;
+ priv->spi_speed_hz /= MCP25XXFD_SCLK_DIVIDER;
+ }
+
+ if (spi->max_speed_hz) {
+ priv->spi_setup_speed_hz = min_t(int,
+ priv->spi_setup_speed_hz,
+ spi->max_speed_hz);
+ priv->spi_speed_hz = min_t(int,
+ priv->spi_speed_hz,
+ spi->max_speed_hz);
+ }
+ /* Configure the SPI bus */
+ spi->bits_per_word = 8;
+ ret = spi_setup(spi);
+ if (ret)
+ goto out_clk;
+
+ ret = mcp25xxfd_power_enable(priv->power, 1);
+ if (ret)
+ goto out_clk;
+
+ SET_NETDEV_DEV(net, &spi->dev);
+
+ ret = mcp25xxfd_hw_probe(spi);
+ /* on error retry a second time */
+ if (ret == -ENODEV) {
+ ret = mcp25xxfd_hw_probe(spi);
+ if (!ret)
+ dev_info(&spi->dev,
+ "found device only during retry\n");
+ }
+ if (ret) {
+ if (ret == -ENODEV)
+ dev_err(&spi->dev,
+ "Cannot initialize MCP%x. Wrong wiring?\n",
+ priv->model);
+ }
+
+ /* setting up GPIO+INT as PUSHPULL , TXCAN PUSH/PULL, no Standby */
+ priv->regs.iocon = 0;
+
+ /* SOF/CLOCKOUT pin 3 */
+ if (priv->config.clock_odiv < 1)
+ priv->regs.iocon |= MCP25XXFD_IOCON_SOF;
+
+ /* INT/GPIO (probably also clockout) as open drain */
+ if (priv->config.gpio_opendrain)
+ priv->regs.iocon |= MCP25XXFD_IOCON_INTOD;
+
+ ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_IOCON, priv->regs.iocon,
+ priv->spi_setup_speed_hz);
+ if (ret)
+ return ret;
+
+ /* and put controller to sleep */
+ mcp25xxfd_hw_sleep(spi);
+
+ ret = register_candev(net);
+ if (ret)
+ goto error_probe;
+
+ /* register debugfs */
+ mcp25xxfd_debugfs_add(priv);
+
+ devm_can_led_init(net);
+
+ netdev_info(net, "MCP%x successfully initialized.\n", priv->model);
+ return 0;
+
+error_probe:
+ mcp25xxfd_power_enable(priv->power, 0);
+
+out_clk:
+ mcp25xxfd_stop_clock(spi, MCP25XXFD_CLK_USER_CAN);
+
+out_free:
+ free_candev(net);
+ dev_err(&spi->dev, "Probe failed, err=%d\n", -ret);
+ return ret;
+}
+
+static int mcp25xxfd_can_remove(struct spi_device *spi)
+{
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct net_device *net = priv->net;
+
+ mcp25xxfd_debugfs_remove(priv);
+
+ unregister_candev(net);
+
+ mcp25xxfd_power_enable(priv->power, 0);
+
+ if (!IS_ERR(priv->clk))
+ clk_disable_unprepare(priv->clk);
+
+ free_candev(net);
+
+ return 0;
+}
+
+static int __maybe_unused mcp25xxfd_can_suspend(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+ struct net_device *net = priv->net;
+
+ priv->force_quit = 1;
+ disable_irq(spi->irq);
+
+ if (netif_running(net)) {
+ netif_device_detach(net);
+
+ mcp25xxfd_hw_sleep(spi);
+ mcp25xxfd_power_enable(priv->transceiver, 0);
+ priv->after_suspend = AFTER_SUSPEND_UP;
+ } else {
+ priv->after_suspend = AFTER_SUSPEND_DOWN;
+ }
+
+ if (!IS_ERR_OR_NULL(priv->power)) {
+ regulator_disable(priv->power);
+ priv->after_suspend |= AFTER_SUSPEND_POWER;
+ }
+
+ return 0;
+}
+
+static int __maybe_unused mcp25xxfd_can_resume(struct device *dev)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
+
+ if (priv->after_suspend & AFTER_SUSPEND_POWER)
+ mcp25xxfd_power_enable(priv->power, 1);
+
+ if (priv->after_suspend & AFTER_SUSPEND_UP)
+ mcp25xxfd_power_enable(priv->transceiver, 1);
+ else
+ priv->after_suspend = 0;
+
+ priv->force_quit = 0;
+
+ enable_irq(spi->irq);
+
+ return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(mcp25xxfd_can_pm_ops, mcp25xxfd_can_suspend,
+ mcp25xxfd_can_resume);
+
+static struct spi_driver mcp25xxfd_can_driver = {
+ .driver = {
+ .name = DEVICE_NAME,
+ .of_match_table = mcp25xxfd_of_match,
+ .pm = &mcp25xxfd_can_pm_ops,
+ },
+ .probe = mcp25xxfd_can_probe,
+ .remove = mcp25xxfd_can_remove,
+};
+
+static int __init mcp25xxfd_can_driver_init(void)
+{
+ int ret;
+
+ ret = spi_register_driver(&mcp25xxfd_can_driver);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+module_init(mcp25xxfd_can_driver_init);
+
+static void __exit mcp25xxfd_can_driver_exit(void)
+{
+ spi_unregister_driver(&mcp25xxfd_can_driver);
+}
+module_exit(mcp25xxfd_can_driver_exit);
+
+MODULE_DESCRIPTION("Microchip 25XXFD 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 3aa9395..0131148 100644
--- a/drivers/net/can/spi/qti-can.c
+++ b/drivers/net/can/spi/qti-can.c
@@ -1049,6 +1049,40 @@
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 @@
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 7cee3e5..2edd193 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -789,7 +789,7 @@
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 @@
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 0c29887..0780900 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -2116,7 +2116,7 @@
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 8aecd8e..15a0850 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -1562,7 +1562,8 @@
}
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 b7d2511..7115f50 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 620a470..fbe3c2c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1425,6 +1425,8 @@
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 8cffcdf..38b5858 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/l2t.h
+++ b/drivers/net/ethernet/chelsio/cxgb3/l2t.h
@@ -75,8 +75,8 @@
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 c71a52a..5478a2a 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -5203,15 +5203,24 @@
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 6620fc8..005c79b5 100644
--- a/drivers/net/ethernet/dec/tulip/de4x5.c
+++ b/drivers/net/ethernet/dec/tulip/de4x5.c
@@ -2109,7 +2109,6 @@
.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 0a48a31..56db37d 100644
--- a/drivers/net/ethernet/emulex/benet/be_ethtool.c
+++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c
@@ -898,7 +898,7 @@
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 @@
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 @@
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 @@
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 051ecc7..1eb3410 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3508,7 +3508,7 @@
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 4cd1633..f38848c 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_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 @@
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 8bbedfc..a0f97c5 100644
--- a/drivers/net/ethernet/intel/e1000e/netdev.c
+++ b/drivers/net/ethernet/intel/e1000e/netdev.c
@@ -4212,7 +4212,7 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
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 7836072..886378c 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -2285,6 +2285,10 @@
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 @@
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 d98b874..f2904af 100644
--- a/drivers/net/ethernet/marvell/mvneta.c
+++ b/drivers/net/ethernet/marvell/mvneta.c
@@ -4162,7 +4162,7 @@
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 @@
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 ff62dc7..0ea1c05 100644
--- a/drivers/net/ethernet/marvell/mvpp2.c
+++ b/drivers/net/ethernet/marvell/mvpp2.c
@@ -3938,7 +3938,7 @@
/* 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 @@
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 @@
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 20de37a..d10c8a8 100644
--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
@@ -1700,6 +1700,7 @@
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 @@
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 @@
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 @@
}
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 @@
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 8a9a332d..74d2db5 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
@@ -1930,6 +1930,8 @@
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 @@
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 b656dd5..3173875 100644
--- a/drivers/net/ethernet/mellanox/mlx4/port.c
+++ b/drivers/net/ethernet/mellanox/mlx4/port.c
@@ -1960,11 +1960,6 @@
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 a01e6c0..b2a745b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/reg.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h
@@ -935,7 +935,7 @@
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 e3ed70a..585a40c 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2044,6 +2044,10 @@
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 c59e8fe..4930019 100644
--- a/drivers/net/ethernet/renesas/sh_eth.c
+++ b/drivers/net/ethernet/renesas/sh_eth.c
@@ -1388,6 +1388,10 @@
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 6f85276..ae9b983 100644
--- a/drivers/net/ethernet/sis/sis900.c
+++ b/drivers/net/ethernet/sis/sis900.c
@@ -1058,7 +1058,7 @@
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 @@
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 @@
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 @@
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 @@
/* 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 @@
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 @@
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 f4074e2..2513694 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
@@ -125,7 +125,7 @@
* 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 2abeba4..5fe3622 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -240,7 +240,8 @@
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 f60f766..92f52a7 100644
--- a/drivers/net/ppp/ppp_mppe.c
+++ b/drivers/net/ppp/ppp_mppe.c
@@ -63,6 +63,7 @@
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 3eb6d48..0acdf73 100644
--- a/drivers/net/team/team.c
+++ b/drivers/net/team/team.c
@@ -2136,12 +2136,12 @@
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 9942054..e33a45e 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -828,18 +828,8 @@
/* 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 @@
{
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 @@
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 01f95d1..2b16a5f 100644
--- a/drivers/net/usb/ipheth.c
+++ b/drivers/net/usb/ipheth.c
@@ -437,17 +437,18 @@
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 4ab82b9..a5acbcb 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -508,6 +508,7 @@
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 @@
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 99ab203..37c3cbe 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -128,6 +128,8 @@
};
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 @@
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);
+ usb_lock_device(udev);
+ usb_driver_release_interface(&carl9170_driver, intf);
+ usb_unlock_device(udev);
- device_release_driver(&udev->dev);
- if (parent)
- device_unlock(parent);
-
- 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 @@
goto err_unrx;
complete(&ar->fw_load_wait);
- usb_put_dev(ar->udev);
+ usb_put_intf(intf);
return;
err_unrx:
@@ -1052,7 +1050,6 @@
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 @@
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 @@
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 0e18067..09dbab4 100644
--- a/drivers/net/wireless/atmel/at76c50x-usb.c
+++ b/drivers/net/wireless/atmel/at76c50x-usb.c
@@ -2583,8 +2583,8 @@
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 6922cbb..5a0699f 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_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 @@
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 bfddabb..fc82bf0 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -3222,6 +3222,7 @@
struct brcmf_pno_scanresults_le *pfn_result;
u32 result_count;
u32 status;
+ u32 datalen;
brcmf_dbg(SCAN, "Enter\n");
@@ -3247,6 +3248,14 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
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 f877301..349cc5c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -339,7 +339,8 @@
} 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 @@
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 @@
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 @@
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 26ff5a9..9cd112e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -181,7 +181,7 @@
*/
#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_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 @@
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 2b9a2bc..ab9f136 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -1114,7 +1114,7 @@
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 053f3b5..acf513f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c
@@ -157,7 +157,7 @@
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 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 @@
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 @@
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 @@
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 @@
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 @@
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 8eff275..d493021 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/vendor.c
@@ -35,9 +35,10 @@
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 @@
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 c21f8bd..25f2a0a 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(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 043bd1c..4a197a3 100644
--- a/drivers/net/wireless/intersil/p54/p54usb.c
+++ b/drivers/net/wireless/intersil/p54/p54usb.c
@@ -33,6 +33,8 @@
MODULE_FIRMWARE("isl3886usb");
MODULE_FIRMWARE("isl3887usb");
+static struct usb_driver p54u_driver;
+
/*
* Note:
*
@@ -921,9 +923,9 @@
{
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 @@
dev_err(&udev->dev, "Firmware not found.\n");
}
+ complete(&priv->fw_wait_load);
+ /*
+ * At this point p54u_disconnect may have already freed
+ * the "priv" context. Do not use it anymore!
+ */
+ priv = NULL;
+
if (err) {
- struct device *parent = priv->udev->dev.parent;
+ dev_err(&intf->dev, "failed to initialize device (%d)\n", err);
- dev_err(&udev->dev, "failed to initialize device (%d)\n", err);
-
- if (parent)
- device_lock(parent);
-
- device_release_driver(&udev->dev);
- /*
- * At this point p54u_disconnect has already freed
- * the "priv" context. Do not use it anymore!
- */
- priv = NULL;
-
- 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 @@
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 @@
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 @@
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 @@
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 4da3541..46d0099 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -4018,16 +4018,20 @@
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 1ff2205..9ddaa76 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfp.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfp.c
@@ -533,5 +533,8 @@
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 4b1894b..395d6ec 100644
--- a/drivers/net/wireless/marvell/mwifiex/fw.h
+++ b/drivers/net/wireless/marvell/mwifiex/fw.h
@@ -1719,9 +1719,10 @@
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 @@
* 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 @@
* 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 c488c30..0f977dc 100644
--- a/drivers/net/wireless/marvell/mwifiex/ie.c
+++ b/drivers/net/wireless/marvell/mwifiex/ie.c
@@ -328,6 +328,8 @@
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 @@
*/
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 @@
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 @@
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 @@
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 78d59a6..97847ee 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -1236,6 +1236,8 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 1532ac9..7f96457 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -1374,7 +1374,7 @@
/* 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 @@
/* 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 dea2fe6..9843560 100644
--- a/drivers/net/wireless/marvell/mwifiex/wmm.c
+++ b/drivers/net/wireless/marvell/mwifiex/wmm.c
@@ -240,7 +240,7 @@
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 4ac928b..7de18ed 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -466,6 +466,11 @@
/* <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 dc478ce..84624c8 100644
--- a/drivers/net/wireless/st/cw1200/main.c
+++ b/drivers/net/wireless/st/cw1200/main.c
@@ -345,6 +345,11 @@
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/nfc/nq-nci.c b/drivers/nfc/nq-nci.c
index 0d9b6f0..e7a3946 100644
--- a/drivers/nfc/nq-nci.c
+++ b/drivers/nfc/nq-nci.c
@@ -150,6 +150,15 @@
return IRQ_HANDLED;
}
+static int is_data_available_for_read(struct nqx_dev *nqx_dev)
+{
+ int ret;
+
+ nqx_enable_irq(nqx_dev);
+ ret = wait_event_interruptible(nqx_dev->read_wq, !nqx_dev->irq_enabled);
+ return ret;
+}
+
static ssize_t nfc_read(struct file *filp, char __user *buf,
size_t count, loff_t *offset)
{
@@ -679,7 +688,6 @@
{
int ret = 0;
- int gpio_retry_count = 0;
unsigned char raw_nci_reset_cmd[] = {0x20, 0x00, 0x01, 0x00};
unsigned char raw_nci_init_cmd[] = {0x20, 0x01, 0x00};
unsigned char nci_get_version_cmd[] = {0x00, 0x04, 0xF1,
@@ -690,7 +698,6 @@
unsigned char init_rsp_len = 0;
unsigned int enable_gpio = nqx_dev->en_gpio;
-reset_enable_gpio:
/* making sure that the NFCC starts in a clean state. */
gpio_set_value(enable_gpio, 0);/* ULPM: Disable */
/* hardware dependent delay */
@@ -746,8 +753,11 @@
}
goto err_nfcc_reset_failed;
}
- /* hardware dependent delay */
- msleep(30);
+ ret = is_data_available_for_read(nqx_dev);
+ if (ret < 0) {
+ nqx_disable_irq(nqx_dev);
+ goto err_nfcc_hw_check;
+ }
/* Read Response of RESET command */
ret = i2c_master_recv(client, nci_reset_rsp,
@@ -755,11 +765,10 @@
if (ret < 0) {
dev_err(&client->dev,
"%s: - i2c_master_recv Error\n", __func__);
- gpio_retry_count = gpio_retry_count + 1;
- if (gpio_retry_count < MAX_RETRY_COUNT)
- goto reset_enable_gpio;
goto err_nfcc_hw_check;
}
+
+ /* send NCI CORE INIT CMD */
ret = nqx_standby_write(nqx_dev, raw_nci_init_cmd,
sizeof(raw_nci_init_cmd));
if (ret < 0) {
@@ -767,8 +776,12 @@
"%s: - i2c_master_send failed for Core INIT\n", __func__);
goto err_nfcc_core_init_fail;
}
- /* hardware dependent delay */
- msleep(30);
+ ret = is_data_available_for_read(nqx_dev);
+ if (ret < 0) {
+ nqx_disable_irq(nqx_dev);
+ goto err_nfcc_hw_check;
+ }
+
/* Read Response of INIT command */
ret = i2c_master_recv(client, nci_init_rsp,
sizeof(nci_init_rsp));
@@ -822,6 +835,11 @@
dev_dbg(&client->dev,
"%s: ## NFCC == PN66T ##\n", __func__);
break;
+ case NFCC_SN100_A:
+ case NFCC_SN100_B:
+ dev_dbg(&client->dev,
+ "%s: ## NFCC == SN100x ##\n", __func__);
+ break;
default:
dev_err(&client->dev,
"%s: - NFCC HW not Supported\n", __func__);
diff --git a/drivers/nfc/nq-nci.h b/drivers/nfc/nq-nci.h
index 87715c2..d17897d 100644
--- a/drivers/nfc/nq-nci.h
+++ b/drivers/nfc/nq-nci.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
@@ -48,6 +48,8 @@
NFCC_NQ_220 = 0x58, /**< NFCC NQ220 */
NFCC_NQ_310 = 0x40, /**< NFCC NQ310 */
NFCC_NQ_330 = 0x51, /**< NFCC NQ330 */
+ NFCC_SN100_A = 0xa3, /**< NFCC SN100_A */
+ NFCC_SN100_B = 0xa4, /**< NFCC SN100_B */
NFCC_PN66T = 0x18, /**< NFCC PN66T */
NFCC_NOT_SUPPORTED = 0xFF /**< NFCC is not supported */
};
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index 66a089d..9108004 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -490,15 +490,26 @@
- (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 @@
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 cf4a90b..e83453e 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1210,12 +1210,27 @@
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 d869236..bd29e59 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -113,8 +113,12 @@
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 979c6ec..8705bfe 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -1765,7 +1765,8 @@
{
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 5b8208b..814373d 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -703,7 +703,7 @@
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 @@
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 c4953ec..7a5306b 100644
--- a/drivers/parisc/ccio-dma.c
+++ b/drivers/parisc/ccio-dma.c
@@ -563,8 +563,6 @@
/* 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 @@
** 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 56918d1..188fab5 100644
--- a/drivers/parisc/sba_iommu.c
+++ b/drivers/parisc/sba_iommu.c
@@ -573,8 +573,7 @@
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 4399de34..daa2eb3 100644
--- a/drivers/parport/share.c
+++ b/drivers/parport/share.c
@@ -895,6 +895,7 @@
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 @@
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 a1dab55..b8a8a92 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -517,6 +517,7 @@
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 @@
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 @@
}
}
+ 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 @@
}
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 @@
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 @@
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 @@
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 d6196f7..7f6b454 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -847,7 +847,7 @@
{
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 @@
/* 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 61332f4..c3964fc 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -337,14 +337,19 @@
* 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 @@
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 @@
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 c614ff7..d3562df 100644
--- a/drivers/pci/hotplug/rpadlpar_core.c
+++ b/drivers/pci/hotplug/rpadlpar_core.c
@@ -55,6 +55,7 @@
if ((rc == 0) && (!strcmp(drc_name, name)))
break;
}
+ of_node_put(parent);
return dn;
}
@@ -78,6 +79,7 @@
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 @@
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 @@
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 55375b1..b2b7e23 100644
--- a/drivers/pinctrl/pinctrl-pistachio.c
+++ b/drivers/pinctrl/pinctrl-pistachio.c
@@ -1368,6 +1368,7 @@
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 @@
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 cfa3e85..d225a83 100644
--- a/drivers/platform/chrome/cros_ec_proto.c
+++ b/drivers/platform/chrome/cros_ec_proto.c
@@ -67,6 +67,17 @@
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 0ab6e90..2c11464 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 @@
__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 7c97381..e211473 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_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index 704308f..eccdeab 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.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
@@ -144,13 +144,15 @@
enum ipa3_usb_transport_type {
IPA_USB_TRANSPORT_TETH,
IPA_USB_TRANSPORT_DPL,
+ IPA_USB_TRANSPORT_TETH_2,
IPA_USB_TRANSPORT_MAX
};
/* Get transport type from tethering protocol */
#define IPA3_USB_GET_TTYPE(__teth_prot) \
(((__teth_prot) == IPA_USB_DIAG) ? \
- IPA_USB_TRANSPORT_DPL : IPA_USB_TRANSPORT_TETH)
+ IPA_USB_TRANSPORT_DPL : (((__teth_prot) == IPA_USB_RMNET_CV2X) ? \
+ IPA_USB_TRANSPORT_TETH_2 : IPA_USB_TRANSPORT_TETH))
/* Does the given transport type is DPL? */
#define IPA3_USB_IS_TTYPE_DPL(__ttype) \
@@ -186,7 +188,7 @@
struct ipa3_usb_teth_prot_context
teth_prot_ctx[IPA_USB_MAX_TETH_PROT_SIZE];
int num_init_prot; /* without dpl */
- struct teth_bridge_init_params teth_bridge_params;
+ struct teth_bridge_init_params teth_bridge_params[IPA_TETH_BRIDGE_MAX];
struct completion dev_ready_comp;
u32 qmi_req_id;
spinlock_t state_lock;
@@ -198,6 +200,7 @@
struct dentry *dfile_state_info;
struct dentry *dent;
struct ipa3_usb_smmu_reg_map smmu_reg_map;
+ struct ipa3_usb_smmu_reg_map smmu_reg_map_dummy;
};
enum ipa3_usb_op {
@@ -704,6 +707,8 @@
case IPA_USB_RMNET:
case IPA_USB_MBIM:
return "teth_bridge";
+ case IPA_USB_RMNET_CV2X:
+ return "teth_bridge_cv2x";
case IPA_USB_DIAG:
return "dpl";
default:
@@ -719,6 +724,8 @@
switch (teth_prot) {
case IPA_USB_RMNET:
return "rmnet";
+ case IPA_USB_RMNET_CV2X:
+ return "rmnet_cv2x";
case IPA_USB_MBIM:
return "mbim";
default:
@@ -728,11 +735,18 @@
return "unsupported";
}
-static int ipa3_usb_init_teth_bridge(void)
+static int ipa3_usb_init_teth_bridge(enum ipa_usb_teth_prot teth_prot)
{
int result;
- result = teth_bridge_init(&ipa3_usb_ctx->teth_bridge_params);
+ if (teth_prot == IPA_USB_RMNET_CV2X)
+ result =
+ teth_bridge_init(
+ &ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2]);
+ else
+ result =
+ teth_bridge_init(
+ &ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1]);
if (result) {
IPA_USB_ERR("Failed to initialize teth_bridge.\n");
return result;
@@ -746,15 +760,26 @@
struct ipa3_usb_transport_type_ctx *ttype_ctx =
&ipa3_usb_ctx->ttype_ctx[ttype];
int result;
+ enum ipa_client_type consumer;
- /* there is one PM resource for teth and one for DPL */
- if (!IPA3_USB_IS_TTYPE_DPL(ttype) && ipa3_usb_ctx->num_init_prot > 0)
+ /*
+ * One PM resource for teth1,
+ * One PM resource for teth2 (CV2X),
+ * One for DPL,
+ */
+
+ if (!IPA3_USB_IS_TTYPE_DPL(ttype) && (ipa3_usb_ctx->num_init_prot > 0)
+ && (ttype != IPA_USB_TRANSPORT_TETH_2))
return 0;
memset(&ttype_ctx->pm_ctx.reg_params, 0,
sizeof(ttype_ctx->pm_ctx.reg_params));
- ttype_ctx->pm_ctx.reg_params.name = (ttype == IPA_USB_TRANSPORT_DPL) ?
- "USB DPL" : "USB";
+ ttype_ctx->pm_ctx.reg_params.name =
+ (ttype == IPA_USB_TRANSPORT_DPL) ?
+ "USB DPL" :
+ (ttype == IPA_USB_TRANSPORT_TETH_2) ?
+ "USB2" : "USB";
+
ttype_ctx->pm_ctx.reg_params.callback = ipa3_usb_pm_cb;
ttype_ctx->pm_ctx.reg_params.user_data = ttype_ctx;
ttype_ctx->pm_ctx.reg_params.group = IPA_PM_GROUP_DEFAULT;
@@ -766,9 +791,12 @@
goto fail_pm_reg;
}
+ consumer = (ttype == IPA_USB_TRANSPORT_DPL) ?
+ IPA_CLIENT_USB_DPL_CONS :
+ (ttype == IPA_USB_TRANSPORT_TETH_2) ?
+ IPA_CLIENT_USB2_CONS : IPA_CLIENT_USB_CONS;
result = ipa_pm_associate_ipa_cons_to_client(ttype_ctx->pm_ctx.hdl,
- (ttype == IPA_USB_TRANSPORT_DPL) ?
- IPA_CLIENT_USB_DPL_CONS : IPA_CLIENT_USB_CONS);
+ consumer);
if (result) {
IPA_USB_ERR("fail to associate cons with PM %d\n", result);
goto fail_pm_cons;
@@ -994,9 +1022,11 @@
goto bad_params;
}
ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data;
- result = ipa3_usb_init_teth_bridge();
+
+ result = ipa3_usb_init_teth_bridge(teth_prot);
if (result)
goto teth_prot_init_fail;
+
ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
IPA_USB_TETH_PROT_INITIALIZED;
ipa3_usb_ctx->num_init_prot++;
@@ -1004,6 +1034,26 @@
ipa3_usb_teth_prot_to_string(teth_prot),
ipa3_usb_teth_bridge_prot_to_string(teth_prot));
break;
+ case IPA_USB_RMNET_CV2X:
+ if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
+ IPA_USB_TETH_PROT_INVALID) {
+ IPA_USB_DBG("%s already initialized\n",
+ ipa3_usb_teth_prot_to_string(teth_prot));
+ result = -EPERM;
+ goto bad_params;
+ }
+ ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data = user_data;
+
+ result = ipa3_usb_init_teth_bridge(teth_prot);
+ if (result)
+ goto teth_prot_init_fail;
+
+ ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
+ IPA_USB_TETH_PROT_INITIALIZED;
+ IPA_USB_DBG("initialized %s %s\n",
+ ipa3_usb_teth_prot_to_string(teth_prot),
+ ipa3_usb_teth_bridge_prot_to_string(teth_prot));
+ break;
case IPA_USB_DIAG:
if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
IPA_USB_TETH_PROT_INVALID) {
@@ -1031,7 +1081,8 @@
teth_prot_init_fail:
if ((IPA3_USB_IS_TTYPE_DPL(ttype))
- || (ipa3_usb_ctx->num_init_prot == 0)) {
+ || (ipa3_usb_ctx->num_init_prot == 0)
+ || (teth_prot == IPA_USB_RMNET_CV2X)) {
if (ipa_pm_is_used()) {
ipa3_usb_deregister_pm(ttype);
} else {
@@ -1114,6 +1165,7 @@
}
break;
case IPA_USB_RMNET:
+ case IPA_USB_RMNET_CV2X:
case IPA_USB_MBIM:
if (ipa3_usb_ctx->teth_prot_ctx[params->teth_prot].state ==
IPA_USB_TETH_PROT_INVALID) {
@@ -1131,6 +1183,102 @@
return true;
}
+/*
+ * ipa3_usb_smmu_map_dummy: Does the same job of ipa3_usb_smmu_map_xdci_channel.
+ * API to map geventcount dummy addr, which will be provided
+ * to GSI from USB to handle sw path. Where USB driver will take
+ * care of replenishing desc to ipa hw. This dummy gevntcount addr
+ * cannot be in same page as other, since other are actual usb hw addr.
+ * We map this dummy addr to AP smmu context, so that there will
+ * not be any NOC issue when IPA/GSI tries to access it.
+ */
+static int ipa3_usb_smmu_map_dummy(
+ struct ipa_usb_xdci_chan_params *params,
+ bool map
+ )
+{
+ int result = 0;
+ u32 gevntcount_r = rounddown(params->gevntcount_low_addr, PAGE_SIZE);
+ u32 xfer_scratch_r =
+ rounddown(params->xfer_scratch.depcmd_low_addr, PAGE_SIZE);
+
+ if ((ipa3_usb_ctx->smmu_reg_map.addr != xfer_scratch_r) &&
+ (ipa3_usb_ctx->smmu_reg_map.cnt != 0)) {
+ IPA_USB_ERR("No support more than 1 page map for USB regs");
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
+ if (map) {
+ if (ipa3_usb_ctx->smmu_reg_map_dummy.cnt == 0) {
+ ipa3_usb_ctx->smmu_reg_map_dummy.addr = gevntcount_r;
+ result = ipa3_smmu_map_peer_reg(
+ ipa3_usb_ctx->smmu_reg_map_dummy.addr, true,
+ IPA_SMMU_CB_AP);
+ if (result) {
+ IPA_USB_ERR("failed to map USB regs %d\n",
+ result);
+ return result;
+ }
+
+ if (ipa3_usb_ctx->smmu_reg_map.cnt == 0) {
+ ipa3_usb_ctx->smmu_reg_map.addr =
+ xfer_scratch_r;
+ result = ipa3_smmu_map_peer_reg(
+ ipa3_usb_ctx->smmu_reg_map.addr, true,
+ IPA_SMMU_CB_AP);
+ if (result) {
+ IPA_USB_ERR(
+ "failed to map USB regs %d\n",
+ result);
+ return result;
+ }
+ }
+ ipa3_usb_ctx->smmu_reg_map.cnt++;
+ ipa3_usb_ctx->smmu_reg_map_dummy.cnt++;
+ }
+ } else {
+ if (gevntcount_r != ipa3_usb_ctx->smmu_reg_map_dummy.addr) {
+ IPA_USB_ERR(
+ "No support for unmap different reg\n");
+ return -EINVAL;
+ }
+
+ if (ipa3_usb_ctx->smmu_reg_map_dummy.cnt == 1) {
+ result = ipa3_smmu_map_peer_reg(
+ ipa3_usb_ctx->smmu_reg_map_dummy.addr, false,
+ IPA_SMMU_CB_AP);
+ if (result) {
+ IPA_USB_ERR("failed to unmap USB regs %d\n",
+ result);
+ return result;
+ }
+
+ if (ipa3_usb_ctx->smmu_reg_map.cnt == 1) {
+ if (xfer_scratch_r !=
+ ipa3_usb_ctx->smmu_reg_map.addr) {
+ IPA_USB_ERR(
+ "No support for un map different reg\n");
+ return -EINVAL;
+ }
+
+ result = ipa3_smmu_map_peer_reg(
+ ipa3_usb_ctx->smmu_reg_map.addr, false,
+ IPA_SMMU_CB_AP);
+ if (result) {
+ IPA_USB_ERR(
+ "failed to unmap USB regs %d\n",
+ result);
+ return result;
+ }
+ }
+ ipa3_usb_ctx->smmu_reg_map.cnt--;
+ ipa3_usb_ctx->smmu_reg_map_dummy.cnt--;
+ }
+ }
+ return result;
+}
+
static int ipa3_usb_smmu_map_xdci_channel(
struct ipa_usb_xdci_chan_params *params, bool map)
{
@@ -1139,13 +1287,22 @@
u32 xfer_scratch_r =
rounddown(params->xfer_scratch.depcmd_low_addr, PAGE_SIZE);
- if (gevntcount_r != xfer_scratch_r) {
+ if ((gevntcount_r != xfer_scratch_r) &&
+ (params->is_sw_path == false)) {
IPA_USB_ERR("No support more than 1 page map for USB regs\n");
WARN_ON(1);
return -EINVAL;
}
- if (map) {
+ if (params->is_sw_path == true) {
+ result = ipa3_usb_smmu_map_dummy(params, map);
+ if (result) {
+ IPA_USB_ERR("failed to %s USB regs %d\n",
+ (map == true)?"map":"unmap",
+ result);
+ return result;
+ }
+ } else if (map) {
if (ipa3_usb_ctx->smmu_reg_map.cnt == 0) {
ipa3_usb_ctx->smmu_reg_map.addr = gevntcount_r;
result = ipa3_smmu_map_peer_reg(
@@ -1184,7 +1341,6 @@
ipa3_usb_ctx->smmu_reg_map.cnt--;
}
-
result = ipa3_smmu_map_peer_buff(params->xfer_ring_base_addr_iova,
params->xfer_ring_len, map, params->sgt_xfer_rings,
IPA_SMMU_CB_AP);
@@ -1266,11 +1422,25 @@
case IPA_USB_RMNET:
case IPA_USB_MBIM:
chan_params.priv =
- ipa3_usb_ctx->teth_bridge_params.private_data;
+ ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].
+ private_data;
chan_params.notify =
- ipa3_usb_ctx->teth_bridge_params.usb_notify_cb;
+ ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].
+ usb_notify_cb;
chan_params.skip_ep_cfg =
- ipa3_usb_ctx->teth_bridge_params.skip_ep_cfg;
+ ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_1].
+ skip_ep_cfg;
+ break;
+ case IPA_USB_RMNET_CV2X:
+ chan_params.priv =
+ ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].
+ private_data;
+ chan_params.notify =
+ ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].
+ usb_notify_cb;
+ chan_params.skip_ep_cfg =
+ ipa3_usb_ctx->teth_bridge_params[IPA_TETH_BRIDGE_2].
+ skip_ep_cfg;
break;
case IPA_USB_DIAG:
chan_params.priv = NULL;
@@ -1571,6 +1741,16 @@
return 0;
}
+static int ipa3_get_tethering_mode(enum ipa_usb_teth_prot teth_prot)
+{
+ if (teth_prot == IPA_USB_RMNET)
+ return TETH_TETHERING_MODE_RMNET;
+ else if (teth_prot == IPA_USB_RMNET_CV2X)
+ return TETH_TETHERING_MODE_RMNET_2;
+ else
+ return TETH_TETHERING_MODE_MBIM;
+}
+
static int ipa3_usb_connect_teth_prot(enum ipa_usb_teth_prot teth_prot)
{
int result;
@@ -1639,6 +1819,7 @@
ipa3_usb_teth_prot_to_string(teth_prot));
break;
case IPA_USB_RMNET:
+ case IPA_USB_RMNET_CV2X:
case IPA_USB_MBIM:
if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state ==
IPA_USB_TETH_PROT_CONNECTED) {
@@ -1646,7 +1827,8 @@
ipa3_usb_teth_prot_to_string(teth_prot));
break;
}
- result = ipa3_usb_init_teth_bridge();
+
+ result = ipa3_usb_init_teth_bridge(teth_prot);
if (result)
return result;
@@ -1658,14 +1840,19 @@
teth_bridge_params.usb_ipa_pipe_hdl =
teth_conn_params->usb_to_ipa_clnt_hdl;
teth_bridge_params.tethering_mode =
- (teth_prot == IPA_USB_RMNET) ?
- (TETH_TETHERING_MODE_RMNET):(TETH_TETHERING_MODE_MBIM);
- teth_bridge_params.client_type = IPA_CLIENT_USB_PROD;
+ ipa3_get_tethering_mode(teth_prot);
+
+ if (teth_prot == IPA_USB_RMNET_CV2X)
+ teth_bridge_params.client_type = IPA_CLIENT_USB2_PROD;
+ else
+ teth_bridge_params.client_type = IPA_CLIENT_USB_PROD;
+
result = ipa3_usb_connect_teth_bridge(&teth_bridge_params);
if (result) {
ipa3_usb_ctx->ttype_ctx[ttype].user_data = NULL;
return result;
}
+
ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
IPA_USB_TETH_PROT_CONNECTED;
ipa3_usb_notify_do(ttype, IPA_USB_DEVICE_READY);
@@ -1704,11 +1891,15 @@
return 0;
}
-static int ipa3_usb_disconnect_teth_bridge(void)
+static int ipa3_usb_disconnect_teth_bridge(enum ipa_usb_teth_prot teth_prot)
{
int result;
- result = teth_bridge_disconnect(IPA_CLIENT_USB_PROD);
+ if (teth_prot == IPA_USB_RMNET_CV2X)
+ result = teth_bridge_disconnect(IPA_CLIENT_USB2_PROD);
+ else
+ result = teth_bridge_disconnect(IPA_CLIENT_USB_PROD);
+
if (result) {
IPA_USB_ERR("failed to disconnect teth_bridge.\n");
return result;
@@ -1774,6 +1965,7 @@
ipa3_usb_teth_prot_to_string(teth_prot));
break;
case IPA_USB_RMNET:
+ case IPA_USB_RMNET_CV2X:
case IPA_USB_MBIM:
if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
IPA_USB_TETH_PROT_CONNECTED) {
@@ -1782,7 +1974,8 @@
ipa3_usb_teth_bridge_prot_to_string(teth_prot));
return -EPERM;
}
- result = ipa3_usb_disconnect_teth_bridge();
+
+ result = ipa3_usb_disconnect_teth_bridge(teth_prot);
if (result)
break;
@@ -1828,8 +2021,7 @@
return -EINVAL;
}
- ttype = (params->teth_prot == IPA_USB_DIAG) ? IPA_USB_TRANSPORT_DPL :
- IPA_USB_TRANSPORT_TETH;
+ ttype = IPA3_USB_GET_TTYPE(params->teth_prot);
if (!ipa3_usb_check_legal_op(IPA_USB_OP_CONNECT, ttype)) {
IPA_USB_ERR("Illegal operation.\n");
@@ -2013,7 +2205,9 @@
for (i = 0 ; i < IPA_USB_MAX_TETH_PROT_SIZE ; i++) {
if (ipa3_usb_ctx->teth_prot_ctx[i].state ==
IPA_USB_TETH_PROT_INITIALIZED) {
- if ((i == IPA_USB_RMNET) || (i == IPA_USB_MBIM))
+ if ((i == IPA_USB_RMNET) ||
+ (i == IPA_USB_MBIM) ||
+ (i == IPA_USB_RMNET_CV2X))
status->inited_prots[status->num_init_prot++] =
ipa3_usb_teth_bridge_prot_to_string(i);
else
@@ -2023,6 +2217,7 @@
IPA_USB_TETH_PROT_CONNECTED) {
switch (i) {
case IPA_USB_RMNET:
+ case IPA_USB_RMNET_CV2X:
case IPA_USB_MBIM:
status->teth_connected_prot =
ipa3_usb_teth_bridge_prot_to_string(i);
@@ -2527,6 +2722,24 @@
ipa3_usb_teth_prot_to_string(teth_prot),
ipa3_usb_teth_bridge_prot_to_string(teth_prot));
break;
+ case IPA_USB_RMNET_CV2X:
+ if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
+ IPA_USB_TETH_PROT_INITIALIZED) {
+ IPA_USB_ERR("%s (%s) is not initialized\n",
+ ipa3_usb_teth_prot_to_string(teth_prot),
+ ipa3_usb_teth_bridge_prot_to_string(teth_prot));
+ result = -EINVAL;
+ goto bad_params;
+ }
+
+ ipa3_usb_ctx->teth_prot_ctx[teth_prot].user_data =
+ NULL;
+ ipa3_usb_ctx->teth_prot_ctx[teth_prot].state =
+ IPA_USB_TETH_PROT_INVALID;
+ IPA_USB_DBG("deinitialized %s (%s)\n",
+ ipa3_usb_teth_prot_to_string(teth_prot),
+ ipa3_usb_teth_bridge_prot_to_string(teth_prot));
+ break;
case IPA_USB_DIAG:
if (ipa3_usb_ctx->teth_prot_ctx[teth_prot].state !=
IPA_USB_TETH_PROT_INITIALIZED) {
@@ -2549,7 +2762,8 @@
}
if (IPA3_USB_IS_TTYPE_DPL(ttype) ||
- (ipa3_usb_ctx->num_init_prot == 0)) {
+ (ipa3_usb_ctx->num_init_prot == 0) ||
+ (teth_prot == IPA_USB_RMNET_CV2X)) {
if (!ipa3_usb_set_state(IPA_USB_INVALID, false, ttype))
IPA_USB_ERR(
"failed to change state to invalid\n");
@@ -2976,6 +3190,9 @@
pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH].pm_ctx;
pm_ctx->hdl = ~0;
pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
+ pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_TETH_2].pm_ctx;
+ pm_ctx->hdl = ~0;
+ pm_ctx->remote_wakeup_work = &ipa3_usb_notify_remote_wakeup_work;
pm_ctx = &ipa3_usb_ctx->ttype_ctx[IPA_USB_TRANSPORT_DPL].pm_ctx;
pm_ctx->hdl = ~0;
pm_ctx->remote_wakeup_work = &ipa3_usb_dpl_notify_remote_wakeup_work;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index 095d60b..50bb9bc 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 @@
* 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 @@
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 6de07dc..80513d2 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -624,6 +624,185 @@
kfree(buff);
}
+static void ipa3_get_usb_ep_info(
+ struct ipa_ioc_get_ep_info *ep_info,
+ struct ipa_ep_pair_info *pair_info
+ )
+{
+ int ep_index = -1, i;
+
+ ep_info->num_ep_pairs = 0;
+ for (i = 0; i < ep_info->max_ep_pairs; i++) {
+ pair_info[i].consumer_pipe_num = -1;
+ pair_info[i].producer_pipe_num = -1;
+ pair_info[i].ep_id = -1;
+ }
+
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD);
+
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB_CONS);
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
+ ep_index;
+ pair_info[ep_info->num_ep_pairs].ep_id =
+ IPA_USB0_EP_ID;
+
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ ep_info->num_ep_pairs++;
+ } else {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ }
+ }
+
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_PROD);
+
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_USB2_CONS);
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
+ ep_index;
+ pair_info[ep_info->num_ep_pairs].ep_id =
+ IPA_USB1_EP_ID;
+
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ ep_info->num_ep_pairs++;
+ } else {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ }
+ }
+}
+
+static void ipa3_get_pcie_ep_info(
+ struct ipa_ioc_get_ep_info *ep_info,
+ struct ipa_ep_pair_info *pair_info
+ )
+{
+ int ep_index = -1, i;
+
+ ep_info->num_ep_pairs = 0;
+ for (i = 0; i < ep_info->max_ep_pairs; i++) {
+ pair_info[i].consumer_pipe_num = -1;
+ pair_info[i].producer_pipe_num = -1;
+ pair_info[i].ep_id = -1;
+ }
+
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI_PROD);
+
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI_CONS);
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
+ ep_index;
+ pair_info[ep_info->num_ep_pairs].ep_id =
+ IPA_PCIE0_EP_ID;
+
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ ep_info->num_ep_pairs++;
+ } else {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ }
+ }
+
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI2_PROD);
+
+ if ((ep_index != -1) && ipa3_ctx->ep[ep_index].valid) {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = ep_index;
+ ep_index = ipa3_get_ep_mapping(IPA_CLIENT_MHI2_CONS);
+ if ((ep_index != -1) && (ipa3_ctx->ep[ep_index].valid)) {
+ pair_info[ep_info->num_ep_pairs].producer_pipe_num =
+ ep_index;
+ pair_info[ep_info->num_ep_pairs].ep_id =
+ IPA_PCIE1_EP_ID;
+
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ ep_info->num_ep_pairs++;
+ } else {
+ pair_info[ep_info->num_ep_pairs].consumer_pipe_num = -1;
+ IPADBG("ep_pair_info consumer_pipe_num %d",
+ pair_info[ep_info->num_ep_pairs].
+ consumer_pipe_num);
+ IPADBG(" producer_pipe_num %d ep_id %d\n",
+ pair_info[ep_info->num_ep_pairs].
+ producer_pipe_num,
+ pair_info[ep_info->num_ep_pairs].ep_id);
+ }
+ }
+}
+
+
+static int ipa3_get_ep_info(struct ipa_ioc_get_ep_info *ep_info,
+ u8 *param)
+{
+ int ret = 0;
+ struct ipa_ep_pair_info *pair_info = (struct ipa_ep_pair_info *)param;
+
+ switch (ep_info->ep_type) {
+ case IPA_DATA_EP_TYP_HSUSB:
+ ipa3_get_usb_ep_info(ep_info, pair_info);
+ break;
+
+ case IPA_DATA_EP_TYP_PCIE:
+ ipa3_get_pcie_ep_info(ep_info, pair_info);
+ break;
+
+ default:
+ IPAERR_RL("Undefined ep_type %d\n", ep_info->ep_type);
+ ret = -EFAULT;
+ break;
+ }
+
+ return ret;
+}
+
static int ipa3_send_gsb_msg(unsigned long usr_param, uint8_t msg_type)
{
int retval;
@@ -689,8 +868,10 @@
struct ipa_ioc_rm_dependency rm_depend;
struct ipa_ioc_nat_dma_cmd *table_dma_cmd;
struct ipa_ioc_get_vlan_mode vlan_mode;
+ struct ipa_ioc_get_ep_info ep_info;
size_t sz;
int pre_entry;
+ unsigned long uptr = 0;
IPADBG("cmd=%x nr=%d\n", cmd, _IOC_NR(cmd));
@@ -1878,6 +2059,60 @@
}
break;
+ case IPA_IOC_GET_PHERIPHERAL_EP_INFO:
+ IPADBG("Got IPA_IOC_GET_EP_INFO\n");
+ if (copy_from_user(&ep_info, (const void __user *)arg,
+ sizeof(struct ipa_ioc_get_ep_info))) {
+ IPAERR_RL("copy_from_user fails\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ if (ep_info.max_ep_pairs != QUERY_MAX_EP_PAIRS)
+ IPAERR_RL("unexpected max_ep_pairs %d\n",
+ ep_info.max_ep_pairs);
+
+ if (ep_info.ep_pair_size !=
+ (QUERY_MAX_EP_PAIRS * sizeof(struct ipa_ep_pair_info)))
+ IPAERR_RL("unexpected ep_pair_size %d\n",
+ ep_info.max_ep_pairs);
+
+ uptr = ep_info.info;
+ if (unlikely(!uptr)) {
+ IPAERR_RL("unexpected NULL info\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ param = kzalloc(ep_info.ep_pair_size, GFP_KERNEL);
+ if (!param) {
+ IPAERR_RL("kzalloc fails\n");
+ retval = -ENOMEM;
+ break;
+ }
+
+ retval = ipa3_get_ep_info(&ep_info, param);
+ if (retval < 0) {
+ IPAERR("ipa3_get_ep_info failed\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ if (copy_to_user((void __user *)uptr, param,
+ ep_info.ep_pair_size)) {
+ IPAERR_RL("copy_to_user fails\n");
+ retval = -EFAULT;
+ break;
+ }
+
+ if (copy_to_user((void __user *)arg, &ep_info,
+ sizeof(struct ipa_ioc_get_ep_info))) {
+ IPAERR_RL("copy_to_user fails\n");
+ retval = -EFAULT;
+ break;
+ }
+ break;
+
default:
IPA_ACTIVE_CLIENTS_DEC_SIMPLE();
return -ENOTTY;
@@ -2619,9 +2854,14 @@
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();
@@ -2636,9 +2876,16 @@
ipa3_q6_pipe_delay(false);
ipa3_set_reset_client_prod_pipe_delay(true,
IPA_CLIENT_USB_PROD);
- if (ipa3_ctx->ipa_config_is_mhi)
+ 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) {
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");
@@ -6371,6 +6618,7 @@
/* map SMEM memory for IPA table accesses */
smem_addr = smem_alloc(SMEM_IPA_FILTER_TABLE, IPA_SMEM_SIZE,
SMEM_MODEM, 0);
+ q6_smem_size = IPA_SMEM_SIZE;
} else {
IPADBG("ipa q6 smem size = %d\n", q6_smem_size);
smem_addr = smem_alloc(SMEM_IPA_FILTER_TABLE, q6_smem_size,
@@ -6383,7 +6631,7 @@
phys_addr_t pa_p;
u32 size_p;
- IPA_SMMU_ROUND_TO_PAGE(iova, pa, IPA_SMEM_SIZE,
+ IPA_SMMU_ROUND_TO_PAGE(iova, pa, q6_smem_size,
iova_p, pa_p, size_p);
IPADBG("mapping 0x%lx to 0x%pa size %d\n",
iova_p, &pa_p, size_p);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
index b090151..2272f5a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.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
@@ -51,7 +51,7 @@
memset(&gen_params, 0, sizeof(gen_params));
gen_params.ipt = ip;
- if (entry->rt_tbl)
+ if (entry->rt_tbl && (!ipa3_check_idr_if_freed(entry->rt_tbl)))
gen_params.rt_tbl_idx = entry->rt_tbl->idx;
else
gen_params.rt_tbl_idx = entry->rule.rt_tbl_idx;
@@ -1400,7 +1400,9 @@
entry->ipacm_installed) {
list_del(&entry->link);
entry->tbl->rule_cnt--;
- if (entry->rt_tbl)
+ if (entry->rt_tbl &&
+ (!ipa3_check_idr_if_freed(
+ entry->rt_tbl)))
entry->rt_tbl->ref_cnt--;
/* if rule id was allocated from idr, remove */
rule_id = entry->rule_id;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 2caa54e..511acf3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -2586,6 +2586,7 @@
void ipa3_disable_prefetch(enum ipa_client_type client);
int ipa3_alloc_common_event_ring(void);
int ipa3_allocate_dma_task_for_gsi(void);
+bool ipa3_check_idr_if_freed(void *ptr);
void ipa3_free_dma_task_for_gsi(void);
int ipa3_set_clock_plan_from_pm(int idx);
void __ipa_gsi_irq_rx_scedule_poll(struct ipa3_sys_context *sys);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index c4eb731..cc15baa 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 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 @@
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_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index ed2a43d..fc03952 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -97,6 +97,7 @@
proc_ctx = (entry->proc_ctx) ? : entry->hdr->proc_ctx;
if ((proc_ctx == NULL) ||
+ ipa3_check_idr_if_freed(proc_ctx) ||
(proc_ctx->cookie != IPA_PROC_HDR_COOKIE)) {
gen_params.hdr_type = IPAHAL_RT_RULE_HDR_NONE;
gen_params.hdr_ofst = 0;
@@ -730,7 +731,8 @@
set = &ipa3_ctx->rt_tbl_set[ip];
list_for_each_entry(entry, &set->head_rt_tbl_list, link) {
- if (!strcmp(name, entry->name))
+ if (!ipa3_check_idr_if_freed(entry) &&
+ !strcmp(name, entry->name))
return entry;
}
@@ -1367,7 +1369,8 @@
if (entry->hdr)
__ipa3_release_hdr(entry->hdr->id);
- else if (entry->proc_ctx)
+ else if (entry->proc_ctx &&
+ (!ipa3_check_idr_if_freed(entry->proc_ctx)))
__ipa3_release_hdr_proc_ctx(entry->proc_ctx->id);
list_del(&entry->link);
entry->tbl->rule_cnt--;
@@ -1568,7 +1571,9 @@
tbl->rule_cnt--;
if (rule->hdr)
__ipa3_release_hdr(rule->hdr->id);
- else if (rule->proc_ctx)
+ else if (rule->proc_ctx &&
+ (!ipa3_check_idr_if_freed(
+ rule->proc_ctx)))
__ipa3_release_hdr_proc_ctx(
rule->proc_ctx->id);
rule->cookie = 0;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 03b0c72..234e7a9 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 @@
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 @@
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 @@
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 @@
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 @@
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,
@@ -2076,6 +2088,7 @@
return false;
if (client == IPA_CLIENT_USB_CONS ||
+ client == IPA_CLIENT_USB2_CONS ||
client == IPA_CLIENT_USB_DPL_CONS ||
client == IPA_CLIENT_MHI_CONS ||
client == IPA_CLIENT_HSIC1_CONS ||
@@ -3856,6 +3869,7 @@
meta.qmap_id = param_in->qmap_id;
if (param_in->client == IPA_CLIENT_USB_PROD ||
+ param_in->client == IPA_CLIENT_USB2_PROD ||
param_in->client == IPA_CLIENT_HSIC1_PROD ||
param_in->client == IPA_CLIENT_ODU_PROD ||
param_in->client == IPA_CLIENT_ETHERNET_PROD) {
@@ -5412,8 +5426,8 @@
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");
@@ -6258,6 +6272,22 @@
&idle_indication_cfg);
}
+bool ipa3_check_idr_if_freed(void *ptr)
+{
+ int id;
+ void *iter_ptr;
+
+ spin_lock(&ipa3_ctx->idr_lock);
+ idr_for_each_entry(&ipa3_ctx->ipa_idr, iter_ptr, id) {
+ if ((uintptr_t)ptr == (uintptr_t)iter_ptr) {
+ spin_unlock(&ipa3_ctx->idr_lock);
+ return false;
+ }
+ }
+ spin_unlock(&ipa3_ctx->idr_lock);
+ return true;
+}
+
void ipa3_init_imm_cmd_desc(struct ipa3_desc *desc,
struct ipahal_imm_cmd_pyld *cmd_pyld)
{
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 530adef..35d5efc 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 @@
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 @@
/* 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/msm/ipa/ipa_v3/teth_bridge.c b/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c
index 0f5c61e..566e7bf 100644
--- a/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c
+++ b/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-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
@@ -38,6 +38,12 @@
#define TETH_ERR(fmt, args...) \
pr_err(TETH_BRIDGE_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+enum ipa_num_teth_iface {
+ IPA_TETH_IFACE_1 = 0,
+ IPA_TETH_IFACE_2 = 1,
+ IPA_TETH_IFACE_MAX
+};
+
/**
* struct ipa3_teth_bridge_ctx - Tethering bridge driver context information
* @class: kernel class pointer
@@ -50,7 +56,7 @@
dev_t dev_num;
struct device *dev;
struct cdev cdev;
- u32 modem_pm_hdl;
+ u32 modem_pm_hdl[IPA_TETH_IFACE_MAX];
};
static struct ipa3_teth_bridge_ctx *ipa3_teth_ctx;
@@ -120,21 +126,32 @@
int ipa3_teth_bridge_disconnect(enum ipa_client_type client)
{
int res = 0;
+ int *pm_hdl = NULL;
TETH_DBG_FUNC_ENTRY();
if (ipa_pm_is_used()) {
- res = ipa_pm_deactivate_sync(ipa3_teth_ctx->modem_pm_hdl);
+
+ if (client == IPA_CLIENT_USB2_PROD)
+ pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2];
+ else
+ pm_hdl = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1];
+
+ res = ipa_pm_deactivate_sync(*pm_hdl);
if (res) {
TETH_ERR("fail to deactivate modem %d\n", res);
return res;
}
- res = ipa_pm_deregister(ipa3_teth_ctx->modem_pm_hdl);
- ipa3_teth_ctx->modem_pm_hdl = ~0;
+ res = ipa_pm_deregister(*pm_hdl);
+ *pm_hdl = ~0;
} else {
- ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
- IPA_RM_RESOURCE_Q6_CONS);
- ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
- IPA_RM_RESOURCE_USB_CONS);
+ if (client == IPA_CLIENT_USB2_PROD) {
+ TETH_ERR("No support for rm added/validated.\n");
+ } else {
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_USB_PROD,
+ IPA_RM_RESOURCE_Q6_CONS);
+ ipa_rm_delete_dependency(IPA_RM_RESOURCE_Q6_PROD,
+ IPA_RM_RESOURCE_USB_CONS);
+ }
}
TETH_DBG_FUNC_EXIT();
@@ -154,23 +171,37 @@
{
int res = 0;
struct ipa_pm_register_params reg_params;
+ u32 *pm = NULL;
memset(®_params, 0, sizeof(reg_params));
TETH_DBG_FUNC_ENTRY();
if (ipa_pm_is_used()) {
- reg_params.name = "MODEM (USB RMNET)";
+ if (connect_params->tethering_mode ==
+ TETH_TETHERING_MODE_RMNET_2) {
+ reg_params.name = "MODEM (USB RMNET_CV2X)";
+ pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_2];
+ } else {
+ reg_params.name = "MODEM (USB RMNET)";
+ pm = &ipa3_teth_ctx->modem_pm_hdl[IPA_TETH_IFACE_1];
+ }
reg_params.group = IPA_PM_GROUP_MODEM;
reg_params.skip_clk_vote = true;
res = ipa_pm_register(®_params,
- &ipa3_teth_ctx->modem_pm_hdl);
+ pm);
if (res) {
TETH_ERR("fail to register with PM %d\n", res);
return res;
}
- res = ipa_pm_activate_sync(ipa3_teth_ctx->modem_pm_hdl);
+ res = ipa_pm_activate_sync(*pm);
+ goto bail;
+ }
+
+ if (connect_params->tethering_mode == TETH_TETHERING_MODE_RMNET_2) {
+ res = -EINVAL;
+ TETH_ERR("No support for rm added/validated.\n");
goto bail;
}
@@ -225,7 +256,7 @@
*/
int ipa3_teth_bridge_driver_init(void)
{
- int res;
+ int res, i;
TETH_DBG("Tethering bridge driver init\n");
ipa3_teth_ctx = kzalloc(sizeof(*ipa3_teth_ctx), GFP_KERNEL);
@@ -266,7 +297,9 @@
goto fail_cdev_add;
}
- ipa3_teth_ctx->modem_pm_hdl = ~0;
+ for (i = 0; i < IPA_TETH_IFACE_MAX; i++)
+ ipa3_teth_ctx->modem_pm_hdl[i] = ~0;
+
TETH_DBG("Tethering bridge driver init OK\n");
return 0;
diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c
index 0bf51d5..f2b9dd8 100644
--- a/drivers/platform/x86/intel_pmc_ipc.c
+++ b/drivers/platform/x86/intel_pmc_ipc.c
@@ -620,13 +620,17 @@
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/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index 69f2e1e..dddc7b0 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-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
@@ -118,6 +118,7 @@
#define QG_SDAM_ESR_DISCHARGE_DELTA_OFFSET 0x6E /* 4-byte 0x6E-0x71 */
#define QG_SDAM_ESR_CHARGE_SF_OFFSET 0x72 /* 2-byte 0x72-0x73 */
#define QG_SDAM_ESR_DISCHARGE_SF_OFFSET 0x74 /* 2-byte 0x74-0x75 */
+#define QG_SDAM_MAGIC_OFFSET 0x80 /* 4-byte 0x80-0x83 */
#define QG_SDAM_MAX_OFFSET 0xA4
/* Below offset is used by PBS */
diff --git a/drivers/power/supply/qcom/qg-sdam.c b/drivers/power/supply/qcom/qg-sdam.c
index a7cb97e..95ac8ec 100644
--- a/drivers/power/supply/qcom/qg-sdam.c
+++ b/drivers/power/supply/qcom/qg-sdam.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-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
@@ -88,6 +88,11 @@
.offset = QG_SDAM_ESR_DISCHARGE_SF_OFFSET,
.length = 2,
},
+ [SDAM_MAGIC] = {
+ .name = "SDAM_MAGIC_OFFSET",
+ .offset = QG_SDAM_MAGIC_OFFSET,
+ .length = 4,
+ },
};
int qg_sdam_write(u8 param, u32 data)
@@ -242,6 +247,23 @@
return 0;
}
+int qg_sdam_clear(void)
+{
+ int i, rc = 0;
+ struct qg_sdam *chip = the_chip;
+ u8 data = 0;
+
+ if (!chip) {
+ pr_err("Invalid sdam-chip pointer\n");
+ return -EINVAL;
+ }
+
+ for (i = SDAM_MIN_OFFSET; i <= SDAM_MAX_OFFSET; i++)
+ rc |= qg_sdam_multibyte_write(i, &data, 1);
+
+ return rc;
+}
+
int qg_sdam_init(struct device *dev)
{
int rc;
diff --git a/drivers/power/supply/qcom/qg-sdam.h b/drivers/power/supply/qcom/qg-sdam.h
index 45218a8..d365f25 100644
--- a/drivers/power/supply/qcom/qg-sdam.h
+++ b/drivers/power/supply/qcom/qg-sdam.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2018 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018-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
@@ -14,6 +14,8 @@
#define __QG_SDAM_H__
#define SDAM_TYPE 0x2E
+#define SDAM_MIN_OFFSET 0x45
+#define SDAM_MAX_OFFSET 0xB3
enum qg_sdam_param {
SDAM_VALID,
@@ -28,6 +30,7 @@
SDAM_ESR_DISCHARGE_DELTA,
SDAM_ESR_CHARGE_SF,
SDAM_ESR_DISCHARGE_SF,
+ SDAM_MAGIC,
SDAM_MAX,
};
@@ -43,5 +46,6 @@
int qg_sdam_read_all(u32 *sdam_data);
int qg_sdam_multibyte_write(u32 offset, u8 *sdam_data, u32 length);
int qg_sdam_multibyte_read(u32 offset, u8 *sdam_data, u32 length);
+int qg_sdam_clear(void);
#endif
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index f84e072..e3ebe66 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -2767,6 +2767,39 @@
return 0;
}
+#define SDAM_MAGIC_NUMBER 0x12345678
+static int qg_sanitize_sdam(struct qpnp_qg *chip)
+{
+ int rc = 0;
+ u32 data = 0;
+
+ rc = qg_sdam_read(SDAM_MAGIC, &data);
+ if (rc < 0) {
+ pr_err("Failed to read SDAM rc=%d\n", rc);
+ return rc;
+ }
+
+ if (data == SDAM_MAGIC_NUMBER) {
+ qg_dbg(chip, QG_DEBUG_PON, "SDAM valid\n");
+ } else if (data == 0) {
+ rc = qg_sdam_write(SDAM_MAGIC, SDAM_MAGIC_NUMBER);
+ if (!rc)
+ qg_dbg(chip, QG_DEBUG_PON, "First boot. SDAM initilized\n");
+ } else {
+ /* SDAM has invalid value */
+ rc = qg_sdam_clear();
+ if (!rc) {
+ pr_err("SDAM uninitialized, SDAM reset\n");
+ rc = qg_sdam_write(SDAM_MAGIC, SDAM_MAGIC_NUMBER);
+ }
+ }
+
+ if (rc < 0)
+ pr_err("Failed in SDAM operation, rc=%d\n", rc);
+
+ return rc;
+}
+
#define ADC_CONV_DLY_512MS 0xA
static int qg_hw_init(struct qpnp_qg *chip)
{
@@ -3794,6 +3827,12 @@
return rc;
}
+ rc = qg_sanitize_sdam(chip);
+ if (rc < 0) {
+ pr_err("Failed to sanitize SDAM, rc=%d\n", rc);
+ return rc;
+ }
+
rc = qg_soc_init(chip);
if (rc < 0) {
pr_err("Failed to initialize SOC scaling init rc=%d\n", rc);
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 1b7af04..addc387 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -303,10 +303,12 @@
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 @@
unsigned int i;
int ret = 0;
- pwmchip_sysfs_unexport_children(chip);
+ pwmchip_sysfs_unexport(chip);
mutex_lock(&pwm_lock);
@@ -360,8 +362,6 @@
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 9d5bd7d..f58a486 100644
--- a/drivers/pwm/pwm-meson.c
+++ b/drivers/pwm/pwm-meson.c
@@ -110,6 +110,10 @@
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 @@
{
u32 value, clk_shift, clk_enable, enable;
unsigned int offset;
+ unsigned long flags;
switch (id) {
case 0:
@@ -250,6 +255,8 @@
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 @@
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 @@
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 @@
{
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 @@
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 @@
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 c0e06f0..9a232eb 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -383,6 +383,8 @@
}
/* 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 50b7a3b..a0c3612 100644
--- a/drivers/pwm/sysfs.c
+++ b/drivers/pwm/sysfs.c
@@ -449,19 +449,6 @@
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 @@
}
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 bad0e0e..ef989a1 100644
--- a/drivers/rapidio/rio_cm.c
+++ b/drivers/rapidio/rio_cm.c
@@ -2145,6 +2145,14 @@
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/qpnp-rtc.c b/drivers/rtc/qpnp-rtc.c
index 06833ef..4b7a1d8 100644
--- a/drivers/rtc/qpnp-rtc.c
+++ b/drivers/rtc/qpnp-rtc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-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
@@ -597,7 +597,7 @@
rtc_ops = &qpnp_rtc_rw_ops;
dev_set_drvdata(&pdev->dev, rtc_dd);
-
+ device_init_wakeup(&pdev->dev, 1);
/* Register the RTC device */
rtc_dd->rtc = rtc_device_register("qpnp_rtc", &pdev->dev,
rtc_ops, THIS_MODULE);
@@ -627,6 +627,7 @@
fail_req_irq:
rtc_device_unregister(rtc_dd->rtc);
fail_rtc_enable:
+ device_init_wakeup(&pdev->dev, 0);
dev_set_drvdata(&pdev->dev, NULL);
return rc;
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
index 19e53b3..166faae 100644
--- a/drivers/rtc/rtc-88pm860x.c
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -414,7 +414,7 @@
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 28c48b3..3c8c6f9 100644
--- a/drivers/rtc/rtc-pcf8523.c
+++ b/drivers/rtc/rtc-pcf8523.c
@@ -82,6 +82,18 @@
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 @@
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 @@
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 f0e57ae..d167652 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -114,7 +114,7 @@
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 3528690..d0090c5 100644
--- a/drivers/s390/cio/qdio_setup.c
+++ b/drivers/s390/cio/qdio_setup.c
@@ -150,6 +150,7 @@
return -ENOMEM;
}
irq_ptr_qs[i] = q;
+ INIT_LIST_HEAD(&q->entry);
}
return 0;
}
@@ -178,6 +179,7 @@
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 30e9fbbf..debe69a 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -80,7 +80,6 @@
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 @@
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 58404e6..6ba4e92 100644
--- a/drivers/s390/net/qeth_l2_main.c
+++ b/drivers/s390/net/qeth_l2_main.c
@@ -2124,7 +2124,7 @@
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 a39a745..aeb9347 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -161,6 +161,7 @@
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 bdb257e..68146b3 100644
--- a/drivers/s390/scsi/zfcp_scsi.c
+++ b/drivers/s390/scsi/zfcp_scsi.c
@@ -124,6 +124,15 @@
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 96a0be1..5df597d 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -237,6 +237,53 @@
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 @@
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 9310a54..1435029 100644
--- a/drivers/s390/scsi/zfcp_unit.c
+++ b/drivers/s390/scsi/zfcp_unit.c
@@ -123,7 +123,7 @@
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 @@
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 5ff9f89..39b2f60 100644
--- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c
+++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c
@@ -829,7 +829,7 @@
((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 2ffe029..e974106 100644
--- a/drivers/scsi/cxgbi/libcxgbi.c
+++ b/drivers/scsi/cxgbi/libcxgbi.c
@@ -637,6 +637,10 @@
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 0b8db8a..9f98c72 100644
--- a/drivers/scsi/hpsa.c
+++ b/drivers/scsi/hpsa.c
@@ -4815,7 +4815,7 @@
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 @@
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 5961705..39bcbec 100644
--- a/drivers/scsi/hpsa_cmd.h
+++ b/drivers/scsi/hpsa_cmd.h
@@ -516,6 +516,7 @@
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 1a6f65d..400eee9 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -978,6 +978,8 @@
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 @@
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 4ac03b1..52afbcf 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1561,6 +1561,9 @@
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 4905455..b5be4df 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -6789,7 +6789,10 @@
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 8173645..9cca5dd 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -901,7 +901,11 @@
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 @@
}
}
+ 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_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 73c99f2..f0fcff0 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -3089,7 +3089,7 @@
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_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 c158967..d220b4f 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -5939,7 +5939,7 @@
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 4fba09b..f50c741 100755
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2324,6 +2324,7 @@
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 @@
} 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 06a0624..b12f7f9 100644
--- a/drivers/scsi/smartpqi/smartpqi_init.c
+++ b/drivers/scsi/smartpqi/smartpqi_init.c
@@ -5478,7 +5478,7 @@
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
old mode 100644
new mode 100755
index f5a6736..6226d75
--- a/drivers/scsi/ufs/ufshcd-pltfrm.c
+++ b/drivers/scsi/ufs/ufshcd-pltfrm.c
@@ -491,6 +491,7 @@
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 a90e661..c62184f 100755
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -2471,7 +2471,8 @@
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 @@
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 @@
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 @@
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 fcfbe2d..df6fabc 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -766,6 +766,7 @@
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 @@
}
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 e929f51..3622697 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -778,7 +778,7 @@
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/bg_rsb.c b/drivers/soc/qcom/bg_rsb.c
index 05fb9ab..c35e385 100644
--- a/drivers/soc/qcom/bg_rsb.c
+++ b/drivers/soc/qcom/bg_rsb.c
@@ -139,6 +139,7 @@
bool is_cnfgrd;
bool blk_rsb_cmnds;
+ bool pending_enable;
};
static void *bgrsb_drv;
@@ -406,6 +407,8 @@
struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
bg_down_work);
+ mutex_lock(&dev->rsb_state_mutex);
+
if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15) == 0)
dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
@@ -428,6 +431,8 @@
if (dev->is_calibrd)
dev->calibration_needed = true;
}
+
+ mutex_unlock(&dev->rsb_state_mutex);
}
static void bgrsb_glink_bgdown_work(struct work_struct *work)
@@ -436,17 +441,19 @@
struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
rsb_glink_down_work);
+ mutex_lock(&dev->rsb_state_mutex);
+
if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
rc = bgrsb_enable(dev, false);
if (rc != 0) {
pr_err("Failed to send disable command to BG\n");
- return;
+ goto unlock;
}
if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO15) != 0) {
pr_err("Failed to un-vote LDO-15\n");
- return;
+ goto unlock;
}
dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
@@ -468,6 +475,9 @@
glink_close(dev->handle);
dev->handle = NULL;
pr_debug("BG Glink Close connection\n");
+
+unlock:
+ mutex_unlock(&dev->rsb_state_mutex);
}
static int bgrsb_tx_msg(struct bgrsb_priv *dev, void *msg, size_t len)
@@ -558,6 +568,7 @@
struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
bg_up_work);
+ mutex_lock(&dev->rsb_state_mutex);
if (bgrsb_ldo_work(dev, BGRSB_ENABLE_LDO11) == 0) {
rc = wait_event_timeout(dev->link_state_wait,
@@ -565,20 +576,24 @@
msecs_to_jiffies(TIMEOUT_MS));
if (rc == 0) {
pr_err("Glink channel connection time out\n");
- return;
+ goto unlock;
}
rc = bgrsb_configr_rsb(dev, true);
if (rc != 0) {
pr_err("BG failed to configure RSB %d\n", rc);
if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0)
dev->bgrsb_current_state = BGRSB_STATE_INIT;
- return;
+ goto unlock;
}
dev->is_cnfgrd = true;
dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
pr_debug("RSB Cofigured\n");
+ if (dev->pending_enable)
+ queue_work(dev->bgrsb_wq, &dev->rsb_up_work);
}
+unlock:
+ mutex_unlock(&dev->rsb_state_mutex);
}
static void bgrsb_glink_bgup_work(struct work_struct *work)
@@ -587,6 +602,7 @@
struct bgrsb_priv *dev = container_of(work, struct bgrsb_priv,
rsb_glink_up_work);
+ mutex_lock(&dev->rsb_state_mutex);
if (bgrsb_ldo_work(dev, BGRSB_ENABLE_LDO11) == 0) {
INIT_WORK(&dev->glink_work, bgrsb_glink_open_work);
@@ -597,19 +613,25 @@
msecs_to_jiffies(TIMEOUT_MS));
if (rc == 0) {
pr_err("Glink channel connection time out\n");
- return;
+ goto unlock;
}
rc = bgrsb_configr_rsb(dev, true);
if (rc != 0) {
pr_err("BG Glink failed to configure RSB %d\n", rc);
if (bgrsb_ldo_work(dev, BGRSB_DISABLE_LDO11) == 0)
dev->bgrsb_current_state = BGRSB_STATE_INIT;
- return;
+ goto unlock;
}
dev->is_cnfgrd = true;
dev->bgrsb_current_state = BGRSB_STATE_RSB_CONFIGURED;
pr_debug("Glink RSB Cofigured\n");
+
+ if (dev->pending_enable)
+ queue_work(dev->bgrsb_wq, &dev->rsb_up_work);
}
+
+unlock:
+ mutex_unlock(&dev->rsb_state_mutex);
}
/**
@@ -625,6 +647,8 @@
switch (opcode) {
case SUBSYS_BEFORE_SHUTDOWN:
+ if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED)
+ dev->pending_enable = true;
queue_work(dev->bgrsb_wq, &dev->bg_down_work);
break;
case SUBSYS_AFTER_POWERUP:
@@ -669,8 +693,13 @@
rsb_up_work);
mutex_lock(&dev->rsb_state_mutex);
+ if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
+ pr_debug("RSB is already enabled\n");
+ goto unlock;
+ }
if (dev->bgrsb_current_state != BGRSB_STATE_RSB_CONFIGURED) {
pr_err("BG is not yet configured for RSB\n");
+ dev->pending_enable = true;
goto unlock;
}
@@ -685,6 +714,7 @@
}
}
dev->bgrsb_current_state = BGRSB_STATE_RSB_ENABLED;
+ dev->pending_enable = false;
pr_debug("RSB Enabled\n");
if (dev->calibration_needed) {
@@ -703,6 +733,7 @@
rsb_down_work);
mutex_lock(&dev->rsb_state_mutex);
+ dev->pending_enable = false;
if (dev->bgrsb_current_state == BGRSB_STATE_RSB_ENABLED) {
rc = bgrsb_enable(dev, false);
@@ -730,9 +761,11 @@
container_of(work, struct bgrsb_priv,
rsb_calibration_work);
+ mutex_lock(&dev->rsb_state_mutex);
+
if (!dev->is_cnfgrd) {
pr_err("RSB is not configured\n");
- return;
+ goto unlock;
}
req.cmd_id = 0x03;
@@ -741,7 +774,7 @@
rc = bgrsb_tx_msg(dev, &req, 5);
if (rc != 0) {
pr_err("Failed to send resolution value to BG\n");
- return;
+ goto unlock;
}
req.cmd_id = 0x04;
@@ -750,10 +783,13 @@
rc = bgrsb_tx_msg(dev, &req, 5);
if (rc != 0) {
pr_err("Failed to send interval value to BG\n");
- return;
+ goto unlock;
}
dev->is_calibrd = true;
pr_debug("RSB Calibbered\n");
+
+unlock:
+ mutex_unlock(&dev->rsb_state_mutex);
}
static void bgrsb_buttn_configration(struct work_struct *work)
@@ -764,9 +800,10 @@
container_of(work, struct bgrsb_priv,
bttn_configr_work);
+ mutex_lock(&dev->rsb_state_mutex);
if (!dev->is_cnfgrd) {
pr_err("RSB is not configured\n");
- return;
+ goto unlock;
}
req.cmd_id = 0x05;
@@ -775,11 +812,36 @@
rc = bgrsb_tx_msg(dev, &req, 5);
if (rc != 0) {
pr_err("Failed to send button configuration cmnd to BG\n");
- return;
+ goto unlock;
}
dev->bttn_configs = 0;
pr_debug("Button configured\n");
+
+unlock:
+ mutex_unlock(&dev->rsb_state_mutex);
+}
+
+static int bgrsb_handle_cmd_in_ssr(struct bgrsb_priv *dev, char *str)
+{
+ long val;
+ int ret;
+ char *tmp;
+
+ tmp = strsep(&str, ":");
+ if (!tmp)
+ return -EINVAL;
+
+ ret = kstrtol(tmp, 10, &val);
+ if (ret < 0)
+ return ret;
+
+ if (val == BGRSB_POWER_ENABLE)
+ dev->pending_enable = true;
+ else if (val == BGRSB_POWER_DISABLE)
+ dev->pending_enable = false;
+
+ return 0;
}
static int split_bg_work(struct bgrsb_priv *dev, char *str)
@@ -868,6 +930,7 @@
}
if (!dev->is_cnfgrd) {
+ bgrsb_handle_cmd_in_ssr(dev, arr);
kfree(arr);
return -ENOMEDIUM;
}
@@ -875,6 +938,7 @@
rc = split_bg_work(dev, arr);
if (rc != 0)
pr_err("Not able to process request\n");
+ kfree(arr);
return count;
}
diff --git a/drivers/soc/qcom/bgcom_spi.c b/drivers/soc/qcom/bgcom_spi.c
index 8ef2c06..7e58fb7 100644
--- a/drivers/soc/qcom/bgcom_spi.c
+++ b/drivers/soc/qcom/bgcom_spi.c
@@ -1078,7 +1078,6 @@
if (ret == 0) {
bg_spi->bg_state = BGCOM_STATE_SUSPEND;
atomic_set(&bg_is_spi_active, 0);
- disable_irq(bg_irq);
}
pr_info("suspended with : %d\n", ret);
return ret;
@@ -1094,8 +1093,6 @@
clnt_handle.bg_spi = spi;
atomic_set(&bg_is_spi_active, 1);
ret = bgcom_resume(&clnt_handle);
- if (ret == 0)
- enable_irq(bg_irq);
pr_info("Bgcom resumed with : %d\n", ret);
return ret;
}
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index e7f689a..4cdf613 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -907,9 +907,8 @@
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 @@
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/icnss.c b/drivers/soc/qcom/icnss.c
index a2cbfd8..f7bd0d9 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -199,6 +199,8 @@
ICNSS_DRIVER_EVENT_UNREGISTER_DRIVER,
ICNSS_DRIVER_EVENT_PD_SERVICE_DOWN,
ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND,
+ ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
+ ICNSS_DRIVER_EVENT_IDLE_RESTART,
ICNSS_DRIVER_EVENT_MAX,
};
@@ -291,6 +293,7 @@
ICNSS_MODE_ON,
ICNSS_BLOCK_SHUTDOWN,
ICNSS_PDR,
+ ICNSS_MODEM_CRASHED,
};
struct ce_irq_list {
@@ -626,6 +629,10 @@
return "PD_SERVICE_DOWN";
case ICNSS_DRIVER_EVENT_FW_EARLY_CRASH_IND:
return "FW_EARLY_CRASH_IND";
+ case ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN:
+ return "IDLE_SHUTDOWN";
+ case ICNSS_DRIVER_EVENT_IDLE_RESTART:
+ return "IDLE_RESTART";
case ICNSS_DRIVER_EVENT_MAX:
return "EVENT_MAX";
}
@@ -1395,7 +1402,7 @@
for (i = 0; i < resp.mem_region_info_len; i++) {
if (resp.mem_region_info[i].size > penv->msa_mem_size ||
- resp.mem_region_info[i].region_addr > max_mapped_addr ||
+ resp.mem_region_info[i].region_addr >= max_mapped_addr ||
resp.mem_region_info[i].region_addr < penv->msa_pa ||
resp.mem_region_info[i].size +
resp.mem_region_info[i].region_addr > max_mapped_addr) {
@@ -2361,6 +2368,7 @@
icnss_call_driver_shutdown(priv);
clear_bit(ICNSS_PDR, &priv->state);
+ clear_bit(ICNSS_MODEM_CRASHED, &priv->state);
clear_bit(ICNSS_REJUVENATE, &priv->state);
clear_bit(ICNSS_PD_RESTART, &priv->state);
priv->early_crash_ind = false;
@@ -2707,6 +2715,51 @@
return ret;
}
+static int icnss_driver_event_idle_shutdown(void *data)
+{
+ int ret = 0;
+
+ if (!penv->ops || !penv->ops->idle_shutdown)
+ return 0;
+
+ if (test_bit(ICNSS_MODEM_CRASHED, &penv->state) ||
+ test_bit(ICNSS_PDR, &penv->state) ||
+ test_bit(ICNSS_REJUVENATE, &penv->state)) {
+ icnss_pr_err("SSR/PDR is already in-progress during idle shutdown callback\n");
+ ret = -EBUSY;
+ } else {
+ icnss_pr_dbg("Calling driver idle shutdown, state: 0x%lx\n",
+ penv->state);
+ icnss_block_shutdown(true);
+ ret = penv->ops->idle_shutdown(&penv->pdev->dev);
+ icnss_block_shutdown(false);
+ }
+
+ return ret;
+}
+
+static int icnss_driver_event_idle_restart(void *data)
+{
+ int ret = 0;
+
+ if (!penv->ops || !penv->ops->idle_restart)
+ return 0;
+
+ if (test_bit(ICNSS_MODEM_CRASHED, &penv->state) ||
+ test_bit(ICNSS_PDR, &penv->state) ||
+ test_bit(ICNSS_REJUVENATE, &penv->state)) {
+ icnss_pr_err("SSR/PDR is already in-progress during idle restart callback\n");
+ ret = -EBUSY;
+ } else {
+ icnss_pr_dbg("Calling driver idle restart, state: 0x%lx\n",
+ penv->state);
+ icnss_block_shutdown(true);
+ ret = penv->ops->idle_restart(&penv->pdev->dev);
+ icnss_block_shutdown(false);
+ }
+
+ return ret;
+}
static void icnss_driver_event_work(struct work_struct *work)
{
@@ -2753,6 +2806,12 @@
ret = icnss_driver_event_early_crash_ind(penv,
event->data);
break;
+ case ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN:
+ ret = icnss_driver_event_idle_shutdown(event->data);
+ break;
+ case ICNSS_DRIVER_EVENT_IDLE_RESTART:
+ ret = icnss_driver_event_idle_restart(event->data);
+ break;
default:
icnss_pr_err("Invalid Event type: %d", event->type);
kfree(event);
@@ -2861,6 +2920,9 @@
priv->is_ssr = true;
+ if (notif->crashed)
+ set_bit(ICNSS_MODEM_CRASHED, &priv->state);
+
if (code == SUBSYS_BEFORE_SHUTDOWN && !notif->crashed &&
test_bit(ICNSS_BLOCK_SHUTDOWN, &priv->state)) {
if (!wait_for_completion_timeout(&priv->unblock_shutdown,
@@ -3745,6 +3807,48 @@
}
EXPORT_SYMBOL(icnss_trigger_recovery);
+int icnss_idle_shutdown(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (!priv) {
+ icnss_pr_err("Invalid drvdata: dev %pK", dev);
+ return -EINVAL;
+ }
+
+ if (test_bit(ICNSS_MODEM_CRASHED, &priv->state) ||
+ test_bit(ICNSS_PDR, &priv->state) ||
+ test_bit(ICNSS_REJUVENATE, &penv->state)) {
+ icnss_pr_err("SSR/PDR is already in-progress during idle shutdown\n");
+ return -EBUSY;
+ }
+
+ return icnss_driver_event_post(ICNSS_DRIVER_EVENT_IDLE_SHUTDOWN,
+ ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
+}
+EXPORT_SYMBOL(icnss_idle_shutdown);
+
+int icnss_idle_restart(struct device *dev)
+{
+ struct icnss_priv *priv = dev_get_drvdata(dev);
+
+ if (!priv) {
+ icnss_pr_err("Invalid drvdata: dev %pK", dev);
+ return -EINVAL;
+ }
+
+ if (test_bit(ICNSS_MODEM_CRASHED, &priv->state) ||
+ test_bit(ICNSS_PDR, &priv->state) ||
+ test_bit(ICNSS_REJUVENATE, &penv->state)) {
+ icnss_pr_err("SSR/PDR is already in-progress during idle restart\n");
+ return -EBUSY;
+ }
+
+ return icnss_driver_event_post(ICNSS_DRIVER_EVENT_IDLE_RESTART,
+ ICNSS_EVENT_SYNC_UNINTERRUPTIBLE, NULL);
+}
+EXPORT_SYMBOL(icnss_idle_restart);
+
static int icnss_smmu_init(struct icnss_priv *priv)
{
@@ -4241,6 +4345,10 @@
continue;
case ICNSS_PDR:
seq_puts(s, "PDR TRIGGERED");
+ continue;
+ case ICNSS_MODEM_CRASHED:
+ seq_puts(s, "MODEM CRASHED");
+ continue;
}
seq_printf(s, "UNKNOWN-%d", i);
diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c
index 4f3c264..aed5ab4 100644
--- a/drivers/soc/qcom/rpmh.c
+++ b/drivers/soc/qcom/rpmh.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-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
@@ -908,6 +908,7 @@
*/
int rpmh_flush(struct rpmh_client *rc)
{
+ DEFINE_RPMH_MSG_ONSTACK(rc, 0, NULL, NULL, rpm_msg);
struct rpmh_req *p;
struct rpmh_mbox *rpm = rc->rpmh;
int ret;
@@ -930,6 +931,13 @@
}
spin_unlock_irqrestore(&rpm->lock, flags);
+ /* Invalidate sleep and wake TCS */
+ rpm_msg.msg.invalidate = true;
+ rpm_msg.msg.is_complete = false;
+ ret = mbox_write_controller_data(rc->chan, &rpm_msg.msg);
+ if (ret)
+ return ret;
+
/* First flush the cached passthru's */
ret = flush_passthru(rc);
if (ret)
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index c9489e3..e82b6ef 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -643,6 +643,9 @@
/* 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 @@
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 3aa9e6e..4ef5443 100644
--- a/drivers/spi/spi-bitbang.c
+++ b/drivers/spi/spi-bitbang.c
@@ -392,7 +392,7 @@
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 f2209ec..6dd195b 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -921,10 +921,14 @@
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 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 093c9cf..07612e8 100644
--- a/drivers/spi/spi-rspi.c
+++ b/drivers/spi/spi-rspi.c
@@ -279,7 +279,8 @@
/* 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 @@
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 @@
/* 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 73779ce..705f515 100644
--- a/drivers/spi/spi-tegra114.c
+++ b/drivers/spi/spi-tegra114.c
@@ -1067,27 +1067,19 @@
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 @@
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 @@
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 @@
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 c54ee66..fe70744 100644
--- a/drivers/spi/spi-topcliff-pch.c
+++ b/drivers/spi/spi-topcliff-pch.c
@@ -1306,18 +1306,27 @@
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 @@
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 c2e85e2..d74d341 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -955,6 +955,8 @@
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 d70568e..2ff7d90 100644
--- a/drivers/ssb/bridge_pcmcia_80211.c
+++ b/drivers/ssb/bridge_pcmcia_80211.c
@@ -113,16 +113,21 @@
.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/android/lowmemorykiller.c b/drivers/staging/android/lowmemorykiller.c
index ecae4c9..d54e68b 100644
--- a/drivers/staging/android/lowmemorykiller.c
+++ b/drivers/staging/android/lowmemorykiller.c
@@ -98,6 +98,153 @@
pr_info(x); \
} while (0)
+
+static DECLARE_WAIT_QUEUE_HEAD(event_wait);
+static DEFINE_SPINLOCK(lmk_event_lock);
+static struct circ_buf event_buffer;
+#define MAX_BUFFERED_EVENTS 8
+#define MAX_TASKNAME 128
+
+struct lmk_event {
+ char taskname[MAX_TASKNAME];
+ pid_t pid;
+ uid_t uid;
+ pid_t group_leader_pid;
+ unsigned long min_flt;
+ unsigned long maj_flt;
+ unsigned long rss_in_pages;
+ short oom_score_adj;
+ short min_score_adj;
+ unsigned long long start_time;
+ struct list_head list;
+};
+
+void handle_lmk_event(struct task_struct *selected, int selected_tasksize,
+ short min_score_adj)
+{
+ int head;
+ int tail;
+ struct lmk_event *events;
+ struct lmk_event *event;
+ int res;
+ char taskname[MAX_TASKNAME];
+
+ res = get_cmdline(selected, taskname, MAX_TASKNAME - 1);
+
+ /* No valid process name means this is definitely not associated with a
+ * userspace activity.
+ */
+
+ if (res <= 0 || res >= MAX_TASKNAME)
+ return;
+
+ taskname[res] = '\0';
+
+ spin_lock(&lmk_event_lock);
+
+ head = event_buffer.head;
+ tail = READ_ONCE(event_buffer.tail);
+
+ /* Do not continue to log if no space remains in the buffer. */
+ if (CIRC_SPACE(head, tail, MAX_BUFFERED_EVENTS) < 1) {
+ spin_unlock(&lmk_event_lock);
+ return;
+ }
+
+ events = (struct lmk_event *) event_buffer.buf;
+ event = &events[head];
+
+ memcpy(event->taskname, taskname, res + 1);
+
+ event->pid = selected->pid;
+ event->uid = from_kuid_munged(current_user_ns(), task_uid(selected));
+ if (selected->group_leader)
+ event->group_leader_pid = selected->group_leader->pid;
+ else
+ event->group_leader_pid = -1;
+ event->min_flt = selected->min_flt;
+ event->maj_flt = selected->maj_flt;
+ event->oom_score_adj = selected->signal->oom_score_adj;
+ event->start_time = nsec_to_clock_t(selected->real_start_time);
+ event->rss_in_pages = selected_tasksize;
+ event->min_score_adj = min_score_adj;
+
+ event_buffer.head = (head + 1) & (MAX_BUFFERED_EVENTS - 1);
+
+ spin_unlock(&lmk_event_lock);
+
+ wake_up_interruptible(&event_wait);
+}
+
+static int lmk_event_show(struct seq_file *s, void *unused)
+{
+ struct lmk_event *events = (struct lmk_event *) event_buffer.buf;
+ int head;
+ int tail;
+ struct lmk_event *event;
+
+ spin_lock(&lmk_event_lock);
+
+ head = event_buffer.head;
+ tail = event_buffer.tail;
+
+ if (head == tail) {
+ spin_unlock(&lmk_event_lock);
+ return -EAGAIN;
+ }
+
+ event = &events[tail];
+
+ seq_printf(s, "%lu %lu %lu %lu %lu %lu %hd %hd %llu\n%s\n",
+ (unsigned long) event->pid, (unsigned long) event->uid,
+ (unsigned long) event->group_leader_pid, event->min_flt,
+ event->maj_flt, event->rss_in_pages, event->oom_score_adj,
+ event->min_score_adj, event->start_time, event->taskname);
+
+ event_buffer.tail = (tail + 1) & (MAX_BUFFERED_EVENTS - 1);
+
+ spin_unlock(&lmk_event_lock);
+ return 0;
+}
+
+static unsigned int lmk_event_poll(struct file *file, poll_table *wait)
+{
+ int ret = 0;
+
+ poll_wait(file, &event_wait, wait);
+ spin_lock(&lmk_event_lock);
+ if (event_buffer.head != event_buffer.tail)
+ ret = POLLIN;
+ spin_unlock(&lmk_event_lock);
+ return ret;
+}
+
+static int lmk_event_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, lmk_event_show, inode->i_private);
+}
+
+static const struct file_operations event_file_ops = {
+ .open = lmk_event_open,
+ .poll = lmk_event_poll,
+ .read = seq_read
+};
+
+static void lmk_event_init(void)
+{
+ struct proc_dir_entry *entry;
+
+ event_buffer.head = 0;
+ event_buffer.tail = 0;
+ event_buffer.buf = kmalloc(
+ sizeof(struct lmk_event) * MAX_BUFFERED_EVENTS, GFP_KERNEL);
+ if (!event_buffer.buf)
+ return;
+ entry = proc_create("lowmemorykiller", 0, NULL, &event_file_ops);
+ if (!entry)
+ pr_err("error creating kernel lmk event file\n");
+}
+
static unsigned long lowmem_count(struct shrinker *s,
struct shrink_control *sc)
{
@@ -635,6 +782,7 @@
lowmem_deathpending_timeout = jiffies + HZ;
rem += selected_tasksize;
rcu_read_unlock();
+ get_task_struct(selected);
/* give the system time to free up the memory */
msleep_interruptible(20);
trace_almk_shrink(selected_tasksize, ret,
@@ -649,6 +797,10 @@
sc->nr_to_scan, sc->gfp_mask, rem);
mutex_unlock(&scan_mutex);
+ if (selected) {
+ handle_lmk_event(selected, selected_tasksize, min_score_adj);
+ put_task_struct(selected);
+ }
return rem;
}
@@ -662,6 +814,7 @@
{
register_shrinker(&lowmem_shrinker);
vmpressure_notifier_register(&lmk_vmpr_nb);
+ lmk_event_init();
return 0;
}
device_initcall(lowmem_init);
diff --git a/drivers/staging/comedi/drivers/amplc_pci230.c b/drivers/staging/comedi/drivers/amplc_pci230.c
index 42945de..d23aa5d 100644
--- a/drivers/staging/comedi/drivers/amplc_pci230.c
+++ b/drivers/staging/comedi/drivers/amplc_pci230.c
@@ -2337,7 +2337,8 @@
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 d5295bb..37133d5 100644
--- a/drivers/staging/comedi/drivers/dt282x.c
+++ b/drivers/staging/comedi/drivers/dt282x.c
@@ -566,7 +566,8 @@
}
#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 50a5b0c2..7ab95ef 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 @@
{
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 @@
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 3f9fe6a..ebbe1ec 100644
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -162,7 +162,8 @@
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 655c7948..2fa4f91 100644
--- a/drivers/tty/ipwireless/main.c
+++ b/drivers/tty/ipwireless/main.c
@@ -113,6 +113,10 @@
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 @@
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 e8e8973..447d791 100644
--- a/drivers/tty/rocket.c
+++ b/drivers/tty/rocket.c
@@ -279,7 +279,7 @@
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 3177264..22d65a3 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -269,7 +269,7 @@
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 @@
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 5b54439..84474f0 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1814,8 +1814,7 @@
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 5331baf..ec3db8d 100644
--- a/drivers/tty/serial/max310x.c
+++ b/drivers/tty/serial/max310x.c
@@ -579,7 +579,7 @@
}
/* 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 99b40d9..7700e8a 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -890,6 +890,7 @@
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 @@
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 2a5979f..ccf9988 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -144,9 +144,6 @@
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 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 @@
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 @@
}
#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 59828d8..5ad978a 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -392,7 +392,7 @@
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 6a15b72..0f98594 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -1621,6 +1621,25 @@
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 @@
.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 876679a..2476d66 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -931,8 +931,8 @@
/* 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 6a4ea98..184a1fb 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -3111,6 +3111,9 @@
{
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 d6c3df6..4ebc1a8 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5738,7 +5738,10 @@
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 733479d..19e819a 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -64,9 +64,15 @@
/* 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 0e54353..120c8f7 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2552,8 +2552,10 @@
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 @@
* 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 @@
* 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/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a2a4438..b9a560b 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -71,6 +71,12 @@
module_param(cpu_to_affin, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(cpu_to_affin, "affin usb irq to this cpu");
+/* Interrupt moderation for normal endpoints */
+static unsigned int dwc3_gadget_imod_val;
+module_param(dwc3_gadget_imod_val, int, 0644);
+MODULE_PARM_DESC(dwc3_gadget_imod_val,
+ "Interrupt moderation in usecs for normal EPs");
+
/* XHCI registers */
#define USB3_HCSPARAMS1 (0x4)
#define USB3_HCCPARAMS2 (0x1c)
@@ -120,6 +126,12 @@
#define GSI_RING_BASE_ADDR_L(n) ((QSCRATCH_REG_OFFSET + 0x130) + (n*4))
#define GSI_RING_BASE_ADDR_H(n) ((QSCRATCH_REG_OFFSET + 0x144) + (n*4))
+#define IMOD(n) ((QSCRATCH_REG_OFFSET + 0x170) + (n*4))
+#define IMOD_EE_EN_MASK BIT(12)
+#define IMOD_EE_CNT_MASK 0x7FF
+
+#define USEC_CNT (QSCRATCH_REG_OFFSET + 0x180)
+
#define GSI_IF_STS (QSCRATCH_REG_OFFSET + 0x1A4)
#define GSI_WR_CTRL_STATE_MASK BIT(15)
@@ -312,7 +324,7 @@
u64 dummy_gsi_db;
dma_addr_t dummy_gsi_db_dma;
- u64 dummy_gevntcnt;
+ u64 *dummy_gevntcnt;
dma_addr_t dummy_gevntcnt_dma;
};
@@ -919,7 +931,7 @@
ch_info->gevntcount_hi_addr =
(u32)((u64)mdwc->dummy_gevntcnt_dma >> 32);
dev_dbg(dwc->dev, "Dummy GEVNTCNT Addr %pK: %llx %x (LSB)\n",
- &mdwc->dummy_gevntcnt,
+ mdwc->dummy_gevntcnt,
(unsigned long long)mdwc->dummy_gevntcnt_dma,
(u32)mdwc->dummy_gevntcnt_dma);
}
@@ -2147,14 +2159,14 @@
* Set-up dummy GEVNTCOUNT address to be passed on to GSI for
* normal (non HW-accelerated) EPs.
*/
- mdwc->dummy_gevntcnt_dma = dma_map_single(dwc->sysdev,
- &mdwc->dummy_gevntcnt,
- sizeof(mdwc->dummy_gevntcnt),
- DMA_FROM_DEVICE);
- if (dma_mapping_error(dwc->sysdev, mdwc->dummy_gevntcnt_dma)) {
- dev_err(dwc->dev, "failed to map dummy geventcount\n");
+ mdwc->dummy_gevntcnt =
+ kzalloc(sizeof(*mdwc->dummy_gevntcnt), GFP_KERNEL);
+ if (!mdwc->dummy_gevntcnt) {
mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
+ break;
}
+
+ mdwc->dummy_gevntcnt_dma = virt_to_phys(mdwc->dummy_gevntcnt);
break;
case DWC3_GSI_EVT_BUF_SETUP:
dev_dbg(mdwc->dev, "DWC3_GSI_EVT_BUF_SETUP\n");
@@ -2229,10 +2241,8 @@
evt->buf, evt->dma);
}
if (mdwc->dummy_gevntcnt_dma) {
- dma_unmap_single(dwc->sysdev, mdwc->dummy_gevntcnt_dma,
- sizeof(mdwc->dummy_gevntcnt),
- DMA_FROM_DEVICE);
mdwc->dummy_gevntcnt_dma = (dma_addr_t)NULL;
+ kfree(mdwc->dummy_gevntcnt);
}
if (mdwc->dummy_gsi_db_dma) {
dma_unmap_single(dwc->sysdev, mdwc->dummy_gsi_db_dma,
@@ -4405,9 +4415,22 @@
msm_dwc3_perf_vote_update(mdwc, true);
schedule_delayed_work(&mdwc->perf_vote_work,
msecs_to_jiffies(1000 * PM_QOS_SAMPLE_SEC));
+ if (dwc3_gadget_imod_val > 0) {
+ dwc3_msm_write_reg(mdwc->base, USEC_CNT, 0x7D);
+ dwc3_msm_write_reg_field(mdwc->base, IMOD(0),
+ IMOD_EE_CNT_MASK,
+ dwc3_gadget_imod_val);
+ dwc3_msm_write_reg_field(mdwc->base, IMOD(0),
+ IMOD_EE_EN_MASK, 0x1);
+ }
} else {
dev_dbg(mdwc->dev, "%s: turn off gadget %s\n",
__func__, dwc->gadget.name);
+ dwc3_msm_write_reg_field(mdwc->base, IMOD(0),
+ IMOD_EE_EN_MASK, 0x0);
+ dwc3_msm_write_reg_field(mdwc->base, IMOD(0),
+ IMOD_EE_CNT_MASK, 0x0);
+ dwc3_msm_write_reg(mdwc->base, USEC_CNT, 0x0);
cancel_delayed_work_sync(&mdwc->perf_vote_work);
msm_dwc3_perf_vote_update(mdwc, false);
pm_qos_remove_request(&mdwc->pm_qos_req_dma);
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 1235287..8438999 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -744,6 +744,21 @@
dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
}
+
+ if (dep->number == 1 && dwc->ep0state != EP0_SETUP_PHASE) {
+ unsigned int dir;
+
+ dbg_log_string("CTRLPEND %d", dwc->ep0state);
+ dir = !!dwc->ep0_expect_in;
+ if (dwc->ep0state == EP0_DATA_PHASE)
+ dwc3_ep0_end_control_data(dwc, dwc->eps[dir]);
+ else
+ dwc3_ep0_end_control_data(dwc, dwc->eps[!dir]);
+
+ dwc->eps[0]->trb_enqueue = 0;
+ dwc->eps[1]->trb_enqueue = 0;
+ }
+
dbg_log_string("DONE for %s(%d)", dep->name, dep->number);
}
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index d58b20a..1cd612a 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -535,6 +535,7 @@
{
int ret;
struct f_gsi *gsi = d_port_to_gsi(d_port);
+ struct f_gsi *gsi_rmnet_v2x = __gsi[USB_PROT_RMNET_V2X_IPA];
struct ipa_usb_xdci_chan_params *in_params =
&d_port->ipa_in_channel_params;
struct ipa_usb_xdci_chan_params *out_params =
@@ -663,6 +664,23 @@
gsi_channel_info.depcmd_hi_addr;
}
+ /*
+ * When both RmNet LTE and V2X instances are enabled in a composition,
+ * set 'is_sw_path' flag to true for LTE, so that IPA can ignore the
+ * dummy address for GEVENTCOUNT register.
+ */
+ in_params->is_sw_path = false;
+ if (gsi->prot_id == USB_PROT_RMNET_IPA &&
+ gsi_rmnet_v2x->function.fs_descriptors)
+ in_params->is_sw_path = true;
+
+ if (d_port->out_ep) {
+ out_params->is_sw_path = false;
+ if (gsi->prot_id == USB_PROT_RMNET_IPA &&
+ gsi_rmnet_v2x->function.fs_descriptors)
+ out_params->is_sw_path = true;
+ }
+
/* Populate connection params */
conn_params->max_pkt_size =
(cdev->gadget->speed == USB_SPEED_SUPER) ?
@@ -2206,7 +2224,6 @@
queue_work(gsi->c_port.uevent_wq,
&gsi->c_port.uevent_work);
- gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
value = 0;
break;
case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8)
@@ -2415,6 +2432,7 @@
unsigned int alt)
{
struct f_gsi *gsi = func_to_gsi(f);
+ struct f_gsi *gsi_rmnet_v2x = __gsi[USB_PROT_RMNET_V2X_IPA];
struct usb_composite_dev *cdev = f->config->cdev;
struct net_device *net;
int ret;
@@ -2489,12 +2507,18 @@
goto notify_ep_disable;
}
- /* Configure EPs for GSI */
+ /*
+ * Configure EPs for GSI. Note that when both RmNet LTE
+ * and V2X instances are enabled in a composition,
+ * configure HW accelerated EPs for V2X instance and
+ * normal EPs for LTE.
+ */
if (gsi->d_port.in_ep &&
gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
if (gsi->prot_id == USB_PROT_DIAG_IPA)
gsi->d_port.in_ep->ep_intr_num = 3;
- else if (gsi->prot_id == USB_PROT_RMNET_V2X_IPA)
+ else if (gsi->prot_id == USB_PROT_RMNET_IPA &&
+ gsi_rmnet_v2x->function.fs_descriptors)
gsi->d_port.in_ep->ep_intr_num = 0;
else
gsi->d_port.in_ep->ep_intr_num = 2;
@@ -2505,7 +2529,8 @@
if (gsi->d_port.out_ep &&
gsi->prot_id <= USB_PROT_RMNET_V2X_IPA) {
- if (gsi->prot_id == USB_PROT_RMNET_V2X_IPA)
+ if (gsi->prot_id == USB_PROT_RMNET_IPA &&
+ gsi_rmnet_v2x->function.fs_descriptors)
gsi->d_port.out_ep->ep_intr_num = 0;
else
gsi->d_port.out_ep->ep_intr_num = 1;
@@ -2575,7 +2600,10 @@
if (gsi->prot_id == USB_PROT_DIAG_IPA ||
gsi->prot_id == USB_PROT_DPL_ETHER ||
gsi->prot_id == USB_PROT_GPS_CTRL ||
- gsi->prot_id == USB_PROT_MBIM_IPA)
+ gsi->prot_id == USB_PROT_MBIM_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_V2X_IPA ||
+ gsi->prot_id == USB_PROT_RMNET_ETHER)
gsi_ctrl_send_cpkt_tomodem(gsi, NULL, 0);
if (gsi->c_port.uevent_wq)
diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 0c71938..53f9bea 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -857,6 +857,8 @@
dev_err(dev, "failed to map buffer\n");
return -EFAULT;
}
+
+ req->dma_mapped = 1;
}
return 0;
@@ -881,9 +883,10 @@
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
req->num_mapped_sgs = 0;
- } else if (req->dma != DMA_ERROR_CODE) {
+ } else if (req->dma_mapped) {
dma_unmap_single(dev, req->dma, req->length,
is_in ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
+ req->dma_mapped = 0;
}
}
EXPORT_SYMBOL_GPL(usb_gadget_unmap_request_by_dev);
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index 948845c..351012c 100644
--- a/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1345,12 +1345,15 @@
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 @@
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 8f32b5e..6df1ade 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -935,8 +935,7 @@
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 fe5db15..a142339 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -668,6 +668,7 @@
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 @@
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 @@
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 @@
/* 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 201bd55..52495fc 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 @@
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 @@
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 @@
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 @@
* 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 13731d5..6e761fa 100644
--- a/drivers/usb/misc/rio500.c
+++ b/drivers/usb/misc/rio500.c
@@ -103,9 +103,22 @@
{
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 @@
{
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 @@
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 @@
"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 @@
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 05bd39d..b7a4ba0 100644
--- a/drivers/usb/misc/sisusbvga/sisusb.c
+++ b/drivers/usb/misc/sisusbvga/sisusb.c
@@ -3041,6 +3041,13 @@
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 @@
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/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index c0c8a88..f7903ad 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2018, Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2019, 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
@@ -879,6 +879,8 @@
mb();
}
+static void msm_chg_block_on(struct msm_otg *);
+
static int msm_otg_reset(struct usb_phy *phy)
{
struct msm_otg *motg = container_of(phy, struct msm_otg, phy);
@@ -977,6 +979,9 @@
*/
msm_usb_bam_enable(CI_CTRL, false);
+ if (phy->otg->state == OTG_STATE_UNDEFINED && motg->rm_pulldown)
+ msm_chg_block_on(motg);
+
return 0;
}
@@ -2458,6 +2463,7 @@
u32 func_ctrl;
/* put the controller in non-driving mode */
+ msm_otg_dbg_log_event(&motg->phy, "PHY NON DRIVE", 0, 0);
func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NONDRIVING;
@@ -2487,12 +2493,36 @@
ulpi_write(phy, 0x6, 0xB);
/* put the controller in normal mode */
+ msm_otg_dbg_log_event(&motg->phy, "PHY MODE NORMAL", 0, 0);
func_ctrl = ulpi_read(phy, ULPI_FUNC_CTRL);
func_ctrl &= ~ULPI_FUNC_CTRL_OPMODE_MASK;
func_ctrl |= ULPI_FUNC_CTRL_OPMODE_NORMAL;
ulpi_write(phy, func_ctrl, ULPI_FUNC_CTRL);
}
+static void msm_otg_set_mode_nondriving(struct msm_otg *motg,
+ bool mode_nondriving)
+{
+ clk_prepare_enable(motg->xo_clk);
+ clk_prepare_enable(motg->phy_csr_clk);
+ clk_prepare_enable(motg->core_clk);
+ clk_prepare_enable(motg->pclk);
+
+ msm_otg_exit_phy_retention(motg);
+
+ if (mode_nondriving)
+ msm_chg_block_on(motg);
+ else
+ msm_chg_block_off(motg);
+
+ msm_otg_enter_phy_retention(motg);
+
+ clk_disable_unprepare(motg->pclk);
+ clk_disable_unprepare(motg->core_clk);
+ clk_disable_unprepare(motg->phy_csr_clk);
+ clk_disable_unprepare(motg->xo_clk);
+}
+
#define MSM_CHG_DCD_TIMEOUT (750 * HZ/1000) /* 750 msec */
#define MSM_CHG_DCD_POLL_TIME (50 * HZ/1000) /* 50 msec */
#define MSM_CHG_PRIMARY_DET_TIME (50 * HZ/1000) /* TVDPSRC_ON */
@@ -3320,6 +3350,8 @@
}
}
+ msm_otg_set_mode_nondriving(motg, true);
+
return ret;
}
@@ -3328,6 +3360,8 @@
int ret = 0;
struct msm_otg *motg = rdev_get_drvdata(rdev);
+ msm_otg_set_mode_nondriving(motg, false);
+
if (motg->rm_pulldown) {
ret = msm_hsusb_ldo_enable(motg, USB_PHY_REG_3P3_OFF);
if (!ret) {
diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c
index 968ade5..6965605 100644
--- a/drivers/usb/renesas_usbhs/fifo.c
+++ b/drivers/usb/renesas_usbhs/fifo.c
@@ -821,9 +821,8 @@
}
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 @@
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 @@
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 @@
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 @@
dma_async_issue_pending(chan);
usbhsf_dma_start(pipe, fifo);
usbhs_pipe_enable(pipe);
+}
-xfer_work_end:
+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;
+
+ usbhs_lock(priv, flags);
+ usbhsf_dma_xfer_preparing(pkt);
usbhs_unlock(priv, flags);
}
@@ -918,8 +924,13 @@
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 @@
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 f54931a..63ff1a4 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1024,6 +1024,7 @@
{ 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 15d220e..ed6b366 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 9f96dd2..d7b31fd 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -1166,6 +1166,10 @@
{ 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 @@
.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 @@
{ 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 9706d21..8fd5e19 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -101,6 +101,7 @@
{ 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 d84c3b3..496cbcc 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 7ca7794..dee100d 100644
--- a/drivers/usb/storage/unusual_realtek.h
+++ b/drivers/usb/storage/unusual_realtek.h
@@ -29,6 +29,11 @@
"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 8e629b6..a5a6a11 100644
--- a/drivers/usb/usbip/stub_dev.c
+++ b/drivers/usb/usbip/stub_dev.c
@@ -315,9 +315,17 @@
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 @@
* 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 @@
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 @@
/* 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 @@
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 @@
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 @@
/* 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 @@
(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 68a1135..2811c4a 100644
--- a/drivers/video/fbdev/core/fbcmap.c
+++ b/drivers/video/fbdev/core/fbcmap.c
@@ -94,6 +94,8 @@
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 de119f1..455a15f 100644
--- a/drivers/video/fbdev/core/modedb.c
+++ b/drivers/video/fbdev/core/modedb.c
@@ -933,6 +933,9 @@
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 4630285..59e1cae 100644
--- a/drivers/video/fbdev/hgafb.c
+++ b/drivers/video/fbdev/hgafb.c
@@ -285,6 +285,8 @@
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 4363c64..4ef9dc9 100644
--- a/drivers/video/fbdev/imsttfb.c
+++ b/drivers/video/fbdev/imsttfb.c
@@ -1516,6 +1516,11 @@
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/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 7eb8c70..4f8015d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.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
@@ -46,6 +46,7 @@
if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
pr_err("%s: Error: lpg_chan=%d pwm request failed",
__func__, ctrl->pwm_lpg_chan);
+ ctrl->pwm_bl = NULL;
}
ctrl->pwm_enabled = 0;
}
@@ -662,6 +663,12 @@
return 0;
}
+ if (pinfo->partial_update_col_addr_offset)
+ roi.x += pinfo->partial_update_col_addr_offset;
+
+ if (pinfo->partial_update_row_addr_offset)
+ roi.y += pinfo->partial_update_row_addr_offset;
+
if (pinfo->dcs_cmd_by_left) {
if (left_or_both && ctrl->ndx == DSI_CTRL_RIGHT) {
/* 2A/2B sent by left already */
@@ -2099,6 +2106,7 @@
static int mdss_dsi_parse_panel_features(struct device_node *np,
struct mdss_dsi_ctrl_pdata *ctrl)
{
+ u32 value[2];
struct mdss_panel_info *pinfo;
if (!np || !ctrl) {
@@ -2116,6 +2124,14 @@
pinfo->partial_update_enabled);
ctrl->set_col_page_addr = mdss_dsi_set_col_page_addr;
if (pinfo->partial_update_enabled) {
+ int rc = of_property_read_u32_array(np,
+ "qcom,partial-update-addr-offset",
+ value, 2);
+ pinfo->partial_update_col_addr_offset =
+ (!rc ? value[0] : 0);
+ pinfo->partial_update_row_addr_offset =
+ (!rc ? value[1] : 0);
+
pinfo->partial_update_roi_merge =
of_property_read_bool(np,
"qcom,partial-update-roi-merge");
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index be6d44f..0fa242e 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-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
@@ -690,6 +690,8 @@
bool esd_rdy;
bool partial_update_supported; /* value from dts if pu is supported */
bool partial_update_enabled; /* is pu currently allowed */
+ u32 partial_update_col_addr_offset; /* panel column addr offset */
+ u32 partial_update_row_addr_offset; /* panel row addr offset */
u32 dcs_cmd_by_left;
u32 partial_update_roi_merge;
struct ion_handle *splash_ihdl;
diff --git a/drivers/w1/w1_io.c b/drivers/w1/w1_io.c
index f4bc8c1..a3ac582 100644
--- a/drivers/w1/w1_io.c
+++ b/drivers/w1/w1_io.c
@@ -437,8 +437,7 @@
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 416903e..e7905c4 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1862,6 +1862,7 @@
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 518dfa1..5098982 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -181,8 +181,10 @@
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 f8c7775..e7fbed5 100644
--- a/drivers/xen/xen-pciback/pciback_ops.c
+++ b/drivers/xen/xen-pciback/pciback_ops.c
@@ -126,8 +126,6 @@
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 0a3c676..07f6ba6 100644
--- a/drivers/xen/xenbus/xenbus_dev_frontend.c
+++ b/drivers/xen/xenbus/xenbus_dev_frontend.c
@@ -536,7 +536,7 @@
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 082d227..6261719 100644
--- a/fs/9p/acl.c
+++ b/fs/9p/acl.c
@@ -276,7 +276,7 @@
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 9b2917a..b18543b 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -859,9 +859,14 @@
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 @@
if (IS_ERR(bprm.file))
return res;
- bprm.cred = prepare_exec_creds();
- res = -ENOMEM;
- if (!bprm.cred)
- goto out;
+ res = kernel_read(bprm.file, pos, bprm.buf, BINPRM_BUF_SIZE);
- /* 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 = 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 fb973cc..395b077 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -511,18 +511,27 @@
}
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 6b29165..7938c48 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -11150,9 +11150,9 @@
* 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 @@
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 @@
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 @@
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 @@
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 4375448..c77114c 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -1952,6 +1952,18 @@
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 75bab76..94441fd 100644
--- a/fs/btrfs/reada.c
+++ b/fs/btrfs/reada.c
@@ -759,6 +759,7 @@
u64 total = 0;
int i;
+again:
do {
enqueued = 0;
mutex_lock(&fs_devices->device_list_mutex);
@@ -771,6 +772,10 @@
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 edae751..307b8ba 100644
--- a/fs/btrfs/root-tree.c
+++ b/fs/btrfs/root-tree.c
@@ -144,10 +144,8 @@
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 1f157fb..510cad4 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -751,7 +751,12 @@
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 a36bb75..02bb7b5 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -2827,6 +2827,12 @@
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 @@
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 dbb78c3..0a829f0 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -4876,6 +4876,7 @@
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 @@
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 9c09aa2..663d668 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -62,6 +62,11 @@
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 44a240c..a112a47 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -134,6 +134,12 @@
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 e7f1773..df3ee0b 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -2892,7 +2892,9 @@
}
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 d2a1a79..a1985a9 100644
--- a/fs/configfs/dir.c
+++ b/fs/configfs/dir.c
@@ -58,15 +58,13 @@
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 @@
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 cfe9117..9f38e7f 100755
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -606,8 +606,6 @@
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 @@
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 74e8d3d..e258a35 100644
--- a/fs/crypto/policy.c
+++ b/fs/crypto/policy.c
@@ -80,6 +80,10 @@
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 b5e1837..5578aa8 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -3624,8 +3624,9 @@
ssize_t ret;
int rw = iov_iter_rw(iter);
-#ifdef CONFIG_FS_ENCRYPTION
- if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode))
+#ifdef CONFIG_EXT4_FS_ENCRYPTION
+ if (IS_ENCRYPTED(inode) && S_ISREG(inode->i_mode)
+ && !fscrypt_using_hardware_encryption(inode))
return 0;
#endif
@@ -5292,7 +5293,7 @@
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 d4c5310..a5403b2 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -1328,10 +1328,8 @@
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 ae2e39f..271b93a 100755
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -517,7 +517,10 @@
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 24fe54e..e67a338 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 @@
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 @@
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;
}
@@ -1729,6 +1741,8 @@
static int f2fs_ioc_start_atomic_write(struct file *filp)
{
struct inode *inode = file_inode(filp);
+ struct f2fs_inode_info *fi = F2FS_I(inode);
+ struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
int ret;
if (!inode_owner_or_capable(inode))
@@ -1769,6 +1783,12 @@
goto out;
}
+ spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
+ if (list_empty(&fi->inmem_ilist))
+ list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
+ spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
+
+ /* add inode in inmem_list first and set atomic_file */
set_inode_flag(inode, FI_ATOMIC_FILE);
clear_inode_flag(inode, FI_ATOMIC_REVOKE_REQUEST);
up_write(&F2FS_I(inode)->i_gc_rwsem[WRITE]);
@@ -1810,11 +1830,8 @@
goto err_out;
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 0, true);
- if (!ret) {
- clear_inode_flag(inode, FI_ATOMIC_FILE);
- F2FS_I(inode)->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
- stat_dec_atomic_write(inode);
- }
+ if (!ret)
+ f2fs_drop_inmem_pages(inode);
} else {
ret = f2fs_do_sync_file(filp, 0, LLONG_MAX, 1, false);
}
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index 2a8dc33..d45a18c 100755
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -185,8 +185,6 @@
void f2fs_register_inmem_page(struct inode *inode, struct page *page)
{
- struct f2fs_sb_info *sbi = F2FS_I_SB(inode);
- struct f2fs_inode_info *fi = F2FS_I(inode);
struct inmem_pages *new;
f2fs_trace_pid(page);
@@ -200,15 +198,11 @@
INIT_LIST_HEAD(&new->list);
/* increase reference count with clean state */
- mutex_lock(&fi->inmem_lock);
get_page(page);
- list_add_tail(&new->list, &fi->inmem_pages);
- spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
- if (list_empty(&fi->inmem_ilist))
- list_add_tail(&fi->inmem_ilist, &sbi->inode_list[ATOMIC_FILE]);
- spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
+ mutex_lock(&F2FS_I(inode)->inmem_lock);
+ list_add_tail(&new->list, &F2FS_I(inode)->inmem_pages);
inc_page_count(F2FS_I_SB(inode), F2FS_INMEM_PAGES);
- mutex_unlock(&fi->inmem_lock);
+ mutex_unlock(&F2FS_I(inode)->inmem_lock);
trace_f2fs_register_inmem_page(page, INMEM);
}
@@ -330,19 +324,17 @@
mutex_lock(&fi->inmem_lock);
__revoke_inmem_pages(inode, &fi->inmem_pages,
true, false, true);
-
- if (list_empty(&fi->inmem_pages)) {
- spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
- if (!list_empty(&fi->inmem_ilist))
- list_del_init(&fi->inmem_ilist);
- spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
- }
mutex_unlock(&fi->inmem_lock);
}
clear_inode_flag(inode, FI_ATOMIC_FILE);
fi->i_gc_failures[GC_FAILURE_ATOMIC] = 0;
stat_dec_atomic_write(inode);
+
+ spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
+ if (!list_empty(&fi->inmem_ilist))
+ list_del_init(&fi->inmem_ilist);
+ spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
}
void f2fs_drop_inmem_page(struct inode *inode, struct page *page)
@@ -471,11 +463,6 @@
mutex_lock(&fi->inmem_lock);
err = __f2fs_commit_inmem_pages(inode);
-
- spin_lock(&sbi->inode_lock[ATOMIC_FILE]);
- if (!list_empty(&fi->inmem_ilist))
- list_del_init(&fi->inmem_ilist);
- spin_unlock(&sbi->inode_lock[ATOMIC_FILE]);
mutex_unlock(&fi->inmem_lock);
clear_inode_flag(inode, FI_ATOMIC_COMMIT);
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index a6de02a..09df641 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -3169,10 +3169,7 @@
#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 3d04b12..392ec56 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -160,12 +160,17 @@
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;
- res = generic_file_fsync(filp, start, end, datasync);
+ err = __generic_file_fsync(filp, start, end, datasync);
+ if (err)
+ return err;
+
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 c33cb1f..7dcad4c 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1678,7 +1678,7 @@
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 @@
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 @@
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 @@
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 066efed..5d31bf1 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -194,7 +194,9 @@
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 @@
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 7a8b1d7..efd44d5 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -136,22 +136,26 @@
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
- atomic_inc(&lru_count);
-
+ list_del(&gl->gl_lru);
list_add_tail(&gl->gl_lru, &lru_list);
- set_bit(GLF_LRU, &gl->gl_flags);
+
+ if (!test_bit(GLF_LRU, &gl->gl_flags)) {
+ set_bit(GLF_LRU, &gl->gl_flags);
+ atomic_inc(&lru_count);
+ }
+
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 @@
!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 @@
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 @@
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 @@
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 8b907c5..3c3d037 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -32,9 +32,10 @@
* @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 @@
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 4acc677..253b034 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -451,9 +451,7 @@
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 @@
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 @@
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 1d1a957..e64f5e7 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1804,8 +1804,13 @@
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 9009989..c886356 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 0bf9e7b..9140b9c 100644
--- a/fs/nfsd/vfs.h
+++ b/fs/nfsd/vfs.h
@@ -116,8 +116,11 @@
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 2903730..e8ace3b 100644
--- a/fs/ocfs2/dcache.c
+++ b/fs/ocfs2/dcache.c
@@ -310,6 +310,18 @@
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 e8818ea..a0fc378 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -1205,3 +1205,21 @@
}
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 388e09a..347c6dc 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -193,9 +193,9 @@
* 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 712b44c..9682bbf 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -448,7 +448,7 @@
* 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 ce77e76..9012312 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -572,12 +572,13 @@
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 01983be..8bfbc8a 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -1585,7 +1585,11 @@
* 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 @@
* 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 fd81702..9e66d85 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -478,13 +478,15 @@
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 @@
/* 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 @@
/* 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 @@
}
/* 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 @@
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 @@
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 @@
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 @@
&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 @@
/* Are we beyond EOF? */
if (etype == -1) {
int ret;
+ loff_t hole_len;
isBeyondEOF = true;
if (count) {
if (c)
@@ -771,7 +797,8 @@
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 6f96247..89f079d 100644
--- a/include/asm-generic/bug.h
+++ b/include/asm-generic/bug.h
@@ -47,6 +47,7 @@
#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 0885c9f..e658303 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -245,7 +245,7 @@
{
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 d4b167f..76ad8a9 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -58,7 +58,7 @@
*/
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 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 __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 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 __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 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 __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 ror8(__u8 word, unsigned int shift)
{
- return (word >> shift) | (word << (8 - shift));
+ return (word >> (shift & 7)) | (word << ((-shift) & 7));
}
/**
diff --git a/include/linux/bluetooth-power.h b/include/linux/bluetooth-power.h
index 901dae0..b4e2128 100644
--- a/include/linux/bluetooth-power.h
+++ b/include/linux/bluetooth-power.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-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
@@ -88,4 +88,7 @@
#define BT_CMD_SLIM_TEST 0xbfac
#define BT_CMD_PWR_CTRL 0xbfad
#define BT_CMD_CHIPSET_VERS 0xbfae
+
+#define BT_RESET_GPIO_HIGH_VAL 0x1
+
#endif /* __LINUX_BLUETOOTH_POWER_H */
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h
index 5a232e8..f9a2c23 100755
--- a/include/linux/cgroup.h
+++ b/include/linux/cgroup.h
@@ -472,7 +472,7 @@
*
* 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 @@
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 8e9b0cb..61650c1 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 7385c7f..51c2f5b 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -177,6 +177,11 @@
# 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 fcdc27c..b2547d9 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -273,11 +273,15 @@
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/diagchar.h b/include/linux/diagchar.h
index d33071c..e04e291 100644
--- a/include/linux/diagchar.h
+++ b/include/linux/diagchar.h
@@ -148,7 +148,7 @@
* a new RANGE of SSIDs to the msg_mask_tbl.
*/
#define MSG_MASK_TBL_CNT 26
-#define APPS_EVENT_LAST_ID 0xCAA
+#define APPS_EVENT_LAST_ID 0xCB4
#define MSG_SSID_0 0
#define MSG_SSID_0_LAST 130
@@ -922,7 +922,7 @@
/* LOG CODES */
static const uint32_t log_code_last_tbl[] = {
0x0, /* EQUIP ID 0 */
- 0x1C9A, /* EQUIP ID 1 */
+ 0x1CB2, /* EQUIP ID 1 */
0x0, /* EQUIP ID 2 */
0x0, /* EQUIP ID 3 */
0x4910, /* EQUIP ID 4 */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9ca2121..1877a8e 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -144,6 +144,9 @@
/* 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(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/hugetlb.h b/include/linux/hugetlb.h
index b699d59..6b8a7b6 100644
--- a/include/linux/hugetlb.h
+++ b/include/linux/hugetlb.h
@@ -92,9 +92,7 @@
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 6cc48ac..40b1473 100644
--- a/include/linux/iio/adc/ad_sigma_delta.h
+++ b/include/linux/iio/adc/ad_sigma_delta.h
@@ -66,6 +66,7 @@
bool irq_dis;
bool bus_locked;
+ bool keep_cs_asserted;
uint8_t comm;
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 2c31666..b0828a0 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -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
@@ -754,6 +754,7 @@
enum teth_tethering_mode {
TETH_TETHERING_MODE_RMNET,
TETH_TETHERING_MODE_MBIM,
+ TETH_TETHERING_MODE_RMNET_2,
TETH_TETHERING_MODE_MAX,
};
diff --git a/include/linux/ipa_usb.h b/include/linux/ipa_usb.h
index cceae83..9dbdb9f 100644
--- a/include/linux/ipa_usb.h
+++ b/include/linux/ipa_usb.h
@@ -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
@@ -19,9 +19,16 @@
IPA_USB_RMNET = 2,
IPA_USB_MBIM = 3,
IPA_USB_DIAG = 4,
+ IPA_USB_RMNET_CV2X = 5,
IPA_USB_MAX_TETH_PROT_SIZE
};
+enum teth_bridge_params {
+ IPA_TETH_BRIDGE_1 = 0,
+ IPA_TETH_BRIDGE_2 = 1,
+ IPA_TETH_BRIDGE_MAX
+};
+
/**
* ipa_usb_teth_params - parameters for RDNIS/ECM initialization API
*
@@ -151,6 +158,7 @@
u64 data_buff_base_addr_iova;
struct sg_table *sgt_xfer_rings;
struct sg_table *sgt_data_buff;
+ bool is_sw_path;
};
/**
diff --git a/include/linux/list_lru.h b/include/linux/list_lru.h
index fa7fd03..f2e9669 100644
--- a/include/linux/list_lru.h
+++ b/include/linux/list_lru.h
@@ -51,6 +51,7 @@
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 fd77f83..5fbbfa6 100644
--- a/include/linux/memcontrol.h
+++ b/include/linux/memcontrol.h
@@ -494,17 +494,6 @@
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 @@
* 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 @@
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,
- 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 @@
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 309f165..e25ecba 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -782,6 +782,10 @@
}
#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 @@
* 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 4f71293..c6ae0d5 100644
--- a/include/linux/pipe_fs_i.h
+++ b/include/linux/pipe_fs_i.h
@@ -107,18 +107,20 @@
/*
* 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 @@
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 b40287e..ef2743c 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -776,7 +776,6 @@
#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_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 01f71e1..aa29357 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -306,14 +306,12 @@
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 12910cf..12a4b09 100644
--- a/include/linux/smpboot.h
+++ b/include/linux/smpboot.h
@@ -30,7 +30,7 @@
* @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 b8ea15a..4fd7dd9 100644
--- a/include/linux/tcp.h
+++ b/include/linux/tcp.h
@@ -434,4 +434,7 @@
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/usb/gadget.h b/include/linux/usb/gadget.h
index 418978e..3aad8b5 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -148,6 +148,7 @@
* by adding a zero length packet as needed;
* @short_not_ok: When reading data, makes short packets be
* treated as errors (queue stops advancing till cleanup).
+ * @dma_mapped: Indicates if request has been mapped to DMA (internal)
* @complete: Function called when request completes, so this request and
* its buffer may be re-used. The function will always be called with
* interrupts disabled, and it must not sleep.
@@ -204,6 +205,7 @@
unsigned no_interrupt:1;
unsigned zero:1;
unsigned short_not_ok:1;
+ unsigned dma_mapped:1;
void (*complete)(struct usb_ep *ep,
struct usb_request *req);
diff --git a/include/linux/vmw_vmci_defs.h b/include/linux/vmw_vmci_defs.h
index 1bd31a3..ce13d46 100644
--- a/include/linux/vmw_vmci_defs.h
+++ b/include/linux/vmw_vmci_defs.h
@@ -75,9 +75,18 @@
/*
* 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 1b3f869..92d2f7d 100644
--- a/include/net/arp.h
+++ b/include/net/arp.h
@@ -17,6 +17,7 @@
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 @@
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 1b1cf33..2b6abd0 100644
--- a/include/net/ip6_tunnel.h
+++ b/include/net/ip6_tunnel.h
@@ -149,9 +149,12 @@
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 7adf438..bf619a6 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -94,6 +94,7 @@
#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 96c2b19..6b7f988 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -53,6 +53,8 @@
#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/icnss.h b/include/soc/qcom/icnss.h
index e55353a..bff4d3f 100644
--- a/include/soc/qcom/icnss.h
+++ b/include/soc/qcom/icnss.h
@@ -51,6 +51,8 @@
int (*resume_noirq)(struct device *dev);
int (*uevent)(struct device *dev, struct icnss_uevent_data *uevent);
int (*set_therm_state)(struct device *dev, unsigned long thermal_state);
+ int (*idle_shutdown)(struct device *dev);
+ int (*idle_restart)(struct device *dev);
};
@@ -151,4 +153,6 @@
extern void icnss_thermal_unregister(struct device *dev);
extern int icnss_get_curr_therm_state(struct device *dev,
unsigned long *thermal_state);
+extern int icnss_idle_restart(struct device *dev);
+extern int icnss_idle_shutdown(struct device *dev);
#endif /* _ICNSS_WLAN_H_ */
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index f6fc1e0..855c13d 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 @@
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 4950953..0ee4a07 100644
--- a/include/trace/events/android_fs.h
+++ b/include/trace/events/android_fs.h
@@ -25,6 +25,15 @@
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 b23d17b..0832c26 100644
--- a/include/trace/events/android_fs_template.h
+++ b/include/trace/events/android_fs_template.h
@@ -61,4 +61,38 @@
__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 03725fe..02137b5 100644
--- a/include/uapi/drm/i915_drm.h
+++ b/include/uapi/drm/i915_drm.h
@@ -756,7 +756,7 @@
__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 e645f17..56186b6 100644
--- a/include/uapi/linux/fuse.h
+++ b/include/uapi/linux/fuse.h
@@ -215,10 +215,12 @@
* 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 e64942a..60a5725 100644
--- a/include/uapi/linux/msm_ipa.h
+++ b/include/uapi/linux/msm_ipa.h
@@ -2,6 +2,7 @@
#define _UAPI_MSM_IPA_H_
#ifndef __KERNEL__
+#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <sys/stat.h>
@@ -30,7 +31,7 @@
*/
#define IPA_IPV6CT_DEV_NAME "ipaIpv6CTTable"
- /**
+/**
* name of the default routing tables for v4 and v6
*/
#define IPA_DFLT_RT_TBL_NAME "ipa_dflt_rt"
@@ -107,8 +108,8 @@
#define IPA_IOCTL_DEL_BRIDGE_VLAN_MAPPING 60
#define IPA_IOCTL_GSB_CONNECT 61
#define IPA_IOCTL_GSB_DISCONNECT 62
-
-
+#define IPA_IOCTL_GET_PHERIPHERAL_EP_INFO 63
+#define IPA_IOCTL_GET_NAT_IN_SRAM_INFO 64
/**
* max size of the header to be inserted
@@ -334,11 +335,14 @@
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 +371,23 @@
(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 +396,8 @@
#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 +419,8 @@
#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) \
@@ -431,7 +441,27 @@
(IPA_CLIENT_IS_TEST_PROD(client) || IPA_CLIENT_IS_TEST_CONS(client))
/**
+ * The following is used to describe the types of memory NAT can
+ * reside in.
+ *
+ * PLEASE KEEP THE FOLLOWING IN SYNC WITH ipa3_nat_mem_in_as_str()
+ * BELOW.
+ */
+enum ipa3_nat_mem_in {
+ IPA_NAT_MEM_IN_DDR = 0,
+ IPA_NAT_MEM_IN_SRAM = 1,
+
+ IPA_NAT_MEM_IN_MAX
+};
+
+#define IPA_VALID_NAT_MEM_IN(t) \
+ ((t) >= IPA_NAT_MEM_IN_DDR && (t) < IPA_NAT_MEM_IN_MAX)
+
+/**
* enum ipa_ip_type - Address family: IPv4 or IPv6
+ *
+ * PLEASE KEEP THE FOLLOWING IN SYNC WITH ipa_ip_type_as_str()
+ * BELOW.
*/
enum ipa_ip_type {
IPA_IP_v4,
@@ -439,6 +469,9 @@
IPA_IP_MAX
};
+#define VALID_IPA_IP_TYPE(t) \
+ ((t) >= IPA_IP_v4 && (t) < IPA_IP_MAX)
+
/**
* enum ipa_rule_type - Type of routing or filtering rule
* Hashable: Rule will be located at the hashable tables
@@ -1627,9 +1660,11 @@
* @expn_table_entries: input parameter, ipv4 expansion rules table number of
* entries
* @ip_addr: input parameter, public ip address
+ * @mem_type: input parameter, type of memory the table resides in
+ * @focus_change: input parameter, are we moving to/from sram or ddr
*/
struct ipa_ioc_v4_nat_init {
- uint8_t tbl_index;
+ uint8_t tbl_index;
uint32_t ipv4_rules_offset;
uint32_t expn_rules_offset;
@@ -1639,6 +1674,9 @@
uint16_t table_entries;
uint16_t expn_table_entries;
uint32_t ip_addr;
+
+ uint8_t mem_type;
+ uint8_t focus_change;
};
/**
@@ -1671,9 +1709,11 @@
/**
* struct ipa_ioc_nat_ipv6ct_table_del - NAT/IPv6CT table delete parameter
* @table_index: input parameter, index of the table
+ * @mem_type: input parameter, type of memory the table resides in
*/
struct ipa_ioc_nat_ipv6ct_table_del {
uint8_t table_index;
+ uint8_t mem_type;
};
/**
@@ -1697,11 +1737,12 @@
* struct ipa_ioc_nat_dma_cmd - To hold multiple nat/ipv6ct dma commands
* @entries: number of dma commands in use
* @dma: data pointer to the dma commands
+ * @mem_type: input parameter, type of memory the table resides in
*/
struct ipa_ioc_nat_dma_cmd {
uint8_t entries;
+ uint8_t mem_type;
struct ipa_ioc_nat_dma_one dma[0];
-
};
/**
@@ -1750,6 +1791,46 @@
char name[IPA_RESOURCE_NAME_MAX];
};
+#define QUERY_MAX_EP_PAIRS 2
+
+#define IPA_USB0_EP_ID 11
+#define IPA_USB1_EP_ID 12
+
+#define IPA_PCIE0_EP_ID 21
+#define IPA_PCIE1_EP_ID 22
+
+enum ipa_peripheral_ep_type {
+ IPA_DATA_EP_TYP_RESERVED = 0,
+ IPA_DATA_EP_TYP_HSIC = 1,
+ IPA_DATA_EP_TYP_HSUSB = 2,
+ IPA_DATA_EP_TYP_PCIE = 3,
+ IPA_DATA_EP_TYP_EMBEDDED = 4,
+ IPA_DATA_EP_TYP_BAM_DMUX,
+};
+
+struct ipa_ep_pair_info {
+ uint32_t consumer_pipe_num;
+ uint32_t producer_pipe_num;
+ uint32_t ep_id;
+};
+
+/**
+ * struct ipa_ioc_get_ep_info - flt/rt counter id query
+ * @ep_type: type USB/PCIE - i/p param
+ * @max_ep_pairs: max number of ep_pairs (constant),
+ (QUERY_MAX_EP_PAIRS)
+ * @num_ep_pairs: number of ep_pairs - o/p param
+ * @ep_pair_size: sizeof(ipa_ep_pair_info) * max_ep_pairs
+ * @info: structure contains ep pair info
+ */
+struct ipa_ioc_get_ep_info {
+ enum ipa_peripheral_ep_type ep_type;
+ uint8_t max_ep_pairs;
+ uint8_t num_ep_pairs;
+ uint32_t ep_pair_size;
+ uintptr_t info;
+};
+
/**
* struct ipa_msg_meta - Format of the message meta-data.
* @msg_type: the type of the message
@@ -2191,6 +2272,14 @@
IPA_IOCTL_GSB_DISCONNECT, \
struct ipa_ioc_gsb_info)
+#define IPA_IOC_GET_PHERIPHERAL_EP_INFO _IOWR(IPA_IOC_MAGIC, \
+ IPA_IOCTL_GET_PHERIPHERAL_EP_INFO, \
+ struct ipa_ioc_get_ep_info)
+
+#define IPA_IOC_GET_NAT_IN_SRAM_INFO _IOWR(IPA_IOC_MAGIC, \
+ IPA_IOCTL_GET_NAT_IN_SRAM_INFO, \
+ struct ipa_nat_in_sram_info)
+
/*
* unique magic number of the Tethering bridge ioctls
*/
@@ -2280,6 +2369,21 @@
uint16_t lcid;
};
+/**
+ * struct ipa_nat_in_sram_info - query for nat in sram particulars
+ * @sram_mem_available_for_nat: Amount SRAM available to fit nat table
+ * @nat_table_offset_into_mmap: Offset into mmap'd vm where table will be
+ * @best_nat_in_sram_size_rqst: The size to request for mmap
+ *
+ * The last two elements above are required to deal with situations
+ * where the SRAM's physical address and size don't play nice with
+ * mmap'ings page size and boundary attributes.
+ */
+struct ipa_nat_in_sram_info {
+ uint32_t sram_mem_available_for_nat;
+ uint32_t nat_table_offset_into_mmap;
+ uint32_t best_nat_in_sram_size_rqst;
+};
#define TETH_BRIDGE_IOC_SET_BRIDGE_MODE _IOW(TETH_BRIDGE_IOC_MAGIC, \
TETH_BRIDGE_IOCTL_SET_BRIDGE_MODE, \
diff --git a/include/uapi/linux/nilfs2_ondisk.h b/include/uapi/linux/nilfs2_ondisk.h
index 2a8a3ad..f9b6b5b 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 @@
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 @@
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 @@
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 3442a26..56e3460 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -282,6 +282,7 @@
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 087b0ef..bbebd25 100644
--- a/include/uapi/linux/tipc_config.h
+++ b/include/uapi/linux/tipc_config.h
@@ -301,8 +301,10 @@
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 @@
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_defs.h b/include/uapi/media/cam_defs.h
index e69fe7a..c0f2f2e 100644
--- a/include/uapi/media/cam_defs.h
+++ b/include/uapi/media/cam_defs.h
@@ -21,6 +21,7 @@
#define CAM_COMMON_OPCODE_BASE_v2 0x150
#define CAM_ACQUIRE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x1)
#define CAM_RELEASE_HW (CAM_COMMON_OPCODE_BASE_v2 + 0x2)
+#define CAM_DUMP_REQ (CAM_COMMON_OPCODE_BASE_v2 + 0x3)
#define CAM_EXT_OPCODE_BASE 0x200
#define CAM_CONFIG_DEV_EXTERNAL (CAM_EXT_OPCODE_BASE + 0x1)
@@ -207,6 +208,30 @@
#define CAM_PACKET_DEV_LRME 17
#define CAM_PACKET_DEV_MAX 18
+/**
+ * struct cam_dump_req_cmd -
+ * Dump the information of issue req id
+ *
+ * @issue_req_id : Issue Request Id
+ * @session_handle : Session Handle
+ * @link_hdl : link handle
+ * @dev_handle : Device Handle
+ * @error_type : Error Type
+ * @buf_handle : Buffer Handle
+ * @offset : offset for the buffer
+ * @reserved : Reserved
+ */
+struct cam_dump_req_cmd {
+ int64_t issue_req_id;
+ int32_t session_handle;
+ int32_t link_hdl;
+ int32_t dev_handle;
+ int32_t error_type;
+ uint32_t buf_handle;
+ int32_t offset;
+ uint32_t reserved;
+};
+
/* constants */
#define CAM_PACKET_MAX_PLANES 3
diff --git a/include/uapi/media/cam_isp.h b/include/uapi/media/cam_isp.h
index 7489b72..50d95c4 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 @@
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 @@
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/include/uapi/media/cam_req_mgr.h b/include/uapi/media/cam_req_mgr.h
index defed87..4a479b0 100644
--- a/include/uapi/media/cam_req_mgr.h
+++ b/include/uapi/media/cam_req_mgr.h
@@ -247,6 +247,7 @@
#define CAM_REQ_MGR_CACHE_OPS (CAM_COMMON_OPCODE_MAX + 12)
#define CAM_REQ_MGR_LINK_CONTROL (CAM_COMMON_OPCODE_MAX + 13)
#define CAM_REQ_MGR_LINK_V2 (CAM_COMMON_OPCODE_MAX + 14)
+#define CAM_REQ_MGR_REQUEST_DUMP (CAM_COMMON_OPCODE_MAX + 15)
/* end of cam_req_mgr opcodes */
#define CAM_MEM_FLAG_HW_READ_WRITE (1<<0)
diff --git a/init/Kconfig b/init/Kconfig
index 158e2c1..dddd378 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -860,6 +860,15 @@
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 02fb438..7d8b291 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -371,7 +371,8 @@
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 @@
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 bf74eaa..6d90b19 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 @@
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 @@
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 b3097bd..084572a 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 108f5be..29071ac 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -28,6 +28,7 @@
# 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_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 @@
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 cd4f413..42b7251 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1095,22 +1095,24 @@
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 641fc19..f102c4d 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -2064,7 +2064,7 @@
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 @@
return ret;
}
-static int cpuhp_smt_enable(void)
+int cpuhp_smt_enable(void)
{
int cpu, ret = 0;
@@ -2322,6 +2322,9 @@
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 2714a17..df64cb9 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -420,14 +420,19 @@
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 @@
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,24 +969,24 @@
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;
-
- cpumask_and(trialcs->cpus_allowed, trialcs->cpus_requested, cpu_active_mask);
}
+ if (!cpumask_subset(trialcs->cpus_requested, cpu_present_mask))
+ return -EINVAL;
+
+ 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))
return 0;
diff --git a/kernel/cred.c b/kernel/cred.c
index 5f264fb..7b92592 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -447,6 +447,15 @@
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 1dbbc81..f990ddc 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -5668,7 +5668,7 @@
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 99becab..8e8b903 100644
--- a/kernel/events/ring_buffer.c
+++ b/kernel/events/ring_buffer.c
@@ -49,14 +49,30 @@
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 @@
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 0000000..9a34e1d
--- /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 0000000..8f69772
--- /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 b26dbc4..81695a4 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -256,6 +256,11 @@
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 @@
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 efba851..ea3370e 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -74,9 +74,7 @@
*/
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 @@
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 @@
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 @@
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 123ccbd..2b8579d 100644
--- a/kernel/rcu/rcuperf.c
+++ b/kernel/rcu/rcuperf.c
@@ -453,6 +453,10 @@
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 @@
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 bf08fee..5393bbc 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -1595,6 +1595,10 @@
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 @@
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 5f10aeb..ef1bd77 100755
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -9235,6 +9235,8 @@
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 @@
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 @@
{
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 0745029..cfe4f40 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -154,7 +154,7 @@
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 8b351c86..e8faa55 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2975,3 +2975,13 @@
#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 9a85525..c34311b 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -893,7 +893,7 @@
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 @@
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 92766f70..23113b8 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2249,6 +2249,8 @@
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 181a7f0..15cf3ee 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1765,7 +1765,7 @@
((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 a3c6446..0dc8c07 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -2726,8 +2726,10 @@
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 11e4af2f..d471752 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 @@
raw_spin_unlock_irqrestore(&base->cpu_base->lock, *flags);
}
cpu_relax();
+ ndelay(TIMER_LOCK_TIGHT_LOOP_DELAY_NS);
}
}
@@ -1043,6 +1045,7 @@
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 6df8927..0a16419 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -639,7 +639,7 @@
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 f7382510..0059764 100644
--- a/kernel/time/tick-internal.h
+++ b/kernel/time/tick-internal.h
@@ -165,3 +165,4 @@
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 af9a29e..018e2f5 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -942,6 +942,7 @@
spin_unlock_irqrestore(&base->lock, *flags);
}
cpu_relax();
+ ndelay(TIMER_LOCK_TIGHT_LOOP_DELAY_NS);
}
}
@@ -1264,6 +1265,7 @@
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 7cc06f2..c7aab15 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -81,6 +81,35 @@
.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 @@
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 7dba55c..1c8f269 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -6301,12 +6301,16 @@
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 @@
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 e5d06c9..5078a31 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -1681,4 +1681,22 @@
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 8964582..cf6337d 100644
--- a/kernel/trace/trace_kdb.c
+++ b/kernel/trace/trace_kdb.c
@@ -40,12 +40,8 @@
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/longlong.h b/lib/mpi/longlong.h
index 0f64fce..08c60d1 100644
--- a/lib/mpi/longlong.h
+++ b/lib/mpi/longlong.h
@@ -176,8 +176,8 @@
#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
__asm__ ("adds %1, %4, %5\n" \
"adc %0, %2, %3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
+ : "=r" (sh), \
+ "=&r" (sl) \
: "%r" ((USItype)(ah)), \
"rI" ((USItype)(bh)), \
"%r" ((USItype)(al)), \
@@ -185,15 +185,15 @@
#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
__asm__ ("subs %1, %4, %5\n" \
"sbc %0, %2, %3" \
- : "=r" ((USItype)(sh)), \
- "=&r" ((USItype)(sl)) \
+ : "=r" (sh), \
+ "=&r" (sl) \
: "r" ((USItype)(ah)), \
"rI" ((USItype)(bh)), \
"r" ((USItype)(al)), \
"rI" ((USItype)(bl)))
#if defined __ARM_ARCH_2__ || defined __ARM_ARCH_3__
#define umul_ppmm(xh, xl, a, b) \
- __asm__ ("%@ Inlined umul_ppmm\n" \
+ __asm__ ("@ Inlined umul_ppmm\n" \
"mov %|r0, %2, lsr #16 @ AAAA\n" \
"mov %|r2, %3, lsr #16 @ BBBB\n" \
"bic %|r1, %2, %|r0, lsl #16 @ aaaa\n" \
@@ -206,19 +206,19 @@
"addcs %|r2, %|r2, #65536\n" \
"adds %1, %|r1, %|r0, lsl #16\n" \
"adc %0, %|r2, %|r0, lsr #16" \
- : "=&r" ((USItype)(xh)), \
- "=r" ((USItype)(xl)) \
+ : "=&r" (xh), \
+ "=r" (xl) \
: "r" ((USItype)(a)), \
"r" ((USItype)(b)) \
: "r0", "r1", "r2")
#else
#define umul_ppmm(xh, xl, a, b) \
- __asm__ ("%@ Inlined umul_ppmm\n" \
- "umull %r1, %r0, %r2, %r3" \
- : "=&r" ((USItype)(xh)), \
- "=&r" ((USItype)(xl)) \
+ __asm__ ("@ Inlined umul_ppmm\n" \
+ "umull %1, %0, %2, %3" \
+ : "=&r" (xh), \
+ "=&r" (xl) \
: "r" ((USItype)(a)), \
- "r" ((USItype)(b)) \
+ "r" ((USItype)(b)) \
: "r0", "r1")
#endif
#define UMUL_TIME 20
diff --git a/lib/mpi/mpi-pow.c b/lib/mpi/mpi-pow.c
index 468fb7c..edf345b 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 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 @@
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 @@
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 7e35fc4..5a07f19 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 8e105ed..9ff4f3b 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 @@
* 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;
diff --git a/mm/cma.c b/mm/cma.c
index 677ed05..b5d2143 100644
--- a/mm/cma.c
+++ b/mm/cma.c
@@ -130,8 +130,10 @@
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 3f7f84c..a701289 100644
--- a/mm/cma_debug.c
+++ b/mm/cma_debug.c
@@ -57,7 +57,7 @@
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);
diff --git a/mm/gup.c b/mm/gup.c
index 99c2f10..6bb7a8e 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -153,7 +153,10 @@
}
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 @@
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 @@
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 @@
*/
#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 @@
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 @@
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 @@
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 @@
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 8b682da..9914da9 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1247,12 +1247,23 @@
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 @@
}
#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 @@
* 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 @@
* 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 @@
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 @@
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 @@
*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 7a40fa2..16361c9 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -42,11 +42,7 @@
#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 @@
}
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 @@
{
int i;
+ lru->memcg_aware = memcg_aware;
+
if (!memcg_aware)
return 0;
diff --git a/mm/memblock.c b/mm/memblock.c
index 3b7d23c..abaed7a 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -929,7 +929,7 @@
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 @@
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 f648acb..a655a50 100644
--- a/mm/mlock.c
+++ b/mm/mlock.c
@@ -633,11 +633,11 @@
* 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 77bc088..c047ff5 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2735,6 +2735,7 @@
} 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 @@
* 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 f77c4ce..f07e0c9 100755
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -5642,13 +5642,15 @@
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 ae11aa9..ded173d 100644
--- a/mm/page_idle.c
+++ b/mm/page_idle.c
@@ -131,7 +131,7 @@
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 @@
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 bd498ef..a671328 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -4362,8 +4362,12 @@
* 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 7f1b45c..ed1e39c 100644
--- a/net/9p/protocol.c
+++ b/net/9p/protocol.c
@@ -622,13 +622,19 @@
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 38aa634..9c0c894 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 5a2ad47..8e4313a 100644
--- a/net/9p/trans_rdma.c
+++ b/net/9p/trans_rdma.c
@@ -254,8 +254,7 @@
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 @@
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 @@
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 149f82b..6ba56f2 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -443,9 +443,11 @@
}
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 fe4fb0c..bd41b78 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -1165,14 +1165,6 @@
!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 @@
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 d49aa4e..ec9b5d1 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -1340,6 +1340,21 @@
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 @@
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 @@
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 @@
}
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 @@
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 ac1552d..e5a9e3d 100644
--- a/net/can/af_can.c
+++ b/net/can/af_can.c
@@ -113,6 +113,7 @@
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 3db31ba..bcc0aa4 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4932,7 +4932,6 @@
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 @@
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 @@
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 20ae57f..ffe7b03 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -878,8 +878,13 @@
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 @@
return -EFAULT;
reglen = ops->get_regs_len(dev);
+ if (reglen <= 0)
+ return reglen;
+
if (regs.len > reglen)
regs.len = reglen;
@@ -1390,13 +1398,16 @@
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 f187917..0513c56 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 @@
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 @@
}
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 @@
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 @@
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 fc7ec7a..3708301 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3147,7 +3147,13 @@
{
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 @@
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 @@
t->control |= (T_STOP);
mutex_unlock(&pktgen_thread_lock);
+ module_put(THIS_MODULE);
return sig;
}
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index d62b582..0e5571d 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-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
@@ -430,12 +430,19 @@
(xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
(xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" : "ERR")),
msg->cmd, msg->cli.node_id, msg->cli.port_id);
- else if (msg->cmd == IPC_ROUTER_CTRL_CMD_HELLO && hdr)
+ else if (msg->cmd == IPC_ROUTER_CTRL_CMD_HELLO && hdr) {
IPC_RTR_INFO(log_ctx,
"CTL MSG %s cmd:0x%x ADDR:0x%x",
(xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
(xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" : "ERR")),
msg->cmd, hdr->src_node_id);
+ if (hdr->src_node_id == 0 || hdr->src_node_id == 3)
+ pr_err("%s: Modem QMI Readiness %s cmd:0x%x ADDR:0x%x\n",
+ __func__,
+ (xchng_type == IPC_ROUTER_LOG_EVENT_RX ? "RX" :
+ (xchng_type == IPC_ROUTER_LOG_EVENT_TX ? "TX" :
+ "ERR")), msg->cmd, hdr->src_node_id);
+ }
else
IPC_RTR_INFO(log_ctx,
"%s UNKNOWN cmd:0x%x",
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index f2e6e87..780dc6f 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -190,6 +190,17 @@
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 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 @@
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 @@
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 @@
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 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 @@
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 ec48d8ea..8b22139 100644
--- a/net/ipv4/proc.c
+++ b/net/ipv4/proc.c
@@ -306,6 +306,7 @@
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 482cf7c..b37e9c4 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -197,7 +197,7 @@
}
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 76da06e..50f4945 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_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 @@
.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 a0e1fc1..ac398b72 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -3359,6 +3359,7 @@
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 6c42ffc..435450f 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -1321,7 +1321,7 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 0116d9e..d6a9526 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -2470,6 +2470,7 @@
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 8d31f60..3f45981 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -1185,6 +1185,11 @@
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 @@
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 93fbace..d962922 100644
--- a/net/ipv4/tcp_timer.c
+++ b/net/ipv4/tcp_timer.c
@@ -172,6 +172,7 @@
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 306d34a..405ec02 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -574,7 +574,11 @@
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 8c2f9ae..6a60111 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -254,9 +254,9 @@
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 @@
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 1e1fa99..0b53d19 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -264,8 +264,14 @@
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 @@
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 @@
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 55d284a..cae2c9e 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -283,7 +283,9 @@
/* 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 @@
struct sockcm_cookie sockc;
struct ipcm6_cookie ipc6;
int addr_len = msg->msg_namelen;
+ int hdrincl;
u16 proto;
int err;
@@ -785,6 +788,13 @@
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 @@
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 @@
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 @@
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 2db6808..6148952 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -291,7 +291,7 @@
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 @@
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 fc60d9d..cdb913e 100644
--- a/net/lapb/lapb_iface.c
+++ b/net/lapb/lapb_iface.c
@@ -182,6 +182,7 @@
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 94425e4..9e4b6bc 100644
--- a/net/llc/llc_output.c
+++ b/net/llc/llc_output.c
@@ -72,6 +72,8 @@
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 8a690eb..6708de1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1403,7 +1403,7 @@
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 b2a2726..5c347d3 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -885,6 +885,7 @@
/* 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 @@
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 @@
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 a37fc00..3f54d48 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1072,9 +1072,6 @@
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 23f6c8b..3b423c5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3568,6 +3568,8 @@
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 caa5986..c0529c4 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -1169,7 +1169,7 @@
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 @@
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 7233ad8..c09ee6c 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -2399,6 +2399,9 @@
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_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 @@
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 @@
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 @@
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 b8d5618..650f8a3 100644
--- a/net/packet/internal.h
+++ b/net/packet/internal.h
@@ -127,6 +127,7 @@
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 91b53d4..78d5d68 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -416,12 +416,14 @@
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 1f03065..beae42b 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -125,10 +125,6 @@
/* 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 @@
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 244eac1..de18a46 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -2718,6 +2718,7 @@
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 9746941..59980de 100644
--- a/net/tipc/core.c
+++ b/net/tipc/core.c
@@ -62,10 +62,6 @@
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 @@
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 @@
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 @@
.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 @@
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 @@
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 @@
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 0cf9403..b7c539a 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -436,7 +436,11 @@
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 @@
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 @@
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 d62affe..5e6dc72 100644
--- a/net/tipc/subscr.c
+++ b/net/tipc/subscr.c
@@ -358,7 +358,7 @@
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 @@
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 @@
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 ffdc214..814dfce 100644
--- a/net/tipc/subscr.h
+++ b/net/tipc/subscr.h
@@ -75,7 +75,8 @@
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 133e726..05033ab 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -174,7 +174,6 @@
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 @@
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 0a67d80..e13e02a5 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -478,7 +478,7 @@
&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 d899a49..3b7d778 100755
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -14397,6 +14397,11 @@
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 97913e1..99e5a2f 100644
--- a/samples/bpf/bpf_load.c
+++ b/samples/bpf/bpf_load.c
@@ -369,7 +369,7 @@
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 12a6940..b8f6165 100755
--- a/scripts/checkstack.pl
+++ b/scripts/checkstack.pl
@@ -45,7 +45,7 @@
$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 0000000..350145d
--- /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 edde825..381acfc 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -65,7 +65,7 @@
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 12262c0..08fe09c 100644
--- a/scripts/gcc-plugins/gcc-common.h
+++ b/scripts/gcc-plugins/gcc-common.h
@@ -135,8 +135,12 @@
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 1381206..96a8d71 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -177,7 +177,7 @@
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 5b85201..7d72e3d 100644
--- a/sound/core/seq/oss/seq_oss_ioctl.c
+++ b/sound/core/seq/oss/seq_oss_ioctl.c
@@ -62,7 +62,7 @@
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 6a7b6ac..499f3e8 100644
--- a/sound/core/seq/oss/seq_oss_rw.c
+++ b/sound/core/seq/oss/seq_oss_rw.c
@@ -174,7 +174,7 @@
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 09491b2..bc6d371 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1905,20 +1905,14 @@
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 f04714d..9cfe4fc 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -550,10 +550,10 @@
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 @@
/* 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 26bd71f..06003b3 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -135,7 +135,8 @@
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 bebddc6..99654e7 100644
--- a/sound/firewire/amdtp-am824.c
+++ b/sound/firewire/amdtp-am824.c
@@ -388,7 +388,7 @@
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 b0395c4..a7ab34d 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -175,9 +175,6 @@
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 789eca1..f2f1d9f 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -1700,9 +1700,6 @@
chip->msi = 0;
}
- if (azx_acquire_irq(chip, 0) < 0)
- return -EBUSY;
-
pci_set_master(pci);
synchronize_irq(bus->irq);
@@ -1809,6 +1806,9 @@
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 822650d..95fb213 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6317,7 +6317,7 @@
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 6e8eb1f..bed6472 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -60,7 +60,7 @@
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 b4d8737..462341f 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -569,6 +569,7 @@
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 90b5948..cba5b5a 100644
--- a/sound/soc/codecs/hdmi-codec.c
+++ b/sound/soc/codecs/hdmi-codec.c
@@ -137,8 +137,12 @@
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 3e65dc7..e7aef841 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -1924,6 +1924,21 @@
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 @@
#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 3c5a980..5a0b17e 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 @@
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 a732b3a..8a2873a 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -172,16 +172,17 @@
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 883087f..3813214 100644
--- a/sound/soc/fsl/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -119,13 +119,13 @@
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 1d82f68..88a438f 100644
--- a/sound/soc/fsl/fsl_asrc.c
+++ b/sound/soc/fsl/fsl_asrc.c
@@ -286,8 +286,8 @@
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 9fadf7e..cb43f57 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -274,12 +274,14 @@
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 b9e42b5..4f8bdb7 100644
--- a/sound/soc/fsl/fsl_utils.c
+++ b/sound/soc/fsl/fsl_utils.c
@@ -75,6 +75,7 @@
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 2553d9c..c4c11ae 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -2469,7 +2469,8 @@
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 fab53f5..a9f99a6 100644
--- a/sound/usb/line6/pcm.c
+++ b/sound/usb/line6/pcm.c
@@ -558,6 +558,11 @@
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 5d2fc5f..f4fd954 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -753,7 +753,7 @@
return err;
}
- kctl->private_value |= (value << 24);
+ kctl->private_value |= ((unsigned int)value << 24);
return 0;
}
@@ -914,7 +914,7 @@
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 fc446343..7e3b87a 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 0000000..2b7b532
--- /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 ae34467..95326c6 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 @@
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 @@
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 b9a95a1..d3d1452 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 3bdb2c7..476e24c 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -186,7 +186,7 @@
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 83fe220..ff38fc6 100755
--- a/tools/perf/check-headers.sh
+++ b/tools/perf/check-headers.sh
@@ -4,6 +4,7 @@
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 88f5143..3c97e27 100644
--- a/tools/perf/ui/tui/helpline.c
+++ b/tools/perf/ui/tui/helpline.c
@@ -23,7 +23,7 @@
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 7123f4d..226f431 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -265,7 +265,7 @@
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 a11f676..de9b369 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -3027,7 +3027,7 @@
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 e72d370..8b39e80 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 8ec7668..f25f72a 100755
--- a/tools/testing/selftests/netfilter/nft_nat.sh
+++ b/tools/testing/selftests/netfilter/nft_nat.sh
@@ -23,7 +23,11 @@
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 9887fd5..91316ab 100644
--- a/tools/testing/selftests/timers/adjtick.c
+++ b/tools/testing/selftests/timers/adjtick.c
@@ -147,6 +147,7 @@
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 a1071bd..a77c70b 100644
--- a/tools/testing/selftests/timers/leapcrash.c
+++ b/tools/testing/selftests/timers/leapcrash.c
@@ -114,6 +114,7 @@
}
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 a2a3924..efdb624 100644
--- a/tools/testing/selftests/timers/mqueue-lat.c
+++ b/tools/testing/selftests/timers/mqueue-lat.c
@@ -113,6 +113,7 @@
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 ff942ff..2e6e94c 100644
--- a/tools/testing/selftests/timers/nanosleep.c
+++ b/tools/testing/selftests/timers/nanosleep.c
@@ -153,6 +153,7 @@
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 2d7898f..ac06cf1 100644
--- a/tools/testing/selftests/timers/nsleep-lat.c
+++ b/tools/testing/selftests/timers/nsleep-lat.c
@@ -166,6 +166,7 @@
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 0ab937a..4e631da 100644
--- a/tools/testing/selftests/timers/raw_skew.c
+++ b/tools/testing/selftests/timers/raw_skew.c
@@ -124,6 +124,7 @@
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 dc88dbc..3ae76ab 100644
--- a/tools/testing/selftests/timers/set-tai.c
+++ b/tools/testing/selftests/timers/set-tai.c
@@ -66,6 +66,7 @@
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 f418492..b038131 100644
--- a/tools/testing/selftests/timers/set-tz.c
+++ b/tools/testing/selftests/timers/set-tz.c
@@ -76,6 +76,7 @@
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 @@
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 e632e11..a4bf736 100644
--- a/tools/testing/selftests/timers/threadtest.c
+++ b/tools/testing/selftests/timers/threadtest.c
@@ -175,6 +175,7 @@
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 60fe3c5..a747645 100644
--- a/tools/testing/selftests/timers/valid-adjtimex.c
+++ b/tools/testing/selftests/timers/valid-adjtimex.c
@@ -134,6 +134,7 @@
/* 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 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 1ebbf23..6d64b2c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1466,6 +1466,7 @@
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,