Merge "msm: vidc: Amend error handling"
diff --git a/Documentation/devicetree/bindings/cnss/icnss.txt b/Documentation/devicetree/bindings/cnss/icnss.txt
index c801e848..700a8f7 100644
--- a/Documentation/devicetree/bindings/cnss/icnss.txt
+++ b/Documentation/devicetree/bindings/cnss/icnss.txt
@@ -28,6 +28,7 @@
- qcom,icnss-vadc: VADC handle for vph_pwr read APIs.
- qcom,icnss-adc_tm: VADC handle for vph_pwr notification APIs.
- qcom,smmu-s1-bypass: Boolean context flag to set SMMU to S1 bypass
+ - qcom,wlan-msa-fixed-region: phandle, specifier pairs to children of /reserved-memory
Example:
@@ -54,6 +55,7 @@
<0 140 0 /* CE10 */ >,
<0 141 0 /* CE11 */ >;
qcom,wlan-msa-memory = <0x200000>;
+ qcom,wlan-msa-fixed-region = <&wlan_msa_mem>;
qcom,smmu-s1-bypass;
vdd-0.8-cx-mx-supply = <&pm8998_l5>;
qcom,vdd-0.8-cx-mx-config = <800000 800000 2400 1000>;
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
index 8598d0c..26cd70e 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,pdc.txt
@@ -28,6 +28,9 @@
Value type: <string>
Definition: Should contain "qcom,pdc-<target>"
+ * "qcom,pdc-sdm845": For sdm845 pin data
+ * "qcom,pdc-sdm670": For sdm670 pin data
+
- reg:
Usage: required
Value type: <prop-encoded-array>
diff --git a/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt b/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
index 937ccb9..58bac0b 100644
--- a/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-sde-rotator.txt
@@ -120,6 +120,8 @@
minimum allowable length configuration value.
- qcom,sde-ubwc-swizzle: A u32 property to specify the default UBWC
swizzle configuration value.
+- qcom,rot-reg-bus: Property to provide Bus scaling for register
+ access for rotator blocks.
Subnode properties:
- compatible: Compatible name used in smmu v2.
@@ -189,6 +191,16 @@
cache-slice-names = "rotator";
cache-slices = <&llcc 4>;
+ rot_reg: qcom,rot-reg-bus {
+ qcom,msm-bus,name = "mdss_rot_reg";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,vectors-KBps =
+ <1 590 0 0>,
+ <1 590 0 76800>;
+ };
+
smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
compatible = "qcom,smmu_sde_rot_unsec";
iommus = <&mdp_smmu 0xe00>;
diff --git a/Documentation/devicetree/bindings/net/mediatek-net.txt b/Documentation/devicetree/bindings/net/mediatek-net.txt
index c010faf..c7194e8 100644
--- a/Documentation/devicetree/bindings/net/mediatek-net.txt
+++ b/Documentation/devicetree/bindings/net/mediatek-net.txt
@@ -7,7 +7,7 @@
* Ethernet controller node
Required properties:
-- compatible: Should be "mediatek,mt7623-eth"
+- compatible: Should be "mediatek,mt2701-eth"
- reg: Address and length of the register set for the device
- interrupts: Should contain the three frame engines interrupts in numeric
order. These are fe_int0, fe_int1 and fe_int2.
diff --git a/Documentation/devicetree/bindings/net/phy.txt b/Documentation/devicetree/bindings/net/phy.txt
index bc1c3c8..62bdc5f 100644
--- a/Documentation/devicetree/bindings/net/phy.txt
+++ b/Documentation/devicetree/bindings/net/phy.txt
@@ -35,6 +35,15 @@
- broken-turn-around: If set, indicates the PHY device does not correctly
release the turn around line low at the end of a MDIO transaction.
+- eee-broken-100tx:
+- eee-broken-1000t:
+- eee-broken-10gt:
+- eee-broken-1000kx:
+- eee-broken-10gkx4:
+- eee-broken-10gkr:
+ Mark the corresponding energy efficient ethernet mode as broken and
+ request the ethernet to stop advertising it.
+
Example:
ethernet-phy@0 {
diff --git a/Documentation/devicetree/bindings/net/ti,dp83867.txt b/Documentation/devicetree/bindings/net/ti,dp83867.txt
index 5d21141..75bcaa3 100644
--- a/Documentation/devicetree/bindings/net/ti,dp83867.txt
+++ b/Documentation/devicetree/bindings/net/ti,dp83867.txt
@@ -3,9 +3,11 @@
Required properties:
- reg - The ID number for the phy, usually a small integer
- ti,rx-internal-delay - RGMII Receive Clock Delay - see dt-bindings/net/ti-dp83867.h
- for applicable values
+ for applicable values. Required only if interface type is
+ PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_RXID
- ti,tx-internal-delay - RGMII Transmit Clock Delay - see dt-bindings/net/ti-dp83867.h
- for applicable values
+ for applicable values. Required only if interface type is
+ PHY_INTERFACE_MODE_RGMII_ID or PHY_INTERFACE_MODE_RGMII_TXID
- ti,fifo-depth - Transmitt FIFO depth- see dt-bindings/net/ti-dp83867.h
for applicable values
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index a9480be..6109fad 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -152,6 +152,7 @@
and reset lines used by this controller.
- reset-names: reset signal name strings sorted in the same order as the resets
property.
+ - qcom,qusb-phy-reg-offset: Provides important phy register offsets in an order defined in phy driver.
Optional properties:
- reg-names: Additional registers corresponding with the following:
@@ -174,7 +175,6 @@
- qcom,hold-reset: Indicates that hold QUSB PHY into reset state.
- qcom,phy-clk-scheme: Should be one of "cml" or "cmos" if ref_clk_addr is provided.
- qcom,major-rev: provide major revision number to differentiate power up sequence. default is 2.0
- - qcom,phy-auto-resume-offset: Provides phy auto-resume register offset.
Example:
qusb_phy: qusb@f9b39000 {
@@ -185,6 +185,13 @@
vdda18-supply = <&pm8994_l6>;
vdda33-supply = <&pm8994_l24>;
qcom,vdd-voltage-level = <1 5 7>;
+ qcom,qusb-phy-reg-offset =
+ <0x240 /* QUSB2PHY_PORT_TUNE1 */
+ 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */
+ 0x210 /* QUSB2PHY_PWR_CTRL1 */
+ 0x230 /* QUSB2PHY_INTR_CTRL */
+ 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */
+ 0x254>; /* QUSB2PHY_TEST1 */
qcom,efuse-bit-pos = <21>;
qcom,efuse-num-bits = <3>;
diff --git a/Makefile b/Makefile
index aebb186..88cab97 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
-SUBLEVEL = 35
+SUBLEVEL = 36
EXTRAVERSION =
NAME = Roaring Lionus
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d04e168..e06ecbb 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -230,6 +230,9 @@
config ARCH_MTD_XIP
bool
+config ARCH_WANT_KMAP_ATOMIC_FLUSH
+ bool
+
config VECTORS_BASE
hex
default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -567,6 +570,7 @@
select SPARSE_IRQ
select USE_OF
select PINCTRL
+ select ARCH_WANT_KMAP_ATOMIC_FLUSH
help
Support for Qualcomm MSM/QSD based systems. This runs on the
apps processor of the MSM/QSD and depends on a shared memory
diff --git a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
index 8f9a69c..efe5399 100644
--- a/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
+++ b/arch/arm/boot/dts/logicpd-torpedo-som.dtsi
@@ -121,7 +121,7 @@
&i2c3 {
clock-frequency = <400000>;
at24@50 {
- compatible = "at24,24c02";
+ compatible = "atmel,24c64";
readonly;
reg = <0x50>;
};
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index e920dd8..f989145 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -222,6 +222,14 @@
dev_err(dev, "failed to idle\n");
}
break;
+ case BUS_NOTIFY_BIND_DRIVER:
+ od = to_omap_device(pdev);
+ if (od && (od->_state == OMAP_DEVICE_STATE_ENABLED) &&
+ pm_runtime_status_suspended(dev)) {
+ od->_driver_status = BUS_NOTIFY_BIND_DRIVER;
+ pm_runtime_set_active(dev);
+ }
+ break;
case BUS_NOTIFY_ADD_DEVICE:
if (pdev->dev.of_node)
omap_device_build_from_dt(pdev);
diff --git a/arch/arm/mm/highmem.c b/arch/arm/mm/highmem.c
index d02f818..5d73327 100644
--- a/arch/arm/mm/highmem.c
+++ b/arch/arm/mm/highmem.c
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/cpu.h>
#include <linux/module.h>
#include <linux/highmem.h>
#include <linux/interrupt.h>
@@ -147,3 +148,58 @@
return (void *)vaddr;
}
+
+#ifdef CONFIG_ARCH_WANT_KMAP_ATOMIC_FLUSH
+static void kmap_remove_unused_cpu(int cpu)
+{
+ int start_idx, idx, type;
+
+ pagefault_disable();
+ type = kmap_atomic_idx();
+ start_idx = type + 1 + KM_TYPE_NR * cpu;
+
+ for (idx = start_idx; idx < KM_TYPE_NR + KM_TYPE_NR * cpu; idx++) {
+ unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
+ pte_t ptep;
+
+ ptep = get_top_pte(vaddr);
+ if (ptep)
+ set_top_pte(vaddr, __pte(0));
+ }
+ pagefault_enable();
+}
+
+static void kmap_remove_unused(void *unused)
+{
+ kmap_remove_unused_cpu(smp_processor_id());
+}
+
+void kmap_atomic_flush_unused(void)
+{
+ on_each_cpu(kmap_remove_unused, NULL, 1);
+}
+
+static int hotplug_kmap_atomic_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ switch (action & (~CPU_TASKS_FROZEN)) {
+ case CPU_DYING:
+ kmap_remove_unused_cpu((int)hcpu);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block hotplug_kmap_atomic_notifier = {
+ .notifier_call = hotplug_kmap_atomic_callback,
+};
+
+static int __init init_kmap_atomic(void)
+{
+ return register_hotcpu_notifier(&hotplug_kmap_atomic_notifier);
+}
+early_initcall(init_kmap_atomic);
+#endif
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 5cbfd9f..f7c7413 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -1211,15 +1211,15 @@
high_memory = __va(arm_lowmem_limit - 1) + 1;
+ if (!memblock_limit)
+ memblock_limit = arm_lowmem_limit;
+
/*
* Round the memblock limit down to a pmd size. This
* helps to ensure that we will allocate memory from the
* last full pmd, which should be mapped.
*/
- if (memblock_limit)
- memblock_limit = round_down(memblock_limit, PMD_SIZE);
- if (!memblock_limit)
- memblock_limit = arm_lowmem_limit;
+ memblock_limit = round_down(memblock_limit, PMD_SIZE);
if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
if (memblock_end_of_DRAM() > arm_lowmem_limit) {
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 84867ba..842c38a 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -108,6 +108,7 @@
select POWER_SUPPLY
select SPARSE_IRQ
select SYSCTL_EXCEPTION_TRACE
+ select THREAD_INFO_IN_TASK
help
ARM 64-bit (AArch64) Linux support.
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
index e6e3491..f150a4c 100644
--- a/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
+++ b/arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
@@ -85,6 +85,18 @@
status = "okay";
pinctrl-0 = <ð_pins>;
pinctrl-names = "default";
+ phy-handle = <ð_phy0>;
+
+ mdio {
+ compatible = "snps,dwmac-mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ eth_phy0: ethernet-phy@0 {
+ reg = <0>;
+ eee-broken-1000t;
+ };
+ };
};
&ir {
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 3c8eaf8..9b20651 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -2,6 +2,17 @@
dtb-$(CONFIG_ARCH_QCOM) += msm8996-mtp.dtb
dtb-$(CONFIG_ARCH_QCOM) += apq8096-db820c.dtb
+
+ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
+ dtbo-$(CONFIG_ARCH_SDM845) += \
+ sdm845-cdp-overlay.dtbo \
+ sdm845-mtp-overlay.dtbo \
+ sdm845-qrd-overlay.dtbo
+
+sdm845-cdp-overlay.dtbo-base := sdm845.dtb
+sdm845-mtp-overlay.dtbo-base := sdm845.dtb
+sdm845-qrd-overlay.dtbo-base := sdm845.dtb
+else
dtb-$(CONFIG_ARCH_SDM845) += sdm845-sim.dtb \
sdm845-rumi.dtb \
sdm845-mtp.dtb \
@@ -14,16 +25,6 @@
sdm845-4k-panel-mtp.dtb \
sdm845-4k-panel-cdp.dtb \
sdm845-4k-panel-qrd.dtb
-
-ifeq ($(CONFIG_BUILD_ARM64_DT_OVERLAY),y)
- dtbo-$(CONFIG_ARCH_SDM845) += \
- sdm845-cdp-overlay.dtbo \
- sdm845-mtp-overlay.dtbo \
- sdm845-qrd-overlay.dtbo
-
-sdm845-cdp-overlay.dtbo-base := sdm845.dtb
-sdm845-mtp-overlay.dtbo-base := sdm845.dtb
-sdm845-qrd-overlay.dtbo-base := sdm845.dtb
endif
dtb-$(CONFIG_ARCH_SDM670) += sdm670-rumi.dtb \
diff --git a/arch/arm64/boot/dts/qcom/pmi8998.dtsi b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
index 71eee1f..c8dc1f4 100644
--- a/arch/arm64/boot/dts/qcom/pmi8998.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8998.dtsi
@@ -436,7 +436,6 @@
qcom,max-current = <12>;
qcom,default-state = "off";
linux,name = "red";
- linux,default-trigger = "battery-charging";
};
green_led: qcom,rgb_1 {
@@ -448,7 +447,6 @@
qcom,max-current = <12>;
qcom,default-state = "off";
linux,name = "green";
- linux,default-trigger = "battery-full";
};
blue_led: qcom,rgb_2 {
@@ -460,7 +458,6 @@
qcom,max-current = <12>;
qcom,default-state = "off";
linux,name = "blue";
- linux,default-trigger = "boot-indication";
};
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
index 86e2948..cce0860 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pinctrl.dtsi
@@ -19,6 +19,7 @@
#gpio-cells = <2>;
interrupt-controller;
#interrupt-cells = <2>;
+ interrupt-parent = <&pdc>;
/* QUPv3 South SE mappings */
/* SE 0 pin mappings */
diff --git a/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi b/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
index 8501d80..f03d9c2 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-pm.dtsi
@@ -195,4 +195,12 @@
reg = <0xc300000 0x1000>, <0xc3f0004 0x4>;
reg-names = "phys_addr_base", "offset_addr";
};
+
+ pdc: interrupt-controller@b220000{
+ compatible = "qcom,pdc-sdm670";
+ reg = <0xb220000 0x400>;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ interrupt-controller;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi b/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi
index 0fb455f..1fa6e26 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-qupv3.dtsi
@@ -42,7 +42,7 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qupv3_se6_4uart_active>;
pinctrl-1 = <&qupv3_se6_4uart_sleep>;
- interrupts-extended = <&intc GIC_SPI 607 0>,
+ interrupts-extended = <&pdc GIC_SPI 607 0>,
<&tlmm 48 0>;
status = "disabled";
qcom,wakeup-byte = <0xFD>;
@@ -60,7 +60,7 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&qupv3_se7_4uart_active>;
pinctrl-1 = <&qupv3_se7_4uart_sleep>;
- interrupts-extended = <&intc GIC_SPI 608 0>,
+ interrupts-extended = <&pdc GIC_SPI 608 0>,
<&tlmm 96 0>;
status = "disabled";
qcom,wakeup-byte = <0xFD>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
index 022f705..b790c04 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
@@ -199,4 +199,27 @@
interrupt-controller;
#interrupt-cells = <2>;
};
+
+ /* ipa - outbound entry to mss */
+ smp2pgpio_ipa_1_out: qcom,smp2pgpio-ipa-1-out {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "ipa";
+ qcom,remote-pid = <1>;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+
+ /* ipa - inbound entry from mss */
+ smp2pgpio_ipa_1_in: qcom,smp2pgpio-ipa-1-in {
+ compatible = "qcom,smp2pgpio";
+ qcom,entry-name = "ipa";
+ qcom,remote-pid = <1>;
+ qcom,is-inbound;
+ gpio-controller;
+ #gpio-cells = <2>;
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
};
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index d663bcd..3eae5f3 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -26,7 +26,7 @@
model = "Qualcomm Technologies, Inc. SDM670";
compatible = "qcom,sdm670";
qcom,msm-id = <336 0x0>;
- interrupt-parent = <&intc>;
+ interrupt-parent = <&pdc>;
aliases {
ufshc1 = &ufshc_mem; /* Embedded UFS slot */
@@ -416,6 +416,7 @@
reg = <0x17a00000 0x10000>, /* GICD */
<0x17a60000 0x100000>; /* GICR * 8 */
interrupts = <1 9 4>;
+ interrupt-parent = <&intc>;
};
timer {
@@ -621,6 +622,38 @@
};
};
+ gpi_dma0: qcom,gpi-dma@0x800000 {
+ #dma-cells = <6>;
+ compatible = "qcom,gpi-dma";
+ reg = <0x800000 0x60000>;
+ reg-names = "gpi-top";
+ interrupts = <0 244 0>, <0 245 0>, <0 246 0>, <0 247 0>,
+ <0 248 0>, <0 249 0>, <0 250 0>, <0 251 0>,
+ <0 252 0>, <0 253 0>, <0 254 0>, <0 255 0>,
+ <0 256 0>;
+ qcom,max-num-gpii = <13>;
+ qcom,gpii-mask = <0xfa>;
+ qcom,ev-factor = <2>;
+ iommus = <&apps_smmu 0x0016 0x0>;
+ status = "ok";
+ };
+
+ gpi_dma1: qcom,gpi-dma@0xa00000 {
+ #dma-cells = <6>;
+ compatible = "qcom,gpi-dma";
+ reg = <0xa00000 0x60000>;
+ reg-names = "gpi-top";
+ interrupts = <0 279 0>, <0 280 0>, <0 281 0>, <0 282 0>,
+ <0 283 0>, <0 284 0>, <0 293 0>, <0 294 0>,
+ <0 295 0>, <0 296 0>, <0 297 0>, <0 298 0>,
+ <0 299 0>;
+ qcom,max-num-gpii = <13>;
+ qcom,gpii-mask = <0xfa>;
+ qcom,ev-factor = <2>;
+ iommus = <&apps_smmu 0x06d6 0x0>;
+ status = "ok";
+ };
+
cpuss_dump {
compatible = "qcom,cpuss-dump";
qcom,l1_i_cache0 {
@@ -1132,6 +1165,170 @@
qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
status = "ok";
};
+
+ qcom,rmnet-ipa {
+ compatible = "qcom,rmnet-ipa3";
+ qcom,rmnet-ipa-ssr;
+ qcom,ipa-loaduC;
+ qcom,ipa-advertise-sg-support;
+ qcom,ipa-napi-enable;
+ };
+
+ ipa_hw: qcom,ipa@01e00000 {
+ compatible = "qcom,ipa";
+ reg = <0x1e00000 0x34000>,
+ <0x1e04000 0x2c000>;
+ reg-names = "ipa-base", "gsi-base";
+ interrupts =
+ <0 311 0>,
+ <0 432 0>;
+ interrupt-names = "ipa-irq", "gsi-irq";
+ qcom,ipa-hw-ver = <13>; /* IPA core version = IPAv3.5.1 */
+ qcom,ipa-hw-mode = <1>;
+ qcom,ee = <0>;
+ qcom,use-ipa-tethering-bridge;
+ qcom,modem-cfg-emb-pipe-flt;
+ qcom,ipa-wdi2;
+ qcom,use-64-bit-dma-mask;
+ qcom,arm-smmu;
+ qcom,smmu-s1-bypass;
+ qcom,bandwidth-vote-for-ipa;
+ qcom,msm-bus,name = "ipa";
+ qcom,msm-bus,num-cases = <4>;
+ qcom,msm-bus,num-paths = <4>;
+ qcom,msm-bus,vectors-KBps =
+ /* No vote */
+ <90 512 0 0>,
+ <90 585 0 0>,
+ <1 676 0 0>,
+ <143 777 0 0>,
+ /* SVS */
+ <90 512 80000 640000>,
+ <90 585 80000 640000>,
+ <1 676 80000 80000>,
+ <143 777 0 150000>,
+ /* NOMINAL */
+ <90 512 206000 960000>,
+ <90 585 206000 960000>,
+ <1 676 206000 160000>,
+ <143 777 0 300000>,
+ /* TURBO */
+ <90 512 206000 3600000>,
+ <90 585 206000 3600000>,
+ <1 676 206000 300000>,
+ <143 777 0 355333>;
+ qcom,bus-vector-names = "MIN", "SVS", "NOMINAL", "TURBO";
+
+ /* IPA RAM mmap */
+ qcom,ipa-ram-mmap = <
+ 0x280 /* ofst_start; */
+ 0x0 /* nat_ofst; */
+ 0x0 /* nat_size; */
+ 0x288 /* v4_flt_hash_ofst; */
+ 0x78 /* v4_flt_hash_size; */
+ 0x4000 /* v4_flt_hash_size_ddr; */
+ 0x308 /* v4_flt_nhash_ofst; */
+ 0x78 /* v4_flt_nhash_size; */
+ 0x4000 /* v4_flt_nhash_size_ddr; */
+ 0x388 /* v6_flt_hash_ofst; */
+ 0x78 /* v6_flt_hash_size; */
+ 0x4000 /* v6_flt_hash_size_ddr; */
+ 0x408 /* v6_flt_nhash_ofst; */
+ 0x78 /* v6_flt_nhash_size; */
+ 0x4000 /* v6_flt_nhash_size_ddr; */
+ 0xf /* v4_rt_num_index; */
+ 0x0 /* v4_modem_rt_index_lo; */
+ 0x7 /* v4_modem_rt_index_hi; */
+ 0x8 /* v4_apps_rt_index_lo; */
+ 0xe /* v4_apps_rt_index_hi; */
+ 0x488 /* v4_rt_hash_ofst; */
+ 0x78 /* v4_rt_hash_size; */
+ 0x4000 /* v4_rt_hash_size_ddr; */
+ 0x508 /* v4_rt_nhash_ofst; */
+ 0x78 /* v4_rt_nhash_size; */
+ 0x4000 /* v4_rt_nhash_size_ddr; */
+ 0xf /* v6_rt_num_index; */
+ 0x0 /* v6_modem_rt_index_lo; */
+ 0x7 /* v6_modem_rt_index_hi; */
+ 0x8 /* v6_apps_rt_index_lo; */
+ 0xe /* v6_apps_rt_index_hi; */
+ 0x588 /* v6_rt_hash_ofst; */
+ 0x78 /* v6_rt_hash_size; */
+ 0x4000 /* v6_rt_hash_size_ddr; */
+ 0x608 /* v6_rt_nhash_ofst; */
+ 0x78 /* v6_rt_nhash_size; */
+ 0x4000 /* v6_rt_nhash_size_ddr; */
+ 0x688 /* modem_hdr_ofst; */
+ 0x140 /* modem_hdr_size; */
+ 0x7c8 /* apps_hdr_ofst; */
+ 0x0 /* apps_hdr_size; */
+ 0x800 /* apps_hdr_size_ddr; */
+ 0x7d0 /* modem_hdr_proc_ctx_ofst; */
+ 0x200 /* modem_hdr_proc_ctx_size; */
+ 0x9d0 /* apps_hdr_proc_ctx_ofst; */
+ 0x200 /* apps_hdr_proc_ctx_size; */
+ 0x0 /* apps_hdr_proc_ctx_size_ddr; */
+ 0x0 /* modem_comp_decomp_ofst; diff */
+ 0x0 /* modem_comp_decomp_size; diff */
+ 0xbd8 /* modem_ofst; */
+ 0x1024 /* modem_size; */
+ 0x2000 /* apps_v4_flt_hash_ofst; */
+ 0x0 /* apps_v4_flt_hash_size; */
+ 0x2000 /* apps_v4_flt_nhash_ofst; */
+ 0x0 /* apps_v4_flt_nhash_size; */
+ 0x2000 /* apps_v6_flt_hash_ofst; */
+ 0x0 /* apps_v6_flt_hash_size; */
+ 0x2000 /* apps_v6_flt_nhash_ofst; */
+ 0x0 /* apps_v6_flt_nhash_size; */
+ 0x80 /* uc_info_ofst; */
+ 0x200 /* uc_info_size; */
+ 0x2000 /* end_ofst; */
+ 0x2000 /* apps_v4_rt_hash_ofst; */
+ 0x0 /* apps_v4_rt_hash_size; */
+ 0x2000 /* apps_v4_rt_nhash_ofst; */
+ 0x0 /* apps_v4_rt_nhash_size; */
+ 0x2000 /* apps_v6_rt_hash_ofst; */
+ 0x0 /* apps_v6_rt_hash_size; */
+ 0x2000 /* apps_v6_rt_nhash_ofst; */
+ 0x0 /* apps_v6_rt_nhash_size; */
+ 0x1c00 /* uc_event_ring_ofst; */
+ 0x400 /* uc_event_ring_size; */
+ >;
+
+ /* smp2p gpio information */
+ qcom,smp2pgpio_map_ipa_1_out {
+ compatible = "qcom,smp2pgpio-map-ipa-1-out";
+ gpios = <&smp2pgpio_ipa_1_out 0 0>;
+ };
+
+ qcom,smp2pgpio_map_ipa_1_in {
+ compatible = "qcom,smp2pgpio-map-ipa-1-in";
+ gpios = <&smp2pgpio_ipa_1_in 0 0>;
+ };
+
+ ipa_smmu_ap: ipa_smmu_ap {
+ compatible = "qcom,ipa-smmu-ap-cb";
+ iommus = <&apps_smmu 0x720 0x0>;
+ qcom,iova-mapping = <0x20000000 0x40000000>;
+ };
+
+ ipa_smmu_wlan: ipa_smmu_wlan {
+ compatible = "qcom,ipa-smmu-wlan-cb";
+ iommus = <&apps_smmu 0x721 0x0>;
+ };
+
+ ipa_smmu_uc: ipa_smmu_uc {
+ compatible = "qcom,ipa-smmu-uc-cb";
+ iommus = <&apps_smmu 0x722 0x0>;
+ qcom,iova-mapping = <0x40000000 0x20000000>;
+ };
+ };
+
+ qcom,ipa_fws {
+ compatible = "qcom,pil-tz-generic";
+ qcom,pas-id = <0xf>;
+ qcom,firmware-name = "ipa_fws";
+ };
};
#include "sdm670-pinctrl.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
index 3ce5611..5fbb1db 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-bus.dtsi
@@ -572,6 +572,18 @@
qcom,prio = <2>;
};
+ mas_xm_pcie_0: mas-xm-pcie-0 {
+ cell-id = <MSM_BUS_MASTER_PCIE>;
+ label = "mas-xm-pcie-0";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,qport = <5>;
+ qcom,connections = <&slv_qns_pcie_a1noc_snoc>;
+ qcom,bus-dev = <&fab_aggre1_noc>;
+ qcom,ap-owned;
+ qcom,prio = <2>;
+ };
+
mas_qhm_a2noc_cfg: mas-qhm-a2noc-cfg {
cell-id = <MSM_BUS_MASTER_A2NOC_CFG>;
label = "mas-qhm-a2noc-cfg";
@@ -648,18 +660,6 @@
qcom,prio = <2>;
};
- mas_xm_pcie_0: mas-xm-pcie-0 {
- cell-id = <MSM_BUS_MASTER_PCIE>;
- label = "mas-xm-pcie-0";
- qcom,buswidth = <8>;
- qcom,agg-ports = <1>;
- qcom,qport = <5>;
- qcom,connections = <&slv_qns_pcie_snoc>;
- qcom,bus-dev = <&fab_aggre1_noc>;
- qcom,ap-owned;
- qcom,prio = <2>;
- };
-
mas_xm_qdss_etr: mas-xm-qdss-etr {
cell-id = <MSM_BUS_MASTER_QDSS_ETR>;
label = "mas-xm-qdss-etr";
@@ -715,6 +715,7 @@
qcom,agg-ports = <1>;
qcom,connections = <&slv_qns_camnoc_uncomp>;
qcom,bus-dev = <&fab_camnoc_virt>;
+ qcom,bcms = <&bcm_mm1>;
};
mas_qxm_camnoc_hf1_uncomp: mas-qxm-camnoc-hf1-uncomp {
@@ -724,6 +725,7 @@
qcom,agg-ports = <1>;
qcom,connections = <&slv_qns_camnoc_uncomp>;
qcom,bus-dev = <&fab_camnoc_virt>;
+ qcom,bcms = <&bcm_mm1>;
};
mas_qxm_camnoc_sf_uncomp: mas-qxm-camnoc-sf-uncomp {
@@ -733,6 +735,7 @@
qcom,agg-ports = <1>;
qcom,connections = <&slv_qns_camnoc_uncomp>;
qcom,bus-dev = <&fab_camnoc_virt>;
+ qcom,bcms = <&bcm_mm1>;
};
mas_qhm_spdm: mas-qhm-spdm {
@@ -1222,6 +1225,19 @@
qcom,prio = <2>;
};
+ mas_xm_gic: mas-xm-gic {
+ cell-id = <MSM_BUS_MASTER_GIC>;
+ label = "mas-xm-gic";
+ qcom,buswidth = <8>;
+ qcom,agg-ports = <1>;
+ qcom,qport = <0>;
+ qcom,connections = <&slv_qxs_imem &slv_qns_memnoc_gc>;
+ qcom,bus-dev = <&fab_system_noc>;
+ qcom,bcms = <&bcm_sn12>;
+ qcom,ap-owned;
+ qcom,prio = <1>;
+ };
+
mas_alc: mas-alc {
cell-id = <MSM_BUS_MASTER_ALC>;
label = "mas-alc";
@@ -1315,6 +1331,15 @@
qcom,bcms = <&bcm_sn9>;
};
+ slv_qns_pcie_a1noc_snoc:slv-qns-pcie-a1noc-snoc {
+ cell-id = <MSM_BUS_SLAVE_ANOC_PCIE_A1NOC_SNOC>;
+ label = "slv-qns-pcie-a1noc-snoc";
+ qcom,buswidth = <16>;
+ qcom,agg-ports = <1>;
+ qcom,bus-dev = <&fab_aggre1_noc>;
+ qcom,connections = <&mas_qnm_pcie_anoc>;
+ };
+
slv_qns_a2noc_snoc:slv-qns-a2noc-snoc {
cell-id = <MSM_BUS_A2NOC_SNOC_SLV>;
label = "slv-qns-a2noc-snoc";
@@ -1348,7 +1373,6 @@
qcom,buswidth = <32>;
qcom,agg-ports = <1>;
qcom,bus-dev = <&fab_camnoc_virt>;
- qcom,bcms = <&bcm_mm1>;
};
slv_qhs_a1_noc_cfg:slv-qhs-a1-noc-cfg {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
index dee2ec2..c4ec012 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-cdp.dtsi
@@ -13,7 +13,7 @@
#include <dt-bindings/gpio/gpio.h>
#include "sdm845-camera-sensor-cdp.dtsi"
-/ {
+&vendor {
bluetooth: bt_wcn3990 {
compatible = "qca,wcn3990";
qca,bt-vdd-io-supply = <&pm8998_s3>;
@@ -188,7 +188,7 @@
qcom,batteryless-platform;
};
-/ {
+&vendor {
extcon_usb1: extcon_usb1 {
compatible = "linux,extcon-usb-gpio";
id-gpio = <&pmi8998_gpios 9 GPIO_ACTIVE_HIGH>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
index fb31b05..1453975 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-mtp.dtsi
@@ -14,7 +14,7 @@
#include "sdm845-camera-sensor-mtp.dtsi"
#include "smb1355.dtsi"
-/ {
+&vendor {
bluetooth: bt_wcn3990 {
compatible = "qca,wcn3990";
qca,bt-vdd-io-supply = <&pm8998_s3>;
@@ -260,7 +260,7 @@
pinctrl-1 = <&flash_led3_front_dis>;
};
-/{
+&vendor {
mtp_batterydata: qcom,battery-data {
qcom,batt-id-range-pct = <15>;
#include "fg-gen3-batterydata-itech-3000mah.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 7982625..9cf18b7 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -13,7 +13,7 @@
#include "smb1355.dtsi"
#include <dt-bindings/gpio/gpio.h>
-/{
+&vendor {
bluetooth: bt_wcn3990 {
compatible = "qca,wcn3990";
qca,bt-vdd-io-supply = <&pm8998_s3>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index 3153e66..41c1876 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -369,6 +369,17 @@
cache-slice-names = "rotator";
cache-slices = <&llcc 4>;
+ /* reg bus scale settings */
+ rot_reg: qcom,rot-reg-bus {
+ qcom,msm-bus,name = "mdss_rot_reg";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,active-only;
+ qcom,msm-bus,vectors-KBps =
+ <1 590 0 0>,
+ <1 590 0 76800>;
+ };
+
smmu_rot_unsec: qcom,smmu_rot_unsec_cb {
compatible = "qcom,smmu_sde_rot_unsec";
iommus = <&apps_smmu 0x1090 0x0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
index 53cb27e..ac16d03 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-usb.dtsi
@@ -113,13 +113,24 @@
/* Primary USB port related QUSB2 PHY */
qusb_phy0: qusb@88e2000 {
compatible = "qcom,qusb2phy-v2";
- reg = <0x088e2000 0x400>;
- reg-names = "qusb_phy_base";
+ reg = <0x088e2000 0x400>,
+ <0x007801e8 0x4>;
+ reg-names = "qusb_phy_base", "efuse_addr";
+ qcom,efuse-bit-pos = <25>;
+ qcom,efuse-num-bits = <3>;
vdd-supply = <&pm8998_l1>;
vdda18-supply = <&pm8998_l12>;
vdda33-supply = <&pm8998_l24>;
qcom,vdd-voltage-level = <0 880000 880000>;
+ qcom,qusb-phy-reg-offset =
+ <0x240 /* QUSB2PHY_PORT_TUNE1 */
+ 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */
+ 0x210 /* QUSB2PHY_PWR_CTRL1 */
+ 0x230 /* QUSB2PHY_INTR_CTRL */
+ 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */
+ 0x254>; /* QUSB2PHY_TEST1 */
+
qcom,qusb-phy-init-seq =
/* <value reg_offset> */
<0x23 0x210 /* PWR_CTRL1 */
@@ -133,7 +144,7 @@
0x21 0x214 /* PWR_CTRL2 */
0x00 0x220 /* IMP_CTRL1 */
0x58 0x224 /* IMP_CTRL2 */
- 0x32 0x240 /* TUNE1 */
+ 0x30 0x240 /* TUNE1 */
0x29 0x244 /* TUNE2 */
0xca 0x248 /* TUNE3 */
0x04 0x24c /* TUNE4 */
@@ -141,8 +152,6 @@
0x00 0x23c /* CHG_CTRL2 */
0x22 0x210>; /* PWR_CTRL1 */
- qcom,phy-auto-resume-offset = <0x254>;
-
phy_type= "utmi";
clocks = <&clock_rpmh RPMH_CXO_CLK>,
<&clock_gcc GCC_USB_PHY_CFG_AHB2PHY_CLK>;
@@ -385,6 +394,14 @@
vdda18-supply = <&pm8998_l12>;
vdda33-supply = <&pm8998_l24>;
qcom,vdd-voltage-level = <0 880000 880000>;
+ qcom,qusb-phy-reg-offset =
+ <0x240 /* QUSB2PHY_PORT_TUNE1 */
+ 0x1a0 /* QUSB2PHY_PLL_COMMON_STATUS_ONE */
+ 0x210 /* QUSB2PHY_PWR_CTRL1 */
+ 0x230 /* QUSB2PHY_INTR_CTRL */
+ 0x0a8 /* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE */
+ 0x254>; /* QUSB2PHY_TEST1 */
+
qcom,qusb-phy-init-seq =
/* <value reg_offset> */
<0x23 0x210 /* PWR_CTRL1 */
@@ -398,7 +415,7 @@
0x21 0x214 /* PWR_CTRL2 */
0x00 0x220 /* IMP_CTRL1 */
0x58 0x224 /* IMP_CTRL2 */
- 0x32 0x240 /* TUNE1 */
+ 0x20 0x240 /* TUNE1 */
0x29 0x244 /* TUNE2 */
0xca 0x248 /* TUNE3 */
0x04 0x24c /* TUNE4 */
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index 2c0373d..8f9618d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -476,6 +476,10 @@
method = "smc";
};
+ chosen {
+ bootargs = "rcupdate.rcu_expedited=1";
+ };
+
soc: soc { };
vendor: vendor {
@@ -969,13 +973,13 @@
qcom,target-dev = <&l3_cpu0>;
qcom,cachemiss-ev = <0x17>;
qcom,core-dev-table =
- < 300000 300000 >,
- < 748800 576000 >,
- < 979200 652800 >,
- < 1209600 806400 >,
- < 1516800 883200 >,
- < 1593600 960000 >,
- < 1708800 1094400 >;
+ < 300000 300000000 >,
+ < 748800 576000000 >,
+ < 979200 652800000 >,
+ < 1209600 806400000 >,
+ < 1516800 883200000 >,
+ < 1593600 960000000 >,
+ < 1708800 1094400000 >;
};
devfreq_l3lat_4: qcom,cpu4-l3lat-mon {
@@ -984,12 +988,12 @@
qcom,target-dev = <&l3_cpu4>;
qcom,cachemiss-ev = <0x17>;
qcom,core-dev-table =
- < 300000 300000 >,
- < 1036800 576000 >,
- < 1190400 806400 >,
- < 1574400 883200 >,
- < 1804800 960000 >,
- < 2092800 1094400 >;
+ < 300000 300000000 >,
+ < 1036800 576000000 >,
+ < 1190400 806400000 >,
+ < 1574400 883200000 >,
+ < 1804800 960000000 >,
+ < 2092800 1094400000 >;
};
cpu_pmu: cpu-pmu {
@@ -2498,6 +2502,7 @@
qcom,xprt-linkid = <1>;
qcom,xprt-version = <1>;
qcom,fragmented-data;
+ qcom,dynamic-wakeup-source;
};
qcom,ipc_router_cdsp_xprt {
@@ -3688,6 +3693,7 @@
};
&bps_gdsc {
+ qcom,support-hw-trigger;
status = "ok";
};
@@ -3700,10 +3706,12 @@
};
&ipe_0_gdsc {
+ qcom,support-hw-trigger;
status = "ok";
};
&ipe_1_gdsc {
+ qcom,support-hw-trigger;
status = "ok";
};
diff --git a/arch/arm64/configs/sdm670_defconfig b/arch/arm64/configs/sdm670_defconfig
index f28a9a6..14243fb 100644
--- a/arch/arm64/configs/sdm670_defconfig
+++ b/arch/arm64/configs/sdm670_defconfig
@@ -265,7 +265,6 @@
CONFIG_BONDING=y
CONFIG_DUMMY=y
CONFIG_TUN=y
-CONFIG_RNDIS_IPA=y
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
@@ -333,7 +332,6 @@
CONFIG_QTI_VIRTUAL_SENSOR=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
-CONFIG_WCD934X_CODEC=y
CONFIG_REGULATOR_FIXED_VOLTAGE=y
CONFIG_REGULATOR_CPRH_KBSS=y
CONFIG_REGULATOR_QPNP_LABIBB=y
@@ -445,6 +443,7 @@
CONFIG_GSI=y
CONFIG_IPA3=y
CONFIG_RMNET_IPA3=y
+CONFIG_RNDIS_IPA=y
CONFIG_IPA_UT=y
CONFIG_SPS=y
CONFIG_SPS_SUPPORT_NDP_BAM=y
@@ -573,7 +572,6 @@
CONFIG_DEBUG_STACK_USAGE=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_LOCKUP_DETECTOR=y
-CONFIG_BOOTPARAM_HARDLOCKUP_PANIC=y
CONFIG_WQ_WATCHDOG=y
CONFIG_PANIC_TIMEOUT=5
CONFIG_PANIC_ON_SCHED_BUG=y
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 9f98841..b60dd01 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -264,9 +264,15 @@
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_USBNET=y
CONFIG_WIL6210=m
# CONFIG_WIL6210_TRACING is not set
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index cd4cbb1..37f7d32 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -271,9 +271,15 @@
CONFIG_PPP=y
CONFIG_PPP_BSDCOMP=y
CONFIG_PPP_DEFLATE=y
+CONFIG_PPP_FILTER=y
CONFIG_PPP_MPPE=y
+CONFIG_PPP_MULTILINK=y
+CONFIG_PPPOE=y
+CONFIG_PPPOL2TP=y
CONFIG_PPPOLAC=y
CONFIG_PPPOPNS=y
+CONFIG_PPP_ASYNC=y
+CONFIG_PPP_SYNC_TTY=y
CONFIG_USB_USBNET=y
CONFIG_WIL6210=m
CONFIG_WCNSS_MEM_PRE_ALLOC=y
diff --git a/arch/arm64/include/asm/Kbuild b/arch/arm64/include/asm/Kbuild
index 44e1d7f..28196b1 100644
--- a/arch/arm64/include/asm/Kbuild
+++ b/arch/arm64/include/asm/Kbuild
@@ -1,7 +1,6 @@
generic-y += bugs.h
generic-y += clkdev.h
generic-y += cputime.h
-generic-y += current.h
generic-y += delay.h
generic-y += div64.h
generic-y += dma.h
diff --git a/arch/arm64/include/asm/acpi.h b/arch/arm64/include/asm/acpi.h
index e517088..de04879 100644
--- a/arch/arm64/include/asm/acpi.h
+++ b/arch/arm64/include/asm/acpi.h
@@ -22,9 +22,9 @@
#define ACPI_MADT_GICC_LENGTH \
(acpi_gbl_FADT.header.revision < 6 ? 76 : 80)
-#define BAD_MADT_GICC_ENTRY(entry, end) \
- (!(entry) || (unsigned long)(entry) + sizeof(*(entry)) > (end) || \
- (entry)->header.length != ACPI_MADT_GICC_LENGTH)
+#define BAD_MADT_GICC_ENTRY(entry, end) \
+ (!(entry) || (entry)->header.length != ACPI_MADT_GICC_LENGTH || \
+ (unsigned long)(entry) + ACPI_MADT_GICC_LENGTH > (end))
/* Basic configuration for ACPI */
#ifdef CONFIG_ACPI
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index e3c80f1..ef5970e 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -176,22 +176,25 @@
/*
* Pseudo-ops for PC-relative adr/ldr/str <reg>, <symbol> where
- * <symbol> is within the range +/- 4 GB of the PC.
+ * <symbol> is within the range +/- 4 GB of the PC when running
+ * in core kernel context. In module context, a movz/movk sequence
+ * is used, since modules may be loaded far away from the kernel
+ * when KASLR is in effect.
*/
/*
* @dst: destination register (64 bit wide)
* @sym: name of the symbol
- * @tmp: optional scratch register to be used if <dst> == sp, which
- * is not allowed in an adrp instruction
*/
- .macro adr_l, dst, sym, tmp=
- .ifb \tmp
+ .macro adr_l, dst, sym
+#ifndef MODULE
adrp \dst, \sym
add \dst, \dst, :lo12:\sym
- .else
- adrp \tmp, \sym
- add \dst, \tmp, :lo12:\sym
- .endif
+#else
+ movz \dst, #:abs_g3:\sym
+ movk \dst, #:abs_g2_nc:\sym
+ movk \dst, #:abs_g1_nc:\sym
+ movk \dst, #:abs_g0_nc:\sym
+#endif
.endm
/*
@@ -202,6 +205,7 @@
* the address
*/
.macro ldr_l, dst, sym, tmp=
+#ifndef MODULE
.ifb \tmp
adrp \dst, \sym
ldr \dst, [\dst, :lo12:\sym]
@@ -209,6 +213,15 @@
adrp \tmp, \sym
ldr \dst, [\tmp, :lo12:\sym]
.endif
+#else
+ .ifb \tmp
+ adr_l \dst, \sym
+ ldr \dst, [\dst]
+ .else
+ adr_l \tmp, \sym
+ ldr \dst, [\tmp]
+ .endif
+#endif
.endm
/*
@@ -218,19 +231,35 @@
* while <src> needs to be preserved.
*/
.macro str_l, src, sym, tmp
+#ifndef MODULE
adrp \tmp, \sym
str \src, [\tmp, :lo12:\sym]
+#else
+ adr_l \tmp, \sym
+ str \src, [\tmp]
+#endif
.endm
/*
+ * @dst: Result of per_cpu(sym, smp_processor_id())
* @sym: The name of the per-cpu variable
- * @reg: Result of per_cpu(sym, smp_processor_id())
* @tmp: scratch register
*/
- .macro this_cpu_ptr, sym, reg, tmp
- adr_l \reg, \sym
+ .macro adr_this_cpu, dst, sym, tmp
+ adr_l \dst, \sym
mrs \tmp, tpidr_el1
- add \reg, \reg, \tmp
+ add \dst, \dst, \tmp
+ .endm
+
+ /*
+ * @dst: Result of READ_ONCE(per_cpu(sym, smp_processor_id()))
+ * @sym: The name of the per-cpu variable
+ * @tmp: scratch register
+ */
+ .macro ldr_this_cpu dst, sym, tmp
+ adr_l \dst, \sym
+ mrs \tmp, tpidr_el1
+ ldr \dst, [\dst, \tmp]
.endm
/*
diff --git a/arch/arm64/include/asm/current.h b/arch/arm64/include/asm/current.h
new file mode 100644
index 0000000..86c4041
--- /dev/null
+++ b/arch/arm64/include/asm/current.h
@@ -0,0 +1,30 @@
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+
+#include <asm/sysreg.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+
+/*
+ * We don't use read_sysreg() as we want the compiler to cache the value where
+ * possible.
+ */
+static __always_inline struct task_struct *get_current(void)
+{
+ unsigned long sp_el0;
+
+ asm ("mrs %0, sp_el0" : "=r" (sp_el0));
+
+ return (struct task_struct *)sp_el0;
+}
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
+
diff --git a/arch/arm64/include/asm/percpu.h b/arch/arm64/include/asm/percpu.h
index 5394c84..d7a3c62 100644
--- a/arch/arm64/include/asm/percpu.h
+++ b/arch/arm64/include/asm/percpu.h
@@ -16,6 +16,8 @@
#ifndef __ASM_PERCPU_H
#define __ASM_PERCPU_H
+#include <asm/stack_pointer.h>
+
static inline void set_my_cpu_offset(unsigned long off)
{
asm volatile("msr tpidr_el1, %0" :: "r" (off) : "memory");
diff --git a/arch/arm64/include/asm/perf_event.h b/arch/arm64/include/asm/perf_event.h
index 38b6a2b..8d5cbec 100644
--- a/arch/arm64/include/asm/perf_event.h
+++ b/arch/arm64/include/asm/perf_event.h
@@ -17,6 +17,8 @@
#ifndef __ASM_PERF_EVENT_H
#define __ASM_PERF_EVENT_H
+#include <asm/stack_pointer.h>
+
#define ARMV8_PMU_MAX_COUNTERS 32
#define ARMV8_PMU_COUNTER_MASK (ARMV8_PMU_MAX_COUNTERS - 1)
diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h
index 0226447..d050d72 100644
--- a/arch/arm64/include/asm/smp.h
+++ b/arch/arm64/include/asm/smp.h
@@ -29,11 +29,22 @@
#ifndef __ASSEMBLY__
+#include <asm/percpu.h>
+
#include <linux/threads.h>
#include <linux/cpumask.h>
#include <linux/thread_info.h>
-#define raw_smp_processor_id() (current_thread_info()->cpu)
+DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
+
+/*
+ * We don't use this_cpu_read(cpu_number) as that has implicit writes to
+ * preempt_count, and associated (compiler) barriers, that we'd like to avoid
+ * the expense of. If we're preemptible, the value can be stale at use anyway.
+ * And we can't use this_cpu_ptr() either, as that winds up recursing back
+ * here under CONFIG_DEBUG_PREEMPT=y.
+ */
+#define raw_smp_processor_id() (*raw_cpu_ptr(&cpu_number))
struct seq_file;
@@ -73,6 +84,7 @@
*/
struct secondary_data {
void *stack;
+ struct task_struct *task;
long status;
};
diff --git a/arch/arm64/include/asm/stack_pointer.h b/arch/arm64/include/asm/stack_pointer.h
new file mode 100644
index 0000000..ffcdf74
--- /dev/null
+++ b/arch/arm64/include/asm/stack_pointer.h
@@ -0,0 +1,9 @@
+#ifndef __ASM_STACK_POINTER_H
+#define __ASM_STACK_POINTER_H
+
+/*
+ * how to get the current stack pointer from C
+ */
+register unsigned long current_stack_pointer asm ("sp");
+
+#endif /* __ASM_STACK_POINTER_H */
diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/suspend.h
index b8a313f..de5600f 100644
--- a/arch/arm64/include/asm/suspend.h
+++ b/arch/arm64/include/asm/suspend.h
@@ -1,7 +1,7 @@
#ifndef __ASM_SUSPEND_H
#define __ASM_SUSPEND_H
-#define NR_CTX_REGS 10
+#define NR_CTX_REGS 12
#define NR_CALLEE_SAVED_REGS 12
/*
diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h
index 4ad25a5..ebd18b7 100644
--- a/arch/arm64/include/asm/thread_info.h
+++ b/arch/arm64/include/asm/thread_info.h
@@ -36,61 +36,31 @@
struct task_struct;
+#include <asm/stack_pointer.h>
#include <asm/types.h>
typedef unsigned long mm_segment_t;
/*
* low level task data that entry.S needs immediate access to.
- * __switch_to() assumes cpu_context follows immediately after cpu_domain.
*/
struct thread_info {
unsigned long flags; /* low level flags */
mm_segment_t addr_limit; /* address limit */
- struct task_struct *task; /* main task structure */
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
u64 ttbr0; /* saved TTBR0_EL1 */
#endif
int preempt_count; /* 0 => preemptable, <0 => bug */
- int cpu; /* cpu */
};
#define INIT_THREAD_INFO(tsk) \
{ \
- .task = &tsk, \
- .flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
.addr_limit = KERNEL_DS, \
}
-#define init_thread_info (init_thread_union.thread_info)
#define init_stack (init_thread_union.stack)
-/*
- * how to get the current stack pointer from C
- */
-register unsigned long current_stack_pointer asm ("sp");
-
-/*
- * how to get the thread information struct from C
- */
-static inline struct thread_info *current_thread_info(void) __attribute_const__;
-
-/*
- * struct thread_info can be accessed directly via sp_el0.
- *
- * We don't use read_sysreg() as we want the compiler to cache the value where
- * possible.
- */
-static inline struct thread_info *current_thread_info(void)
-{
- unsigned long sp_el0;
-
- asm ("mrs %0, sp_el0" : "=r" (sp_el0));
-
- return (struct thread_info *)sp_el0;
-}
-
#define thread_saved_pc(tsk) \
((unsigned long)(tsk->thread.cpu_context.pc))
#define thread_saved_sp(tsk) \
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c
index 5cdbc55..b3bb7ef 100644
--- a/arch/arm64/kernel/asm-offsets.c
+++ b/arch/arm64/kernel/asm-offsets.c
@@ -36,17 +36,13 @@
{
DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
BLANK();
- DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
- DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
- DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
+ DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags));
+ DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count));
+ DEFINE(TSK_TI_ADDR_LIMIT, offsetof(struct task_struct, thread_info.addr_limit));
#ifdef CONFIG_ARM64_SW_TTBR0_PAN
- DEFINE(TI_TTBR0, offsetof(struct thread_info, ttbr0));
+ DEFINE(TSK_TI_TTBR0, offsetof(struct task_struct, thread_info.ttbr0));
#endif
- DEFINE(TI_TASK, offsetof(struct thread_info, task));
- DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
-#ifdef CONFIG_ARM64_SW_TTBR0_PAN
- DEFINE(TSK_TI_TTBR0, offsetof(struct thread_info, ttbr0));
-#endif
+ DEFINE(TSK_STACK, offsetof(struct task_struct, stack));
BLANK();
DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context));
BLANK();
@@ -129,6 +125,7 @@
DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime));
BLANK();
DEFINE(CPU_BOOT_STACK, offsetof(struct secondary_data, stack));
+ DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task));
BLANK();
#ifdef CONFIG_KVM_ARM_HOST
DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt));
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index c44a933..718c4c8 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -93,9 +93,8 @@
.if \el == 0
mrs x21, sp_el0
- mov tsk, sp
- and tsk, tsk, #~(THREAD_SIZE - 1) // Ensure MDSCR_EL1.SS is clear,
- ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug
+ ldr_this_cpu tsk, __entry_task, x20 // Ensure MDSCR_EL1.SS is clear,
+ ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug
disable_step_tsk x19, x20 // exceptions when scheduling.
mov x29, xzr // fp pointed to user-space
@@ -103,10 +102,10 @@
add x21, sp, #S_FRAME_SIZE
get_thread_info tsk
/* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */
- ldr x20, [tsk, #TI_ADDR_LIMIT]
+ ldr x20, [tsk, #TSK_TI_ADDR_LIMIT]
str x20, [sp, #S_ORIG_ADDR_LIMIT]
mov x20, #TASK_SIZE_64
- str x20, [tsk, #TI_ADDR_LIMIT]
+ str x20, [tsk, #TSK_TI_ADDR_LIMIT]
/* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */
.endif /* \el == 0 */
mrs x22, elr_el1
@@ -168,7 +167,7 @@
.if \el != 0
/* Restore the task's original addr_limit. */
ldr x20, [sp, #S_ORIG_ADDR_LIMIT]
- str x20, [tsk, #TI_ADDR_LIMIT]
+ str x20, [tsk, #TSK_TI_ADDR_LIMIT]
/* No need to restore UAO, it will be restored from SPSR_EL1 */
.endif
@@ -252,15 +251,16 @@
mov x19, sp // preserve the original sp
/*
- * Compare sp with the current thread_info, if the top
- * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and
- * should switch to the irq stack.
+ * Compare sp with the base of the task stack.
+ * If the top ~(THREAD_SIZE - 1) bits match, we are on a task stack,
+ * and should switch to the irq stack.
*/
- and x25, x19, #~(THREAD_SIZE - 1)
- cmp x25, tsk
- b.ne 9998f
+ ldr x25, [tsk, TSK_STACK]
+ eor x25, x25, x19
+ and x25, x25, #~(THREAD_SIZE - 1)
+ cbnz x25, 9998f
- this_cpu_ptr irq_stack, x25, x26
+ adr_this_cpu x25, irq_stack, x26
mov x26, #IRQ_STACK_START_SP
add x26, x25, x26
@@ -488,9 +488,9 @@
irq_handler
#ifdef CONFIG_PREEMPT
- ldr w24, [tsk, #TI_PREEMPT] // get preempt count
+ ldr w24, [tsk, #TSK_TI_PREEMPT] // get preempt count
cbnz w24, 1f // preempt count != 0
- ldr x0, [tsk, #TI_FLAGS] // get flags
+ ldr x0, [tsk, #TSK_TI_FLAGS] // get flags
tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling?
bl el1_preempt
1:
@@ -505,7 +505,7 @@
el1_preempt:
mov x24, lr
1: bl preempt_schedule_irq // irq en/disable is done inside
- ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS
+ ldr x0, [tsk, #TSK_TI_FLAGS] // get new tasks TI_FLAGS
tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling?
ret x24
#endif
@@ -735,8 +735,7 @@
ldp x29, x9, [x8], #16
ldr lr, [x8]
mov sp, x9
- and x9, x9, #~(THREAD_SIZE - 1)
- msr sp_el0, x9
+ msr sp_el0, x1
ret
ENDPROC(cpu_switch_to)
@@ -747,7 +746,7 @@
ret_fast_syscall:
disable_irq // disable interrupts
str x0, [sp, #S_X0] // returned x0
- ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing
+ ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for syscall tracing
and x2, x1, #_TIF_SYSCALL_WORK
cbnz x2, ret_fast_syscall_trace
and x2, x1, #_TIF_WORK_MASK
@@ -767,14 +766,14 @@
#ifdef CONFIG_TRACE_IRQFLAGS
bl trace_hardirqs_on // enabled while in userspace
#endif
- ldr x1, [tsk, #TI_FLAGS] // re-check for single-step
+ ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for single-step
b finish_ret_to_user
/*
* "slow" syscall return path.
*/
ret_to_user:
disable_irq // disable interrupts
- ldr x1, [tsk, #TI_FLAGS]
+ ldr x1, [tsk, #TSK_TI_FLAGS]
and x2, x1, #_TIF_WORK_MASK
cbnz x2, work_pending
finish_ret_to_user:
@@ -807,7 +806,7 @@
enable_dbg_and_irq
ct_user_exit 1
- ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks
+ ldr x16, [tsk, #TSK_TI_FLAGS] // check for syscall hooks
tst x16, #_TIF_SYSCALL_WORK
b.ne __sys_trace
cmp scno, sc_nr // check upper syscall limit
diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S
index c7d26bb..7ee6d74 100644
--- a/arch/arm64/kernel/head.S
+++ b/arch/arm64/kernel/head.S
@@ -428,7 +428,8 @@
__primary_switched:
adrp x4, init_thread_union
add sp, x4, #THREAD_SIZE
- msr sp_el0, x4 // Save thread_info
+ adr_l x5, init_task
+ msr sp_el0, x5 // Save thread_info
adr_l x8, vectors // load VBAR_EL1 with virtual
msr vbar_el1, x8 // vector table address
@@ -699,10 +700,10 @@
isb
adr_l x0, secondary_data
- ldr x0, [x0, #CPU_BOOT_STACK] // get secondary_data.stack
- mov sp, x0
- and x0, x0, #~(THREAD_SIZE - 1)
- msr sp_el0, x0 // save thread_info
+ ldr x1, [x0, #CPU_BOOT_STACK] // get secondary_data.stack
+ mov sp, x1
+ ldr x2, [x0, #CPU_BOOT_TASK]
+ msr sp_el0, x2
mov x29, #0
b secondary_start_kernel
ENDPROC(__secondary_switched)
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index fc1a286..5fe594e 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -45,6 +45,7 @@
#include <linux/personality.h>
#include <linux/notifier.h>
#include <trace/events/power.h>
+#include <linux/percpu.h>
#include <asm/alternative.h>
#include <asm/compat.h>
@@ -390,6 +391,20 @@
}
/*
+ * We store our current task in sp_el0, which is clobbered by userspace. Keep a
+ * shadow copy so that we can restore this upon entry from userspace.
+ *
+ * This is *only* for exception entry from EL0, and is not valid until we
+ * __switch_to() a user task.
+ */
+DEFINE_PER_CPU(struct task_struct *, __entry_task);
+
+static void entry_task_switch(struct task_struct *next)
+{
+ __this_cpu_write(__entry_task, next);
+}
+
+/*
* Thread switching.
*/
struct task_struct *__switch_to(struct task_struct *prev,
@@ -401,6 +416,7 @@
tls_thread_switch(next);
hw_breakpoint_thread_switch(next);
contextidr_thread_switch(next);
+ entry_task_switch(next);
uao_thread_switch(next);
/*
@@ -418,27 +434,35 @@
unsigned long get_wchan(struct task_struct *p)
{
struct stackframe frame;
- unsigned long stack_page;
+ unsigned long stack_page, ret = 0;
int count = 0;
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
+ stack_page = (unsigned long)try_get_task_stack(p);
+ if (!stack_page)
+ return 0;
+
frame.fp = thread_saved_fp(p);
frame.sp = thread_saved_sp(p);
frame.pc = thread_saved_pc(p);
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
frame.graph = p->curr_ret_stack;
#endif
- stack_page = (unsigned long)task_stack_page(p);
do {
if (frame.sp < stack_page ||
frame.sp >= stack_page + THREAD_SIZE ||
unwind_frame(p, &frame))
- return 0;
- if (!in_sched_functions(frame.pc))
- return frame.pc;
+ goto out;
+ if (!in_sched_functions(frame.pc)) {
+ ret = frame.pc;
+ goto out;
+ }
} while (count ++ < 16);
- return 0;
+
+out:
+ put_task_stack(p);
+ return ret;
}
unsigned long arch_align_stack(unsigned long sp)
diff --git a/arch/arm64/kernel/return_address.c b/arch/arm64/kernel/return_address.c
index 1718706..12a87f2 100644
--- a/arch/arm64/kernel/return_address.c
+++ b/arch/arm64/kernel/return_address.c
@@ -12,6 +12,7 @@
#include <linux/export.h>
#include <linux/ftrace.h>
+#include <asm/stack_pointer.h>
#include <asm/stacktrace.h>
struct return_address_data {
diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c
index 49f3ae0..ae02756 100644
--- a/arch/arm64/kernel/setup.c
+++ b/arch/arm64/kernel/setup.c
@@ -312,7 +312,7 @@
* faults in case uaccess_enable() is inadvertently called by the init
* thread.
*/
- init_thread_info.ttbr0 = virt_to_phys(empty_zero_page);
+ init_task.thread_info.ttbr0 = virt_to_phys(empty_zero_page);
#endif
#ifdef CONFIG_VT
diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S
index 1bec41b..df67652 100644
--- a/arch/arm64/kernel/sleep.S
+++ b/arch/arm64/kernel/sleep.S
@@ -125,9 +125,6 @@
/* load sp from context */
ldr x2, [x0, #CPU_CTX_SP]
mov sp, x2
- /* save thread_info */
- and x2, x2, #~(THREAD_SIZE - 1)
- msr sp_el0, x2
/*
* cpu_do_resume expects x0 to contain context address pointer
*/
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 0f62709..2437f15 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -58,6 +58,9 @@
#define CREATE_TRACE_POINTS
#include <trace/events/ipi.h>
+DEFINE_PER_CPU_READ_MOSTLY(int, cpu_number);
+EXPORT_PER_CPU_SYMBOL(cpu_number);
+
/*
* as from 2.5, kernels no longer have an init_tasks structure
* so we need some other way of telling a new secondary core
@@ -147,6 +150,7 @@
* We need to tell the secondary core where to find its stack and the
* page tables.
*/
+ secondary_data.task = idle;
secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
update_cpu_boot_status(CPU_MMU_OFF);
__flush_dcache_area(&secondary_data, sizeof(secondary_data));
@@ -171,6 +175,7 @@
pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
}
+ secondary_data.task = NULL;
secondary_data.stack = NULL;
status = READ_ONCE(secondary_data.status);
if (ret && status) {
@@ -209,7 +214,10 @@
asmlinkage void secondary_start_kernel(void)
{
struct mm_struct *mm = &init_mm;
- unsigned int cpu = smp_processor_id();
+ unsigned int cpu;
+
+ cpu = task_cpu(current);
+ set_my_cpu_offset(per_cpu_offset(cpu));
/*
* All kernel threads share the same mm context; grab a
@@ -218,8 +226,6 @@
atomic_inc(&mm->mm_count);
current->active_mm = mm;
- set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
-
pr_debug("CPU%u: Booted secondary processor\n", cpu);
/*
@@ -733,6 +739,8 @@
*/
for_each_possible_cpu(cpu) {
+ per_cpu(cpu_number, cpu) = cpu;
+
if (cpu == smp_processor_id())
continue;
@@ -1035,7 +1043,7 @@
#ifdef CONFIG_HOTPLUG_CPU
int any_cpu = raw_smp_processor_id();
- if (cpu_ops[any_cpu]->cpu_die)
+ if (cpu_ops[any_cpu] && cpu_ops[any_cpu]->cpu_die)
return true;
#endif
return false;
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index bedf97d..900c1ec 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -22,6 +22,7 @@
#include <linux/stacktrace.h>
#include <asm/irq.h>
+#include <asm/stack_pointer.h>
#include <asm/stacktrace.h>
/*
@@ -128,7 +129,6 @@
break;
}
}
-EXPORT_SYMBOL(walk_stackframe);
#ifdef CONFIG_STACKTRACE
struct stack_trace_data {
@@ -181,6 +181,9 @@
struct stack_trace_data data;
struct stackframe frame;
+ if (!try_get_task_stack(tsk))
+ return;
+
data.trace = trace;
data.skip = trace->skip;
@@ -202,6 +205,8 @@
walk_stackframe(tsk, &frame, save_trace, &data);
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
+
+ put_task_stack(tsk);
}
EXPORT_SYMBOL(save_stack_trace_tsk);
diff --git a/arch/arm64/kernel/suspend.c b/arch/arm64/kernel/suspend.c
index bb0cd78..1e3be90 100644
--- a/arch/arm64/kernel/suspend.c
+++ b/arch/arm64/kernel/suspend.c
@@ -47,12 +47,6 @@
cpu_uninstall_idmap();
/*
- * Restore per-cpu offset before any kernel
- * subsystem relying on it has a chance to run.
- */
- set_my_cpu_offset(per_cpu_offset(cpu));
-
- /*
* PSTATE was not saved over suspend/resume, re-enable any detected
* features that might not have been set correctly.
*/
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index d8253fb..e576c1d 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -38,6 +38,7 @@
#include <asm/esr.h>
#include <asm/insn.h>
#include <asm/traps.h>
+#include <asm/stack_pointer.h>
#include <asm/stacktrace.h>
#include <asm/exception.h>
#include <asm/system_misc.h>
@@ -147,6 +148,9 @@
if (!tsk)
tsk = current;
+ if (!try_get_task_stack(tsk))
+ return;
+
/*
* Switching between stacks is valid when tracing current and in
* non-preemptible context.
@@ -212,6 +216,8 @@
stack + sizeof(struct pt_regs));
}
}
+
+ put_task_stack(tsk);
}
void show_stack(struct task_struct *tsk, unsigned long *sp)
@@ -227,10 +233,9 @@
#endif
#define S_SMP " SMP"
-static int __die(const char *str, int err, struct thread_info *thread,
- struct pt_regs *regs)
+static int __die(const char *str, int err, struct pt_regs *regs)
{
- struct task_struct *tsk = thread->task;
+ struct task_struct *tsk = current;
static int die_counter;
int ret;
@@ -245,7 +250,8 @@
print_modules();
__show_regs(regs);
pr_emerg("Process %.*s (pid: %d, stack limit = 0x%p)\n",
- TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+ TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk),
+ end_of_stack(tsk));
if (!user_mode(regs)) {
dump_backtrace(regs, tsk);
@@ -310,7 +316,6 @@
*/
void die(const char *str, struct pt_regs *regs, int err)
{
- struct thread_info *thread = current_thread_info();
enum bug_trap_type bug_type = BUG_TRAP_TYPE_NONE;
unsigned long flags = oops_begin();
int ret;
@@ -320,7 +325,7 @@
if (bug_type != BUG_TRAP_TYPE_NONE && !strlen(str))
str = "Oops - BUG";
- ret = __die(str, err, thread, regs);
+ ret = __die(str, err, regs);
oops_end(flags, regs, ret);
}
diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c
index 0a34644..d0ffade 100644
--- a/arch/arm64/mm/fault.c
+++ b/arch/arm64/mm/fault.c
@@ -40,7 +40,6 @@
#include <asm/system_misc.h>
#include <asm/pgtable.h>
#include <asm/tlbflush.h>
-#include <asm/kryo3xx-arm64-edac.h>
#include <soc/qcom/scm.h>
struct fault_info {
@@ -521,7 +520,6 @@
*/
static int do_bad(unsigned long addr, unsigned int esr, struct pt_regs *regs)
{
- kryo3xx_poll_cache_errors(NULL);
return 1;
}
diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S
index 61330c9..8d21250 100644
--- a/arch/arm64/mm/proc.S
+++ b/arch/arm64/mm/proc.S
@@ -116,11 +116,14 @@
mrs x8, mdscr_el1
mrs x9, oslsr_el1
mrs x10, sctlr_el1
+ mrs x11, tpidr_el1
+ mrs x12, sp_el0
stp x2, x3, [x0]
stp x4, xzr, [x0, #16]
stp x5, x6, [x0, #32]
stp x7, x8, [x0, #48]
stp x9, x10, [x0, #64]
+ stp x11, x12, [x0, #80]
ret
ENDPROC(cpu_do_suspend)
@@ -136,6 +139,7 @@
ldp x6, x8, [x0, #32]
ldp x9, x10, [x0, #48]
ldp x11, x12, [x0, #64]
+ ldp x13, x14, [x0, #80]
msr tpidr_el0, x2
msr tpidrro_el0, x3
msr contextidr_el1, x4
@@ -158,6 +162,8 @@
msr mdscr_el1, x10
msr sctlr_el1, x12
+ msr tpidr_el1, x13
+ msr sp_el0, x14
/*
* Restore oslsr_el1 by writing oslar_el1
*/
diff --git a/arch/mips/kernel/entry.S b/arch/mips/kernel/entry.S
index 7791840..db07793 100644
--- a/arch/mips/kernel/entry.S
+++ b/arch/mips/kernel/entry.S
@@ -11,6 +11,7 @@
#include <asm/asm.h>
#include <asm/asmmacro.h>
#include <asm/compiler.h>
+#include <asm/irqflags.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/stackframe.h>
@@ -137,6 +138,7 @@
andi t0, a2, _TIF_NEED_RESCHED # a2 is preloaded with TI_FLAGS
beqz t0, work_notifysig
work_resched:
+ TRACE_IRQS_OFF
jal schedule
local_irq_disable # make sure need_resched and
@@ -173,6 +175,7 @@
beqz t0, work_pending # trace bit set?
local_irq_enable # could let syscall_trace_leave()
# call schedule() instead
+ TRACE_IRQS_ON
move a0, sp
jal syscall_trace_leave
b resume_userspace
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index cf05220..d1bb506 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -106,8 +106,8 @@
beq t0, t1, dtb_found
#endif
li t1, -2
- beq a0, t1, dtb_found
move t2, a1
+ beq a0, t1, dtb_found
li t2, 0
dtb_found:
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index 7cf653e..60c4d45 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -56,7 +56,6 @@
* state. Actually per-core rather than per-CPU.
*/
static DEFINE_PER_CPU_ALIGNED(u32*, ready_count);
-static DEFINE_PER_CPU_ALIGNED(void*, ready_count_alloc);
/* Indicates online CPUs coupled with the current CPU */
static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled);
@@ -642,7 +641,6 @@
{
enum cps_pm_state state;
unsigned core = cpu_data[cpu].core;
- unsigned dlinesz = cpu_data[cpu].dcache.linesz;
void *entry_fn, *core_rc;
for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) {
@@ -662,16 +660,11 @@
}
if (!per_cpu(ready_count, core)) {
- core_rc = kmalloc(dlinesz * 2, GFP_KERNEL);
+ core_rc = kmalloc(sizeof(u32), GFP_KERNEL);
if (!core_rc) {
pr_err("Failed allocate core %u ready_count\n", core);
return -ENOMEM;
}
- per_cpu(ready_count_alloc, core) = core_rc;
-
- /* Ensure ready_count is aligned to a cacheline boundary */
- core_rc += dlinesz - 1;
- core_rc = (void *)((unsigned long)core_rc & ~(dlinesz - 1));
per_cpu(ready_count, core) = core_rc;
}
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index ec87ef9..b0b29cb 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -199,6 +199,8 @@
{
struct pt_regs regs;
mm_segment_t old_fs = get_fs();
+
+ regs.cp0_status = KSU_KERNEL;
if (sp) {
regs.regs[29] = (unsigned long)sp;
regs.regs[31] = 0;
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index f257316..e5bfbf6 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -298,9 +298,17 @@
*
* For pHyp, we have to enable IO for log retrieval. Otherwise,
* 0xFF's is always returned from PCI config space.
+ *
+ * When the @severity is EEH_LOG_PERM, the PE is going to be
+ * removed. Prior to that, the drivers for devices included in
+ * the PE will be closed. The drivers rely on working IO path
+ * to bring the devices to quiet state. Otherwise, PCI traffic
+ * from those devices after they are removed is like to cause
+ * another unexpected EEH error.
*/
if (!(pe->type & EEH_PE_PHB)) {
- if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG))
+ if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG) ||
+ severity == EEH_LOG_PERM)
eeh_pci_enable(pe, EEH_OPT_THAW_MMIO);
/*
diff --git a/arch/s390/include/asm/ctl_reg.h b/arch/s390/include/asm/ctl_reg.h
index d7697ab..8e136b88 100644
--- a/arch/s390/include/asm/ctl_reg.h
+++ b/arch/s390/include/asm/ctl_reg.h
@@ -15,7 +15,9 @@
BUILD_BUG_ON(sizeof(addrtype) != (high - low + 1) * sizeof(long));\
asm volatile( \
" lctlg %1,%2,%0\n" \
- : : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high));\
+ : \
+ : "Q" (*(addrtype *)(&array)), "i" (low), "i" (high) \
+ : "memory"); \
}
#define __ctl_store(array, low, high) { \
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index e1b1ce6..5cbf03c 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -1021,7 +1021,7 @@
unsigned long order = get_order(size);
unsigned long p;
- p = __get_free_pages(GFP_KERNEL, order);
+ p = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!p) {
prom_printf("SUN4V: Error, cannot allocate queue.\n");
prom_halt();
diff --git a/arch/sparc/kernel/traps_64.c b/arch/sparc/kernel/traps_64.c
index 496fa92..d44fb80 100644
--- a/arch/sparc/kernel/traps_64.c
+++ b/arch/sparc/kernel/traps_64.c
@@ -2051,6 +2051,73 @@
atomic_inc(&sun4v_resum_oflow_cnt);
}
+/* Given a set of registers, get the virtual addressi that was being accessed
+ * by the faulting instructions at tpc.
+ */
+static unsigned long sun4v_get_vaddr(struct pt_regs *regs)
+{
+ unsigned int insn;
+
+ if (!copy_from_user(&insn, (void __user *)regs->tpc, 4)) {
+ return compute_effective_address(regs, insn,
+ (insn >> 25) & 0x1f);
+ }
+ return 0;
+}
+
+/* Attempt to handle non-resumable errors generated from userspace.
+ * Returns true if the signal was handled, false otherwise.
+ */
+bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
+ struct sun4v_error_entry *ent) {
+
+ unsigned int attrs = ent->err_attrs;
+
+ if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
+ unsigned long addr = ent->err_raddr;
+ siginfo_t info;
+
+ if (addr == ~(u64)0) {
+ /* This seems highly unlikely to ever occur */
+ pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory error detected in unknown location!\n");
+ } else {
+ unsigned long page_cnt = DIV_ROUND_UP(ent->err_size,
+ PAGE_SIZE);
+
+ /* Break the unfortunate news. */
+ pr_emerg("SUN4V NON-RECOVERABLE ERROR: Memory failed at %016lX\n",
+ addr);
+ pr_emerg("SUN4V NON-RECOVERABLE ERROR: Claiming %lu ages.\n",
+ page_cnt);
+
+ while (page_cnt-- > 0) {
+ if (pfn_valid(addr >> PAGE_SHIFT))
+ get_page(pfn_to_page(addr >> PAGE_SHIFT));
+ addr += PAGE_SIZE;
+ }
+ }
+ info.si_signo = SIGKILL;
+ info.si_errno = 0;
+ info.si_trapno = 0;
+ force_sig_info(info.si_signo, &info, current);
+
+ return true;
+ }
+ if (attrs & SUN4V_ERR_ATTRS_PIO) {
+ siginfo_t info;
+
+ info.si_signo = SIGBUS;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void __user *)sun4v_get_vaddr(regs);
+ force_sig_info(info.si_signo, &info, current);
+
+ return true;
+ }
+
+ /* Default to doing nothing */
+ return false;
+}
+
/* We run with %pil set to PIL_NORMAL_MAX and PSTATE_IE enabled in %pstate.
* Log the event, clear the first word of the entry, and die.
*/
@@ -2075,6 +2142,12 @@
put_cpu();
+ if (!(regs->tstate & TSTATE_PRIV) &&
+ sun4v_nonresum_error_user_handled(regs, &local_copy)) {
+ /* DON'T PANIC: This userspace error was handled. */
+ return;
+ }
+
#ifdef CONFIG_PCI
/* Check for the special PCI poke sequence. */
if (pci_poke_in_progress && pci_poke_cpu == cpu) {
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index a66854d..6de58f1 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -430,9 +430,6 @@
{
unsigned long random_addr, min_addr;
- /* By default, keep output position unchanged. */
- *virt_addr = *output;
-
if (cmdline_find_option_bool("nokaslr")) {
warn("KASLR disabled: 'nokaslr' on cmdline.");
return;
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index b3c5a5f0..c945acd 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -338,7 +338,7 @@
unsigned long output_len)
{
const unsigned long kernel_total_size = VO__end - VO__text;
- unsigned long virt_addr = (unsigned long)output;
+ unsigned long virt_addr = LOAD_PHYSICAL_ADDR;
/* Retain x86 boot parameters pointer passed from startup_32/64. */
boot_params = rmode;
@@ -397,7 +397,7 @@
#ifndef CONFIG_RELOCATABLE
if ((unsigned long)output != LOAD_PHYSICAL_ADDR)
error("Destination address does not match LOAD_PHYSICAL_ADDR");
- if ((unsigned long)output != virt_addr)
+ if (virt_addr != LOAD_PHYSICAL_ADDR)
error("Destination virtual address changed when not relocatable");
#endif
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 1c8355e..766a521 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -81,8 +81,6 @@
unsigned long output_size,
unsigned long *virt_addr)
{
- /* No change from existing output location. */
- *virt_addr = *output;
}
#endif
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 38623e2..9604b25 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -505,6 +505,10 @@
if (event->attr.precise_ip > precise)
return -EOPNOTSUPP;
+
+ /* There's no sense in having PEBS for non sampling events: */
+ if (!is_sampling_event(event))
+ return -EINVAL;
}
/*
* check that PEBS LBR correction does not conflict with
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 3bdb917..f0f197f 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3164,13 +3164,16 @@
if (x86_pmu.flags & PMU_FL_EXCL_CNTRS) {
for_each_cpu(i, topology_sibling_cpumask(cpu)) {
+ struct cpu_hw_events *sibling;
struct intel_excl_cntrs *c;
- c = per_cpu(cpu_hw_events, i).excl_cntrs;
+ sibling = &per_cpu(cpu_hw_events, i);
+ c = sibling->excl_cntrs;
if (c && c->core_id == core_id) {
cpuc->kfree_on_online[1] = cpuc->excl_cntrs;
cpuc->excl_cntrs = c;
- cpuc->excl_thread_id = 1;
+ if (!sibling->excl_thread_id)
+ cpuc->excl_thread_id = 1;
break;
}
}
@@ -3975,7 +3978,7 @@
x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
}
- x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+ x86_pmu.intel_ctrl = (1ULL << x86_pmu.num_counters) - 1;
if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
diff --git a/arch/x86/events/intel/uncore_snbep.c b/arch/x86/events/intel/uncore_snbep.c
index 2724277..afe8024 100644
--- a/arch/x86/events/intel/uncore_snbep.c
+++ b/arch/x86/events/intel/uncore_snbep.c
@@ -2686,7 +2686,7 @@
void hswep_uncore_cpu_init(void)
{
- int pkg = topology_phys_to_logical_pkg(0);
+ int pkg = boot_cpu_data.logical_proc_id;
if (hswep_uncore_cbox.num_boxes > boot_cpu_data.x86_max_cores)
hswep_uncore_cbox.num_boxes = boot_cpu_data.x86_max_cores;
diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
index e9cd7be..19d14ac 100644
--- a/arch/x86/include/asm/kvm_emulate.h
+++ b/arch/x86/include/asm/kvm_emulate.h
@@ -221,6 +221,9 @@
void (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
void (*set_nmi_mask)(struct x86_emulate_ctxt *ctxt, bool masked);
+
+ unsigned (*get_hflags)(struct x86_emulate_ctxt *ctxt);
+ void (*set_hflags)(struct x86_emulate_ctxt *ctxt, unsigned hflags);
};
typedef u32 __attribute__((vector_size(16))) sse128_t;
@@ -290,7 +293,6 @@
/* interruptibility state, as a result of execution of STI or MOV SS */
int interruptibility;
- int emul_flags;
bool perm_ok; /* do not check permissions if true */
bool ud; /* inject an #UD if host doesn't support insn */
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index eea88fe..6e57edf 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -694,6 +694,7 @@
crystal_khz = 24000; /* 24.0 MHz */
break;
case INTEL_FAM6_SKYLAKE_X:
+ case INTEL_FAM6_ATOM_DENVERTON:
crystal_khz = 25000; /* 25.0 MHz */
break;
case INTEL_FAM6_ATOM_GOLDMONT:
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 9f676ad..de36660 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -2543,7 +2543,7 @@
u64 smbase;
int ret;
- if ((ctxt->emul_flags & X86EMUL_SMM_MASK) == 0)
+ if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_MASK) == 0)
return emulate_ud(ctxt);
/*
@@ -2592,11 +2592,11 @@
return X86EMUL_UNHANDLEABLE;
}
- if ((ctxt->emul_flags & X86EMUL_SMM_INSIDE_NMI_MASK) == 0)
+ if ((ctxt->ops->get_hflags(ctxt) & X86EMUL_SMM_INSIDE_NMI_MASK) == 0)
ctxt->ops->set_nmi_mask(ctxt, false);
- ctxt->emul_flags &= ~X86EMUL_SMM_INSIDE_NMI_MASK;
- ctxt->emul_flags &= ~X86EMUL_SMM_MASK;
+ ctxt->ops->set_hflags(ctxt, ctxt->ops->get_hflags(ctxt) &
+ ~(X86EMUL_SMM_INSIDE_NMI_MASK | X86EMUL_SMM_MASK));
return X86EMUL_CONTINUE;
}
@@ -5312,6 +5312,7 @@
const struct x86_emulate_ops *ops = ctxt->ops;
int rc = X86EMUL_CONTINUE;
int saved_dst_type = ctxt->dst.type;
+ unsigned emul_flags;
ctxt->mem_read.pos = 0;
@@ -5326,6 +5327,7 @@
goto done;
}
+ emul_flags = ctxt->ops->get_hflags(ctxt);
if (unlikely(ctxt->d &
(No64|Undefined|Sse|Mmx|Intercept|CheckPerm|Priv|Prot|String))) {
if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) ||
@@ -5359,7 +5361,7 @@
fetch_possible_mmx_operand(ctxt, &ctxt->dst);
}
- if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
+ if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && ctxt->intercept) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_PRE_EXCEPT);
if (rc != X86EMUL_CONTINUE)
@@ -5388,7 +5390,7 @@
goto done;
}
- if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
+ if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_EXCEPT);
if (rc != X86EMUL_CONTINUE)
@@ -5442,7 +5444,7 @@
special_insn:
- if (unlikely(ctxt->emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
+ if (unlikely(emul_flags & X86EMUL_GUEST_MASK) && (ctxt->d & Intercept)) {
rc = emulator_check_intercept(ctxt, ctxt->intercept,
X86_ICPT_POST_MEMACCESS);
if (rc != X86EMUL_CONTINUE)
diff --git a/arch/x86/kvm/pmu_intel.c b/arch/x86/kvm/pmu_intel.c
index 9d4a850..5ab4a36 100644
--- a/arch/x86/kvm/pmu_intel.c
+++ b/arch/x86/kvm/pmu_intel.c
@@ -294,7 +294,7 @@
((u64)1 << edx.split.bit_width_fixed) - 1;
}
- pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+ pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
(((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
pmu->global_ctrl_mask = ~pmu->global_ctrl;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 89b98e0..04e6bbb 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -2455,7 +2455,7 @@
if (!(vmcs12->exception_bitmap & (1u << nr)))
return 0;
- nested_vmx_vmexit(vcpu, to_vmx(vcpu)->exit_reason,
+ nested_vmx_vmexit(vcpu, EXIT_REASON_EXCEPTION_NMI,
vmcs_read32(VM_EXIT_INTR_INFO),
vmcs_readl(EXIT_QUALIFICATION));
return 1;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 62cde4f..3dbcb09 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4999,6 +4999,8 @@
if (var.unusable) {
memset(desc, 0, sizeof(*desc));
+ if (base3)
+ *base3 = 0;
return false;
}
@@ -5154,6 +5156,16 @@
kvm_x86_ops->set_nmi_mask(emul_to_vcpu(ctxt), masked);
}
+static unsigned emulator_get_hflags(struct x86_emulate_ctxt *ctxt)
+{
+ return emul_to_vcpu(ctxt)->arch.hflags;
+}
+
+static void emulator_set_hflags(struct x86_emulate_ctxt *ctxt, unsigned emul_flags)
+{
+ kvm_set_hflags(emul_to_vcpu(ctxt), emul_flags);
+}
+
static const struct x86_emulate_ops emulate_ops = {
.read_gpr = emulator_read_gpr,
.write_gpr = emulator_write_gpr,
@@ -5193,6 +5205,8 @@
.intercept = emulator_intercept,
.get_cpuid = emulator_get_cpuid,
.set_nmi_mask = emulator_set_nmi_mask,
+ .get_hflags = emulator_get_hflags,
+ .set_hflags = emulator_set_hflags,
};
static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)
@@ -5245,7 +5259,6 @@
BUILD_BUG_ON(HF_GUEST_MASK != X86EMUL_GUEST_MASK);
BUILD_BUG_ON(HF_SMM_MASK != X86EMUL_SMM_MASK);
BUILD_BUG_ON(HF_SMM_INSIDE_NMI_MASK != X86EMUL_SMM_INSIDE_NMI_MASK);
- ctxt->emul_flags = vcpu->arch.hflags;
init_decode_cache(ctxt);
vcpu->arch.emulate_regs_need_sync_from_vcpu = false;
@@ -5636,8 +5649,6 @@
unsigned long rflags = kvm_x86_ops->get_rflags(vcpu);
toggle_interruptibility(vcpu, ctxt->interruptibility);
vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
- if (vcpu->arch.hflags != ctxt->emul_flags)
- kvm_set_hflags(vcpu, ctxt->emul_flags);
kvm_rip_write(vcpu, ctxt->eip);
if (r == EMULATE_DONE)
kvm_vcpu_check_singlestep(vcpu, rflags, &r);
@@ -6111,7 +6122,8 @@
kvm_x86_ops->patch_hypercall(vcpu, instruction);
- return emulator_write_emulated(ctxt, rip, instruction, 3, NULL);
+ return emulator_write_emulated(ctxt, rip, instruction, 3,
+ &ctxt->exception);
}
static int dm_request_for_irq_injection(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 14b9dd7..9a324fc 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -94,10 +94,10 @@
*/
void sync_global_pgds(unsigned long start, unsigned long end, int removed)
{
- unsigned long address;
+ unsigned long addr;
- for (address = start; address <= end; address += PGDIR_SIZE) {
- const pgd_t *pgd_ref = pgd_offset_k(address);
+ for (addr = start; addr <= end; addr = ALIGN(addr + 1, PGDIR_SIZE)) {
+ const pgd_t *pgd_ref = pgd_offset_k(addr);
struct page *page;
/*
@@ -113,7 +113,7 @@
pgd_t *pgd;
spinlock_t *pgt_lock;
- pgd = (pgd_t *)page_address(page) + pgd_index(address);
+ pgd = (pgd_t *)page_address(page) + pgd_index(addr);
/* the pgt_lock only for Xen */
pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
spin_lock(pgt_lock);
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index e4f8009..a75103e 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -293,7 +293,7 @@
* We were not able to extract an address from the instruction,
* probably because there was something invalid in it.
*/
- if (info->si_addr == (void *)-1) {
+ if (info->si_addr == (void __user *)-1) {
err = -EINVAL;
goto err_out;
}
@@ -525,15 +525,7 @@
if (!kernel_managing_mpx_tables(current->mm))
return -EINVAL;
- if (do_mpx_bt_fault()) {
- force_sig(SIGSEGV, current);
- /*
- * The force_sig() is essentially "handling" this
- * exception, so we do not pass up the error
- * from do_mpx_bt_fault().
- */
- }
- return 0;
+ return do_mpx_bt_fault();
}
/*
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index a7655f6..75fb011 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -263,8 +263,6 @@
{
struct flush_tlb_info info;
- if (end == 0)
- end = start + PAGE_SIZE;
info.flush_mm = mm;
info.flush_start = start;
info.flush_end = end;
@@ -393,7 +391,7 @@
}
if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
- flush_tlb_others(mm_cpumask(mm), mm, start, 0UL);
+ flush_tlb_others(mm_cpumask(mm), mm, start, start + PAGE_SIZE);
preempt_enable();
}
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c
index c42202d..d6eaaa2 100644
--- a/drivers/block/xen-blkback/blkback.c
+++ b/drivers/block/xen-blkback/blkback.c
@@ -609,8 +609,6 @@
unsigned long timeout;
int ret;
- xen_blkif_get(blkif);
-
set_freezable();
while (!kthread_should_stop()) {
if (try_to_freeze())
@@ -665,7 +663,6 @@
print_stats(ring);
ring->xenblkd = NULL;
- xen_blkif_put(blkif);
return 0;
}
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c
index 9b69fe4..5dfe6e8 100644
--- a/drivers/block/xen-blkback/xenbus.c
+++ b/drivers/block/xen-blkback/xenbus.c
@@ -255,7 +255,6 @@
if (ring->xenblkd) {
kthread_stop(ring->xenblkd);
wake_up(&ring->shutdown_wq);
- ring->xenblkd = NULL;
}
/* The above kthread_stop() guarantees that at this point we
@@ -316,8 +315,10 @@
static void xen_blkif_free(struct xen_blkif *blkif)
{
- xen_blkif_disconnect(blkif);
+ WARN_ON(xen_blkif_disconnect(blkif));
xen_vbd_free(&blkif->vbd);
+ kfree(blkif->be->mode);
+ kfree(blkif->be);
/* Make sure everything is drained before shutting down */
kmem_cache_free(xen_blkif_cachep, blkif);
@@ -512,8 +513,6 @@
/* Put the reference we set in xen_blkif_alloc(). */
xen_blkif_put(be->blkif);
- kfree(be->mode);
- kfree(be);
return 0;
}
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ce86c27..13fac71 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -572,6 +572,13 @@
goto bail;
if (sess->smmu.enabled) {
attrs = DMA_ATTR_EXEC_MAPPING;
+
+ if (map->attr & FASTRPC_ATTR_NON_COHERENT ||
+ (sess->smmu.coherent && map->uncached))
+ attrs |= DMA_ATTR_FORCE_NON_COHERENT;
+ else if (map->attr & FASTRPC_ATTR_COHERENT)
+ attrs |= DMA_ATTR_FORCE_COHERENT;
+
VERIFY(err, map->table->nents ==
msm_dma_map_sg_attrs(sess->dev,
map->table->sgl, map->table->nents,
@@ -1121,7 +1128,7 @@
for (i = 0; i < M_FDLIST; i++)
fdlist[i] = 0;
crclist = (uint32_t *)&fdlist[M_FDLIST];
- memset(crclist, 0, sizeof(uint32_t)*M_FDLIST);
+ memset(crclist, 0, sizeof(uint32_t)*M_CRCLIST);
/* copy non ion buffers */
PERF(ctx->fl->profile, ctx->fl->perf.copy,
@@ -1169,10 +1176,14 @@
int i = ctx->overps[oix]->raix;
struct fastrpc_mmap *map = ctx->maps[i];
- if (ctx->fl->sctx->smmu.coherent)
- continue;
if (map && map->uncached)
continue;
+ if (ctx->fl->sctx->smmu.coherent &&
+ !(map && (map->attr & FASTRPC_ATTR_NON_COHERENT)))
+ continue;
+ if (map && (map->attr & FASTRPC_ATTR_COHERENT))
+ continue;
+
if (rpra[i].buf.len && ctx->overps[oix]->mstart)
dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
@@ -1261,6 +1272,12 @@
continue;
if (!rpra[i].buf.len)
continue;
+ if (ctx->fl->sctx->smmu.coherent &&
+ !(map && (map->attr & FASTRPC_ATTR_NON_COHERENT)))
+ continue;
+ if (map && (map->attr & FASTRPC_ATTR_COHERENT))
+ continue;
+
if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
buf_page_start(rpra[i].buf.pv))
continue;
@@ -1291,6 +1308,12 @@
continue;
if (!rpra[i].buf.len)
continue;
+ if (ctx->fl->sctx->smmu.coherent &&
+ !(map && (map->attr & FASTRPC_ATTR_NON_COHERENT)))
+ continue;
+ if (map && (map->attr & FASTRPC_ATTR_COHERENT))
+ continue;
+
if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
buf_page_start(rpra[i].buf.pv)) {
continue;
@@ -1726,6 +1749,8 @@
cid = ctx - &gcinfo[0];
fastrpc_glink_close(ctx->chan, cid);
ctx->chan = 0;
+ glink_unregister_link_state_cb(ctx->link.link_notify_handle);
+ ctx->link.link_notify_handle = NULL;
mutex_unlock(&me->smd_mutex);
pr_info("'closed /dev/%s c %d %d'\n", gcinfo[cid].name,
MAJOR(me->dev_no), cid);
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index fb7afa3..e3fe064 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -36,6 +36,12 @@
/* Set for buffers that have no virtual mapping in userspace */
#define FASTRPC_ATTR_NOVA 0x1
+/* Set for buffers that are NOT dma coherent */
+#define FASTRPC_ATTR_NON_COHERENT 0x2
+
+/* Set for buffers that are dma coherent */
+#define FASTRPC_ATTR_COHERENT 0x4
+
/* Driver should operate in parallel with the co-processor */
#define FASTRPC_MODE_PARALLEL 0
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
index 89fba64..a0a9ab6 100644
--- a/drivers/char/diag/diag_debugfs.c
+++ b/drivers/char/diag/diag_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, 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
@@ -264,8 +264,10 @@
struct list_head *temp;
struct diag_cmd_reg_t *item = NULL;
+ mutex_lock(&driver->cmd_reg_mutex);
if (diag_dbgfs_table_index == driver->cmd_reg_count) {
diag_dbgfs_table_index = 0;
+ mutex_unlock(&driver->cmd_reg_mutex);
return 0;
}
@@ -274,6 +276,7 @@
buf = kcalloc(buf_size, sizeof(char), GFP_KERNEL);
if (ZERO_OR_NULL_PTR(buf)) {
pr_err("diag: %s, Error allocating memory\n", __func__);
+ mutex_unlock(&driver->cmd_reg_mutex);
return -ENOMEM;
}
buf_size = ksize(buf);
@@ -318,6 +321,7 @@
break;
}
diag_dbgfs_table_index = i;
+ mutex_unlock(&driver->cmd_reg_mutex);
*ppos = 0;
ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 471a301..8f890c1 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1870,7 +1870,7 @@
{
struct ports_device *portdev;
- portdev = container_of(work, struct ports_device, control_work);
+ portdev = container_of(work, struct ports_device, config_work);
if (!use_multiport(portdev)) {
struct virtio_device *vdev;
struct port *port;
diff --git a/drivers/clk/clk-scpi.c b/drivers/clk/clk-scpi.c
index 2a3e9d8..96d37175 100644
--- a/drivers/clk/clk-scpi.c
+++ b/drivers/clk/clk-scpi.c
@@ -290,13 +290,15 @@
of_node_put(child);
return ret;
}
- }
- /* Add the virtual cpufreq device */
- cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
- -1, NULL, 0);
- if (IS_ERR(cpufreq_dev))
- pr_warn("unable to register cpufreq device");
+ if (match->data != &scpi_dvfs_ops)
+ continue;
+ /* Add the virtual cpufreq device if it's DVFS clock provider */
+ cpufreq_dev = platform_device_register_simple("scpi-cpufreq",
+ -1, NULL, 0);
+ if (IS_ERR(cpufreq_dev))
+ pr_warn("unable to register cpufreq device");
+ }
return 0;
}
diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c
index d6d4257..5b2db3c 100644
--- a/drivers/cpufreq/s3c2416-cpufreq.c
+++ b/drivers/cpufreq/s3c2416-cpufreq.c
@@ -400,7 +400,6 @@
rate = clk_get_rate(s3c_freq->hclk);
if (rate < 133 * 1000 * 1000) {
pr_err("cpufreq: HCLK not at 133MHz\n");
- clk_put(s3c_freq->hclk);
ret = -EINVAL;
goto err_armclk;
}
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 7536aa9b..827ee8f 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -571,22 +571,21 @@
int best_level = -1;
uint32_t latency_us = pm_qos_request_for_cpu(PM_QOS_CPU_DMA_LATENCY,
dev->cpu);
- uint32_t sleep_us =
- (uint32_t)(ktime_to_us(tick_nohz_get_sleep_length()));
+ s64 sleep_us = ktime_to_us(tick_nohz_get_sleep_length());
uint32_t modified_time_us = 0;
uint32_t next_event_us = 0;
int i, idx_restrict;
uint32_t lvl_latency_us = 0;
uint64_t predicted = 0;
uint32_t htime = 0, idx_restrict_time = 0;
- uint32_t next_wakeup_us = sleep_us;
+ uint32_t next_wakeup_us = (uint32_t)sleep_us;
uint32_t *min_residency = get_per_cpu_min_residency(dev->cpu);
uint32_t *max_residency = get_per_cpu_max_residency(dev->cpu);
if (!cpu)
return -EINVAL;
- if (sleep_disabled)
+ if (sleep_disabled || sleep_us < 0)
return 0;
idx_restrict = cpu->nlevels + 1;
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 9215931..f2bb512 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -707,7 +707,8 @@
ge.timestamp = ktime_get_real_ns();
- if (le->eflags & GPIOEVENT_REQUEST_BOTH_EDGES) {
+ if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
+ && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
int level = gpiod_get_value_cansleep(le->desc);
if (level)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index 82dc8d2..bfb4b91 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -83,6 +83,13 @@
}
break;
}
+
+ if (!(*out_ring && (*out_ring)->adev)) {
+ DRM_ERROR("Ring %d is not initialized on IP %d\n",
+ ring, ip_type);
+ return -EINVAL;
+ }
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
index 6f3c891..4cb347e 100644
--- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c
+++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c
@@ -64,6 +64,7 @@
MODULE_FIRMWARE("radeon/oland_k_smc.bin");
MODULE_FIRMWARE("radeon/hainan_smc.bin");
MODULE_FIRMWARE("radeon/hainan_k_smc.bin");
+MODULE_FIRMWARE("radeon/banks_k_2_smc.bin");
union power_info {
struct _ATOM_POWERPLAY_INFO info;
@@ -7721,10 +7722,11 @@
((adev->pdev->device == 0x6660) ||
(adev->pdev->device == 0x6663) ||
(adev->pdev->device == 0x6665) ||
- (adev->pdev->device == 0x6667))) ||
- ((adev->pdev->revision == 0xc3) &&
- (adev->pdev->device == 0x6665)))
+ (adev->pdev->device == 0x6667))))
chip_name = "hainan_k";
+ else if ((adev->pdev->revision == 0xc3) &&
+ (adev->pdev->device == 0x6665))
+ chip_name = "banks_k_2";
else
chip_name = "hainan";
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
index 6feed72..50f0cf2 100644
--- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c
@@ -43,9 +43,13 @@
#define GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT 0x04
#define GRBM_GFX_INDEX__VCE_INSTANCE_MASK 0x10
+#define GRBM_GFX_INDEX__VCE_ALL_PIPE 0x07
+
#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR0 0x8616
#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR1 0x8617
#define mmVCE_LMI_VCPU_CACHE_40BIT_BAR2 0x8618
+#define mmGRBM_GFX_INDEX_DEFAULT 0xE0000000
+
#define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02
#define VCE_V3_0_FW_SIZE (384 * 1024)
@@ -54,6 +58,9 @@
#define FW_52_8_3 ((52 << 24) | (8 << 16) | (3 << 8))
+#define GET_VCE_INSTANCE(i) ((i) << GRBM_GFX_INDEX__VCE_INSTANCE__SHIFT \
+ | GRBM_GFX_INDEX__VCE_ALL_PIPE)
+
static void vce_v3_0_mc_resume(struct amdgpu_device *adev, int idx);
static void vce_v3_0_set_ring_funcs(struct amdgpu_device *adev);
static void vce_v3_0_set_irq_funcs(struct amdgpu_device *adev);
@@ -249,7 +256,7 @@
if (adev->vce.harvest_config & (1 << idx))
continue;
- WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
vce_v3_0_mc_resume(adev, idx);
WREG32_FIELD(VCE_STATUS, JOB_BUSY, 1);
@@ -273,7 +280,7 @@
}
}
- WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+ WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
mutex_unlock(&adev->grbm_idx_mutex);
return 0;
@@ -288,7 +295,7 @@
if (adev->vce.harvest_config & (1 << idx))
continue;
- WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, idx);
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(idx));
if (adev->asic_type >= CHIP_STONEY)
WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x200001);
@@ -306,7 +313,7 @@
vce_v3_0_set_vce_sw_clock_gating(adev, false);
}
- WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+ WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
mutex_unlock(&adev->grbm_idx_mutex);
return 0;
@@ -586,17 +593,17 @@
* VCE team suggest use bit 3--bit 6 for busy status check
*/
mutex_lock(&adev->grbm_idx_mutex);
- WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
}
- WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0x10);
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(1));
if (RREG32(mmVCE_STATUS) & AMDGPU_VCE_STATUS_BUSY_MASK) {
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE0, 1);
srbm_soft_reset = REG_SET_FIELD(srbm_soft_reset, SRBM_SOFT_RESET, SOFT_RESET_VCE1, 1);
}
- WREG32_FIELD(GRBM_GFX_INDEX, INSTANCE_INDEX, 0);
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(0));
mutex_unlock(&adev->grbm_idx_mutex);
if (srbm_soft_reset) {
@@ -734,7 +741,7 @@
if (adev->vce.harvest_config & (1 << i))
continue;
- WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, i);
+ WREG32(mmGRBM_GFX_INDEX, GET_VCE_INSTANCE(i));
if (enable) {
/* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */
@@ -753,7 +760,7 @@
vce_v3_0_set_vce_sw_clock_gating(adev, enable);
}
- WREG32_FIELD(GRBM_GFX_INDEX, VCE_INSTANCE, 0);
+ WREG32(mmGRBM_GFX_INDEX, mmGRBM_GFX_INDEX_DEFAULT);
mutex_unlock(&adev->grbm_idx_mutex);
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
index 2028980..5b261c1 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c
@@ -200,7 +200,7 @@
cgs_set_clockgating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
- AMD_CG_STATE_UNGATE);
+ AMD_CG_STATE_GATE);
cgs_set_powergating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
@@ -218,7 +218,7 @@
cgs_set_clockgating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
- AMD_PG_STATE_GATE);
+ AMD_PG_STATE_UNGATE);
cz_dpm_update_vce_dpm(hwmgr);
cz_enable_disable_vce_dpm(hwmgr, true);
return 0;
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
index 9604249..189ec94 100644
--- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
+++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c
@@ -1402,14 +1402,22 @@
cz_hwmgr->vce_dpm.hard_min_clk,
PPSMC_MSG_SetEclkHardMin));
} else {
- /*EPR# 419220 -HW limitation to to */
- cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
- smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
- PPSMC_MSG_SetEclkHardMin,
- cz_get_eclk_level(hwmgr,
- cz_hwmgr->vce_dpm.hard_min_clk,
- PPSMC_MSG_SetEclkHardMin));
-
+ /*Program HardMin based on the vce_arbiter.ecclk */
+ if (hwmgr->vce_arbiter.ecclk == 0) {
+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+ PPSMC_MSG_SetEclkHardMin, 0);
+ /* disable ECLK DPM 0. Otherwise VCE could hang if
+ * switching SCLK from DPM 0 to 6/7 */
+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+ PPSMC_MSG_SetEclkSoftMin, 1);
+ } else {
+ cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk;
+ smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+ PPSMC_MSG_SetEclkHardMin,
+ cz_get_eclk_level(hwmgr,
+ cz_hwmgr->vce_dpm.hard_min_clk,
+ PPSMC_MSG_SetEclkHardMin));
+ }
}
return 0;
}
diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h
index 7abda94..3bedcf7 100644
--- a/drivers/gpu/drm/ast/ast_drv.h
+++ b/drivers/gpu/drm/ast/ast_drv.h
@@ -113,7 +113,11 @@
struct ttm_bo_kmap_obj cache_kmap;
int next_cursor;
bool support_wide_screen;
- bool DisableP2A;
+ enum {
+ ast_use_p2a,
+ ast_use_dt,
+ ast_use_defaults
+ } config_mode;
enum ast_tx_chip tx_chip_type;
u8 dp501_maxclk;
diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c
index 533e762..fb99762 100644
--- a/drivers/gpu/drm/ast/ast_main.c
+++ b/drivers/gpu/drm/ast/ast_main.c
@@ -62,13 +62,84 @@
return ret;
}
+static void ast_detect_config_mode(struct drm_device *dev, u32 *scu_rev)
+{
+ struct device_node *np = dev->pdev->dev.of_node;
+ struct ast_private *ast = dev->dev_private;
+ uint32_t data, jregd0, jregd1;
+
+ /* Defaults */
+ ast->config_mode = ast_use_defaults;
+ *scu_rev = 0xffffffff;
+
+ /* Check if we have device-tree properties */
+ if (np && !of_property_read_u32(np, "aspeed,scu-revision-id",
+ scu_rev)) {
+ /* We do, disable P2A access */
+ ast->config_mode = ast_use_dt;
+ DRM_INFO("Using device-tree for configuration\n");
+ return;
+ }
+
+ /* Not all families have a P2A bridge */
+ if (dev->pdev->device != PCI_CHIP_AST2000)
+ return;
+
+ /*
+ * The BMC will set SCU 0x40 D[12] to 1 if the P2 bridge
+ * is disabled. We force using P2A if VGA only mode bit
+ * is set D[7]
+ */
+ jregd0 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd0, 0xff);
+ jregd1 = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xd1, 0xff);
+ if (!(jregd0 & 0x80) || !(jregd1 & 0x10)) {
+ /* Double check it's actually working */
+ data = ast_read32(ast, 0xf004);
+ if (data != 0xFFFFFFFF) {
+ /* P2A works, grab silicon revision */
+ ast->config_mode = ast_use_p2a;
+
+ DRM_INFO("Using P2A bridge for configuration\n");
+
+ /* Read SCU7c (silicon revision register) */
+ ast_write32(ast, 0xf004, 0x1e6e0000);
+ ast_write32(ast, 0xf000, 0x1);
+ *scu_rev = ast_read32(ast, 0x1207c);
+ return;
+ }
+ }
+
+ /* We have a P2A bridge but it's disabled */
+ DRM_INFO("P2A bridge disabled, using default configuration\n");
+}
static int ast_detect_chip(struct drm_device *dev, bool *need_post)
{
struct ast_private *ast = dev->dev_private;
- uint32_t data, jreg;
+ uint32_t jreg, scu_rev;
+
+ /*
+ * If VGA isn't enabled, we need to enable now or subsequent
+ * access to the scratch registers will fail. We also inform
+ * our caller that it needs to POST the chip
+ * (Assumption: VGA not enabled -> need to POST)
+ */
+ if (!ast_is_vga_enabled(dev)) {
+ ast_enable_vga(dev);
+ DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
+ *need_post = true;
+ } else
+ *need_post = false;
+
+
+ /* Enable extended register access */
+ ast_enable_mmio(dev);
ast_open_key(ast);
+ /* Find out whether P2A works or whether to use device-tree */
+ ast_detect_config_mode(dev, &scu_rev);
+
+ /* Identify chipset */
if (dev->pdev->device == PCI_CHIP_AST1180) {
ast->chip = AST1100;
DRM_INFO("AST 1180 detected\n");
@@ -80,12 +151,7 @@
ast->chip = AST2300;
DRM_INFO("AST 2300 detected\n");
} else if (dev->pdev->revision >= 0x10) {
- uint32_t data;
- ast_write32(ast, 0xf004, 0x1e6e0000);
- ast_write32(ast, 0xf000, 0x1);
-
- data = ast_read32(ast, 0x1207c);
- switch (data & 0x0300) {
+ switch (scu_rev & 0x0300) {
case 0x0200:
ast->chip = AST1100;
DRM_INFO("AST 1100 detected\n");
@@ -110,26 +176,6 @@
}
}
- /*
- * If VGA isn't enabled, we need to enable now or subsequent
- * access to the scratch registers will fail. We also inform
- * our caller that it needs to POST the chip
- * (Assumption: VGA not enabled -> need to POST)
- */
- if (!ast_is_vga_enabled(dev)) {
- ast_enable_vga(dev);
- ast_enable_mmio(dev);
- DRM_INFO("VGA not enabled on entry, requesting chip POST\n");
- *need_post = true;
- } else
- *need_post = false;
-
- /* Check P2A Access */
- ast->DisableP2A = true;
- data = ast_read32(ast, 0xf004);
- if (data != 0xFFFFFFFF)
- ast->DisableP2A = false;
-
/* Check if we support wide screen */
switch (ast->chip) {
case AST1180:
@@ -146,17 +192,12 @@
ast->support_wide_screen = true;
else {
ast->support_wide_screen = false;
- if (ast->DisableP2A == false) {
- /* Read SCU7c (silicon revision register) */
- ast_write32(ast, 0xf004, 0x1e6e0000);
- ast_write32(ast, 0xf000, 0x1);
- data = ast_read32(ast, 0x1207c);
- data &= 0x300;
- if (ast->chip == AST2300 && data == 0x0) /* ast1300 */
- ast->support_wide_screen = true;
- if (ast->chip == AST2400 && data == 0x100) /* ast1400 */
- ast->support_wide_screen = true;
- }
+ if (ast->chip == AST2300 &&
+ (scu_rev & 0x300) == 0x0) /* ast1300 */
+ ast->support_wide_screen = true;
+ if (ast->chip == AST2400 &&
+ (scu_rev & 0x300) == 0x100) /* ast1400 */
+ ast->support_wide_screen = true;
}
break;
}
@@ -220,85 +261,102 @@
static int ast_get_dram_info(struct drm_device *dev)
{
+ struct device_node *np = dev->pdev->dev.of_node;
struct ast_private *ast = dev->dev_private;
- uint32_t data, data2;
- uint32_t denum, num, div, ref_pll;
+ uint32_t mcr_cfg, mcr_scu_mpll, mcr_scu_strap;
+ uint32_t denum, num, div, ref_pll, dsel;
- if (ast->DisableP2A)
- {
+ switch (ast->config_mode) {
+ case ast_use_dt:
+ /*
+ * If some properties are missing, use reasonable
+ * defaults for AST2400
+ */
+ if (of_property_read_u32(np, "aspeed,mcr-configuration",
+ &mcr_cfg))
+ mcr_cfg = 0x00000577;
+ if (of_property_read_u32(np, "aspeed,mcr-scu-mpll",
+ &mcr_scu_mpll))
+ mcr_scu_mpll = 0x000050C0;
+ if (of_property_read_u32(np, "aspeed,mcr-scu-strap",
+ &mcr_scu_strap))
+ mcr_scu_strap = 0;
+ break;
+ case ast_use_p2a:
+ ast_write32(ast, 0xf004, 0x1e6e0000);
+ ast_write32(ast, 0xf000, 0x1);
+ mcr_cfg = ast_read32(ast, 0x10004);
+ mcr_scu_mpll = ast_read32(ast, 0x10120);
+ mcr_scu_strap = ast_read32(ast, 0x10170);
+ break;
+ case ast_use_defaults:
+ default:
ast->dram_bus_width = 16;
ast->dram_type = AST_DRAM_1Gx16;
ast->mclk = 396;
+ return 0;
}
+
+ if (mcr_cfg & 0x40)
+ ast->dram_bus_width = 16;
else
- {
- ast_write32(ast, 0xf004, 0x1e6e0000);
- ast_write32(ast, 0xf000, 0x1);
- data = ast_read32(ast, 0x10004);
+ ast->dram_bus_width = 32;
- if (data & 0x40)
- ast->dram_bus_width = 16;
- else
- ast->dram_bus_width = 32;
-
- if (ast->chip == AST2300 || ast->chip == AST2400) {
- switch (data & 0x03) {
- case 0:
- ast->dram_type = AST_DRAM_512Mx16;
- break;
- default:
- case 1:
- ast->dram_type = AST_DRAM_1Gx16;
- break;
- case 2:
- ast->dram_type = AST_DRAM_2Gx16;
- break;
- case 3:
- ast->dram_type = AST_DRAM_4Gx16;
- break;
- }
- } else {
- switch (data & 0x0c) {
- case 0:
- case 4:
- ast->dram_type = AST_DRAM_512Mx16;
- break;
- case 8:
- if (data & 0x40)
- ast->dram_type = AST_DRAM_1Gx16;
- else
- ast->dram_type = AST_DRAM_512Mx32;
- break;
- case 0xc:
- ast->dram_type = AST_DRAM_1Gx32;
- break;
- }
- }
-
- data = ast_read32(ast, 0x10120);
- data2 = ast_read32(ast, 0x10170);
- if (data2 & 0x2000)
- ref_pll = 14318;
- else
- ref_pll = 12000;
-
- denum = data & 0x1f;
- num = (data & 0x3fe0) >> 5;
- data = (data & 0xc000) >> 14;
- switch (data) {
- case 3:
- div = 0x4;
- break;
- case 2:
- case 1:
- div = 0x2;
+ if (ast->chip == AST2300 || ast->chip == AST2400) {
+ switch (mcr_cfg & 0x03) {
+ case 0:
+ ast->dram_type = AST_DRAM_512Mx16;
break;
default:
- div = 0x1;
+ case 1:
+ ast->dram_type = AST_DRAM_1Gx16;
+ break;
+ case 2:
+ ast->dram_type = AST_DRAM_2Gx16;
+ break;
+ case 3:
+ ast->dram_type = AST_DRAM_4Gx16;
break;
}
- ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
+ } else {
+ switch (mcr_cfg & 0x0c) {
+ case 0:
+ case 4:
+ ast->dram_type = AST_DRAM_512Mx16;
+ break;
+ case 8:
+ if (mcr_cfg & 0x40)
+ ast->dram_type = AST_DRAM_1Gx16;
+ else
+ ast->dram_type = AST_DRAM_512Mx32;
+ break;
+ case 0xc:
+ ast->dram_type = AST_DRAM_1Gx32;
+ break;
+ }
}
+
+ if (mcr_scu_strap & 0x2000)
+ ref_pll = 14318;
+ else
+ ref_pll = 12000;
+
+ denum = mcr_scu_mpll & 0x1f;
+ num = (mcr_scu_mpll & 0x3fe0) >> 5;
+ dsel = (mcr_scu_mpll & 0xc000) >> 14;
+ switch (dsel) {
+ case 3:
+ div = 0x4;
+ break;
+ case 2:
+ case 1:
+ div = 0x2;
+ break;
+ default:
+ div = 0x1;
+ break;
+ }
+ ast->mclk = ref_pll * (num + 2) / (denum + 2) * (div * 1000);
return 0;
}
diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c
index 270e8fb..c7c58be 100644
--- a/drivers/gpu/drm/ast/ast_post.c
+++ b/drivers/gpu/drm/ast/ast_post.c
@@ -375,17 +375,14 @@
ast_enable_mmio(dev);
ast_set_def_ext_reg(dev);
- if (ast->DisableP2A == false)
- {
+ if (ast->config_mode == ast_use_p2a) {
if (ast->chip == AST2300 || ast->chip == AST2400)
ast_init_dram_2300(dev);
else
ast_init_dram_reg(dev);
ast_init_3rdtx(dev);
- }
- else
- {
+ } else {
if (ast->tx_chip_type != AST_TX_NONE)
ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xa3, 0xcf, 0x80); /* Enable DVO */
}
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
index 169ac96..fe0e85b 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c
@@ -116,9 +116,14 @@
struct list_head list;
bool found;
+ /*
+ * XXX: The DRM_MM_SEARCH_BELOW is really a hack to trick
+ * drm_mm into giving out a low IOVA after address space
+ * rollover. This needs a proper fix.
+ */
ret = drm_mm_insert_node_in_range(&mmu->mm, node,
size, 0, mmu->last_iova, ~0UL,
- DRM_MM_SEARCH_DEFAULT);
+ mmu->last_iova ? DRM_MM_SEARCH_DEFAULT : DRM_MM_SEARCH_BELOW);
if (ret != -ENOSPC)
break;
diff --git a/drivers/gpu/drm/msm/dp/dp_aux.c b/drivers/gpu/drm/msm/dp/dp_aux.c
index 70581e2..67c6b2d 100644
--- a/drivers/gpu/drm/msm/dp/dp_aux.c
+++ b/drivers/gpu/drm/msm/dp/dp_aux.c
@@ -131,13 +131,14 @@
return -ETIMEDOUT;
}
- pr_debug("aux status %s\n",
- dp_aux_get_error(aux->aux_error_num));
-
- if (aux->aux_error_num == DP_AUX_ERR_NONE)
+ if (aux->aux_error_num == DP_AUX_ERR_NONE) {
ret = len;
- else
+ } else {
+ pr_err_ratelimited("aux err: %s\n",
+ dp_aux_get_error(aux->aux_error_num));
+
ret = -EINVAL;
+ }
return ret;
}
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.c b/drivers/gpu/drm/msm/dp/dp_catalog.c
index 9361b52..5825ba8 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.c
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.c
@@ -471,6 +471,8 @@
dp_catalog_get_priv(ctrl);
base = catalog->io->ctrl_io.base;
+ pr_debug("DP_CONFIGURATION_CTRL=0x%x\n", cfg);
+
dp_write(base + DP_CONFIGURATION_CTRL, cfg);
dp_write(base + DP_MAINLINK_LEVELS, 0xa08);
dp_write(base + MMSS_DP_ASYNC_FIFO_CONFIG, 0x1);
@@ -507,10 +509,7 @@
dp_catalog_get_priv(ctrl);
base = catalog->io->ctrl_io.base;
- mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);
-
if (enable) {
- mainlink_ctrl |= BIT(0);
dp_write(base + DP_MAINLINK_CTRL, 0x02000000);
wmb(); /* make sure mainlink is turned off before reset */
dp_write(base + DP_MAINLINK_CTRL, 0x02000002);
@@ -520,8 +519,9 @@
dp_write(base + DP_MAINLINK_CTRL, 0x02000001);
wmb(); /* make sure mainlink turned on */
} else {
+ mainlink_ctrl = dp_read(base + DP_MAINLINK_CTRL);
mainlink_ctrl &= ~BIT(0);
- dp_write(base + DP_MAINLINK_CTRL, 0x0);
+ dp_write(base + DP_MAINLINK_CTRL, mainlink_ctrl);
}
}
@@ -543,14 +543,16 @@
misc_val |= (tb << 5);
misc_val |= BIT(0); /* Configure clock to synchronous mode */
- pr_debug("isc settings = 0x%x\n", misc_val);
+ pr_debug("misc settings = 0x%x\n", misc_val);
dp_write(base + DP_MISC1_MISC0, misc_val);
}
-static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl)
+static void dp_catalog_ctrl_config_msa(struct dp_catalog_ctrl *ctrl,
+ u32 rate)
{
u32 pixel_m, pixel_n;
u32 mvid, nvid;
+ u32 const link_rate = 540000;
struct dp_catalog_private *catalog;
void __iomem *base_cc, *base_ctrl;
@@ -570,6 +572,11 @@
mvid = (pixel_m & 0xFFFF) * 5;
nvid = (0xFFFF & (~pixel_n)) + (pixel_m & 0xFFFF);
+ pr_debug("rate = %d\n", rate);
+
+ if (link_rate == rate)
+ nvid *= 2;
+
pr_debug("mvid=0x%x, nvid=0x%x\n", mvid, nvid);
dp_write(base_ctrl + DP_SOFTWARE_MVID, mvid);
dp_write(base_ctrl + DP_SOFTWARE_NVID, nvid);
@@ -593,7 +600,7 @@
bit = 1;
bit <<= (pattern - 1);
- pr_debug("bit=%d train=%d\n", bit, pattern);
+ pr_debug("hw: bit=%d train=%d\n", bit, pattern);
dp_write(base + DP_STATE_CTRL, bit);
bit = 8;
@@ -792,7 +799,7 @@
base0 = catalog->io->ln_tx0_io.base;
base1 = catalog->io->ln_tx1_io.base;
- pr_debug("v=%d p=%d\n", v_level, p_level);
+ pr_debug("hw: v=%d p=%d\n", v_level, p_level);
value0 = vm_voltage_swing[v_level][p_level];
value1 = vm_pre_emphasis[v_level][p_level];
@@ -814,8 +821,11 @@
dp_write(base0 + TXn_TX_EMP_POST1_LVL, value1);
dp_write(base1 + TXn_TX_EMP_POST1_LVL, value1);
- pr_debug("host PHY settings: value0=0x%x value1=0x%x",
- value0, value1);
+ pr_debug("hw: vx_value=0x%x px_value=0x%x\n",
+ value0, value1);
+ } else {
+ pr_err("invalid vx (0x%x=0x%x), px (0x%x=0x%x\n",
+ v_level, value0, p_level, value1);
}
}
diff --git a/drivers/gpu/drm/msm/dp/dp_catalog.h b/drivers/gpu/drm/msm/dp/dp_catalog.h
index ce88569..c9916c72 100644
--- a/drivers/gpu/drm/msm/dp/dp_catalog.h
+++ b/drivers/gpu/drm/msm/dp/dp_catalog.h
@@ -58,7 +58,7 @@
void (*lane_mapping)(struct dp_catalog_ctrl *ctrl);
void (*mainlink_ctrl)(struct dp_catalog_ctrl *ctrl, bool enable);
void (*config_misc)(struct dp_catalog_ctrl *ctrl, u32 cc, u32 tb);
- void (*config_msa)(struct dp_catalog_ctrl *ctrl);
+ void (*config_msa)(struct dp_catalog_ctrl *ctrl, u32 rate);
void (*set_pattern)(struct dp_catalog_ctrl *ctrl, u32 pattern);
void (*reset)(struct dp_catalog_ctrl *ctrl);
bool (*mainlink_ready)(struct dp_catalog_ctrl *ctrl);
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.c b/drivers/gpu/drm/msm/dp/dp_ctrl.c
index 706398db2..b78f0df 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.c
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.c
@@ -67,6 +67,7 @@
bool psm_enabled;
bool orientation;
+ atomic_t aborted;
u32 pixel_rate;
u32 vic;
@@ -92,6 +93,20 @@
complete(&ctrl->video_comp);
}
+static void dp_ctrl_abort(struct dp_ctrl *dp_ctrl)
+{
+ struct dp_ctrl_private *ctrl;
+
+ if (!dp_ctrl) {
+ pr_err("Invalid input data\n");
+ return;
+ }
+
+ ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
+
+ atomic_set(&ctrl->aborted, 1);
+}
+
static void dp_ctrl_state_ctrl(struct dp_ctrl_private *ctrl, u32 state)
{
ctrl->catalog->state_ctrl(ctrl->catalog, state);
@@ -109,8 +124,6 @@
ctrl = container_of(dp_ctrl, struct dp_ctrl_private, dp_ctrl);
- drm_dp_link_power_down(ctrl->aux->drm_aux, &ctrl->panel->dp_link);
-
reinit_completion(&ctrl->idle_comp);
dp_ctrl_state_ctrl(ctrl, ST_PUSH_IDLE);
@@ -135,6 +148,10 @@
tbd = ctrl->link->get_test_bits_depth(ctrl->link,
ctrl->panel->pinfo.bpp);
+
+ if (tbd == DP_TEST_BIT_DEPTH_UNKNOWN)
+ tbd = DP_TEST_BIT_DEPTH_8;
+
config |= tbd << 8;
/* Num of Lanes */
@@ -170,9 +187,6 @@
ctrl->panel->pinfo.bpp);
cc = ctrl->link->get_colorimetry_config(ctrl->link);
ctrl->catalog->config_misc(ctrl->catalog, cc, tb);
-
- ctrl->catalog->config_msa(ctrl->catalog);
-
ctrl->panel->timing_cfg(ctrl->panel);
}
@@ -226,7 +240,7 @@
{
u32 const multiplier = 1000000;
u64 pclk, lclk;
- u8 bpp, ln_cnt, link_rate;
+ u8 bpp, ln_cnt;
int run_idx = 0;
u32 lwidth, h_blank;
u32 fifo_empty = 0;
@@ -289,7 +303,6 @@
u64 brute_force_threshold = 10;
u64 diff_abs;
- link_rate = ctrl->link->link_rate;
ln_cnt = ctrl->link->lane_count;
bpp = pinfo->bpp;
@@ -309,7 +322,7 @@
even_distribution = 0;
min_hblank = 0;
- lclk = drm_dp_bw_code_to_link_rate(link_rate) * DP_KHZ_TO_HZ;
+ lclk = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code) * DP_KHZ_TO_HZ;
pr_debug("pclk=%lld, active_width=%d, h_blank=%d\n",
pclk, lwidth, h_blank);
@@ -734,14 +747,12 @@
max_level_reached |= BIT(5);
}
- pr_debug("max_level_reached = 0x%x\n", max_level_reached);
-
pre_emphasis_level <<= 3;
for (i = 0; i < 4; i++)
buf[i] = voltage_level | pre_emphasis_level | max_level_reached;
- pr_debug("p|v=0x%x\n", voltage_level | pre_emphasis_level);
+ pr_debug("sink: p|v=0x%x\n", voltage_level | pre_emphasis_level);
return drm_dp_dpcd_write(ctrl->aux->drm_aux, 0x103, buf, 4);
}
@@ -749,8 +760,6 @@
{
struct dp_link *link = ctrl->link;
- pr_debug("v=%d p=%d\n", link->v_level, link->p_level);
-
ctrl->catalog->update_vx_px(ctrl->catalog,
link->v_level, link->p_level);
@@ -762,15 +771,38 @@
{
u8 buf[4];
- pr_debug("pattern=%x\n", pattern);
+ pr_debug("sink: pattern=%x\n", pattern);
buf[0] = pattern;
drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_TRAINING_PATTERN_SET, buf, 1);
}
+static int dp_ctrl_read_link_status(struct dp_ctrl_private *ctrl,
+ u8 *link_status)
+{
+ int ret = 0, len;
+ u32 const offset = DP_LANE_ALIGN_STATUS_UPDATED - DP_LANE0_1_STATUS;
+ u32 link_status_read_max_retries = 100;
+
+ while (--link_status_read_max_retries) {
+ len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
+ link_status);
+ if (len != DP_LINK_STATUS_SIZE) {
+ pr_err("DP link status read failed, err: %d\n", len);
+ ret = len;
+ break;
+ }
+
+ if (!(link_status[offset] & DP_LINK_STATUS_UPDATED))
+ break;
+ }
+
+ return ret;
+}
+
static int dp_ctrl_link_train_1(struct dp_ctrl_private *ctrl)
{
- int tries, old_v_level, ret = 0, len = 0;
+ int tries, old_v_level, ret = 0;
u8 link_status[DP_LINK_STATUS_SIZE];
int const maximum_retries = 5;
@@ -780,7 +812,7 @@
ctrl->catalog->set_pattern(ctrl->catalog, 0x01);
dp_ctrl_train_pattern_set(ctrl, DP_TRAINING_PATTERN_1 |
- DP_RECOVERED_CLOCK_OUT_EN); /* train_1 */
+ DP_LINK_SCRAMBLING_DISABLE); /* train_1 */
dp_ctrl_update_vx_px(ctrl);
tries = 0;
@@ -788,36 +820,35 @@
while (1) {
drm_dp_link_train_clock_recovery_delay(ctrl->panel->dpcd);
- len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
- link_status);
- if (len < DP_LINK_STATUS_SIZE) {
- pr_err("[%s]: DP link status read failed\n", __func__);
- ret = -1;
+ ret = dp_ctrl_read_link_status(ctrl, link_status);
+ if (ret)
break;
- }
if (drm_dp_clock_recovery_ok(link_status,
ctrl->link->lane_count)) {
- ret = 0;
break;
}
if (ctrl->link->v_level == DP_LINK_VOLTAGE_MAX) {
- ret = -1;
- break; /* quit */
+ pr_err_ratelimited("max v_level reached\n");
+ ret = -EAGAIN;
+ break;
}
if (old_v_level == ctrl->link->v_level) {
tries++;
if (tries >= maximum_retries) {
- ret = -1;
- break; /* quit */
+ pr_err("max tries reached\n");
+ ret = -EAGAIN;
+ break;
}
} else {
tries = 0;
old_v_level = ctrl->link->v_level;
}
+ pr_debug("clock recovery not done, adjusting vx px\n");
+
ctrl->link->adjust_levels(ctrl->link, link_status);
dp_ctrl_update_vx_px(ctrl);
}
@@ -828,27 +859,41 @@
static int dp_ctrl_link_rate_down_shift(struct dp_ctrl_private *ctrl)
{
int ret = 0;
+ u32 min_req_link_rate_khz;
+ u32 new_proposed_link_bw_code;
+ u32 new_proposed_link_rate_khz;
if (!ctrl)
return -EINVAL;
- switch (ctrl->link->link_rate) {
+ min_req_link_rate_khz = ctrl->panel->get_min_req_link_rate(ctrl->panel);
+
+ switch (ctrl->link->bw_code) {
case DP_LINK_RATE_810:
- ctrl->link->link_rate = DP_LINK_BW_5_4;
+ new_proposed_link_bw_code = DP_LINK_BW_5_4;
break;
case DP_LINK_BW_5_4:
- ctrl->link->link_rate = DP_LINK_BW_2_7;
+ new_proposed_link_bw_code = DP_LINK_BW_2_7;
break;
case DP_LINK_BW_2_7:
- ctrl->link->link_rate = DP_LINK_BW_1_62;
- break;
case DP_LINK_BW_1_62:
default:
- ret = -EINVAL;
+ new_proposed_link_bw_code = DP_LINK_BW_1_62;
break;
};
- pr_debug("new rate=%d\n", ctrl->link->link_rate);
+ new_proposed_link_rate_khz = drm_dp_bw_code_to_link_rate(
+ new_proposed_link_bw_code);
+
+ pr_debug("new proposed link rate=%d khz\n", new_proposed_link_rate_khz);
+ pr_debug("min required link rate=%d khz\n", min_req_link_rate_khz);
+
+ if (new_proposed_link_rate_khz >= min_req_link_rate_khz)
+ ctrl->link->bw_code = new_proposed_link_bw_code;
+ else
+ pr_debug("can't go below min required link rate\n");
+
+ pr_debug("new bw code=0x%x\n", ctrl->link->bw_code);
return ret;
}
@@ -861,11 +906,15 @@
static int dp_ctrl_link_training_2(struct dp_ctrl_private *ctrl)
{
- int tries = 0, ret = 0, len = 0;
+ int tries = 0, ret = 0;
char pattern;
int const maximum_retries = 5;
u8 link_status[DP_LINK_STATUS_SIZE];
+ dp_ctrl_state_ctrl(ctrl, 0);
+ /* Make sure to clear the current pattern before starting a new one */
+ wmb();
+
if (drm_dp_tps3_supported(ctrl->panel->dpcd))
pattern = DP_TRAINING_PATTERN_3;
else
@@ -878,21 +927,15 @@
do {
drm_dp_link_train_channel_eq_delay(ctrl->panel->dpcd);
- len = drm_dp_dpcd_read_link_status(ctrl->aux->drm_aux,
- link_status);
- if (len < DP_LINK_STATUS_SIZE) {
- pr_err("[%s]: DP link status read failed\n", __func__);
- ret = -1;
+ ret = dp_ctrl_read_link_status(ctrl, link_status);
+ if (ret)
break;
- }
- if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count)) {
- ret = 0;
+ if (drm_dp_channel_eq_ok(link_status, ctrl->link->lane_count))
break;
- }
if (tries > maximum_retries) {
- ret = -1;
+ ret = -EAGAIN;
break;
}
tries++;
@@ -907,61 +950,45 @@
static int dp_ctrl_link_train(struct dp_ctrl_private *ctrl)
{
int ret = 0;
- struct drm_dp_link dp_link;
+ u8 encoding = 0x1;
+ struct drm_dp_link link_info = {0};
ctrl->link->p_level = 0;
ctrl->link->v_level = 0;
dp_ctrl_config_ctrl(ctrl);
- dp_ctrl_state_ctrl(ctrl, 0);
- dp_link.num_lanes = ctrl->link->lane_count;
- dp_link.rate = ctrl->link->link_rate;
- dp_link.capabilities = ctrl->panel->dp_link.capabilities;
- drm_dp_link_configure(ctrl->aux->drm_aux, &dp_link);
+ link_info.num_lanes = ctrl->link->lane_count;
+ link_info.rate = drm_dp_bw_code_to_link_rate(ctrl->link->bw_code);
+ link_info.capabilities = ctrl->panel->link_info.capabilities;
+
+ drm_dp_link_configure(ctrl->aux->drm_aux, &link_info);
+ drm_dp_dpcd_write(ctrl->aux->drm_aux, DP_MAIN_LINK_CHANNEL_CODING_SET,
+ &encoding, 1);
ret = dp_ctrl_link_train_1(ctrl);
- if (ret < 0) {
- if (!dp_ctrl_link_rate_down_shift(ctrl)) {
- pr_debug("retry with lower rate\n");
-
- dp_ctrl_clear_training_pattern(ctrl);
- return -EAGAIN;
- }
-
- pr_err("Training 1 failed\n");
- ret = -EINVAL;
- goto clear;
+ if (ret) {
+ pr_err("link training #1 failed\n");
+ goto end;
}
- pr_debug("Training 1 completed successfully\n");
-
- dp_ctrl_state_ctrl(ctrl, 0);
-
- /* Make sure to clear the current pattern before starting a new one */
- wmb();
+ /* print success info as this is a result of user initiated action */
+ pr_info("link training #1 successful\n");
ret = dp_ctrl_link_training_2(ctrl);
- if (ret < 0) {
- if (!dp_ctrl_link_rate_down_shift(ctrl)) {
- pr_debug("retry with lower rate\n");
-
- dp_ctrl_clear_training_pattern(ctrl);
- return -EAGAIN;
- }
-
- pr_err("Training 2 failed\n");
- ret = -EINVAL;
- goto clear;
+ if (ret) {
+ pr_err("link training #2 failed\n");
+ goto end;
}
- pr_debug("Training 2 completed successfully\n");
+ /* print success info as this is a result of user initiated action */
+ pr_debug("link training #2 successful\n");
+end:
dp_ctrl_state_ctrl(ctrl, 0);
/* Make sure to clear the current pattern before starting a new one */
wmb();
-clear:
dp_ctrl_clear_training_pattern(ctrl);
return ret;
}
@@ -973,7 +1000,7 @@
ctrl->catalog->mainlink_ctrl(ctrl->catalog, true);
- drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->dp_link);
+ drm_dp_link_power_up(ctrl->aux->drm_aux, &ctrl->panel->link_info);
if (ctrl->link->phy_pattern_requested(ctrl->link))
goto end;
@@ -1018,6 +1045,8 @@
cfg++;
}
+ pr_debug("setting rate=%d on clk=%s\n", rate, name);
+
if (num)
cfg->rate = rate;
else
@@ -1031,7 +1060,7 @@
ctrl->power->set_pixel_clk_parent(ctrl->power);
dp_ctrl_set_clock_rate(ctrl, "ctrl_link_clk",
- drm_dp_bw_code_to_link_rate(ctrl->link->link_rate));
+ drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
dp_ctrl_set_clock_rate(ctrl, "ctrl_pixel_clk", ctrl->pixel_rate);
@@ -1128,6 +1157,9 @@
dp_ctrl_configure_source_params(ctrl);
+ ctrl->catalog->config_msa(ctrl->catalog,
+ drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
+
reinit_completion(&ctrl->idle_comp);
if (ctrl->psm_enabled) {
@@ -1148,16 +1180,20 @@
static int dp_ctrl_on_hpd(struct dp_ctrl_private *ctrl)
{
int ret = 0;
+ u32 rate = ctrl->panel->link_info.rate;
+ u32 link_train_max_retries = 100;
+
+ atomic_set(&ctrl->aborted, 0);
ctrl->power->clk_enable(ctrl->power, DP_CORE_PM, true);
ctrl->catalog->hpd_config(ctrl->catalog, true);
- ctrl->link->link_rate = ctrl->panel->get_link_rate(ctrl->panel);
- ctrl->link->lane_count = ctrl->panel->dp_link.num_lanes;
+ ctrl->link->bw_code = drm_dp_link_rate_to_bw_code(rate);
+ ctrl->link->lane_count = ctrl->panel->link_info.num_lanes;
ctrl->pixel_rate = ctrl->panel->pinfo.pixel_clk_khz;
- pr_debug("link_rate=%d, lane_count=%d, pixel_rate=%d\n",
- ctrl->link->link_rate, ctrl->link->lane_count,
+ pr_debug("bw_code=%d, lane_count=%d, pixel_rate=%d\n",
+ ctrl->link->bw_code, ctrl->link->lane_count,
ctrl->pixel_rate);
ctrl->catalog->phy_lane_cfg(ctrl->catalog,
@@ -1174,8 +1210,25 @@
if (ctrl->psm_enabled)
ret = ctrl->link->send_psm_request(ctrl->link, false);
- while (-EAGAIN == dp_ctrl_setup_main_link(ctrl, true))
- pr_debug("MAIN LINK TRAINING RETRY\n");
+ while (--link_train_max_retries && !atomic_read(&ctrl->aborted)) {
+ ctrl->catalog->config_msa(ctrl->catalog,
+ drm_dp_bw_code_to_link_rate(ctrl->link->bw_code));
+
+ ret = dp_ctrl_setup_main_link(ctrl, true);
+ if (!ret)
+ break;
+
+ /* try with lower link rate */
+ dp_ctrl_link_rate_down_shift(ctrl);
+
+ ctrl->catalog->mainlink_ctrl(ctrl->catalog, false);
+
+ dp_ctrl_disable_mainlink_clocks(ctrl);
+ /* hw recommended delay before re-enabling clocks */
+ msleep(20);
+
+ dp_ctrl_enable_mainlink_clocks(ctrl);
+ }
pr_debug("End-\n");
@@ -1292,6 +1345,7 @@
dp_ctrl->on = dp_ctrl_on;
dp_ctrl->off = dp_ctrl_off;
dp_ctrl->push_idle = dp_ctrl_push_idle;
+ dp_ctrl->abort = dp_ctrl_abort;
dp_ctrl->isr = dp_ctrl_isr;
return dp_ctrl;
diff --git a/drivers/gpu/drm/msm/dp/dp_ctrl.h b/drivers/gpu/drm/msm/dp/dp_ctrl.h
index 474e0ad..2ecfa0d 100644
--- a/drivers/gpu/drm/msm/dp/dp_ctrl.h
+++ b/drivers/gpu/drm/msm/dp/dp_ctrl.h
@@ -28,6 +28,7 @@
int (*on)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
void (*off)(struct dp_ctrl *dp_ctrl, bool hpd_irq);
void (*push_idle)(struct dp_ctrl *dp_ctrl);
+ void (*abort)(struct dp_ctrl *dp_ctrl);
void (*isr)(struct dp_ctrl *dp_ctrl);
};
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 5a33fdb..b45cf4d 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -12,7 +12,7 @@
*
*/
-#define pr_fmt(fmt) "[drm-dp]: %s: " fmt, __func__
+#define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
#include <linux/module.h>
#include <linux/slab.h>
@@ -45,7 +45,7 @@
struct platform_device *pdev;
struct dentry *root;
- struct mutex lock;
+ struct completion notification_comp;
struct dp_usbpd *usbpd;
struct dp_parser *parser;
@@ -171,7 +171,7 @@
pr_err("invalid param(s), dev %pK, pdev %pK, master %pK\n",
dev, pdev, master);
rc = -EINVAL;
- goto error;
+ goto end;
}
drm = dev_get_drvdata(master);
@@ -180,14 +180,12 @@
pr_err("invalid param(s), drm %pK, dp %pK\n",
drm, dp);
rc = -EINVAL;
- goto error;
+ goto end;
}
dp->dp_display.drm_dev = drm;
priv = drm->dev_private;
- mutex_lock(&dp->lock);
-
rc = dp_display_debugfs_init(dp);
if (rc) {
pr_err("[%s]Debugfs init failed, rc=%d\n", dp->name, rc);
@@ -218,8 +216,6 @@
goto end;
}
end:
- mutex_unlock(&dp->lock);
-error:
return rc;
}
@@ -240,17 +236,10 @@
return;
}
- mutex_lock(&dp->lock);
-
(void)dp->power->power_client_deinit(dp->power);
-
- (void) dp->panel->sde_edid_deregister(dp->panel);
-
- (void) dp->aux->drm_aux_deregister(dp->aux);
-
+ (void)dp->panel->sde_edid_deregister(dp->panel);
+ (void)dp->aux->drm_aux_deregister(dp->aux);
(void)dp_display_debugfs_deinit(dp);
-
- mutex_unlock(&dp->lock);
}
static const struct component_ops dp_display_comp_ops = {
@@ -276,8 +265,13 @@
dp->parser->max_pclk_khz);
dp->dp_display.is_connected = true;
+
drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
+ reinit_completion(&dp->notification_comp);
+ if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
+ pr_warn("timeout\n");
+
return rc;
}
@@ -316,8 +310,15 @@
static void dp_display_process_hpd_low(struct dp_display_private *dp)
{
+ /* cancel any pending request */
+ dp->ctrl->abort(dp->ctrl);
+
dp->dp_display.is_connected = false;
drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
+
+ reinit_completion(&dp->notification_comp);
+ if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
+ pr_warn("timeout\n");
}
static int dp_display_usbpd_configure_cb(struct device *dev)
@@ -338,11 +339,10 @@
goto end;
}
- mutex_lock(&dp->lock);
dp_display_host_init(dp);
+
if (dp->usbpd->hpd_high)
dp_display_process_hpd_high(dp);
- mutex_unlock(&dp->lock);
end:
return rc;
}
@@ -365,11 +365,16 @@
goto end;
}
- mutex_lock(&dp->lock);
+ /* cancel any pending request */
+ dp->ctrl->abort(dp->ctrl);
dp->dp_display.is_connected = false;
drm_helper_hpd_irq_event(dp->dp_display.connector->dev);
+ reinit_completion(&dp->notification_comp);
+ if (!wait_for_completion_timeout(&dp->notification_comp, HZ * 2))
+ pr_warn("timeout\n");
+
/*
* If a cable/dongle is connected to the TX device but
* no sink device is connected, we call host
@@ -381,8 +386,6 @@
*/
if (!dp->power_on && dp->core_initialized)
dp_display_host_deinit(dp);
-
- mutex_unlock(&dp->lock);
end:
return rc;
}
@@ -403,8 +406,6 @@
return -ENODEV;
}
- mutex_lock(&dp->lock);
-
if (dp->usbpd->hpd_irq) {
dp->hpd_irq_on = true;
rc = dp->link->process_request(dp->link);
@@ -423,7 +424,6 @@
dp_display_process_hpd_high(dp);
}
end:
- mutex_unlock(&dp->lock);
return rc;
}
@@ -543,18 +543,29 @@
dp = container_of(dp_display, struct dp_display_private, dp_display);
- mutex_lock(&dp->lock);
rc = dp->ctrl->on(dp->ctrl, dp->hpd_irq_on);
if (!rc)
dp->power_on = true;
- mutex_unlock(&dp->lock);
error:
return rc;
}
-static int dp_display_post_enable(struct dp_display *dp)
+static int dp_display_post_enable(struct dp_display *dp_display)
{
- return 0;
+ int rc = 0;
+ struct dp_display_private *dp;
+
+ if (!dp_display) {
+ pr_err("invalid input\n");
+ rc = -EINVAL;
+ goto end;
+ }
+
+ dp = container_of(dp_display, struct dp_display_private, dp_display);
+
+ complete_all(&dp->notification_comp);
+end:
+ return rc;
}
static int dp_display_pre_disable(struct dp_display *dp_display)
@@ -570,9 +581,7 @@
dp = container_of(dp_display, struct dp_display_private, dp_display);
- mutex_lock(&dp->lock);
dp->ctrl->push_idle(dp->ctrl);
- mutex_unlock(&dp->lock);
error:
return rc;
}
@@ -590,11 +599,12 @@
dp = container_of(dp_display, struct dp_display_private, dp_display);
- mutex_lock(&dp->lock);
dp->ctrl->off(dp->ctrl, dp->hpd_irq_on);
dp_display_host_deinit(dp);
+
dp->power_on = false;
- mutex_unlock(&dp->lock);
+
+ complete_all(&dp->notification_comp);
error:
return rc;
}
@@ -668,7 +678,8 @@
if (!dp)
return -ENOMEM;
- mutex_init(&dp->lock);
+ init_completion(&dp->notification_comp);
+
dp->pdev = pdev;
dp->name = "drm_dp";
diff --git a/drivers/gpu/drm/msm/dp/dp_link.c b/drivers/gpu/drm/msm/dp/dp_link.c
index 741acfca..2beac0d 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.c
+++ b/drivers/gpu/drm/msm/dp/dp_link.c
@@ -47,13 +47,6 @@
DP_TEST_VIDEO_PATTERN_COLOR_SQUARE = 0x03,
};
-enum test_bit_depth {
- DP_TEST_BIT_DEPTH_6 = 0x00,
- DP_TEST_BIT_DEPTH_8 = 0x01,
- DP_TEST_BIT_DEPTH_10 = 0x02,
- DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
-};
-
enum dp_link_response {
TEST_ACK = 0x1,
TEST_NACK = 0x2,
@@ -765,12 +758,12 @@
*
* Returns true if the requested link rate is supported.
*/
-static bool dp_link_is_link_rate_valid(u32 link_rate)
+static bool dp_link_is_link_rate_valid(u32 bw_code)
{
- return ((link_rate == DP_LINK_BW_1_62) ||
- (link_rate == DP_LINK_BW_2_7) ||
- (link_rate == DP_LINK_BW_5_4) ||
- (link_rate == DP_LINK_RATE_810));
+ return ((bw_code == DP_LINK_BW_1_62) ||
+ (bw_code == DP_LINK_BW_2_7) ||
+ (bw_code == DP_LINK_BW_5_4) ||
+ (bw_code == DP_LINK_RATE_810));
}
/**
@@ -1101,7 +1094,7 @@
link->request.test_lane_count);
link->dp_link.lane_count = link->request.test_lane_count;
- link->dp_link.link_rate = link->request.test_link_rate;
+ link->dp_link.bw_code = link->request.test_link_rate;
return 0;
}
@@ -1216,7 +1209,7 @@
pr_debug("start\n");
link->dp_link.lane_count = link->request.test_lane_count;
- link->dp_link.link_rate = link->request.test_link_rate;
+ link->dp_link.bw_code = link->request.test_link_rate;
dp_link_parse_vx_px(link);
@@ -1517,7 +1510,7 @@
dp_link->p_level = DP_LINK_PRE_EMPHASIS_LEVEL_1;
}
- pr_debug("v_level=%d, p_level=%d\n",
+ pr_debug("adjusted: v_level=%d, p_level=%d\n",
dp_link->v_level, dp_link->p_level);
return 0;
diff --git a/drivers/gpu/drm/msm/dp/dp_link.h b/drivers/gpu/drm/msm/dp/dp_link.h
index 26249d6..8ea43da 100644
--- a/drivers/gpu/drm/msm/dp/dp_link.h
+++ b/drivers/gpu/drm/msm/dp/dp_link.h
@@ -46,11 +46,18 @@
DS_PORT_STATUS_CHANGED = 0x200,
};
+enum test_bit_depth {
+ DP_TEST_BIT_DEPTH_6 = 0x00,
+ DP_TEST_BIT_DEPTH_8 = 0x01,
+ DP_TEST_BIT_DEPTH_10 = 0x02,
+ DP_TEST_BIT_DEPTH_UNKNOWN = 0xFFFFFFFF,
+};
+
struct dp_link {
u32 test_requested;
u32 lane_count;
- u32 link_rate;
+ u32 bw_code;
u32 v_level;
u32 p_level;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.c b/drivers/gpu/drm/msm/dp/dp_panel.c
index 4496e9a..5f25b2d 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.c
+++ b/drivers/gpu/drm/msm/dp/dp_panel.c
@@ -16,6 +16,8 @@
#include "dp_panel.h"
+#define DP_PANEL_DEFAULT_BPP 24
+
enum {
DP_LINK_RATE_MULTIPLIER = 27000000,
};
@@ -25,14 +27,16 @@
struct dp_panel dp_panel;
struct dp_aux *aux;
struct dp_catalog_panel *catalog;
+ bool lane_switch_supported;
};
static int dp_panel_read_dpcd(struct dp_panel *dp_panel)
{
int rlen, rc = 0;
struct dp_panel_private *panel;
- struct drm_dp_link *dp_link;
+ struct drm_dp_link *link_info;
u8 major = 0, minor = 0;
+ unsigned long caps = DP_LINK_CAP_ENHANCED_FRAMING;
if (!dp_panel) {
pr_err("invalid input\n");
@@ -41,7 +45,7 @@
}
panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
- dp_link = &dp_panel->dp_link;
+ link_info = &dp_panel->link_info;
rlen = drm_dp_dpcd_read(panel->aux->drm_aux, DP_DPCD_REV,
dp_panel->dpcd, (DP_RECEIVER_CAP_SIZE + 1));
@@ -51,22 +55,26 @@
goto end;
}
- dp_link->revision = dp_panel->dpcd[DP_DPCD_REV];
+ link_info->revision = dp_panel->dpcd[DP_DPCD_REV];
- major = (dp_link->revision >> 4) & 0x0f;
- minor = dp_link->revision & 0x0f;
+ major = (link_info->revision >> 4) & 0x0f;
+ minor = link_info->revision & 0x0f;
pr_debug("version: %d.%d\n", major, minor);
- dp_link->rate =
+ link_info->rate =
drm_dp_bw_code_to_link_rate(dp_panel->dpcd[DP_MAX_LINK_RATE]);
- pr_debug("link_rate=%d\n", dp_link->rate);
+ pr_debug("link_rate=%d\n", link_info->rate);
- dp_link->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
+ if (panel->lane_switch_supported)
+ link_info->num_lanes = dp_panel->dpcd[DP_MAX_LANE_COUNT] &
DP_MAX_LANE_COUNT_MASK;
- pr_debug("lane_count=%d\n", dp_link->num_lanes);
+ else
+ link_info->num_lanes = 2;
+
+ pr_debug("lane_count=%d\n", link_info->num_lanes);
if (dp_panel->dpcd[DP_MAX_LANE_COUNT] & DP_ENHANCED_FRAME_CAP)
- dp_link->capabilities |= DP_LINK_CAP_ENHANCED_FRAMING;
+ link_info->capabilities |= caps;
end:
return rc;
@@ -74,26 +82,26 @@
static u32 dp_panel_get_max_pclk(struct dp_panel *dp_panel)
{
- struct dp_panel_private *panel;
- struct drm_dp_link *dp_link;
- u32 bpc, bpp, max_data_rate_khz, max_pclk_rate_khz;
+ struct drm_dp_link *link_info;
const u8 num_components = 3;
+ u32 bpc, bpp, max_data_rate_khz, max_pclk_rate_khz;
if (!dp_panel) {
pr_err("invalid input\n");
return 0;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
- dp_link = &dp_panel->dp_link;
+ link_info = &dp_panel->link_info;
bpc = sde_get_sink_bpc(dp_panel->edid_ctrl);
bpp = bpc * num_components;
+ if (!bpp)
+ bpp = DP_PANEL_DEFAULT_BPP;
- max_data_rate_khz = (dp_link->num_lanes * dp_link->rate * 8);
+ max_data_rate_khz = (link_info->num_lanes * link_info->rate * 8);
max_pclk_rate_khz = max_data_rate_khz / bpp;
- pr_debug("bpp=%d, max_lane_cnt=%d\n", bpp, dp_link->num_lanes);
+ pr_debug("bpp=%d, max_lane_cnt=%d\n", bpp, link_info->num_lanes);
pr_debug("max_data_rate=%dKHz, max_pclk_rate=%dKHz\n",
max_data_rate_khz, max_pclk_rate_khz);
@@ -196,7 +204,7 @@
static int dp_panel_init_panel_info(struct dp_panel *dp_panel)
{
int rc = 0;
- struct dp_panel_private *panel;
+ struct dp_panel_info *pinfo;
if (!dp_panel) {
pr_err("invalid input\n");
@@ -204,18 +212,38 @@
goto end;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
+ pinfo = &dp_panel->pinfo;
+
+ /*
+ * print resolution info as this is a result
+ * of user initiated action of cable connection
+ */
+ pr_info("SET NEW RESOLUTION:\n");
+ pr_info("%dx%d@%dfps\n", pinfo->h_active,
+ pinfo->v_active, pinfo->refresh_rate);
+ pr_info("h_porches(back|front|width) = (%d|%d|%d)\n",
+ pinfo->h_back_porch,
+ pinfo->h_front_porch,
+ pinfo->h_sync_width);
+ pr_info("v_porches(back|front|width) = (%d|%d|%d)\n",
+ pinfo->v_back_porch,
+ pinfo->v_front_porch,
+ pinfo->v_sync_width);
+ pr_info("pixel clock (KHz)=(%d)\n", pinfo->pixel_clk_khz);
+ pr_info("bpp = %d\n", pinfo->bpp);
+ pr_info("active low (h|v)=(%d|%d)\n", pinfo->h_active_low,
+ pinfo->v_active_low);
+
+ pinfo->bpp = max_t(u32, 18, min_t(u32, pinfo->bpp, 30));
+ pr_info("updated bpp = %d\n", pinfo->bpp);
end:
return rc;
}
-static u32 dp_panel_get_link_rate(struct dp_panel *dp_panel)
+static u32 dp_panel_get_min_req_link_rate(struct dp_panel *dp_panel)
{
const u32 encoding_factx10 = 8;
- const u32 ln_to_link_ratio = 10;
- u32 min_link_rate, reminder = 0;
- u32 calc_link_rate = 0, lane_cnt, max_rate = 0;
- struct dp_panel_private *panel;
+ u32 min_link_rate_khz = 0, lane_cnt;
struct dp_panel_info *pinfo;
if (!dp_panel) {
@@ -223,54 +251,19 @@
goto end;
}
- panel = container_of(dp_panel, struct dp_panel_private, dp_panel);
-
- lane_cnt = dp_panel->dp_link.num_lanes;
- max_rate = drm_dp_link_rate_to_bw_code(dp_panel->dp_link.rate);
+ lane_cnt = dp_panel->link_info.num_lanes;
pinfo = &dp_panel->pinfo;
- /*
- * The max pixel clock supported is 675Mhz. The
- * current calculations below will make sure
- * the min_link_rate is within 32 bit limits.
- * Any changes in the section of code should
- * consider this limitation.
- */
- min_link_rate = (u32)div_u64(pinfo->pixel_clk_khz * 1000,
- (lane_cnt * encoding_factx10));
- min_link_rate /= ln_to_link_ratio;
- min_link_rate = (min_link_rate * pinfo->bpp);
- min_link_rate = (u32)div_u64_rem(min_link_rate * 10,
- DP_LINK_RATE_MULTIPLIER, &reminder);
+ /* num_lanes * lane_count * 8 >= pclk * bpp * 10 */
+ min_link_rate_khz = pinfo->pixel_clk_khz /
+ (lane_cnt * encoding_factx10);
+ min_link_rate_khz *= pinfo->bpp;
- /*
- * To avoid any fractional values,
- * increment the min_link_rate
- */
- if (reminder)
- min_link_rate += 1;
- pr_debug("min_link_rate = %d\n", min_link_rate);
-
- if (min_link_rate <= DP_LINK_BW_1_62)
- calc_link_rate = DP_LINK_BW_1_62;
- else if (min_link_rate <= DP_LINK_BW_2_7)
- calc_link_rate = DP_LINK_BW_2_7;
- else if (min_link_rate <= DP_LINK_BW_5_4)
- calc_link_rate = DP_LINK_BW_5_4;
- else if (min_link_rate <= DP_LINK_RATE_810)
- calc_link_rate = DP_LINK_RATE_810;
- else {
- /* Cap the link rate to the max supported rate */
- pr_debug("link_rate = %d is unsupported\n", min_link_rate);
- calc_link_rate = DP_LINK_RATE_810;
- }
-
- if (calc_link_rate > max_rate)
- calc_link_rate = max_rate;
-
- pr_debug("calc_link_rate = 0x%x\n", calc_link_rate);
+ pr_debug("min lclk req=%d khz for pclk=%d khz, lanes=%d, bpp=%d\n",
+ min_link_rate_khz, pinfo->pixel_clk_khz, lane_cnt,
+ pinfo->bpp);
end:
- return calc_link_rate;
+ return min_link_rate_khz;
}
struct dp_panel *dp_panel_get(struct device *dev, struct dp_aux *aux,
@@ -303,7 +296,7 @@
dp_panel->init_info = dp_panel_init_panel_info;
dp_panel->timing_cfg = dp_panel_timing_cfg;
dp_panel->read_dpcd = dp_panel_read_dpcd;
- dp_panel->get_link_rate = dp_panel_get_link_rate;
+ dp_panel->get_min_req_link_rate = dp_panel_get_min_req_link_rate;
dp_panel->get_max_pclk = dp_panel_get_max_pclk;
return dp_panel;
diff --git a/drivers/gpu/drm/msm/dp/dp_panel.h b/drivers/gpu/drm/msm/dp/dp_panel.h
index b63c51f..6cca0f1 100644
--- a/drivers/gpu/drm/msm/dp/dp_panel.h
+++ b/drivers/gpu/drm/msm/dp/dp_panel.h
@@ -40,7 +40,7 @@
struct dp_panel {
/* dpcd raw data */
u8 dpcd[DP_RECEIVER_CAP_SIZE];
- struct drm_dp_link dp_link;
+ struct drm_dp_link link_info;
struct sde_edid_ctrl *edid_ctrl;
struct dp_panel_info pinfo;
@@ -53,7 +53,7 @@
int (*init_info)(struct dp_panel *dp_panel);
int (*timing_cfg)(struct dp_panel *dp_panel);
int (*read_dpcd)(struct dp_panel *dp_panel);
- u32 (*get_link_rate)(struct dp_panel *dp_panel);
+ u32 (*get_min_req_link_rate)(struct dp_panel *dp_panel);
u32 (*get_max_pclk)(struct dp_panel *dp_panel);
};
diff --git a/drivers/gpu/drm/msm/dp/dp_usbpd.c b/drivers/gpu/drm/msm/dp/dp_usbpd.c
index 6ef8266..c6ed918 100644
--- a/drivers/gpu/drm/msm/dp/dp_usbpd.c
+++ b/drivers/gpu/drm/msm/dp/dp_usbpd.c
@@ -345,12 +345,8 @@
pd->vdo = *vdos;
dp_usbpd_get_status(pd);
- if (pd->dp_cb && pd->dp_cb->attention) {
- pd->dp_cb->attention(pd->dev);
-
- if (!pd->dp_usbpd.alt_mode_cfg_done)
- dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
- }
+ if (!pd->dp_usbpd.alt_mode_cfg_done)
+ dp_usbpd_send_event(pd, DP_USBPD_EVT_CONFIGURE);
break;
case DP_USBPD_VDM_STATUS:
pd->vdo = *vdos;
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 810d0d6..11f1c4f 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -58,13 +58,14 @@
#define MSM_VERSION_PATCHLEVEL 0
#define TEARDOWN_DEADLOCK_RETRY_MAX 5
+#define HPD_STRING_SIZE 30
static void msm_drm_helper_hotplug_event(struct drm_device *dev)
{
struct drm_connector *connector;
- char *event_string;
+ char name[HPD_STRING_SIZE], status[HPD_STRING_SIZE];
char const *connector_name;
- char *envp[2];
+ char *envp[3];
if (!dev) {
DRM_ERROR("hotplug_event failed, invalid input\n");
@@ -74,12 +75,6 @@
if (!dev->mode_config.poll_enabled)
return;
- event_string = kzalloc(SZ_4K, GFP_KERNEL);
- if (!event_string) {
- DRM_ERROR("failed to allocate event string\n");
- return;
- }
-
mutex_lock(&dev->mode_config.mutex);
drm_for_each_connector(connector, dev) {
/* Only handle HPD capable connectors. */
@@ -93,17 +88,20 @@
else
connector_name = "unknown";
- snprintf(event_string, SZ_4K, "name=%s status=%s\n",
- connector_name,
+ snprintf(name, HPD_STRING_SIZE, "name=%s", connector_name);
+
+ snprintf(status, HPD_STRING_SIZE, "status=%s",
drm_get_connector_status_name(connector->status));
- DRM_DEBUG("generating hotplug event [%s]\n", event_string);
- envp[0] = event_string;
- envp[1] = NULL;
+
+ DRM_DEBUG("generating hotplug event [%s]: [%s]\n",
+ name, status);
+ envp[0] = name;
+ envp[1] = status;
+ envp[2] = NULL;
kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE,
envp);
}
mutex_unlock(&dev->mode_config.mutex);
- kfree(event_string);
}
static void msm_fb_output_poll_changed(struct drm_device *dev)
@@ -126,21 +124,10 @@
int msm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
- struct msm_drm_private *priv;
-
- if (!dev)
- return -EINVAL;
-
if (msm_is_suspend_blocked(dev)) {
DRM_DEBUG("rejecting commit during suspend\n");
return -EBUSY;
}
-
- priv = dev->dev_private;
- if (priv && priv->kms && priv->kms->funcs &&
- priv->kms->funcs->atomic_check)
- return priv->kms->funcs->atomic_check(priv->kms, state);
-
return drm_atomic_helper_check(dev, state);
}
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index eb10d6b..35e6b71 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -75,9 +75,6 @@
const struct msm_format *msm_fmt,
const struct drm_mode_fb_cmd2 *cmd,
struct drm_gem_object **bos);
- /* perform complete atomic check of given atomic state */
- int (*atomic_check)(struct msm_kms *kms,
- struct drm_atomic_state *state);
/* misc: */
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 7417514..63979dd 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -979,7 +979,7 @@
* On certain HW, if using 2 LM, ROIs must be split evenly between the
* LMs and be of equal width.
*/
- if (sde_crtc->num_mixers == 1)
+ if (sde_crtc->num_mixers < 2)
return 0;
roi[0] = &crtc_state->lm_roi[0];
@@ -2021,6 +2021,16 @@
if (unlikely(!sde_crtc->num_mixers))
return;
+ /*
+ * For planes without commit update, drm framework will not add
+ * those planes to current state since hardware update is not
+ * required. However, if those planes were power collapsed since
+ * last commit cycle, driver has to restore the hardware state
+ * of those planes explicitly here prior to plane flush.
+ */
+ drm_atomic_crtc_for_each_plane(plane, crtc)
+ sde_plane_restore(plane);
+
/* wait for acquire fences before anything else is done */
_sde_crtc_wait_for_fences(crtc);
@@ -2339,8 +2349,6 @@
_sde_crtc_rp_duplicate(&old_cstate->rp, &cstate->rp);
- cstate->idle_pc = sde_crtc->idle_pc;
-
return &cstate->base;
}
@@ -2441,24 +2449,6 @@
sde_encoder_virt_restore(encoder);
}
- } else if (event_type == SDE_POWER_EVENT_PRE_DISABLE) {
- /*
- * Serialize h/w idle state update with crtc atomic check.
- * Grab the modeset lock to ensure that there is no on-going
- * atomic check, then increment the idle_pc counter. The next
- * atomic check will detect a new idle_pc since the counter
- * has advanced between the old_state and new_state, and
- * therefore properly reprogram all relevant drm objects'
- * hardware.
- */
- drm_modeset_lock_crtc(crtc, NULL);
-
- sde_crtc->idle_pc++;
-
- SDE_DEBUG("crtc%d idle_pc:%d\n", crtc->base.id,
- sde_crtc->idle_pc);
- SDE_EVT32(DRMID(crtc), sde_crtc->idle_pc);
-
} else if (event_type == SDE_POWER_EVENT_POST_DISABLE) {
struct drm_plane *plane;
@@ -2469,7 +2459,6 @@
drm_atomic_crtc_for_each_plane(plane, crtc)
sde_plane_set_revalidate(plane, true);
- drm_modeset_unlock_crtc(crtc);
sde_cp_crtc_suspend(crtc);
}
@@ -2599,8 +2588,7 @@
sde_crtc->power_event = sde_power_handle_register_event(
&priv->phandle,
- SDE_POWER_EVENT_POST_ENABLE | SDE_POWER_EVENT_POST_DISABLE |
- SDE_POWER_EVENT_PRE_DISABLE,
+ SDE_POWER_EVENT_POST_ENABLE | SDE_POWER_EVENT_POST_DISABLE,
sde_crtc_handle_power_event, crtc, sde_crtc->name);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index f021477..0d72ff1 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -125,7 +125,6 @@
* @vblank_cb_time : ktime at vblank count reset
* @vblank_refcount : reference count for vblank enable request
* @suspend : whether or not a suspend operation is in progress
- * @idle_pc : count of current idle power collapse request
* @feature_list : list of color processing features supported on a crtc
* @active_list : list of color processing features are active
* @dirty_list : list of color processing features are dirty
@@ -174,7 +173,6 @@
ktime_t vblank_cb_time;
atomic_t vblank_refcount;
bool suspend;
- u32 idle_pc;
struct list_head feature_list;
struct list_head active_list;
@@ -280,7 +278,6 @@
* @sbuf_cfg: stream buffer configuration
* @sbuf_prefill_line: number of line for inline rotator prefetch
* @sbuf_flush_mask: flush mask for inline rotator
- * @idle_pc: count of idle power collapse request when state is duplicated
*/
struct sde_crtc_state {
struct drm_crtc_state base;
@@ -310,8 +307,6 @@
u32 sbuf_prefill_line;
u32 sbuf_flush_mask;
- u32 idle_pc;
-
struct sde_crtc_respool rp;
};
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 7b620bf..b9fbd62 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -1376,48 +1376,6 @@
sde_crtc_cancel_pending_flip(priv->crtcs[i], file);
}
-static int sde_kms_atomic_check(struct msm_kms *kms,
- struct drm_atomic_state *state)
-{
- struct sde_kms *sde_kms = to_sde_kms(kms);
- struct drm_device *dev = sde_kms->dev;
- struct drm_crtc *crtc;
- struct drm_crtc_state *crtc_state;
- int rc, i;
-
- if (!kms || !state)
- return -EINVAL;
-
- /*
- * Add planes (and other affected DRM objects, if any) to new state
- * if idle power collapse occurred since previous commit.
- * Since atomic state is a delta from the last, if the user-space
- * did not request any changes on a plane/connector, that object
- * will not be included in the new atomic state. Idle power collapse
- * is driver-autonomous, so the driver needs to ensure that all
- * hardware is reprogrammed as the power comes back on by forcing
- * the drm objects attached to the CRTC into the new atomic state.
- */
- for_each_crtc_in_state(state, crtc, crtc_state, i) {
- struct sde_crtc_state *cstate = to_sde_crtc_state(crtc_state);
- struct sde_crtc_state *old_cstate =
- to_sde_crtc_state(crtc->state);
-
- if (cstate->idle_pc != old_cstate->idle_pc) {
- SDE_DEBUG("crtc%d idle_pc:%d/%d\n",
- crtc->base.id, cstate->idle_pc,
- old_cstate->idle_pc);
- SDE_EVT32(DRMID(crtc), cstate->idle_pc,
- old_cstate->idle_pc);
- rc = drm_atomic_add_affected_planes(state, crtc);
- if (rc)
- return rc;
- }
- }
-
- return drm_atomic_helper_check(dev, state);
-}
-
static struct msm_gem_address_space*
_sde_kms_get_address_space(struct msm_kms *kms,
unsigned int domain)
@@ -1458,7 +1416,6 @@
.enable_vblank = sde_kms_enable_vblank,
.disable_vblank = sde_kms_disable_vblank,
.check_modified_format = sde_format_check_modified_format,
- .atomic_check = sde_kms_atomic_check,
.get_format = sde_get_msm_format,
.round_pixclk = sde_kms_round_pixclk,
.destroy = sde_kms_destroy,
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 6d5c09d..8077756 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -94,25 +94,6 @@
SDE_PLANE_QOS_PANIC_CTRL = BIT(2),
};
-/**
- * enum sde_plane_sclcheck_state - User scaler data status
- *
- * @SDE_PLANE_SCLCHECK_NONE: No user data provided
- * @SDE_PLANE_SCLCHECK_INVALID: Invalid user data provided
- * @SDE_PLANE_SCLCHECK_SCALER_V1: Valid scaler v1 data
- * @SDE_PLANE_SCLCHECK_SCALER_V1_CHECK: Unchecked scaler v1 data
- * @SDE_PLANE_SCLCHECK_SCALER_V2: Valid scaler v2 data
- * @SDE_PLANE_SCLCHECK_SCALER_V2_CHECK: Unchecked scaler v2 data
- */
-enum sde_plane_sclcheck_state {
- SDE_PLANE_SCLCHECK_NONE,
- SDE_PLANE_SCLCHECK_INVALID,
- SDE_PLANE_SCLCHECK_SCALER_V1,
- SDE_PLANE_SCLCHECK_SCALER_V1_CHECK,
- SDE_PLANE_SCLCHECK_SCALER_V2,
- SDE_PLANE_SCLCHECK_SCALER_V2_CHECK,
-};
-
/*
* struct sde_plane - local sde plane structure
* @aspace: address space pointer
@@ -124,7 +105,6 @@
* @sbuf_mode: force stream buffer mode if set
* @sbuf_writeback: force stream buffer writeback if set
* @revalidate: force revalidation of all the plane properties
- * @scaler_check_state: Indicates status of user provided pixle extension data
* @blob_rot_caps: Pointer to rotator capability blob
*/
struct sde_plane {
@@ -140,7 +120,6 @@
struct sde_hw_pipe *pipe_hw;
struct sde_hw_pipe_cfg pipe_cfg;
struct sde_hw_sharp_cfg sharp_cfg;
- struct sde_hw_scaler3_cfg *scaler3_cfg;
struct sde_hw_pipe_qos_cfg pipe_qos_cfg;
uint32_t color_fill;
bool is_error;
@@ -152,9 +131,6 @@
u32 sbuf_writeback;
bool revalidate;
- struct sde_hw_pixel_ext pixel_ext;
- enum sde_plane_sclcheck_state scaler_check_state;
-
struct sde_csc_cfg csc_cfg;
struct sde_csc_cfg *csc_usr_ptr;
struct sde_csc_cfg *csc_ptr;
@@ -972,16 +948,12 @@
struct sde_hw_scaler3_cfg *cfg;
int ret = 0;
- if (!psde || !psde->scaler3_cfg) {
+ if (!psde || !pstate) {
SDE_ERROR("invalid args\n");
return -EINVAL;
- } else if (!pstate) {
- /* pstate is expected to be null on forced color fill */
- SDE_DEBUG("null pstate\n");
- return -EINVAL;
}
- cfg = psde->scaler3_cfg;
+ cfg = &pstate->scaler3_cfg;
cfg->dir_lut = msm_property_get_blob(
&psde->property_info,
@@ -1001,6 +973,7 @@
}
static void _sde_plane_setup_scaler3(struct sde_plane *psde,
+ struct sde_plane_state *pstate,
uint32_t src_w, uint32_t src_h, uint32_t dst_w, uint32_t dst_h,
struct sde_hw_scaler3_cfg *scale_cfg,
const struct sde_format *fmt,
@@ -1008,16 +981,17 @@
{
uint32_t decimated, i;
- if (!psde || !scale_cfg || !fmt || !chroma_subsmpl_h ||
+ if (!psde || !pstate || !scale_cfg || !fmt || !chroma_subsmpl_h ||
!chroma_subsmpl_v) {
- SDE_ERROR("psde %pK scale_cfg %pK fmt %pK smp_h %d smp_v %d\n"
- , psde, scale_cfg, fmt, chroma_subsmpl_h,
+ SDE_ERROR(
+ "psde %d pstate %d scale_cfg %d fmt %d smp_h %d smp_v %d\n",
+ !!psde, !!pstate, !!scale_cfg, !!fmt, chroma_subsmpl_h,
chroma_subsmpl_v);
return;
}
memset(scale_cfg, 0, sizeof(*scale_cfg));
- memset(&psde->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
+ memset(&pstate->pixel_ext, 0, sizeof(struct sde_hw_pixel_ext));
decimated = DECIMATED_DIMENSION(src_w,
psde->pipe_cfg.horz_decimation);
@@ -1055,9 +1029,9 @@
}
scale_cfg->preload_x[i] = SDE_QSEED3_DEFAULT_PRELOAD_H;
scale_cfg->preload_y[i] = SDE_QSEED3_DEFAULT_PRELOAD_V;
- psde->pixel_ext.num_ext_pxls_top[i] =
+ pstate->pixel_ext.num_ext_pxls_top[i] =
scale_cfg->src_height[i];
- psde->pixel_ext.num_ext_pxls_left[i] =
+ pstate->pixel_ext.num_ext_pxls_left[i] =
scale_cfg->src_width[i];
}
if (!(SDE_FORMAT_IS_YUV(fmt)) && (src_h == dst_h)
@@ -1327,19 +1301,19 @@
}
static void _sde_plane_setup_scaler(struct sde_plane *psde,
- const struct sde_format *fmt,
- struct sde_plane_state *pstate)
+ struct sde_plane_state *pstate,
+ const struct sde_format *fmt, bool color_fill)
{
struct sde_hw_pixel_ext *pe;
uint32_t chroma_subsmpl_h, chroma_subsmpl_v;
- if (!psde || !fmt) {
+ if (!psde || !fmt || !pstate) {
SDE_ERROR("invalid arg(s), plane %d fmt %d state %d\n",
psde != 0, fmt != 0, pstate != 0);
return;
}
- pe = &(psde->pixel_ext);
+ pe = &pstate->pixel_ext;
psde->pipe_cfg.horz_decimation =
sde_plane_get_property(pstate, PLANE_PROP_H_DECIMATE);
@@ -1354,23 +1328,25 @@
/* update scaler */
if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
- int error;
+ int rc;
- error = _sde_plane_setup_scaler3_lut(psde, pstate);
- if (error || psde->debugfs_default_scale ||
- psde->scaler_check_state !=
- SDE_PLANE_SCLCHECK_SCALER_V2) {
+ if (!color_fill && !psde->debugfs_default_scale)
+ rc = _sde_plane_setup_scaler3_lut(psde, pstate);
+ else
+ rc = -EINVAL;
+ if (rc || pstate->scaler_check_state !=
+ SDE_PLANE_SCLCHECK_SCALER_V2) {
/* calculate default config for QSEED3 */
- _sde_plane_setup_scaler3(psde,
+ _sde_plane_setup_scaler3(psde, pstate,
psde->pipe_cfg.src_rect.w,
psde->pipe_cfg.src_rect.h,
psde->pipe_cfg.dst_rect.w,
psde->pipe_cfg.dst_rect.h,
- psde->scaler3_cfg, fmt,
+ &pstate->scaler3_cfg, fmt,
chroma_subsmpl_h, chroma_subsmpl_v);
}
- } else if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
- !pstate || psde->debugfs_default_scale) {
+ } else if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V1 ||
+ color_fill || psde->debugfs_default_scale) {
uint32_t deci_dim, i;
/* calculate default configuration for QSEED2 */
@@ -1446,9 +1422,9 @@
{
const struct sde_format *fmt;
const struct drm_plane *plane;
- const struct sde_plane_state *pstate;
+ struct sde_plane_state *pstate;
- if (!psde) {
+ if (!psde || !psde->base.state) {
SDE_ERROR("invalid plane\n");
return -EINVAL;
}
@@ -1480,7 +1456,7 @@
psde->pipe_cfg.src_rect.y = 0;
psde->pipe_cfg.src_rect.w = psde->pipe_cfg.dst_rect.w;
psde->pipe_cfg.src_rect.h = psde->pipe_cfg.dst_rect.h;
- _sde_plane_setup_scaler(psde, fmt, 0);
+ _sde_plane_setup_scaler(psde, pstate, fmt, true);
if (psde->pipe_hw->ops.setup_format)
psde->pipe_hw->ops.setup_format(psde->pipe_hw,
@@ -1494,7 +1470,7 @@
if (psde->pipe_hw->ops.setup_pe)
psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
- &psde->pixel_ext);
+ &pstate->pixel_ext);
}
return 0;
@@ -2860,6 +2836,7 @@
}
static int _sde_plane_validate_scaler_v2(struct sde_plane *psde,
+ struct sde_plane_state *pstate,
const struct sde_format *fmt,
uint32_t img_w, uint32_t img_h,
uint32_t src_w, uint32_t src_h,
@@ -2867,17 +2844,16 @@
{
int i;
- if (!psde || !fmt) {
+ if (!psde || !pstate || !fmt) {
SDE_ERROR_PLANE(psde, "invalid arguments\n");
return -EINVAL;
}
/* don't run checks unless scaler data was changed */
- if (psde->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK ||
- !psde->scaler3_cfg)
+ if (pstate->scaler_check_state != SDE_PLANE_SCLCHECK_SCALER_V2_CHECK)
return 0;
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
+ pstate->scaler_check_state = SDE_PLANE_SCLCHECK_INVALID;
for (i = 0; i < SDE_MAX_PLANES; i++) {
uint32_t hor_req_pixels, hor_fetch_pixels;
@@ -2907,17 +2883,17 @@
src_h_tmp >>= 1;
}
- hor_req_pixels = psde->pixel_ext.roi_w[i];
- vert_req_pixels = psde->pixel_ext.roi_h[i];
+ hor_req_pixels = pstate->pixel_ext.roi_w[i];
+ vert_req_pixels = pstate->pixel_ext.roi_h[i];
hor_fetch_pixels = DECIMATED_DIMENSION(src_w_tmp +
- (int8_t)(psde->pixel_ext.left_ftch[i] & 0xFF) +
- (int8_t)(psde->pixel_ext.right_ftch[i] & 0xFF),
- deci_w);
+ (int8_t)(pstate->pixel_ext.left_ftch[i] & 0xFF) +
+ (int8_t)(pstate->pixel_ext.right_ftch[i] & 0xFF),
+ deci_w);
vert_fetch_pixels = DECIMATED_DIMENSION(src_h_tmp +
- (int8_t)(psde->pixel_ext.top_ftch[i] & 0xFF) +
- (int8_t)(psde->pixel_ext.btm_ftch[i] & 0xFF),
- deci_h);
+ (int8_t)(pstate->pixel_ext.top_ftch[i] & 0xFF) +
+ (int8_t)(pstate->pixel_ext.btm_ftch[i] & 0xFF),
+ deci_h);
if ((hor_req_pixels != hor_fetch_pixels) ||
(hor_fetch_pixels > img_w) ||
@@ -2937,20 +2913,20 @@
* for Y and UV plane
*/
if (i != 3 &&
- (hor_req_pixels != psde->scaler3_cfg->src_width[i] ||
- vert_req_pixels != psde->scaler3_cfg->src_height[i])) {
+ (hor_req_pixels != pstate->scaler3_cfg.src_width[i] ||
+ vert_req_pixels != pstate->scaler3_cfg.src_height[i])) {
SDE_ERROR_PLANE(psde,
"roi[%d] %d/%d, scaler src %dx%d, src %dx%d\n",
- i, psde->pixel_ext.roi_w[i],
- psde->pixel_ext.roi_h[i],
- psde->scaler3_cfg->src_width[i],
- psde->scaler3_cfg->src_height[i],
+ i, pstate->pixel_ext.roi_w[i],
+ pstate->pixel_ext.roi_h[i],
+ pstate->scaler3_cfg.src_width[i],
+ pstate->scaler3_cfg.src_height[i],
src_w, src_h);
return -EINVAL;
}
}
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
+ pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
return 0;
}
@@ -3089,7 +3065,7 @@
"too much scaling requested %ux%u->%ux%u\n",
src_deci_w, src_deci_h, dst.w, dst.h);
ret = -E2BIG;
- } else if (_sde_plane_validate_scaler_v2(psde, fmt,
+ } else if (_sde_plane_validate_scaler_v2(psde, pstate, fmt,
rstate->out_fb_width,
rstate->out_fb_height,
src.w, src.h, deci_w, deci_h)) {
@@ -3388,7 +3364,7 @@
psde->pipe_cfg.src_rect = src;
psde->pipe_cfg.dst_rect = dst;
- _sde_plane_setup_scaler(psde, fmt, pstate);
+ _sde_plane_setup_scaler(psde, pstate, fmt, false);
/* check for color fill */
psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
@@ -3405,7 +3381,7 @@
if (psde->pipe_hw->ops.setup_pe &&
(pstate->multirect_index != SDE_SSPP_RECT_1))
psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
- &psde->pixel_ext);
+ &pstate->pixel_ext);
/**
* when programmed in multirect mode, scalar block will be
@@ -3415,8 +3391,8 @@
if (psde->pipe_hw->ops.setup_scaler &&
pstate->multirect_index != SDE_SSPP_RECT_1)
psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
- &psde->pipe_cfg, &psde->pixel_ext,
- psde->scaler3_cfg);
+ &psde->pipe_cfg, &pstate->pixel_ext,
+ &pstate->scaler3_cfg);
/* update excl rect */
if (psde->pipe_hw->ops.setup_excl_rect)
@@ -3598,6 +3574,29 @@
}
}
+void sde_plane_restore(struct drm_plane *plane)
+{
+ struct sde_plane *psde;
+
+ if (!plane || !plane->state) {
+ SDE_ERROR("invalid plane\n");
+ return;
+ }
+
+ psde = to_sde_plane(plane);
+
+ /*
+ * Revalidate is only true here if idle PC occurred and
+ * there is no plane state update in current commit cycle.
+ */
+ if (!psde->revalidate)
+ return;
+
+ SDE_DEBUG_PLANE(psde, "\n");
+
+ /* last plane state is same as current state */
+ sde_plane_atomic_update(plane, plane->state);
+}
/* helper to install properties which are common to planes and crtcs */
static void _sde_plane_install_properties(struct drm_plane *plane,
@@ -3879,18 +3878,19 @@
psde->csc_usr_ptr = &psde->csc_cfg;
}
-static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde, void *usr)
+static inline void _sde_plane_set_scaler_v1(struct sde_plane *psde,
+ struct sde_plane_state *pstate, void *usr)
{
struct sde_drm_scaler_v1 scale_v1;
struct sde_hw_pixel_ext *pe;
int i;
- if (!psde) {
- SDE_ERROR("invalid plane\n");
+ if (!psde || !pstate) {
+ SDE_ERROR("invalid argument(s)\n");
return;
}
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
+ pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
if (!usr) {
SDE_DEBUG_PLANE(psde, "scale data removed\n");
return;
@@ -3905,7 +3905,7 @@
msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V1);
/* populate from user space */
- pe = &(psde->pixel_ext);
+ pe = &pstate->pixel_ext;
memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
for (i = 0; i < SDE_MAX_PLANES; i++) {
pe->init_phase_x[i] = scale_v1.init_phase_x[i];
@@ -3930,7 +3930,7 @@
pe->roi_h[i] = scale_v1.pe.num_ext_pxls_tb[i];
}
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
+ pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V1;
SDE_EVT32_VERBOSE(DRMID(&psde->base));
SDE_DEBUG_PLANE(psde, "user property data copied\n");
@@ -3944,13 +3944,13 @@
int i;
struct sde_hw_scaler3_cfg *cfg;
- if (!psde || !psde->scaler3_cfg) {
- SDE_ERROR("invalid plane\n");
+ if (!psde || !pstate) {
+ SDE_ERROR("invalid argument(s)\n");
return;
}
- cfg = psde->scaler3_cfg;
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
+ cfg = &pstate->scaler3_cfg;
+ pstate->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
if (!usr) {
SDE_DEBUG_PLANE(psde, "scale data removed\n");
return;
@@ -3971,7 +3971,7 @@
msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V2);
/* populate from user space */
- pe = &(psde->pixel_ext);
+ pe = &pstate->pixel_ext;
memset(pe, 0, sizeof(struct sde_hw_pixel_ext));
cfg->enable = scale_v2.enable;
cfg->dir_en = scale_v2.dir_en;
@@ -4029,7 +4029,7 @@
pe->btm_rpt[i] = scale_v2.pe.btm_rpt[i];
pe->roi_h[i] = scale_v2.pe.num_ext_pxls_tb[i];
}
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
+ pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2_CHECK;
SDE_EVT32_VERBOSE(DRMID(&psde->base), cfg->enable, cfg->de.enable,
cfg->src_width[0], cfg->src_height[0],
@@ -4098,7 +4098,8 @@
_sde_plane_set_csc_v1(psde, (void *)val);
break;
case PLANE_PROP_SCALER_V1:
- _sde_plane_set_scaler_v1(psde, (void *)val);
+ _sde_plane_set_scaler_v1(psde, pstate,
+ (void *)val);
break;
case PLANE_PROP_SCALER_V2:
_sde_plane_set_scaler_v2(psde, pstate,
@@ -4602,7 +4603,6 @@
plane = &psde->base;
psde->pipe = pipe;
psde->is_virtual = (master_plane_id != 0);
- psde->scaler_check_state = SDE_PLANE_SCLCHECK_NONE;
INIT_LIST_HEAD(&psde->mplane_list);
master_plane = drm_plane_find(dev, master_plane_id);
if (master_plane) {
@@ -4631,17 +4631,6 @@
goto clean_sspp;
}
- if (psde->features & BIT(SDE_SSPP_SCALER_QSEED3)) {
- psde->scaler3_cfg = kzalloc(sizeof(struct sde_hw_scaler3_cfg),
- GFP_KERNEL);
- if (!psde->scaler3_cfg) {
- SDE_ERROR("[%u]failed to allocate scale struct\n",
- pipe);
- ret = -ENOMEM;
- goto clean_sspp;
- }
- }
-
format_list = psde->pipe_sblk->format_list;
if (master_plane_id) {
@@ -4711,9 +4700,6 @@
clean_sspp:
if (psde && psde->pipe_hw)
sde_hw_sspp_destroy(psde->pipe_hw);
-
- if (psde && psde->scaler3_cfg)
- kfree(psde->scaler3_cfg);
clean_plane:
kfree(psde);
exit:
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index ccbf005..be0ea67 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -100,6 +100,25 @@
#define SDE_PLANE_DIRTY_ALL 0xFFFFFFFF
/**
+ * enum sde_plane_sclcheck_state - User scaler data status
+ *
+ * @SDE_PLANE_SCLCHECK_NONE: No user data provided
+ * @SDE_PLANE_SCLCHECK_INVALID: Invalid user data provided
+ * @SDE_PLANE_SCLCHECK_SCALER_V1: Valid scaler v1 data
+ * @SDE_PLANE_SCLCHECK_SCALER_V1_CHECK: Unchecked scaler v1 data
+ * @SDE_PLANE_SCLCHECK_SCALER_V2: Valid scaler v2 data
+ * @SDE_PLANE_SCLCHECK_SCALER_V2_CHECK: Unchecked scaler v2 data
+ */
+enum sde_plane_sclcheck_state {
+ SDE_PLANE_SCLCHECK_NONE,
+ SDE_PLANE_SCLCHECK_INVALID,
+ SDE_PLANE_SCLCHECK_SCALER_V1,
+ SDE_PLANE_SCLCHECK_SCALER_V1_CHECK,
+ SDE_PLANE_SCLCHECK_SCALER_V2,
+ SDE_PLANE_SCLCHECK_SCALER_V2_CHECK,
+};
+
+/**
* struct sde_plane_state: Define sde extension of drm plane state object
* @base: base drm plane state object
* @property_values: cached plane property values
@@ -112,6 +131,9 @@
* @multirect_index: index of the rectangle of SSPP
* @multirect_mode: parallel or time multiplex multirect mode
* @pending: whether the current update is still pending
+ * @scaler3_cfg: configuration data for scaler3
+ * @pixel_ext: configuration data for pixel extensions
+ * @scaler_check_state: indicates status of user provided pixel extension data
* @cdp_cfg: CDP configuration
*/
struct sde_plane_state {
@@ -127,6 +149,11 @@
uint32_t multirect_mode;
bool pending;
+ /* scaler configuration */
+ struct sde_hw_scaler3_cfg scaler3_cfg;
+ struct sde_hw_pixel_ext pixel_ext;
+ enum sde_plane_sclcheck_state scaler_check_state;
+
/* @sc_cfg: system_cache configuration */
struct sde_hw_pipe_sc_cfg sc_cfg;
struct sde_plane_rot_state rot;
@@ -190,6 +217,12 @@
bool sde_plane_is_sbuf_mode(struct drm_plane *plane, u32 *prefill);
/**
+ * sde_plane_restore - restore hw state if previously power collapsed
+ * @plane: Pointer to drm plane structure
+ */
+void sde_plane_restore(struct drm_plane *plane);
+
+/**
* sde_plane_flush - final plane operations before commit flush
* @plane: Pointer to drm plane structure
*/
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 242cd64..28a2d4d 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -630,7 +630,7 @@
}
#else
static int sde_power_data_bus_parse(struct platform_device *pdev,
- struct sde_power_data_bus_handle *pdbus)
+ struct sde_power_data_bus_handle *pdbus, const char *name)
{
return 0;
}
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 3333e8a..b75d809 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -115,6 +115,8 @@
MODULE_FIRMWARE("radeon/hainan_smc.bin");
MODULE_FIRMWARE("radeon/hainan_k_smc.bin");
+MODULE_FIRMWARE("radeon/si58_mc.bin");
+
static u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
static void si_pcie_gen3_enable(struct radeon_device *rdev);
static void si_program_aspm(struct radeon_device *rdev);
@@ -1650,6 +1652,7 @@
int err;
int new_fw = 0;
bool new_smc = false;
+ bool si58_fw = false;
DRM_DEBUG("\n");
@@ -1742,6 +1745,10 @@
default: BUG();
}
+ /* this memory configuration requires special firmware */
+ if (((RREG32(MC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
+ si58_fw = true;
+
DRM_INFO("Loading %s Microcode\n", new_chip_name);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
@@ -1845,7 +1852,10 @@
}
}
- snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
+ if (si58_fw)
+ snprintf(fw_name, sizeof(fw_name), "radeon/si58_mc.bin");
+ else
+ snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
index 13db8a2..1f013d4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmdbuf_res.c
@@ -321,6 +321,7 @@
list_for_each_entry_safe(entry, next, &man->list, head)
vmw_cmdbuf_res_free(man, entry);
+ drm_ht_remove(&man->resources);
kfree(man);
}
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index ed0129f..1f97888 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -205,13 +205,16 @@
0x3410, 0x3410, 0x3800, 0x3801,
};
-static const unsigned int a6xx_gmu_registers[] = {
+static const unsigned int a6xx_gmu_gx_registers[] = {
/* GMU GX */
0x1A800, 0x1A800, 0x1A810, 0x1A813, 0x1A816, 0x1A816, 0x1A818, 0x1A81B,
0x1A81E, 0x1A81E, 0x1A820, 0x1A823, 0x1A826, 0x1A826, 0x1A828, 0x1A82B,
0x1A82E, 0x1A82E, 0x1A830, 0x1A833, 0x1A836, 0x1A836, 0x1A838, 0x1A83B,
0x1A83E, 0x1A83E, 0x1A840, 0x1A843, 0x1A846, 0x1A846, 0x1A880, 0x1A884,
0x1A900, 0x1A92B, 0x1A940, 0x1A940,
+};
+
+static const unsigned int a6xx_gmu_registers[] = {
/* GMU TCM */
0x1B400, 0x1C3FF, 0x1C400, 0x1D3FF,
/* GMU CX */
@@ -1321,11 +1324,19 @@
static void a6xx_snapshot_gmu(struct kgsl_device *device,
struct kgsl_snapshot *snapshot)
{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+
if (!kgsl_gmu_isenabled(device))
return;
adreno_snapshot_registers(device, snapshot, a6xx_gmu_registers,
ARRAY_SIZE(a6xx_gmu_registers) / 2);
+
+ if (gpudev->gx_is_on(adreno_dev))
+ adreno_snapshot_registers(device, snapshot,
+ a6xx_gmu_gx_registers,
+ ARRAY_SIZE(a6xx_gmu_gx_registers) / 2);
}
/* a6xx_snapshot_sqe() - Dump SQE data in snapshot */
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 4e67efb..129e99c 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -2225,21 +2225,23 @@
if (fd != 0)
dmabuf = dma_buf_get(fd - 1);
}
- up_read(¤t->mm->mmap_sem);
- if (IS_ERR_OR_NULL(dmabuf))
+ if (IS_ERR_OR_NULL(dmabuf)) {
+ up_read(¤t->mm->mmap_sem);
return dmabuf ? PTR_ERR(dmabuf) : -ENODEV;
+ }
ret = kgsl_setup_dma_buf(device, pagetable, entry, dmabuf);
if (ret) {
dma_buf_put(dmabuf);
+ up_read(¤t->mm->mmap_sem);
return ret;
}
/* Setup the user addr/cache mode for cache operations */
entry->memdesc.useraddr = hostptr;
_setup_cache_mode(entry, vma);
-
+ up_read(¤t->mm->mmap_sem);
return 0;
}
#else
diff --git a/drivers/gpu/msm/kgsl_gmu.c b/drivers/gpu/msm/kgsl_gmu.c
index c9f1483..dff46d2 100644
--- a/drivers/gpu/msm/kgsl_gmu.c
+++ b/drivers/gpu/msm/kgsl_gmu.c
@@ -436,6 +436,7 @@
struct kgsl_device *device = container_of(gmu, struct kgsl_device, gmu);
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
struct adreno_gpudev *gpudev = ADRENO_GPU_DEVICE(adreno_dev);
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
int perf_idx = INVALID_DCVS_IDX, bw_idx = INVALID_DCVS_IDX;
if (gpu_pwrlevel < gmu->num_gpupwrlevels)
@@ -448,6 +449,10 @@
(bw_idx == INVALID_DCVS_IDX))
return -EINVAL;
+ if (bw_idx == INVALID_DCVS_IDX)
+ /* Use default BW, algorithm changes on V2 */
+ bw_idx = pwr->pwrlevels[gpu_pwrlevel].bus_freq;
+
if (ADRENO_QUIRK(adreno_dev, ADRENO_QUIRK_HFI_USE_REG))
return gpudev->rpmh_gpu_pwrctrl(adreno_dev,
GMU_DCVS_NOHFI, perf_idx, bw_idx);
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index b1bce80..8008e06 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -427,6 +427,15 @@
if (ret)
goto out_unlock;
+ /*
+ * The HID over I2C specification states that if a DEVICE needs time
+ * after the PWR_ON request, it should utilise CLOCK stretching.
+ * However, it has been observered that the Windows driver provides a
+ * 1ms sleep between the PWR_ON and RESET requests and that some devices
+ * rely on this.
+ */
+ usleep_range(1000, 5000);
+
i2c_hid_dbg(ihid, "resetting...\n");
ret = i2c_hid_command(client, &hid_reset_cmd, NULL, 0);
diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c
index d0ae889..9e6f443 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-etr.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c
@@ -933,6 +933,7 @@
if (WARN_ON_ONCE(drvdata->config_type != TMC_CONFIG_TYPE_ETR))
return -EINVAL;
+ mutex_lock(&drvdata->mem_lock);
spin_lock_irqsave(&drvdata->spinlock, flags);
if (drvdata->reading) {
ret = -EBUSY;
@@ -964,6 +965,7 @@
drvdata->reading = true;
out:
spin_unlock_irqrestore(&drvdata->spinlock, flags);
+ mutex_unlock(&drvdata->mem_lock);
return ret;
}
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 012c56e..98fcd01 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -142,7 +142,11 @@
{
struct tmc_drvdata *drvdata = container_of(file->private_data,
struct tmc_drvdata, miscdev);
- char *bufp = drvdata->buf + *ppos;
+ char *bufp;
+
+ mutex_lock(&drvdata->mem_lock);
+
+ bufp = drvdata->buf + *ppos;
if (*ppos + len > drvdata->len)
len = drvdata->len - *ppos;
@@ -165,6 +169,7 @@
if (copy_to_user(data, bufp, len)) {
dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+ mutex_unlock(&drvdata->mem_lock);
return -EFAULT;
}
@@ -172,6 +177,8 @@
dev_dbg(drvdata->dev, "%s: %zu bytes copied, %d bytes left\n",
__func__, len, (int)(drvdata->len - *ppos));
+
+ mutex_unlock(&drvdata->mem_lock);
return len;
}
diff --git a/drivers/i2c/busses/i2c-brcmstb.c b/drivers/i2c/busses/i2c-brcmstb.c
index 0652281..78792b4 100644
--- a/drivers/i2c/busses/i2c-brcmstb.c
+++ b/drivers/i2c/busses/i2c-brcmstb.c
@@ -465,6 +465,7 @@
u8 *tmp_buf;
int len = 0;
int xfersz = brcmstb_i2c_get_xfersz(dev);
+ u32 cond, cond_per_msg;
if (dev->is_suspended)
return -EBUSY;
@@ -481,10 +482,11 @@
pmsg->buf ? pmsg->buf[0] : '0', pmsg->len);
if (i < (num - 1) && (msgs[i + 1].flags & I2C_M_NOSTART))
- brcmstb_set_i2c_start_stop(dev, ~(COND_START_STOP));
+ cond = ~COND_START_STOP;
else
- brcmstb_set_i2c_start_stop(dev,
- COND_RESTART | COND_NOSTOP);
+ cond = COND_RESTART | COND_NOSTOP;
+
+ brcmstb_set_i2c_start_stop(dev, cond);
/* Send slave address */
if (!(pmsg->flags & I2C_M_NOSTART)) {
@@ -497,13 +499,24 @@
}
}
+ cond_per_msg = cond;
+
/* Perform data transfer */
while (len) {
bytes_to_xfer = min(len, xfersz);
- if (len <= xfersz && i == (num - 1))
- brcmstb_set_i2c_start_stop(dev,
- ~(COND_START_STOP));
+ if (len <= xfersz) {
+ if (i == (num - 1))
+ cond_per_msg = cond_per_msg &
+ ~(COND_RESTART | COND_NOSTOP);
+ else
+ cond_per_msg = cond;
+ } else {
+ cond_per_msg = (cond_per_msg & ~COND_RESTART) |
+ COND_NOSTOP;
+ }
+
+ brcmstb_set_i2c_start_stop(dev, cond_per_msg);
rc = brcmstb_i2c_xfer_bsc_data(dev, tmp_buf,
bytes_to_xfer, pmsg);
@@ -512,6 +525,8 @@
len -= bytes_to_xfer;
tmp_buf += bytes_to_xfer;
+
+ cond_per_msg = COND_NOSTART | COND_NOSTOP;
}
}
diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c
index 051ab8e..6aa2e36 100644
--- a/drivers/i2c/busses/i2c-qcom-geni.c
+++ b/drivers/i2c/busses/i2c-qcom-geni.c
@@ -123,32 +123,40 @@
static void geni_i2c_err(struct geni_i2c_dev *gi2c, int err)
{
- u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
- u32 rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
- u32 tx_st = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
u32 m_cmd = readl_relaxed(gi2c->base + SE_GENI_M_CMD0);
+ u32 m_stat = readl_relaxed(gi2c->base + SE_GENI_M_IRQ_STATUS);
u32 geni_s = readl_relaxed(gi2c->base + SE_GENI_STATUS);
u32 geni_ios = readl_relaxed(gi2c->base + SE_GENI_IOS);
+ u32 dma = readl_relaxed(gi2c->base + SE_GENI_DMA_MODE_EN);
+ u32 rx_st, tx_st;
+
+ if (gi2c->cur)
+ GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+ "len:%d, slv-addr:0x%x, RD/WR:%d\n", gi2c->cur->len,
+ gi2c->cur->addr, gi2c->cur->flags);
if (err == I2C_NACK || err == GENI_ABORT_DONE) {
GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev, "%s\n",
- gi2c_log[err].msg);
- GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
- "m_stat:0x%x, tx_stat:0x%x, rx_stat:0x%x, ",
- m_stat, tx_st, rx_st);
- GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
- "m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
- m_cmd, geni_s, geni_ios);
+ gi2c_log[err].msg);
+ goto err_ret;
} else {
GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev, "%s\n",
gi2c_log[err].msg);
- GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
- "m_stat:0x%x, tx_stat:0x%x, rx_stat:0x%x, ",
- m_stat, tx_st, rx_st);
- GENI_SE_ERR(gi2c->ipcl, true, gi2c->dev,
+ }
+ if (dma) {
+ rx_st = readl_relaxed(gi2c->base + SE_DMA_RX_IRQ_STAT);
+ tx_st = readl_relaxed(gi2c->base + SE_DMA_TX_IRQ_STAT);
+ } else {
+ rx_st = readl_relaxed(gi2c->base + SE_GENI_RX_FIFO_STATUS);
+ tx_st = readl_relaxed(gi2c->base + SE_GENI_TX_FIFO_STATUS);
+ }
+ GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
+ "DMA:%d tx_stat:0x%x, rx_stat:0x%x, irq-stat:0x%x\n",
+ dma, tx_st, rx_st, m_stat);
+ GENI_SE_DBG(gi2c->ipcl, false, gi2c->dev,
"m_cmd:0x%x, geni_status:0x%x, geni_ios:0x%x\n",
m_cmd, geni_s, geni_ios);
- }
+err_ret:
gi2c->err = gi2c_log[err].err;
}
@@ -185,7 +193,6 @@
if (!dma)
writel_relaxed(0, (gi2c->base +
SE_GENI_TX_WATERMARK_REG));
- gi2c->err = -EIO;
goto irqret;
}
@@ -310,11 +317,12 @@
ret = geni_se_rx_dma_prep(gi2c->wrapper_dev,
gi2c->base, msgs[i].buf,
msgs[i].len, &rx_dma);
- if (ret)
+ if (ret) {
mode = FIFO_MODE;
+ ret = geni_se_select_mode(gi2c->base,
+ mode);
+ }
}
- if (mode == FIFO_MODE)
- geni_se_select_mode(gi2c->base, mode);
} else {
dev_dbg(gi2c->dev,
"WRITE:n:%d,i:%d len:%d, stretch:%d, m_param:0x%x\n",
@@ -327,15 +335,15 @@
ret = geni_se_tx_dma_prep(gi2c->wrapper_dev,
gi2c->base, msgs[i].buf,
msgs[i].len, &tx_dma);
- if (ret)
+ if (ret) {
mode = FIFO_MODE;
+ ret = geni_se_select_mode(gi2c->base,
+ mode);
+ }
}
- if (mode == FIFO_MODE) {
- geni_se_select_mode(gi2c->base, mode);
- /* Get FIFO IRQ */
+ if (mode == FIFO_MODE) /* Get FIFO IRQ */
geni_write_reg(1, gi2c->base,
SE_GENI_TX_WATERMARK_REG);
- }
}
/* Ensure FIFO write go through before waiting for Done evet */
mb();
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
index 71232e5..20ec347 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v1.c
@@ -1267,6 +1267,7 @@
u32 doorbell[2];
doorbell[0] = cons_index & ((hr_cq->cq_depth << 1) - 1);
+ doorbell[1] = 0;
roce_set_bit(doorbell[1], ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_HW_SYNS_S, 1);
roce_set_field(doorbell[1], ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_M,
ROCEE_DB_OTHERS_H_ROCEE_DB_OTH_CMD_S, 3);
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 11a13b5..41800b6 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3857,11 +3857,9 @@
u8 vector, u32 dest_apicid, int devid)
{
struct irte_ga *irte = (struct irte_ga *) entry;
- struct iommu_dev_data *dev_data = search_dev_data(devid);
irte->lo.val = 0;
irte->hi.val = 0;
- irte->lo.fields_remap.guest_mode = dev_data ? dev_data->use_vapic : 0;
irte->lo.fields_remap.int_type = delivery_mode;
irte->lo.fields_remap.dm = dest_mode;
irte->hi.fields.vector = vector;
@@ -3917,10 +3915,10 @@
struct irte_ga *irte = (struct irte_ga *) entry;
struct iommu_dev_data *dev_data = search_dev_data(devid);
- if (!dev_data || !dev_data->use_vapic) {
+ if (!dev_data || !dev_data->use_vapic ||
+ !irte->lo.fields_remap.guest_mode) {
irte->hi.fields.vector = vector;
irte->lo.fields_remap.destination = dest_apicid;
- irte->lo.fields_remap.guest_mode = 0;
modify_irte_ga(devid, index, irte, NULL);
}
}
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index f8ed8c9..a0b4ac6 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -695,9 +695,9 @@
out_unregister:
mmu_notifier_unregister(&pasid_state->mn, mm);
+ mmput(mm);
out_free:
- mmput(mm);
free_pasid_state(pasid_state);
out:
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 2db0d64..d92a352 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -112,8 +112,7 @@
unsigned long lo, hi;
resource_list_for_each_entry(window, &bridge->windows) {
- if (resource_type(window->res) != IORESOURCE_MEM &&
- resource_type(window->res) != IORESOURCE_IO)
+ if (resource_type(window->res) != IORESOURCE_MEM)
continue;
lo = iova_pfn(iovad, window->res->start - window->offset);
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 87fcbf7..002f8a4 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1144,7 +1144,7 @@
if (!dma_pte_present(pte) || dma_pte_superpage(pte))
goto next;
- level_pfn = pfn & level_mask(level - 1);
+ level_pfn = pfn & level_mask(level);
level_pte = phys_to_virt(dma_pte_addr(pte));
if (level > 2)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 6c3f8a2..83cbf20 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -386,36 +386,30 @@
device->dev = dev;
ret = sysfs_create_link(&dev->kobj, &group->kobj, "iommu_group");
- if (ret) {
- kfree(device);
- return ret;
- }
+ if (ret)
+ goto err_free_device;
device->name = kasprintf(GFP_KERNEL, "%s", kobject_name(&dev->kobj));
rename:
if (!device->name) {
- sysfs_remove_link(&dev->kobj, "iommu_group");
- kfree(device);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err_remove_link;
}
ret = sysfs_create_link_nowarn(group->devices_kobj,
&dev->kobj, device->name);
if (ret) {
- kfree(device->name);
if (ret == -EEXIST && i >= 0) {
/*
* Account for the slim chance of collision
* and append an instance to the name.
*/
+ kfree(device->name);
device->name = kasprintf(GFP_KERNEL, "%s.%d",
kobject_name(&dev->kobj), i++);
goto rename;
}
-
- sysfs_remove_link(&dev->kobj, "iommu_group");
- kfree(device);
- return ret;
+ goto err_free_name;
}
kobject_get(group->devices_kobj);
@@ -427,8 +421,10 @@
mutex_lock(&group->mutex);
list_add_tail(&device->list, &group->devices);
if (group->domain)
- __iommu_attach_device(group->domain, dev);
+ ret = __iommu_attach_device(group->domain, dev);
mutex_unlock(&group->mutex);
+ if (ret)
+ goto err_put_group;
/* Notify any listeners about change to group. */
blocking_notifier_call_chain(&group->notifier,
@@ -439,6 +435,21 @@
pr_info("Adding device %s to group %d\n", dev_name(dev), group->id);
return 0;
+
+err_put_group:
+ mutex_lock(&group->mutex);
+ list_del(&device->list);
+ mutex_unlock(&group->mutex);
+ dev->iommu_group = NULL;
+ kobject_put(group->devices_kobj);
+err_free_name:
+ kfree(device->name);
+err_remove_link:
+ sysfs_remove_link(&dev->kobj, "iommu_group");
+err_free_device:
+ kfree(device);
+ pr_err("Failed to add device %s to group %d: %d\n", dev_name(dev), group->id, ret);
+ return ret;
}
EXPORT_SYMBOL_GPL(iommu_group_add_device);
diff --git a/drivers/irqchip/qcom/Kconfig b/drivers/irqchip/qcom/Kconfig
index e4a7a88..b892109 100644
--- a/drivers/irqchip/qcom/Kconfig
+++ b/drivers/irqchip/qcom/Kconfig
@@ -13,3 +13,10 @@
default y if ARCH_SDM845
help
QTI Power Domain Controller for SDM845
+
+config QTI_PDC_SDM670
+ bool "QTI PDC SDM670"
+ select QTI_PDC
+ default y if ARCH_SDM670
+ help
+ QTI Power Domain Controller for SDM670
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
index 1b7856d..5e99040 100644
--- a/drivers/irqchip/qcom/Makefile
+++ b/drivers/irqchip/qcom/Makefile
@@ -1,2 +1,3 @@
obj-$(CONFIG_QTI_PDC) += pdc.o
obj-$(CONFIG_QTI_PDC_SDM845) += pdc-sdm845.o
+obj-$(CONFIG_QTI_PDC_SDM670) += pdc-sdm670.o
diff --git a/drivers/irqchip/qcom/pdc-sdm670.c b/drivers/irqchip/qcom/pdc-sdm670.c
new file mode 100644
index 0000000..7bd6333
--- /dev/null
+++ b/drivers/irqchip/qcom/pdc-sdm670.c
@@ -0,0 +1,139 @@
+/* Copyright (c) 2017, 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/irqchip.h>
+#include "pdc.h"
+
+static struct pdc_pin sdm670_data[] = {
+ {0, 512}, /* rpmh_wake */
+ {1, 513}, /* ee0_apps_hlos_spmi_periph_irq */
+ {2, 514}, /* ee1_apps_trustzone_spmi_periph_irq */
+ {3, 515}, /* secure_wdog_expired */
+ {4, 516}, /* secure_wdog_bark_irq */
+ {5, 517}, /* aop_wdog_expired_irq */
+ {6, 518}, /* qmp_usb3_lfps_rxterm_irq */
+ {7, 519}, /* not-connected */
+ {8, 520}, /* eud_p0_dmse_int_mx */
+ {9, 521}, /* eud_p0_dpse_int_mx */
+ {10, 522}, /* not-connected */
+ {11, 523}, /* not-connected */
+ {12, 524}, /* eud_int_mx[1] */
+ {13, 525}, /* ssc_xpu_irq_summary */
+ {14, 526}, /* wd_bite_apps */
+ {15, 527}, /* ssc_vmidmt_irq_summary */
+ {16, 528}, /* q6ss_irq_out_apps_ipc[4] */
+ {17, 529}, /* not-connected */
+ {18, 530}, /* aoss_pmic_arb_mpu_xpu_summary_irq */
+ {19, 531}, /* apps_pdc_irq_in_19 */
+ {20, 532}, /* apps_pdc_irq_in_20 */
+ {21, 533}, /* apps_pdc_irq_in_21 */
+ {22, 534}, /* pdc_apps_epcb_timeout_summary_irq */
+ {23, 535}, /* spmi_protocol_irq */
+ {24, 536}, /* tsense0_tsense_max_min_int */
+ {25, 537}, /* tsense1_tsense_max_min_int */
+ {26, 538}, /* tsense0_upper_lower_intr */
+ {27, 539}, /* tsense1_upper_lower_intr */
+ {28, 540}, /* tsense0_critical_intr */
+ {29, 541}, /* tsense1_critical_intr */
+ {30, 542}, /* core_bi_px_gpio_1 */
+ {31, 543}, /* core_bi_px_gpio_3 */
+ {32, 544}, /* core_bi_px_gpio_5 */
+ {33, 545}, /* core_bi_px_gpio_10 */
+ {34, 546}, /* core_bi_px_gpio_11 */
+ {35, 547}, /* core_bi_px_gpio_20 */
+ {36, 548}, /* core_bi_px_gpio_22 */
+ {37, 549}, /* core_bi_px_gpio_24 */
+ {38, 550}, /* core_bi_px_gpio_26 */
+ {39, 551}, /* core_bi_px_gpio_30 */
+ {41, 553}, /* core_bi_px_gpio_32 */
+ {42, 554}, /* core_bi_px_gpio_34 */
+ {43, 555}, /* core_bi_px_gpio_36 */
+ {44, 556}, /* core_bi_px_gpio_37 */
+ {45, 557}, /* core_bi_px_gpio_38 */
+ {46, 558}, /* core_bi_px_gpio_39 */
+ {47, 559}, /* core_bi_px_gpio_40 */
+ {49, 561}, /* core_bi_px_gpio_43 */
+ {50, 562}, /* core_bi_px_gpio_44 */
+ {51, 563}, /* core_bi_px_gpio_46 */
+ {52, 564}, /* core_bi_px_gpio_48 */
+ {54, 566}, /* core_bi_px_gpio_52 */
+ {55, 567}, /* core_bi_px_gpio_53 */
+ {56, 568}, /* core_bi_px_gpio_54 */
+ {57, 569}, /* core_bi_px_gpio_56 */
+ {58, 570}, /* core_bi_px_gpio_57 */
+ {59, 571}, /* bi_px_ssc_23 */
+ {60, 572}, /* bi_px_ssc_24 */
+ {61, 573}, /* bi_px_ssc_25 */
+ {62, 574}, /* bi_px_ssc_26 */
+ {63, 575}, /* bi_px_ssc_27 */
+ {64, 576}, /* bi_px_ssc_28 */
+ {65, 577}, /* bi_px_ssc_29 */
+ {66, 578}, /* core_bi_px_gpio_66 */
+ {67, 579}, /* core_bi_px_gpio_68 */
+ {68, 580}, /* bi_px_ssc_20 */
+ {69, 581}, /* bi_px_ssc_30 */
+ {70, 582}, /* core_bi_px_gpio_77 */
+ {71, 583}, /* core_bi_px_gpio_78 */
+ {72, 584}, /* core_bi_px_gpio_79 */
+ {73, 585}, /* core_bi_px_gpio_80 */
+ {74, 586}, /* core_bi_px_gpio_84 */
+ {75, 587}, /* core_bi_px_gpio_85 */
+ {76, 588}, /* core_bi_px_gpio_86 */
+ {77, 589}, /* core_bi_px_gpio_88 */
+ {79, 591}, /* core_bi_px_gpio_91 */
+ {80, 592}, /* core_bi_px_gpio_92 */
+ {81, 593}, /* core_bi_px_gpio_95 */
+ {82, 594}, /* core_bi_px_gpio_96 */
+ {83, 595}, /* core_bi_px_gpio_97 */
+ {84, 596}, /* core_bi_px_gpio_101 */
+ {85, 597}, /* core_bi_px_gpio_103 */
+ {86, 598}, /* bi_px_ssc_22 */
+ {87, 599}, /* core_bi_px_to_mpm[6] */
+ {88, 600}, /* core_bi_px_to_mpm[0] */
+ {89, 601}, /* core_bi_px_to_mpm[1] */
+ {90, 602}, /* core_bi_px_gpio_115 */
+ {91, 603}, /* core_bi_px_gpio_116 */
+ {92, 604}, /* core_bi_px_gpio_117 */
+ {93, 605}, /* core_bi_px_gpio_118 */
+ {94, 641}, /* core_bi_px_gpio_119 */
+ {95, 642}, /* core_bi_px_gpio_120 */
+ {96, 643}, /* core_bi_px_gpio_121 */
+ {97, 644}, /* core_bi_px_gpio_122 */
+ {98, 645}, /* core_bi_px_gpio_123 */
+ {99, 646}, /* core_bi_px_gpio_124 */
+ {100, 647}, /* core_bi_px_gpio_125 */
+ {101, 648}, /* core_bi_px_to_mpm[5] */
+ {102, 649}, /* core_bi_px_gpio_127 */
+ {103, 650}, /* core_bi_px_gpio_128 */
+ {104, 651}, /* core_bi_px_gpio_129 */
+ {105, 652}, /* core_bi_px_gpio_130 */
+ {106, 653}, /* core_bi_px_gpio_132 */
+ {107, 654}, /* core_bi_px_gpio_133 */
+ {108, 655}, /* core_bi_px_gpio_145 */
+ {119, 666}, /* core_bi_px_to_mpm[2] */
+ {120, 667}, /* core_bi_px_to_mpm[3] */
+ {121, 668}, /* core_bi_px_to_mpm[4] */
+ {122, 669}, /* core_bi_px_gpio_41 */
+ {123, 670}, /* core_bi_px_gpio_89 */
+ {124, 671}, /* core_bi_px_gpio_31 */
+ {125, 95}, /* core_bi_px_gpio_49 */
+ {-1}
+};
+
+static int __init qcom_pdc_gic_init(struct device_node *node,
+ struct device_node *parent)
+{
+ return qcom_pdc_init(node, parent, sdm670_data);
+}
+
+IRQCHIP_DECLARE(pdc_sdm670, "qcom,pdc-sdm670", qcom_pdc_gic_init);
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index bde20b4..be91a65 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -909,7 +909,7 @@
/* If we were just busy waiting for TCS, dump the state and return */
if (ret == -EBUSY) {
- pr_info("TCS Busy, retrying RPMH message send\n");
+ pr_info_ratelimited("TCS Busy, retrying RPMH message send\n");
dump_tcs_stats(drv);
ret = -EAGAIN;
}
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index be869a9..0b678b5 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -1095,6 +1095,19 @@
return;
}
+ /*
+ * Increment the unmapped blocks. This prevents a race between the
+ * passdown io and reallocation of freed blocks.
+ */
+ r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
+ if (r) {
+ metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
+ bio_io_error(m->bio);
+ cell_defer_no_holder(tc, m->cell);
+ mempool_free(m, pool->mapping_pool);
+ return;
+ }
+
discard_parent = bio_alloc(GFP_NOIO, 1);
if (!discard_parent) {
DMWARN("%s: unable to allocate top level discard bio for passdown. Skipping passdown.",
@@ -1115,19 +1128,6 @@
end_discard(&op, r);
}
}
-
- /*
- * Increment the unmapped blocks. This prevents a race between the
- * passdown io and reallocation of freed blocks.
- */
- r = dm_pool_inc_data_range(pool->pmd, m->data_block, data_end);
- if (r) {
- metadata_operation_failed(pool, "dm_pool_inc_data_range", r);
- bio_io_error(m->bio);
- cell_defer_no_holder(tc, m->cell);
- mempool_free(m, pool->mapping_pool);
- return;
- }
}
static void process_prepared_discard_passdown_pt2(struct dm_thin_new_mapping *m)
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
index a195c15..df2642c 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_core.c
@@ -2583,6 +2583,7 @@
{
int ret = 0, i;
int usecases;
+ struct device_node *node;
mgr->data_bus.bus_scale_pdata = msm_bus_cl_get_pdata(dev);
if (IS_ERR_OR_NULL(mgr->data_bus.bus_scale_pdata)) {
@@ -2594,12 +2595,27 @@
}
}
- mgr->reg_bus.bus_scale_pdata = &rot_reg_bus_scale_table;
- usecases = mgr->reg_bus.bus_scale_pdata->num_usecases;
- for (i = 0; i < usecases; i++) {
- rot_reg_bus_usecases[i].num_paths = 1;
- rot_reg_bus_usecases[i].vectors =
- &rot_reg_bus_vectors[i];
+ node = of_get_child_by_name(dev->dev.of_node, "qcom,rot-reg-bus");
+ if (node) {
+ mgr->reg_bus.bus_scale_pdata
+ = msm_bus_pdata_from_node(dev, node);
+ if (IS_ERR_OR_NULL(mgr->reg_bus.bus_scale_pdata)) {
+ SDEROT_ERR("reg bus pdata parsing failed\n");
+ ret = PTR_ERR(mgr->reg_bus.bus_scale_pdata);
+ if (!mgr->reg_bus.bus_scale_pdata)
+ ret = -EINVAL;
+ mgr->reg_bus.bus_scale_pdata = NULL;
+ }
+ } else {
+ SDEROT_DBG(
+ "no DT entries, configuring default reg bus table\n");
+ mgr->reg_bus.bus_scale_pdata = &rot_reg_bus_scale_table;
+ usecases = mgr->reg_bus.bus_scale_pdata->num_usecases;
+ for (i = 0; i < usecases; i++) {
+ rot_reg_bus_usecases[i].num_paths = 1;
+ rot_reg_bus_usecases[i].vectors =
+ &rot_reg_bus_vectors[i];
+ }
}
return ret;
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index 9daf053..9f8b341 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -827,6 +827,11 @@
[HAL_VIDEO_DOMAIN_DECODER] = __calculate_decoder,
};
+ if (d->domain >= ARRAY_SIZE(calc)) {
+ dprintk(VIDC_ERR, "%s: invalid domain %d\n",
+ __func__, d->domain);
+ return 0;
+ }
return calc[d->domain](d, gm);
}
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index acca9f4..6e28e70 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -804,6 +804,10 @@
}
bufreq->buffer_count_min =
MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+ bufreq->buffer_count_min_host =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+ bufreq->buffer_count_actual =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
if (msm_comm_get_stream_output_mode(inst) ==
HAL_VIDEO_DECODER_SECONDARY) {
@@ -819,6 +823,10 @@
bufreq->buffer_count_min =
MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS;
+ bufreq->buffer_count_min_host =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+ bufreq->buffer_count_actual =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
bufreq = get_buff_req_buffer(inst,
HAL_BUFFER_OUTPUT2);
@@ -831,6 +839,11 @@
bufreq->buffer_count_min =
MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS;
+ bufreq->buffer_count_min_host =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+ bufreq->buffer_count_actual =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+
} else {
bufreq = get_buff_req_buffer(inst,
@@ -843,6 +856,10 @@
}
bufreq->buffer_count_min =
MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS;
+ bufreq->buffer_count_min_host =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
+ bufreq->buffer_count_actual =
+ MIN_NUM_THUMBNAIL_MODE_OUTPUT_BUFFERS;
}
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index e2ea2bc..90a38bb 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1897,6 +1897,23 @@
vui_timing_info.time_scale = NSEC_PER_SEC;
break;
}
+ case V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE:
+ case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
+ case V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_WIDTH:
+ case V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_HEIGHT:
+ case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_WIDTH:
+ case V4L2_CID_MPEG_VIDC_VIDEO_BLUR_HEIGHT:
+ case V4L2_CID_MPEG_VIDC_VIDEO_LAYER_ID:
+ case V4L2_CID_MPEG_VIDC_VENC_PARAM_LAYER_BITRATE:
+ case V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MIN:
+ case V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MIN:
+ case V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MIN:
+ case V4L2_CID_MPEG_VIDC_VIDEO_I_FRAME_QP_MAX:
+ case V4L2_CID_MPEG_VIDC_VIDEO_P_FRAME_QP_MAX:
+ case V4L2_CID_MPEG_VIDC_VIDEO_B_FRAME_QP_MAX:
+ dprintk(VIDC_DBG, "Set the control : %#x using ext ctrl\n",
+ ctrl->id);
+ break;
default:
dprintk(VIDC_ERR, "Unsupported index: %x\n", ctrl->id);
rc = -ENOTSUPP;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index b645b22..844a4e1 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -131,8 +131,10 @@
struct v4l2_ctrl **cluster = kmalloc(sizeof(struct v4l2_ctrl *) *
num_ctrls, GFP_KERNEL);
- if (!cluster || !inst)
+ if (!cluster || !inst) {
+ kfree(cluster);
return NULL;
+ }
for (c = 0; c < num_ctrls; c++)
cluster[c] = inst->ctrls[c];
@@ -985,16 +987,16 @@
complete(&(core->completions[index]));
}
+static void put_inst_helper(struct kref *kref)
+{
+ struct msm_vidc_inst *inst = container_of(kref,
+ struct msm_vidc_inst, kref);
+
+ msm_vidc_destroy(inst);
+}
+
static void put_inst(struct msm_vidc_inst *inst)
{
- void put_inst_helper(struct kref *kref)
- {
- struct msm_vidc_inst *inst = container_of(kref,
- struct msm_vidc_inst, kref);
-
- msm_vidc_destroy(inst);
- }
-
if (!inst)
return;
@@ -1241,7 +1243,7 @@
if (ctrl) {
v4l2_ctrl_modify_range(ctrl, capability->min,
capability->max, ctrl->step,
- capability->min);
+ ctrl->default_value);
dprintk(VIDC_DBG,
"%s: Updated Range = %lld --> %lld Def value = %lld\n",
ctrl->name, ctrl->minimum, ctrl->maximum,
@@ -1778,6 +1780,12 @@
return;
}
mutex_lock(&inst->outputbufs.lock);
+ if (list_empty(&inst->outputbufs.list)) {
+ dprintk(VIDC_DBG, "%s: no OUTPUT buffers allocated\n",
+ __func__);
+ mutex_unlock(&inst->outputbufs.lock);
+ return;
+ }
list_for_each_entry(binfo, &inst->outputbufs.list, list) {
if (binfo->buffer_ownership != DRIVER) {
dprintk(VIDC_DBG,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 1359515..039b457 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -371,20 +371,20 @@
return 0;
}
+/* A comparator to compare loads (needed later on) */
+static int cmp(const void *a, const void *b)
+{
+ /* want to sort in reverse so flip the comparison */
+ return ((struct allowed_clock_rates_table *)b)->clock_rate -
+ ((struct allowed_clock_rates_table *)a)->clock_rate;
+}
+
static int msm_vidc_load_allowed_clocks_table(
struct msm_vidc_platform_resources *res)
{
int rc = 0;
struct platform_device *pdev = res->pdev;
- /* A comparator to compare loads (needed later on) */
- int cmp(const void *a, const void *b)
- {
- /* want to sort in reverse so flip the comparison */
- return ((struct allowed_clock_rates_table *)b)->clock_rate -
- ((struct allowed_clock_rates_table *)a)->clock_rate;
- }
-
if (!of_find_property(pdev->dev.of_node,
"qcom,allowed-clock-rates", NULL)) {
dprintk(VIDC_DBG, "qcom,allowed-clock-rates not found\n");
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 093f28a..3e9448b 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -479,12 +479,17 @@
struct mmc_devfeq_clk_scaling *clk_scaling;
int err = 0;
int abort;
+ unsigned long pflags = current->flags;
+
+ /* Ensure scaling would happen even in memory pressure conditions */
+ current->flags |= PF_MEMALLOC;
if (!(host && freq)) {
pr_err("%s: unexpected host/freq parameter\n", __func__);
err = -EINVAL;
goto out;
}
+
clk_scaling = &host->clk_scaling;
if (!clk_scaling->enable)
@@ -548,6 +553,7 @@
rel_host:
mmc_release_host(host);
out:
+ tsk_restore_flags(current, pflags, PF_MEMALLOC);
return err;
}
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 9d2424b..d9fab22 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -101,6 +101,9 @@
#define BRCMNAND_MIN_BLOCKSIZE (8 * 1024)
#define BRCMNAND_MIN_DEVSIZE (4ULL * 1024 * 1024)
+#define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY)
+#define NAND_POLL_STATUS_TIMEOUT_MS 100
+
/* Controller feature flags */
enum {
BRCMNAND_HAS_1K_SECTORS = BIT(0),
@@ -765,6 +768,31 @@
CS_SELECT_AUTO_DEVICE_ID_CFG = BIT(30),
};
+static int bcmnand_ctrl_poll_status(struct brcmnand_controller *ctrl,
+ u32 mask, u32 expected_val,
+ unsigned long timeout_ms)
+{
+ unsigned long limit;
+ u32 val;
+
+ if (!timeout_ms)
+ timeout_ms = NAND_POLL_STATUS_TIMEOUT_MS;
+
+ limit = jiffies + msecs_to_jiffies(timeout_ms);
+ do {
+ val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
+ if ((val & mask) == expected_val)
+ return 0;
+
+ cpu_relax();
+ } while (time_after(limit, jiffies));
+
+ dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n",
+ expected_val, val & mask);
+
+ return -ETIMEDOUT;
+}
+
static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
{
u32 val = en ? CS_SELECT_NAND_WP : 0;
@@ -1024,12 +1052,39 @@
if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) {
static int old_wp = -1;
+ int ret;
if (old_wp != wp) {
dev_dbg(ctrl->dev, "WP %s\n", wp ? "on" : "off");
old_wp = wp;
}
+
+ /*
+ * make sure ctrl/flash ready before and after
+ * changing state of #WP pin
+ */
+ ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY |
+ NAND_STATUS_READY,
+ NAND_CTRL_RDY |
+ NAND_STATUS_READY, 0);
+ if (ret)
+ return;
+
brcmnand_set_wp(ctrl, wp);
+ chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+ /* NAND_STATUS_WP 0x00 = protected, 0x80 = not protected */
+ ret = bcmnand_ctrl_poll_status(ctrl,
+ NAND_CTRL_RDY |
+ NAND_STATUS_READY |
+ NAND_STATUS_WP,
+ NAND_CTRL_RDY |
+ NAND_STATUS_READY |
+ (wp ? 0 : NAND_STATUS_WP), 0);
+
+ if (ret)
+ dev_err_ratelimited(&host->pdev->dev,
+ "nand #WP expected %s\n",
+ wp ? "on" : "off");
}
}
@@ -1157,15 +1212,15 @@
static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
{
struct brcmnand_controller *ctrl = host->ctrl;
- u32 intfc;
+ int ret;
dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
BUG_ON(ctrl->cmd_pending != 0);
ctrl->cmd_pending = cmd;
- intfc = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
- WARN_ON(!(intfc & INTFC_CTLR_READY));
+ ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0);
+ WARN_ON(ret);
mb(); /* flush previous writes */
brcmnand_write_reg(ctrl, BRCMNAND_CMD_START,
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
index ca106d4..3424435 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-dev.c
@@ -2825,8 +2825,10 @@
/* Flush Tx queues */
ret = xgbe_flush_tx_queues(pdata);
- if (ret)
+ if (ret) {
+ netdev_err(pdata->netdev, "error flushing TX queues\n");
return ret;
+ }
/*
* Initialize DMA related features
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
index 0f0f3014..1e4e8b2 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-drv.c
@@ -877,7 +877,9 @@
DBGPR("-->xgbe_start\n");
- hw_if->init(pdata);
+ ret = hw_if->init(pdata);
+ if (ret)
+ return ret;
ret = phy_if->phy_start(pdata);
if (ret)
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 5cc0f8c..20e569b 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1097,7 +1097,7 @@
{
#ifdef CONFIG_INET
struct tcphdr *th;
- int len, nw_off, tcp_opt_len;
+ int len, nw_off, tcp_opt_len = 0;
if (tcp_ts)
tcp_opt_len = 12;
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 679679a4..e858b1a 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -48,8 +48,9 @@
struct bgx {
u8 bgx_id;
struct lmac lmac[MAX_LMAC_PER_BGX];
- int lmac_count;
+ u8 lmac_count;
u8 max_lmac;
+ u8 acpi_lmac_idx;
void __iomem *reg_base;
struct pci_dev *pdev;
bool is_dlm;
@@ -1159,13 +1160,13 @@
if (acpi_bus_get_device(handle, &adev))
goto out;
- acpi_get_mac_address(dev, adev, bgx->lmac[bgx->lmac_count].mac);
+ acpi_get_mac_address(dev, adev, bgx->lmac[bgx->acpi_lmac_idx].mac);
- SET_NETDEV_DEV(&bgx->lmac[bgx->lmac_count].netdev, dev);
+ SET_NETDEV_DEV(&bgx->lmac[bgx->acpi_lmac_idx].netdev, dev);
- bgx->lmac[bgx->lmac_count].lmacid = bgx->lmac_count;
+ bgx->lmac[bgx->acpi_lmac_idx].lmacid = bgx->acpi_lmac_idx;
+ bgx->acpi_lmac_idx++; /* move to next LMAC */
out:
- bgx->lmac_count++;
return AE_OK;
}
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c
index 0e74529..30e8550 100644
--- a/drivers/net/ethernet/emulex/benet/be_cmds.c
+++ b/drivers/net/ethernet/emulex/benet/be_cmds.c
@@ -1118,7 +1118,7 @@
err:
mutex_unlock(&adapter->mcc_lock);
- if (status == MCC_STATUS_UNAUTHORIZED_REQUEST)
+ if (base_status(status) == MCC_STATUS_UNAUTHORIZED_REQUEST)
status = -EPERM;
return status;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 9711ca4..b3c9cbe 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -319,6 +319,13 @@
if (ether_addr_equal(addr->sa_data, adapter->dev_mac))
return 0;
+ /* BE3 VFs without FILTMGMT privilege are not allowed to set its MAC
+ * address
+ */
+ if (BEx_chip(adapter) && be_virtfn(adapter) &&
+ !check_privilege(adapter, BE_PRIV_FILTMGMT))
+ return -EPERM;
+
/* if device is not running, copy MAC to netdev->dev_addr */
if (!netif_running(netdev))
goto done;
@@ -3630,7 +3637,11 @@
static void be_disable_if_filters(struct be_adapter *adapter)
{
- be_dev_mac_del(adapter, adapter->pmac_id[0]);
+ /* Don't delete MAC on BE3 VFs without FILTMGMT privilege */
+ if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
+ check_privilege(adapter, BE_PRIV_FILTMGMT))
+ be_dev_mac_del(adapter, adapter->pmac_id[0]);
+
be_clear_uc_list(adapter);
be_clear_mc_list(adapter);
@@ -3783,8 +3794,9 @@
if (status)
return status;
- /* For BE3 VFs, the PF programs the initial MAC address */
- if (!(BEx_chip(adapter) && be_virtfn(adapter))) {
+ /* Don't add MAC on BE3 VFs without FILTMGMT privilege */
+ if (!BEx_chip(adapter) || !be_virtfn(adapter) ||
+ check_privilege(adapter, BE_PRIV_FILTMGMT)) {
status = be_dev_mac_add(adapter, adapter->netdev->dev_addr);
if (status)
return status;
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index d391bee..3f4e711 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -2951,7 +2951,7 @@
}
/* try reuse page */
- if (unlikely(page_count(page) != 1))
+ if (unlikely(page_count(page) != 1 || page_is_pfmemalloc(page)))
return false;
/* change offset to the other half */
diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c
index 03dca73..b375ae9 100644
--- a/drivers/net/ethernet/ibm/ibmveth.c
+++ b/drivers/net/ethernet/ibm/ibmveth.c
@@ -1604,8 +1604,11 @@
netdev->netdev_ops = &ibmveth_netdev_ops;
netdev->ethtool_ops = &netdev_ethtool_ops;
SET_NETDEV_DEV(netdev, &dev->dev);
- netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
- NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
+ netdev->hw_features = NETIF_F_SG;
+ if (vio_get_attribute(dev, "ibm,illan-options", NULL) != NULL) {
+ netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM |
+ NETIF_F_RXCSUM;
+ }
netdev->features |= netdev->hw_features;
diff --git a/drivers/net/ethernet/korina.c b/drivers/net/ethernet/korina.c
index 1799fe1..c051987 100644
--- a/drivers/net/ethernet/korina.c
+++ b/drivers/net/ethernet/korina.c
@@ -900,10 +900,10 @@
DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR,
&lp->rx_dma_regs->dmasm);
- korina_free_ring(dev);
-
napi_disable(&lp->napi);
+ korina_free_ring(dev);
+
if (korina_init(dev) < 0) {
printk(KERN_ERR "%s: cannot restart device\n", dev->name);
return;
@@ -1064,12 +1064,12 @@
tmp = tmp | DMA_STAT_DONE | DMA_STAT_HALT | DMA_STAT_ERR;
writel(tmp, &lp->rx_dma_regs->dmasm);
- korina_free_ring(dev);
-
napi_disable(&lp->napi);
cancel_work_sync(&lp->restart_task);
+ korina_free_ring(dev);
+
free_irq(lp->rx_irq, dev);
free_irq(lp->tx_irq, dev);
free_irq(lp->ovr_irq, dev);
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c
index cd3638e..0509996 100644
--- a/drivers/net/ethernet/mellanox/mlx4/eq.c
+++ b/drivers/net/ethernet/mellanox/mlx4/eq.c
@@ -554,8 +554,9 @@
break;
case MLX4_EVENT_TYPE_SRQ_LIMIT:
- mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT\n",
- __func__);
+ mlx4_dbg(dev, "%s: MLX4_EVENT_TYPE_SRQ_LIMIT. srq_no=0x%x, eq 0x%x\n",
+ __func__, be32_to_cpu(eqe->event.srq.srqn),
+ eq->eqn);
case MLX4_EVENT_TYPE_SRQ_CATAS_ERROR:
if (mlx4_is_master(dev)) {
/* forward only to slave owning the SRQ */
@@ -570,15 +571,19 @@
eq->eqn, eq->cons_index, ret);
break;
}
- mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
- __func__, slave,
- be32_to_cpu(eqe->event.srq.srqn),
- eqe->type, eqe->subtype);
+ if (eqe->type ==
+ MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+ mlx4_warn(dev, "%s: slave:%d, srq_no:0x%x, event: %02x(%02x)\n",
+ __func__, slave,
+ be32_to_cpu(eqe->event.srq.srqn),
+ eqe->type, eqe->subtype);
if (!ret && slave != dev->caps.function) {
- mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
- __func__, eqe->type,
- eqe->subtype, slave);
+ if (eqe->type ==
+ MLX4_EVENT_TYPE_SRQ_CATAS_ERROR)
+ mlx4_warn(dev, "%s: sending event %02x(%02x) to slave:%d\n",
+ __func__, eqe->type,
+ eqe->subtype, slave);
mlx4_slave_event(dev, slave, eqe);
break;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h
index 21ce0b7..6180ad4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -283,13 +283,15 @@
struct mlx5e_rx_am_stats {
int ppms; /* packets per msec */
+ int bpms; /* bytes per msec */
int epms; /* events per msec */
};
struct mlx5e_rx_am_sample {
- ktime_t time;
- unsigned int pkt_ctr;
- u16 event_ctr;
+ ktime_t time;
+ u32 pkt_ctr;
+ u32 byte_ctr;
+ u16 event_ctr;
};
struct mlx5e_rx_am { /* Adaptive Moderation */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
index 3744e2f..da1d73f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
@@ -1183,11 +1183,11 @@
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
- info->tx_types = (BIT(1) << HWTSTAMP_TX_OFF) |
- (BIT(1) << HWTSTAMP_TX_ON);
+ info->tx_types = BIT(HWTSTAMP_TX_OFF) |
+ BIT(HWTSTAMP_TX_ON);
- info->rx_filters = (BIT(1) << HWTSTAMP_FILTER_NONE) |
- (BIT(1) << HWTSTAMP_FILTER_ALL);
+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_ALL);
return 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index d4fa851..ea58234 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -3846,7 +3846,8 @@
return netdev;
err_cleanup_nic:
- profile->cleanup(priv);
+ if (profile->cleanup)
+ profile->cleanup(priv);
free_netdev(netdev);
return NULL;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
index cbfac06..23ccec4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx_am.c
@@ -183,28 +183,27 @@
mlx5e_am_step(am);
}
+#define IS_SIGNIFICANT_DIFF(val, ref) \
+ (((100 * abs((val) - (ref))) / (ref)) > 10) /* more than 10% difference */
+
static int mlx5e_am_stats_compare(struct mlx5e_rx_am_stats *curr,
struct mlx5e_rx_am_stats *prev)
{
- int diff;
-
- if (!prev->ppms)
- return curr->ppms ? MLX5E_AM_STATS_BETTER :
+ if (!prev->bpms)
+ return curr->bpms ? MLX5E_AM_STATS_BETTER :
MLX5E_AM_STATS_SAME;
- diff = curr->ppms - prev->ppms;
- if (((100 * abs(diff)) / prev->ppms) > 10) /* more than 10% diff */
- return (diff > 0) ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_WORSE;
+ if (IS_SIGNIFICANT_DIFF(curr->bpms, prev->bpms))
+ return (curr->bpms > prev->bpms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
- if (!prev->epms)
- return curr->epms ? MLX5E_AM_STATS_WORSE :
- MLX5E_AM_STATS_SAME;
+ if (IS_SIGNIFICANT_DIFF(curr->ppms, prev->ppms))
+ return (curr->ppms > prev->ppms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
- diff = curr->epms - prev->epms;
- if (((100 * abs(diff)) / prev->epms) > 10) /* more than 10% diff */
- return (diff < 0) ? MLX5E_AM_STATS_BETTER :
- MLX5E_AM_STATS_WORSE;
+ if (IS_SIGNIFICANT_DIFF(curr->epms, prev->epms))
+ return (curr->epms < prev->epms) ? MLX5E_AM_STATS_BETTER :
+ MLX5E_AM_STATS_WORSE;
return MLX5E_AM_STATS_SAME;
}
@@ -266,10 +265,13 @@
{
s->time = ktime_get();
s->pkt_ctr = rq->stats.packets;
+ s->byte_ctr = rq->stats.bytes;
s->event_ctr = rq->cq.event_ctr;
}
#define MLX5E_AM_NEVENTS 64
+#define BITS_PER_TYPE(type) (sizeof(type) * BITS_PER_BYTE)
+#define BIT_GAP(bits, end, start) ((((end) - (start)) + BIT_ULL(bits)) & (BIT_ULL(bits) - 1))
static void mlx5e_am_calc_stats(struct mlx5e_rx_am_sample *start,
struct mlx5e_rx_am_sample *end,
@@ -277,13 +279,17 @@
{
/* u32 holds up to 71 minutes, should be enough */
u32 delta_us = ktime_us_delta(end->time, start->time);
- unsigned int npkts = end->pkt_ctr - start->pkt_ctr;
+ u32 npkts = BIT_GAP(BITS_PER_TYPE(u32), end->pkt_ctr, start->pkt_ctr);
+ u32 nbytes = BIT_GAP(BITS_PER_TYPE(u32), end->byte_ctr,
+ start->byte_ctr);
if (!delta_us)
return;
- curr_stats->ppms = (npkts * USEC_PER_MSEC) / delta_us;
- curr_stats->epms = (MLX5E_AM_NEVENTS * USEC_PER_MSEC) / delta_us;
+ curr_stats->ppms = DIV_ROUND_UP(npkts * USEC_PER_MSEC, delta_us);
+ curr_stats->bpms = DIV_ROUND_UP(nbytes * USEC_PER_MSEC, delta_us);
+ curr_stats->epms = DIV_ROUND_UP(MLX5E_AM_NEVENTS * USEC_PER_MSEC,
+ delta_us);
}
void mlx5e_rx_am_work(struct work_struct *work)
@@ -308,7 +314,8 @@
switch (am->state) {
case MLX5E_AM_MEASURE_IN_PROGRESS:
- nevents = rq->cq.event_ctr - am->start_sample.event_ctr;
+ nevents = BIT_GAP(BITS_PER_TYPE(u16), rq->cq.event_ctr,
+ am->start_sample.event_ctr);
if (nevents < MLX5E_AM_NEVENTS)
break;
mlx5e_am_sample(rq, &end_sample);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index d776db7..5bea0bf 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -155,8 +155,9 @@
},
};
-#define FW_INIT_TIMEOUT_MILI 2000
-#define FW_INIT_WAIT_MS 2
+#define FW_INIT_TIMEOUT_MILI 2000
+#define FW_INIT_WAIT_MS 2
+#define FW_PRE_INIT_TIMEOUT_MILI 10000
static int wait_fw_init(struct mlx5_core_dev *dev, u32 max_wait_mili)
{
@@ -956,6 +957,15 @@
*/
dev->state = MLX5_DEVICE_STATE_UP;
+ /* wait for firmware to accept initialization segments configurations
+ */
+ err = wait_fw_init(dev, FW_PRE_INIT_TIMEOUT_MILI);
+ if (err) {
+ dev_err(&dev->pdev->dev, "Firmware over %d MS in pre-initializing state, aborting\n",
+ FW_PRE_INIT_TIMEOUT_MILI);
+ goto out;
+ }
+
err = mlx5_cmd_init(dev);
if (err) {
dev_err(&pdev->dev, "Failed initializing command interface, aborting\n");
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
index 6905630..9e31a33 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
@@ -1178,7 +1178,8 @@
static int
mlxsw_sp_nexthop_group_mac_update(struct mlxsw_sp *mlxsw_sp,
- struct mlxsw_sp_nexthop_group *nh_grp)
+ struct mlxsw_sp_nexthop_group *nh_grp,
+ bool reallocate)
{
u32 adj_index = nh_grp->adj_index; /* base */
struct mlxsw_sp_nexthop *nh;
@@ -1193,7 +1194,7 @@
continue;
}
- if (nh->update) {
+ if (nh->update || reallocate) {
err = mlxsw_sp_nexthop_mac_update(mlxsw_sp,
adj_index, nh);
if (err)
@@ -1254,7 +1255,8 @@
/* Nothing was added or removed, so no need to reallocate. Just
* update MAC on existing adjacency indexes.
*/
- err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+ err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp,
+ false);
if (err) {
dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
goto set_trap;
@@ -1282,7 +1284,7 @@
nh_grp->adj_index_valid = 1;
nh_grp->adj_index = adj_index;
nh_grp->ecmp_size = ecmp_size;
- err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp);
+ err = mlxsw_sp_nexthop_group_mac_update(mlxsw_sp, nh_grp, true);
if (err) {
dev_warn(mlxsw_sp->bus_info->dev, "Failed to update neigh MAC in adjacency table.\n");
goto set_trap;
diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c
index 510ff62..11623aa 100644
--- a/drivers/net/ethernet/renesas/ravb_main.c
+++ b/drivers/net/ethernet/renesas/ravb_main.c
@@ -229,18 +229,6 @@
int ring_size;
int i;
- /* Free RX skb ringbuffer */
- if (priv->rx_skb[q]) {
- for (i = 0; i < priv->num_rx_ring[q]; i++)
- dev_kfree_skb(priv->rx_skb[q][i]);
- }
- kfree(priv->rx_skb[q]);
- priv->rx_skb[q] = NULL;
-
- /* Free aligned TX buffers */
- kfree(priv->tx_align[q]);
- priv->tx_align[q] = NULL;
-
if (priv->rx_ring[q]) {
for (i = 0; i < priv->num_rx_ring[q]; i++) {
struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
@@ -269,6 +257,18 @@
priv->tx_ring[q] = NULL;
}
+ /* Free RX skb ringbuffer */
+ if (priv->rx_skb[q]) {
+ for (i = 0; i < priv->num_rx_ring[q]; i++)
+ dev_kfree_skb(priv->rx_skb[q][i]);
+ }
+ kfree(priv->rx_skb[q]);
+ priv->rx_skb[q] = NULL;
+
+ /* Free aligned TX buffers */
+ kfree(priv->tx_align[q]);
+ priv->tx_align[q] = NULL;
+
/* Free TX skb ringbuffer.
* SKBs are freed by ravb_tx_free() call above.
*/
diff --git a/drivers/net/ethernet/sfc/falcon.c b/drivers/net/ethernet/sfc/falcon.c
index 1a70926..1bfb214 100644
--- a/drivers/net/ethernet/sfc/falcon.c
+++ b/drivers/net/ethernet/sfc/falcon.c
@@ -2801,6 +2801,11 @@
.timer_period_max = 1 << FRF_AB_TC_TIMER_VAL_WIDTH,
.offload_features = NETIF_F_IP_CSUM,
.mcdi_max_ver = -1,
+#ifdef CONFIG_SFC_SRIOV
+ .vswitching_probe = efx_port_dummy_op_int,
+ .vswitching_restore = efx_port_dummy_op_int,
+ .vswitching_remove = efx_port_dummy_op_void,
+#endif
};
const struct efx_nic_type falcon_b0_nic_type = {
@@ -2902,4 +2907,9 @@
.offload_features = NETIF_F_IP_CSUM | NETIF_F_RXHASH | NETIF_F_NTUPLE,
.mcdi_max_ver = -1,
.max_rx_ip_filters = FR_BZ_RX_FILTER_TBL0_ROWS,
+#ifdef CONFIG_SFC_SRIOV
+ .vswitching_probe = efx_port_dummy_op_int,
+ .vswitching_restore = efx_port_dummy_op_int,
+ .vswitching_remove = efx_port_dummy_op_void,
+#endif
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index ac3d39c..890e4b0 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -346,6 +346,7 @@
if (of_phy_is_fixed_link(np))
of_phy_deregister_fixed_link(np);
of_node_put(plat->phy_node);
+ of_node_put(plat->mdio_node);
}
#else
struct plat_stmmacenet_data *
diff --git a/drivers/net/phy/dp83848.c b/drivers/net/phy/dp83848.c
index 800b39f..a10d0e7 100644
--- a/drivers/net/phy/dp83848.c
+++ b/drivers/net/phy/dp83848.c
@@ -17,6 +17,7 @@
#include <linux/phy.h>
#define TI_DP83848C_PHY_ID 0x20005ca0
+#define TI_DP83620_PHY_ID 0x20005ce0
#define NS_DP83848C_PHY_ID 0x20005c90
#define TLK10X_PHY_ID 0x2000a210
#define TI_DP83822_PHY_ID 0x2000a240
@@ -77,6 +78,7 @@
static struct mdio_device_id __maybe_unused dp83848_tbl[] = {
{ TI_DP83848C_PHY_ID, 0xfffffff0 },
{ NS_DP83848C_PHY_ID, 0xfffffff0 },
+ { TI_DP83620_PHY_ID, 0xfffffff0 },
{ TLK10X_PHY_ID, 0xfffffff0 },
{ TI_DP83822_PHY_ID, 0xfffffff0 },
{ }
@@ -106,6 +108,7 @@
static struct phy_driver dp83848_driver[] = {
DP83848_PHY_DRIVER(TI_DP83848C_PHY_ID, "TI DP83848C 10/100 Mbps PHY"),
DP83848_PHY_DRIVER(NS_DP83848C_PHY_ID, "NS DP83848C 10/100 Mbps PHY"),
+ DP83848_PHY_DRIVER(TI_DP83620_PHY_ID, "TI DP83620 10/100 Mbps PHY"),
DP83848_PHY_DRIVER(TLK10X_PHY_ID, "TI TLK10X 10/100 Mbps PHY"),
DP83848_PHY_DRIVER(TI_DP83822_PHY_ID, "TI DP83822 10/100 Mbps PHY"),
};
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index 91177a4..4cad955 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -113,12 +113,16 @@
ret = of_property_read_u32(of_node, "ti,rx-internal-delay",
&dp83867->rx_id_delay);
- if (ret)
+ if (ret &&
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID))
return ret;
ret = of_property_read_u32(of_node, "ti,tx-internal-delay",
&dp83867->tx_id_delay);
- if (ret)
+ if (ret &&
+ (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+ phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID))
return ret;
return of_property_read_u32(of_node, "ti,fifo-depth",
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 2f70f80..c60c147 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -1200,7 +1200,8 @@
int err;
/* Check the fiber mode first */
- if (phydev->supported & SUPPORTED_FIBRE) {
+ if (phydev->supported & SUPPORTED_FIBRE &&
+ phydev->interface != PHY_INTERFACE_MODE_SGMII) {
err = phy_write(phydev, MII_MARVELL_PHY_PAGE, MII_M1111_FIBER);
if (err < 0)
goto error;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index a9be26f..edd30eb 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1384,6 +1384,9 @@
{
int val = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
+ /* Mask prohibited EEE modes */
+ val &= ~phydev->eee_broken_modes;
+
phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, val);
return 0;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 14d57d0..32b555a 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1146,6 +1146,43 @@
}
/**
+ * genphy_config_eee_advert - disable unwanted eee mode advertisement
+ * @phydev: target phy_device struct
+ *
+ * Description: Writes MDIO_AN_EEE_ADV after disabling unsupported energy
+ * efficent ethernet modes. Returns 0 if the PHY's advertisement hasn't
+ * changed, and 1 if it has changed.
+ */
+static int genphy_config_eee_advert(struct phy_device *phydev)
+{
+ int broken = phydev->eee_broken_modes;
+ int old_adv, adv;
+
+ /* Nothing to disable */
+ if (!broken)
+ return 0;
+
+ /* If the following call fails, we assume that EEE is not
+ * supported by the phy. If we read 0, EEE is not advertised
+ * In both case, we don't need to continue
+ */
+ adv = phy_read_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN);
+ if (adv <= 0)
+ return 0;
+
+ old_adv = adv;
+ adv &= ~broken;
+
+ /* Advertising remains unchanged with the broken mask */
+ if (old_adv == adv)
+ return 0;
+
+ phy_write_mmd_indirect(phydev, MDIO_AN_EEE_ADV, MDIO_MMD_AN, adv);
+
+ return 1;
+}
+
+/**
* genphy_setup_forced - configures/forces speed/duplex from @phydev
* @phydev: target phy_device struct
*
@@ -1203,15 +1240,20 @@
*/
int genphy_config_aneg(struct phy_device *phydev)
{
- int result;
+ int err, changed;
+
+ changed = genphy_config_eee_advert(phydev);
if (AUTONEG_ENABLE != phydev->autoneg)
return genphy_setup_forced(phydev);
- result = genphy_config_advert(phydev);
- if (result < 0) /* error */
- return result;
- if (result == 0) {
+ err = genphy_config_advert(phydev);
+ if (err < 0) /* error */
+ return err;
+
+ changed |= err;
+
+ if (changed == 0) {
/* Advertisement hasn't changed, but maybe aneg was never on to
* begin with? Or maybe phy was isolated?
*/
@@ -1221,16 +1263,16 @@
return ctl;
if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
- result = 1; /* do restart aneg */
+ changed = 1; /* do restart aneg */
}
/* Only restart aneg if we are advertising something different
* than we were before.
*/
- if (result > 0)
- result = genphy_restart_aneg(phydev);
+ if (changed > 0)
+ return genphy_restart_aneg(phydev);
- return result;
+ return 0;
}
EXPORT_SYMBOL(genphy_config_aneg);
@@ -1588,6 +1630,33 @@
__set_phy_supported(phydev, max_speed);
}
+static void of_set_phy_eee_broken(struct phy_device *phydev)
+{
+ struct device_node *node = phydev->mdio.dev.of_node;
+ u32 broken = 0;
+
+ if (!IS_ENABLED(CONFIG_OF_MDIO))
+ return;
+
+ if (!node)
+ return;
+
+ if (of_property_read_bool(node, "eee-broken-100tx"))
+ broken |= MDIO_EEE_100TX;
+ if (of_property_read_bool(node, "eee-broken-1000t"))
+ broken |= MDIO_EEE_1000T;
+ if (of_property_read_bool(node, "eee-broken-10gt"))
+ broken |= MDIO_EEE_10GT;
+ if (of_property_read_bool(node, "eee-broken-1000kx"))
+ broken |= MDIO_EEE_1000KX;
+ if (of_property_read_bool(node, "eee-broken-10gkx4"))
+ broken |= MDIO_EEE_10GKX4;
+ if (of_property_read_bool(node, "eee-broken-10gkr"))
+ broken |= MDIO_EEE_10GKR;
+
+ phydev->eee_broken_modes = broken;
+}
+
/**
* phy_probe - probe and init a PHY device
* @dev: device to probe and init
@@ -1625,6 +1694,11 @@
of_set_phy_supported(phydev);
phydev->advertising = phydev->supported;
+ /* Get the EEE modes we want to prohibit. We will ask
+ * the PHY stop advertising these mode later on
+ */
+ of_set_phy_eee_broken(phydev);
+
/* Set the state to READY by default */
phydev->state = PHY_READY;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 7ca9989..1568aed 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -47,8 +47,16 @@
*/
DECLARE_EWMA(pkt_len, 1, 64)
+/* With mergeable buffers we align buffer address and use the low bits to
+ * encode its true size. Buffer size is up to 1 page so we need to align to
+ * square root of page size to ensure we reserve enough bits to encode the true
+ * size.
+ */
+#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2)
+
/* Minimum alignment for mergeable packet buffers. */
-#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, 256)
+#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \
+ 1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT)
#define VIRTNET_DRIVER_VERSION "1.0.0"
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index ee02605..642df93 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -36,12 +36,14 @@
#include <net/addrconf.h>
#include <net/l3mdev.h>
#include <net/fib_rules.h>
+#include <net/netns/generic.h>
#define DRV_NAME "vrf"
#define DRV_VERSION "1.0"
#define FIB_RULE_PREF 1000 /* default preference for FIB rules */
-static bool add_fib_rules = true;
+
+static unsigned int vrf_net_id;
struct net_vrf {
struct rtable __rcu *rth;
@@ -1237,6 +1239,8 @@
struct nlattr *tb[], struct nlattr *data[])
{
struct net_vrf *vrf = netdev_priv(dev);
+ bool *add_fib_rules;
+ struct net *net;
int err;
if (!data || !data[IFLA_VRF_TABLE])
@@ -1252,13 +1256,15 @@
if (err)
goto out;
- if (add_fib_rules) {
+ net = dev_net(dev);
+ add_fib_rules = net_generic(net, vrf_net_id);
+ if (*add_fib_rules) {
err = vrf_add_fib_rules(dev);
if (err) {
unregister_netdevice(dev);
goto out;
}
- add_fib_rules = false;
+ *add_fib_rules = false;
}
out:
@@ -1341,16 +1347,38 @@
.notifier_call = vrf_device_event,
};
+/* Initialize per network namespace state */
+static int __net_init vrf_netns_init(struct net *net)
+{
+ bool *add_fib_rules = net_generic(net, vrf_net_id);
+
+ *add_fib_rules = true;
+
+ return 0;
+}
+
+static struct pernet_operations vrf_net_ops __net_initdata = {
+ .init = vrf_netns_init,
+ .id = &vrf_net_id,
+ .size = sizeof(bool),
+};
+
static int __init vrf_init_module(void)
{
int rc;
register_netdevice_notifier(&vrf_notifier_block);
- rc = rtnl_link_register(&vrf_link_ops);
+ rc = register_pernet_subsys(&vrf_net_ops);
if (rc < 0)
goto error;
+ rc = rtnl_link_register(&vrf_link_ops);
+ if (rc < 0) {
+ unregister_pernet_subsys(&vrf_net_ops);
+ goto error;
+ }
+
return 0;
error:
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c
index 55c4408..963e533 100644
--- a/drivers/net/vxlan.c
+++ b/drivers/net/vxlan.c
@@ -2285,7 +2285,7 @@
= container_of(p, struct vxlan_fdb, hlist);
unsigned long timeout;
- if (f->state & NUD_PERMANENT)
+ if (f->state & (NUD_PERMANENT | NUD_NOARP))
continue;
timeout = f->used + vxlan->cfg.age_interval * HZ;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 78d9966..0f5dde1 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -5913,7 +5913,6 @@
u32 i, j;
u32 total;
u32 chaninfo;
- u32 index;
pbuf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL);
@@ -5961,33 +5960,36 @@
ch.bw == BRCMU_CHAN_BW_80)
continue;
- channel = band->channels;
- index = band->n_channels;
+ channel = NULL;
for (j = 0; j < band->n_channels; j++) {
- if (channel[j].hw_value == ch.control_ch_num) {
- index = j;
+ if (band->channels[j].hw_value == ch.control_ch_num) {
+ channel = &band->channels[j];
break;
}
}
- channel[index].center_freq =
- ieee80211_channel_to_frequency(ch.control_ch_num,
- band->band);
- channel[index].hw_value = ch.control_ch_num;
+ if (!channel) {
+ /* It seems firmware supports some channel we never
+ * considered. Something new in IEEE standard?
+ */
+ brcmf_err("Ignoring unexpected firmware channel %d\n",
+ ch.control_ch_num);
+ continue;
+ }
/* assuming the chanspecs order is HT20,
* HT40 upper, HT40 lower, and VHT80.
*/
if (ch.bw == BRCMU_CHAN_BW_80) {
- channel[index].flags &= ~IEEE80211_CHAN_NO_80MHZ;
+ channel->flags &= ~IEEE80211_CHAN_NO_80MHZ;
} else if (ch.bw == BRCMU_CHAN_BW_40) {
- brcmf_update_bw40_channel_flag(&channel[index], &ch);
+ brcmf_update_bw40_channel_flag(channel, &ch);
} else {
/* enable the channel and disable other bandwidths
* for now as mentioned order assure they are enabled
* for subsequent chanspecs.
*/
- channel[index].flags = IEEE80211_CHAN_NO_HT40 |
- IEEE80211_CHAN_NO_80MHZ;
+ channel->flags = IEEE80211_CHAN_NO_HT40 |
+ IEEE80211_CHAN_NO_80MHZ;
ch.bw = BRCMU_CHAN_BW_20;
cfg->d11inf.encchspec(&ch);
chaninfo = ch.chspec;
@@ -5995,11 +5997,11 @@
&chaninfo);
if (!err) {
if (chaninfo & WL_CHAN_RADAR)
- channel[index].flags |=
+ channel->flags |=
(IEEE80211_CHAN_RADAR |
IEEE80211_CHAN_NO_IR);
if (chaninfo & WL_CHAN_PASSIVE)
- channel[index].flags |=
+ channel->flags |=
IEEE80211_CHAN_NO_IR;
}
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
index 63a051b..bec7d9c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c
@@ -843,8 +843,10 @@
return;
IWL_DEBUG_TEMP(mvm, "Thermal zone device unregister\n");
- thermal_zone_device_unregister(mvm->tz_device.tzone);
- mvm->tz_device.tzone = NULL;
+ if (mvm->tz_device.tzone) {
+ thermal_zone_device_unregister(mvm->tz_device.tzone);
+ mvm->tz_device.tzone = NULL;
+ }
}
static void iwl_mvm_cooling_device_unregister(struct iwl_mvm *mvm)
@@ -853,8 +855,10 @@
return;
IWL_DEBUG_TEMP(mvm, "Cooling device unregister\n");
- thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
- mvm->cooling_dev.cdev = NULL;
+ if (mvm->cooling_dev.cdev) {
+ thermal_cooling_device_unregister(mvm->cooling_dev.cdev);
+ mvm->cooling_dev.cdev = NULL;
+ }
}
#endif /* CONFIG_THERMAL */
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c
index 74dc2bf..b009d79 100644
--- a/drivers/net/xen-netback/interface.c
+++ b/drivers/net/xen-netback/interface.c
@@ -221,18 +221,18 @@
{
struct xenvif *vif = netdev_priv(dev);
struct xenvif_queue *queue = NULL;
- unsigned int num_queues = vif->num_queues;
unsigned long rx_bytes = 0;
unsigned long rx_packets = 0;
unsigned long tx_bytes = 0;
unsigned long tx_packets = 0;
unsigned int index;
+ spin_lock(&vif->lock);
if (vif->queues == NULL)
goto out;
/* Aggregate tx and rx stats from each queue */
- for (index = 0; index < num_queues; ++index) {
+ for (index = 0; index < vif->num_queues; ++index) {
queue = &vif->queues[index];
rx_bytes += queue->stats.rx_bytes;
rx_packets += queue->stats.rx_packets;
@@ -241,6 +241,8 @@
}
out:
+ spin_unlock(&vif->lock);
+
vif->dev->stats.rx_bytes = rx_bytes;
vif->dev->stats.rx_packets = rx_packets;
vif->dev->stats.tx_bytes = tx_bytes;
diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c
index 8674e18..b44f37f 100644
--- a/drivers/net/xen-netback/xenbus.c
+++ b/drivers/net/xen-netback/xenbus.c
@@ -493,11 +493,22 @@
static void backend_disconnect(struct backend_info *be)
{
if (be->vif) {
+ unsigned int queue_index;
+
xen_unregister_watchers(be->vif);
#ifdef CONFIG_DEBUG_FS
xenvif_debugfs_delif(be->vif);
#endif /* CONFIG_DEBUG_FS */
xenvif_disconnect_data(be->vif);
+ for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
+ xenvif_deinit_queue(&be->vif->queues[queue_index]);
+
+ spin_lock(&be->vif->lock);
+ vfree(be->vif->queues);
+ be->vif->num_queues = 0;
+ be->vif->queues = NULL;
+ spin_unlock(&be->vif->lock);
+
xenvif_disconnect_ctrl(be->vif);
}
}
@@ -1040,6 +1051,8 @@
err:
if (be->vif->num_queues > 0)
xenvif_disconnect_data(be->vif); /* Clean up existing queues */
+ for (queue_index = 0; queue_index < be->vif->num_queues; ++queue_index)
+ xenvif_deinit_queue(&be->vif->queues[queue_index]);
vfree(be->vif->queues);
be->vif->queues = NULL;
be->vif->num_queues = 0;
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 0cdcb21..599cf50 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -321,7 +321,7 @@
queue->rx.req_prod_pvt = req_prod;
/* Not enough requests? Try again later. */
- if (req_prod - queue->rx.rsp_cons < NET_RX_SLOTS_MIN) {
+ if (req_prod - queue->rx.sring->req_prod < NET_RX_SLOTS_MIN) {
mod_timer(&queue->rx_refill_timer, jiffies + (HZ/10));
return;
}
diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c
index b480859..3456f53 100644
--- a/drivers/nvdimm/pmem.c
+++ b/drivers/nvdimm/pmem.c
@@ -87,7 +87,9 @@
rc = memcpy_from_pmem(mem + off, pmem_addr, len);
kunmap_atomic(mem);
- return rc;
+ if (rc)
+ return -EIO;
+ return 0;
}
static int pmem_do_bvec(struct pmem_device *pmem, struct page *page,
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 0144376..b40a074 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -353,6 +353,21 @@
return 0;
}
+static void __intel_gpio_set_direction(void __iomem *padcfg0, bool input)
+{
+ u32 value;
+
+ value = readl(padcfg0);
+ if (input) {
+ value &= ~PADCFG0_GPIORXDIS;
+ value |= PADCFG0_GPIOTXDIS;
+ } else {
+ value &= ~PADCFG0_GPIOTXDIS;
+ value |= PADCFG0_GPIORXDIS;
+ }
+ writel(value, padcfg0);
+}
+
static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
struct pinctrl_gpio_range *range,
unsigned pin)
@@ -375,11 +390,11 @@
/* Disable SCI/SMI/NMI generation */
value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
- /* Disable TX buffer and enable RX (this will be input) */
- value &= ~PADCFG0_GPIORXDIS;
- value |= PADCFG0_GPIOTXDIS;
writel(value, padcfg0);
+ /* Disable TX buffer and enable RX (this will be input) */
+ __intel_gpio_set_direction(padcfg0, true);
+
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
return 0;
@@ -392,18 +407,11 @@
struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
void __iomem *padcfg0;
unsigned long flags;
- u32 value;
raw_spin_lock_irqsave(&pctrl->lock, flags);
padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
-
- value = readl(padcfg0);
- if (input)
- value |= PADCFG0_GPIOTXDIS;
- else
- value &= ~PADCFG0_GPIOTXDIS;
- writel(value, padcfg0);
+ __intel_gpio_set_direction(padcfg0, input);
raw_spin_unlock_irqrestore(&pctrl->lock, flags);
diff --git a/drivers/pinctrl/qcom/pinctrl-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpi.c
index fedd5f0..11f954e 100644
--- a/drivers/pinctrl/qcom/pinctrl-lpi.c
+++ b/drivers/pinctrl/qcom/pinctrl-lpi.c
@@ -448,6 +448,7 @@
unsigned int offset,
unsigned int gpio)
{
+ struct lpi_gpio_state *state = gpiochip_get_data(chip);
struct pinctrl_pin_desc pindesc;
struct lpi_gpio_pad *pad;
unsigned int func;
@@ -463,7 +464,7 @@
"pull up"
};
- pctldev = pctldev ? : to_gpio_state(chip)->ctrl;
+ pctldev = pctldev ? : state->ctrl;
pindesc = pctldev->desc->pins[offset];
pad = pctldev->desc->pins[offset].drv_data;
ctl_reg = lpi_gpio_read(pad, LPI_GPIO_REG_DIR_CTL);
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index 23103da..808391f 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -422,7 +422,7 @@
/**
* ipa_cfg_ep_nat() - IPA end-point NAT configuration
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
- * @ipa_ep_cfg: [in] IPA end-point configuration params
+ * @ep_nat: [in] IPA NAT end-point configuration params
*
* Returns: 0 on success, negative on failure
*
@@ -439,6 +439,27 @@
EXPORT_SYMBOL(ipa_cfg_ep_nat);
/**
+* ipa_cfg_ep_conn_track() - IPA end-point IPv6CT configuration
+* @clnt_hdl: [in] opaque client handle assigned by IPA to client
+* @ep_conn_track: [in] IPA IPv6CT end-point configuration params
+*
+* Returns: 0 on success, negative on failure
+*
+* Note: Should not be called from atomic context
+*/
+int ipa_cfg_ep_conn_track(u32 clnt_hdl,
+ const struct ipa_ep_cfg_conn_track *ep_conn_track)
+{
+ int ret;
+
+ IPA_API_DISPATCH_RETURN(ipa_cfg_ep_conn_track, clnt_hdl,
+ ep_conn_track);
+
+ return ret;
+}
+EXPORT_SYMBOL(ipa_cfg_ep_conn_track);
+
+/**
* ipa_cfg_ep_hdr() - IPA end-point header configuration
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
* @ipa_ep_cfg: [in] IPA end-point configuration params
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index bfe1608..d3d4178 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -34,6 +34,9 @@
int (*ipa_cfg_ep_nat)(u32 clnt_hdl,
const struct ipa_ep_cfg_nat *ipa_ep_cfg);
+ int (*ipa_cfg_ep_conn_track)(u32 clnt_hdl,
+ const struct ipa_ep_cfg_conn_track *ipa_ep_cfg);
+
int (*ipa_cfg_ep_hdr)(u32 clnt_hdl,
const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 50804ee..69c83d4 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -26,7 +26,8 @@
log_info.file = __FILENAME__; \
log_info.line = __LINE__; \
log_info.type = EP; \
- log_info.id_string = ipa_clients_strings[client]
+ log_info.id_string = (client < 0 || client >= IPA_CLIENT_MAX) \
+ ? "Invalid Client" : ipa_clients_strings[client]
#define IPA_ACTIVE_CLIENTS_PREP_SIMPLE(log_info) \
log_info.file = __FILENAME__; \
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
index 4b62927..dc27636 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_intf.c
@@ -516,15 +516,15 @@
char __user *start;
struct ipa_push_msg *msg = NULL;
int ret;
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
int locked;
start = buf;
+ add_wait_queue(&ipa_ctx->msg_waitq, &wait);
while (1) {
mutex_lock(&ipa_ctx->msg_lock);
locked = 1;
- prepare_to_wait(&ipa_ctx->msg_waitq, &wait, TASK_INTERRUPTIBLE);
if (!list_empty(&ipa_ctx->msg_list)) {
msg = list_first_entry(&ipa_ctx->msg_list,
struct ipa_push_msg, link);
@@ -576,10 +576,10 @@
locked = 0;
mutex_unlock(&ipa_ctx->msg_lock);
- schedule();
+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}
- finish_wait(&ipa_ctx->msg_waitq, &wait);
+ remove_wait_queue(&ipa_ctx->msg_waitq, &wait);
if (start != buf && ret != -EFAULT)
ret = buf - start;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 1e2b200..a5fb576 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -745,7 +745,7 @@
retval = -EFAULT;
break;
}
- if (ipa4_nat_mdfy_pdn(&mdfy_pdn)) {
+ if (ipa3_nat_mdfy_pdn(&mdfy_pdn)) {
retval = -EFAULT;
break;
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index 2d08767..1af968e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -644,6 +644,12 @@
}
gsi_ep_cfg_ptr = ipa3_get_gsi_ep_info(ep->client);
+ if (gsi_ep_cfg_ptr == NULL) {
+ IPAERR("Error ipa3_get_gsi_ep_info ret NULL\n");
+ result = -EFAULT;
+ goto write_evt_scratch_fail;
+ }
+
params->chan_params.evt_ring_hdl = ep->gsi_evt_ring_hdl;
params->chan_params.ch_id = gsi_ep_cfg_ptr->ipa_gsi_chan_num;
gsi_res = gsi_alloc_channel(¶ms->chan_params, gsi_dev_hdl,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index 5e789af..24c3d62 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -264,6 +264,7 @@
return scnprintf(
dbg_buff, IPA_MAX_MSG_LEN,
"IPA_ENDP_INIT_NAT_%u=0x%x\n"
+ "IPA_ENDP_INIT_CONN_TRACK_n%u=0x%x\n"
"IPA_ENDP_INIT_HDR_%u=0x%x\n"
"IPA_ENDP_INIT_HDR_EXT_%u=0x%x\n"
"IPA_ENDP_INIT_MODE_%u=0x%x\n"
@@ -274,6 +275,7 @@
"IPA_ENDP_INIT_DEAGGR_%u=0x%x\n"
"IPA_ENDP_INIT_CFG_%u=0x%x\n",
pipe, ipahal_read_reg_n(IPA_ENDP_INIT_NAT_n, pipe),
+ pipe, ipahal_read_reg_n(IPA_ENDP_INIT_CONN_TRACK_n, pipe),
pipe, ipahal_read_reg_n(IPA_ENDP_INIT_HDR_n, pipe),
pipe, ipahal_read_reg_n(IPA_ENDP_INIT_HDR_EXT_n, pipe),
pipe, ipahal_read_reg_n(IPA_ENDP_INIT_MODE_n, pipe),
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 6a5ec31..fcb7c72 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -1495,6 +1495,9 @@
int ipa3_cfg_ep_nat(u32 clnt_hdl, const struct ipa_ep_cfg_nat *ipa_ep_cfg);
+int ipa3_cfg_ep_conn_track(u32 clnt_hdl,
+ const struct ipa_ep_cfg_conn_track *ep_conn_track);
+
int ipa3_cfg_ep_hdr(u32 clnt_hdl, const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
int ipa3_cfg_ep_hdr_ext(u32 clnt_hdl,
@@ -1597,7 +1600,7 @@
int ipa3_nat_del_cmd(struct ipa_ioc_v4_nat_del *del);
-int ipa4_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn);
+int ipa3_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn);
/*
* Messaging
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
index da965e7..fe6d245 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_intf.c
@@ -522,17 +522,15 @@
char __user *start;
struct ipa3_push_msg *msg = NULL;
int ret;
- DEFINE_WAIT(wait);
+ DEFINE_WAIT_FUNC(wait, woken_wake_function);
int locked;
start = buf;
+ add_wait_queue(&ipa3_ctx->msg_waitq, &wait);
while (1) {
mutex_lock(&ipa3_ctx->msg_lock);
locked = 1;
- prepare_to_wait(&ipa3_ctx->msg_waitq,
- &wait,
- TASK_INTERRUPTIBLE);
if (!list_empty(&ipa3_ctx->msg_list)) {
msg = list_first_entry(&ipa3_ctx->msg_list,
@@ -585,10 +583,10 @@
locked = 0;
mutex_unlock(&ipa3_ctx->msg_lock);
- schedule();
+ wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
}
- finish_wait(&ipa3_ctx->msg_waitq, &wait);
+ remove_wait_queue(&ipa3_ctx->msg_waitq, &wait);
if (start != buf && ret != -EFAULT)
ret = buf - start;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 0dd86fa..b19ef8b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -191,7 +191,7 @@
static int ipa_mhi_start_gsi_channel(enum ipa_client_type client,
int ipa_ep_idx, struct start_gsi_channel *params)
{
- int res;
+ int res = 0;
struct gsi_evt_ring_props ev_props;
struct ipa_mhi_msi_info *msi;
struct gsi_chan_props ch_props;
@@ -241,7 +241,6 @@
if (res) {
IPA_MHI_ERR("gsi_alloc_evt_ring failed %d\n", res);
goto fail_alloc_evt;
- return res;
}
IPA_MHI_DBG("client %d, caching event ring hdl %lu\n",
client,
@@ -259,7 +258,6 @@
IPA_MHI_ERR("event ring wp is not updated. base=wp=0x%llx\n",
params->ev_ctx_host->wp);
goto fail_alloc_ch;
- return res;
}
IPA_MHI_DBG("Ring event db: evt_ring_hdl=%lu host_wp=0x%llx\n",
@@ -270,7 +268,6 @@
IPA_MHI_ERR("fail to ring evt ring db %d. hdl=%lu wp=0x%llx\n",
res, ep->gsi_evt_ring_hdl, params->ev_ctx_host->wp);
goto fail_alloc_ch;
- return res;
}
memset(&ch_props, 0, sizeof(ch_props));
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
index 6acc4d8..a153f2d 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c
@@ -643,14 +643,14 @@
}
/**
-* ipa4_nat_mdfy_pdn() - Modify a PDN entry in PDN config table in IPA SRAM
+* ipa3_nat_mdfy_pdn() - Modify a PDN entry in PDN config table in IPA SRAM
* @mdfy_pdn: [in] PDN info to be written to SRAM
*
* Called by NAT client driver to modify an entry in the PDN config table
*
* Returns: 0 on success, negative on failure
*/
-int ipa4_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn)
+int ipa3_nat_mdfy_pdn(struct ipa_ioc_nat_pdn_entry *mdfy_pdn)
{
struct ipahal_imm_cmd_dma_shared_mem mem_cmd = { 0 };
struct ipa3_desc desc;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
index 73738bf..80c3996 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c
@@ -1178,10 +1178,13 @@
}
/* clean the QMI msg cache */
+ mutex_lock(&ipa3_qmi_lock);
if (ipa3_qmi_ctx != NULL) {
vfree(ipa3_qmi_ctx);
ipa3_qmi_ctx = NULL;
}
+ mutex_unlock(&ipa3_qmi_lock);
+
ipa3_svc_handle = 0;
ipa3_qmi_modem_init_fin = false;
ipa3_qmi_indication_fin = false;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index edd5b54..11da6b3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -2487,8 +2487,8 @@
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
* @ipa_ep_cfg: [in] IPA end-point configuration params
*
- * This includes nat, header, mode, aggregation and route settings and is a one
- * shot API to configure the IPA end-point fully
+ * This includes nat, IPv6CT, header, mode, aggregation and route settings and
+ * is a one shot API to configure the IPA end-point fully
*
* Returns: 0 on success, negative on failure
*
@@ -2525,6 +2525,13 @@
if (result)
return result;
+ if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
+ result = ipa3_cfg_ep_conn_track(clnt_hdl,
+ &ipa_ep_cfg->conn_track);
+ if (result)
+ return result;
+ }
+
result = ipa3_cfg_ep_mode(clnt_hdl, &ipa_ep_cfg->mode);
if (result)
return result;
@@ -2550,7 +2557,7 @@
return 0;
}
-const char *ipa3_get_nat_en_str(enum ipa_nat_en_type nat_en)
+static const char *ipa3_get_nat_en_str(enum ipa_nat_en_type nat_en)
{
switch (nat_en) {
case (IPA_BYPASS_NAT):
@@ -2564,10 +2571,22 @@
return "undefined";
}
+static const char *ipa3_get_ipv6ct_en_str(enum ipa_ipv6ct_en_type ipv6ct_en)
+{
+ switch (ipv6ct_en) {
+ case (IPA_BYPASS_IPV6CT):
+ return "ipv6ct disabled";
+ case (IPA_ENABLE_IPV6CT):
+ return "ipv6ct enabled";
+ }
+
+ return "undefined";
+}
+
/**
* ipa3_cfg_ep_nat() - IPA end-point NAT configuration
* @clnt_hdl: [in] opaque client handle assigned by IPA to client
- * @ipa_ep_cfg: [in] IPA end-point configuration params
+ * @ep_nat: [in] IPA NAT end-point configuration params
*
* Returns: 0 on success, negative on failure
*
@@ -2605,6 +2624,49 @@
return 0;
}
+/**
+ * ipa3_cfg_ep_conn_track() - IPA end-point IPv6CT configuration
+ * @clnt_hdl: [in] opaque client handle assigned by IPA to client
+ * @ep_conn_track: [in] IPA IPv6CT end-point configuration params
+ *
+ * Returns: 0 on success, negative on failure
+ *
+ * Note: Should not be called from atomic context
+ */
+int ipa3_cfg_ep_conn_track(u32 clnt_hdl,
+ const struct ipa_ep_cfg_conn_track *ep_conn_track)
+{
+ if (clnt_hdl >= ipa3_ctx->ipa_num_pipes ||
+ ipa3_ctx->ep[clnt_hdl].valid == 0 || ep_conn_track == NULL) {
+ IPAERR("bad parm, clnt_hdl = %d , ep_valid = %d\n",
+ clnt_hdl,
+ ipa3_ctx->ep[clnt_hdl].valid);
+ return -EINVAL;
+ }
+
+ if (IPA_CLIENT_IS_CONS(ipa3_ctx->ep[clnt_hdl].client)) {
+ IPAERR("IPv6CT does not apply to IPA out EP %d\n", clnt_hdl);
+ return -EINVAL;
+ }
+
+ IPADBG("pipe=%d, conn_track_en=%d(%s)\n",
+ clnt_hdl,
+ ep_conn_track->conn_track_en,
+ ipa3_get_ipv6ct_en_str(ep_conn_track->conn_track_en));
+
+ /* copy over EP cfg */
+ ipa3_ctx->ep[clnt_hdl].cfg.conn_track = *ep_conn_track;
+
+ IPA_ACTIVE_CLIENTS_INC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+ ipahal_write_reg_n_fields(IPA_ENDP_INIT_CONN_TRACK_n, clnt_hdl,
+ ep_conn_track);
+
+ IPA_ACTIVE_CLIENTS_DEC_EP(ipa3_get_client_mapping(clnt_hdl));
+
+ return 0;
+}
+
/**
* ipa3_cfg_ep_status() - IPA end-point status configuration
@@ -4286,6 +4348,7 @@
api_ctrl->ipa_disable_endpoint = NULL;
api_ctrl->ipa_cfg_ep = ipa3_cfg_ep;
api_ctrl->ipa_cfg_ep_nat = ipa3_cfg_ep_nat;
+ api_ctrl->ipa_cfg_ep_conn_track = ipa3_cfg_ep_conn_track;
api_ctrl->ipa_cfg_ep_hdr = ipa3_cfg_ep_hdr;
api_ctrl->ipa_cfg_ep_hdr_ext = ipa3_cfg_ep_hdr_ext;
api_ctrl->ipa_cfg_ep_mode = ipa3_cfg_ep_mode;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index ae1b989..57d44e3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -45,6 +45,7 @@
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS),
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT),
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_NAT),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT),
};
#define IPAHAL_MEM_ALLOC(__size, __is_atomic_ctx) \
@@ -838,10 +839,13 @@
{
enum ipahal_pkt_status_opcode opcode = 0;
enum ipahal_pkt_status_exception exception_type = 0;
+ bool is_ipv6;
struct ipa_pkt_status_hw *hw_status =
(struct ipa_pkt_status_hw *)unparsed_status;
+ is_ipv6 = (hw_status->status_mask & 0x80) ? false : true;
+
status->pkt_len = hw_status->pkt_len;
status->endp_src_idx = hw_status->endp_src_idx;
status->endp_dest_idx = hw_status->endp_dest_idx;
@@ -933,7 +937,10 @@
exception_type = IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT;
break;
case 64:
- exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
+ if (is_ipv6)
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT;
+ else
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
break;
default:
IPAHAL_ERR("unsupported Status Exception type 0x%x\n",
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 724cdec..0f322b5 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -434,7 +434,12 @@
IPAHAL_PKT_STATUS_EXCEPTION_PACKET_THRESHOLD,
IPAHAL_PKT_STATUS_EXCEPTION_FRAG_RULE_MISS,
IPAHAL_PKT_STATUS_EXCEPTION_SW_FILT,
+ /*
+ * NAT and IPv6CT have the same value at HW.
+ * NAT for IPv4 and IPv6CT for IPv6 exceptions
+ */
IPAHAL_PKT_STATUS_EXCEPTION_NAT,
+ IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT,
IPAHAL_PKT_STATUS_EXCEPTION_MAX,
};
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index af717cd..0dccb5b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -43,6 +43,7 @@
__stringify(IPA_ENDP_INIT_ROUTE_n),
__stringify(IPA_ENDP_INIT_MODE_n),
__stringify(IPA_ENDP_INIT_NAT_n),
+ __stringify(IPA_ENDP_INIT_CONN_TRACK_n),
__stringify(IPA_ENDP_INIT_CTRL_n),
__stringify(IPA_ENDP_INIT_CTRL_SCND_n),
__stringify(IPA_ENDP_INIT_HOL_BLOCK_EN_n),
@@ -724,6 +725,17 @@
IPA_ENDP_INIT_NAT_n_NAT_EN_BMSK);
}
+static void ipareg_construct_endp_init_conn_track_n(enum ipahal_reg_name reg,
+ const void *fields, u32 *val)
+{
+ struct ipa_ep_cfg_conn_track *ep_ipv6ct =
+ (struct ipa_ep_cfg_conn_track *)fields;
+
+ IPA_SETFIELD_IN_REG(*val, ep_ipv6ct->conn_track_en,
+ IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_SHFT,
+ IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_BMSK);
+}
+
static void ipareg_construct_endp_init_mode_n(enum ipahal_reg_name reg,
const void *fields, u32 *val)
{
@@ -1494,6 +1506,10 @@
[IPA_HW_v4_0][IPA_CLKON_CFG] = {
ipareg_construct_dummy, ipareg_parse_dummy,
0x00000044, 0},
+ [IPA_HW_v4_0][IPA_ENDP_INIT_CONN_TRACK_n] = {
+ ipareg_construct_endp_init_conn_track_n,
+ ipareg_parse_dummy,
+ 0x00000850, 0x70},
};
/*
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
index 79e2b9c..3df49ce 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.h
@@ -46,6 +46,7 @@
IPA_ENDP_INIT_ROUTE_n,
IPA_ENDP_INIT_MODE_n,
IPA_ENDP_INIT_NAT_n,
+ IPA_ENDP_INIT_CONN_TRACK_n,
IPA_ENDP_INIT_CTRL_n,
IPA_ENDP_INIT_CTRL_SCND_n,
IPA_ENDP_INIT_HOL_BLOCK_EN_n,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
index 17bad03..664d254 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg_i.h
@@ -118,6 +118,10 @@
#define IPA_ENDP_INIT_NAT_n_NAT_EN_BMSK 0x3
#define IPA_ENDP_INIT_NAT_n_NAT_EN_SHFT 0x0
+/* IPA_ENDP_INIT_CONN_TRACK_n register */
+#define IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_BMSK 0x1
+#define IPA_ENDP_INIT_CONN_TRACK_n_CONN_TRACK_EN_SHFT 0x0
+
/* IPA_ENDP_INIT_CTRL_n register */
#define IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_BMSK 0x1
#define IPA_ENDP_INIT_CTRL_n_ENDP_SUSPEND_SHFT 0x0
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c
index a528e16..e55260d 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.c
+++ b/drivers/platform/msm/seemp_core/seemp_logk.c
@@ -13,6 +13,11 @@
#define pr_fmt(fmt) "seemp: %s: " fmt, __func__
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/seemp_instrumentation.h>
+#include <soc/qcom/scm.h>
+
#include "seemp_logk.h"
#include "seemp_ringbuf.h"
@@ -24,6 +29,8 @@
#define FOUR_MB 4
#define YEAR_BASE 1900
+#define EL2_SCM_ID 0x02001902
+
static struct seemp_logk_dev *slogk_dev;
static unsigned int ring_sz = FOUR_MB;
@@ -49,11 +56,15 @@
static struct seemp_source_mask *pmask;
static unsigned int num_sources;
+static void *el2_shared_mem;
+static struct task_struct *rtic_thread;
+
static long seemp_logk_reserve_rdblks(
struct seemp_logk_dev *sdev, unsigned long arg);
static long seemp_logk_set_mask(unsigned long arg);
static long seemp_logk_set_mapping(unsigned long arg);
static long seemp_logk_check_filter(unsigned long arg);
+static int seemp_logk_rtic_thread(void *data);
void* (*seemp_logk_kernel_begin)(char **buf);
@@ -569,6 +580,15 @@
}
}
+ if (!rtic_thread && el2_shared_mem) {
+ rtic_thread = kthread_run(seemp_logk_rtic_thread,
+ NULL, "seemp_logk_rtic_thread");
+ if (IS_ERR(rtic_thread)) {
+ pr_err("rtic_thread creation failed");
+ rtic_thread = NULL;
+ }
+ }
+
return 0;
}
@@ -580,10 +600,59 @@
.mmap = seemp_logk_mmap,
};
+static int seemp_logk_rtic_thread(void *data)
+{
+ struct el2_report_header_t *header;
+ __u64 last_sequence_number = 0;
+ int last_pos = -1;
+ int i;
+ int num_entries = (PAGE_SIZE - sizeof(struct el2_report_header_t))
+ / sizeof(struct el2_report_data_t);
+ header = (struct el2_report_header_t *) el2_shared_mem;
+
+ while (!kthread_should_stop()) {
+ for (i = 1; i < num_entries + 1; i++) {
+ struct el2_report_data_t *report;
+ int cur_pos = last_pos + i;
+
+ if (cur_pos >= num_entries)
+ cur_pos -= num_entries;
+
+ report = el2_shared_mem +
+ sizeof(struct el2_report_header_t) +
+ cur_pos * sizeof(struct el2_report_data_t);
+
+ /* determine legitimacy of report */
+ if (report->report_valid &&
+ report->sequence_number <=
+ header->num_incidents &&
+ (last_sequence_number == 0
+ || report->sequence_number >
+ last_sequence_number)) {
+ seemp_logk_rtic(report->report_type,
+ report->report.incident.actor,
+ report->report.incident.asset_id,
+ report->report.incident.asset_category,
+ report->report.incident.response);
+ last_sequence_number = report->sequence_number;
+ } else {
+ last_pos = cur_pos - 1;
+ break;
+ }
+ }
+
+ /* periodically check el2 report every second */
+ ssleep(1);
+ }
+
+ return 0;
+}
+
__init int seemp_logk_init(void)
{
int ret;
int devno = 0;
+ struct scm_desc desc = {0};
num_sources = 0;
kmalloc_flag = 0;
@@ -650,6 +719,21 @@
init_waitqueue_head(&slogk_dev->readers_wq);
init_waitqueue_head(&slogk_dev->writers_wq);
rwlock_init(&filter_lock);
+
+ el2_shared_mem = (void *) __get_free_page(GFP_KERNEL);
+ if (el2_shared_mem) {
+ desc.arginfo = SCM_ARGS(2, SCM_RW, SCM_VAL);
+ desc.args[0] = (uint64_t) virt_to_phys(el2_shared_mem);
+ desc.args[1] = PAGE_SIZE;
+ ret = scm_call2(EL2_SCM_ID, &desc);
+ if (ret || desc.ret[0] || desc.ret[1]) {
+ pr_err("SCM call failed with ret val = %d %d %d",
+ ret, (int)desc.ret[0], (int)desc.ret[1]);
+ free_page((unsigned long) el2_shared_mem);
+ el2_shared_mem = NULL;
+ }
+ }
+
return 0;
class_destroy_fail:
class_destroy(cl);
@@ -666,6 +750,11 @@
{
dev_t devno = MKDEV(slogk_dev->major, slogk_dev->minor);
+ if (rtic_thread) {
+ kthread_stop(rtic_thread);
+ rtic_thread = NULL;
+ }
+
seemp_logk_detach();
cdev_del(&slogk_dev->cdev);
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.h b/drivers/platform/msm/seemp_core/seemp_logk.h
index 1a41d4c..871de0e 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.h
+++ b/drivers/platform/msm/seemp_core/seemp_logk.h
@@ -158,4 +158,45 @@
__u32 hash;
bool isOn;
};
+
+/* report region header */
+struct el2_report_header_t {
+ __u64 report_version; /* Version of the EL2 report */
+ __u64 mp_catalog_version;
+ /* Version of MP catalogue used for kernel protection */
+ __u8 protection_enabled; /* Kernel Assets protected by EL2 */
+ __u8 pad1;
+ __u8 pad2;
+ __u8 pad3;
+ __u32 pad4;
+ __u64 num_incidents; /* Number of Incidents Observed by EL2 */
+};
+
+/* individual report contents */
+union el2_report {
+ struct {
+ __u8 asset_id[0x20]; /* Asset Identifier */
+ __u64 actor;
+ /* Actor that caused the Incident. */
+ __u8 asset_category; /* Asset Category */
+ __u8 response; /* Response From EL2 */
+ __u16 pad1;
+ __u32 pad2;
+ } incident;
+ struct {
+ __u64 reserved; /* TBD */
+ } info;
+};
+
+/* individual report */
+struct el2_report_data_t {
+ __u8 report_valid;
+ /* Flag to indicate whether report instance is valid */
+ __u8 report_type; /* Report Type */
+ __u8 pad1;
+ __u8 pad2;
+ __u64 sequence_number; /* Sequence number of the report */
+ union el2_report report; /* Report Contents */
+};
+
#endif
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index a7614fc..2f1615e 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -813,6 +813,7 @@
case 8:
case 7:
case 6:
+ case 1:
ideapad_input_report(priv, vpc_bit);
break;
case 5:
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 8c43c4e..08e1505 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -46,7 +46,7 @@
static char *type_text[] = {
"Unknown", "Battery", "UPS", "Mains", "USB", "USB_DCP",
"USB_CDP", "USB_ACA", "USB_HVDCP", "USB_HVDCP_3", "USB_PD",
- "Wireless", "BMS", "Parallel", "Main", "Wipower",
+ "Wireless", "USB_FLOAT", "BMS", "Parallel", "Main", "Wipower",
"TYPEC", "TYPEC_UFP", "TYPEC_DFP"
};
static char *status_text[] = {
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index 7e6a4e8..cdd09dd 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -51,9 +51,12 @@
#define PROFILE_LOAD "fg_profile_load"
#define DELTA_SOC "fg_delta_soc"
-/* Delta BSOC votable reasons */
+/* Delta BSOC irq votable reasons */
#define DELTA_BSOC_IRQ_VOTER "fg_delta_bsoc_irq"
+/* Battery missing irq votable reasons */
+#define BATT_MISS_IRQ_VOTER "fg_batt_miss_irq"
+
#define DEBUG_PRINT_BUFFER_SIZE 64
/* 3 byte address + 1 space character */
#define ADDR_LEN 4
@@ -361,6 +364,7 @@
struct fg_irq_info *irqs;
struct votable *awake_votable;
struct votable *delta_bsoc_irq_en_votable;
+ struct votable *batt_miss_irq_en_votable;
struct fg_sram_param *sp;
struct fg_alg_flag *alg_flags;
int *debug_mask;
@@ -467,6 +471,7 @@
extern int64_t twos_compliment_extend(int64_t val, int s_bit_pos);
extern s64 fg_float_decode(u16 val);
extern bool is_input_present(struct fg_chip *chip);
+extern bool is_qnovo_en(struct fg_chip *chip);
extern void fg_circ_buf_add(struct fg_circ_buf *buf, int val);
extern void fg_circ_buf_clr(struct fg_circ_buf *buf);
extern int fg_circ_buf_avg(struct fg_circ_buf *buf, int *avg);
diff --git a/drivers/power/supply/qcom/fg-util.c b/drivers/power/supply/qcom/fg-util.c
index 839a771..38d9594 100644
--- a/drivers/power/supply/qcom/fg-util.c
+++ b/drivers/power/supply/qcom/fg-util.c
@@ -106,14 +106,17 @@
static bool is_usb_present(struct fg_chip *chip)
{
union power_supply_propval pval = {0, };
+ int rc;
if (!chip->usb_psy)
chip->usb_psy = power_supply_get_by_name("usb");
- if (chip->usb_psy)
- power_supply_get_property(chip->usb_psy,
- POWER_SUPPLY_PROP_PRESENT, &pval);
- else
+ if (!chip->usb_psy)
+ return false;
+
+ rc = power_supply_get_property(chip->usb_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ if (rc < 0)
return false;
return pval.intval != 0;
@@ -122,14 +125,17 @@
static bool is_dc_present(struct fg_chip *chip)
{
union power_supply_propval pval = {0, };
+ int rc;
if (!chip->dc_psy)
chip->dc_psy = power_supply_get_by_name("dc");
- if (chip->dc_psy)
- power_supply_get_property(chip->dc_psy,
- POWER_SUPPLY_PROP_PRESENT, &pval);
- else
+ if (!chip->dc_psy)
+ return false;
+
+ rc = power_supply_get_property(chip->dc_psy,
+ POWER_SUPPLY_PROP_PRESENT, &pval);
+ if (rc < 0)
return false;
return pval.intval != 0;
@@ -140,6 +146,25 @@
return is_usb_present(chip) || is_dc_present(chip);
}
+bool is_qnovo_en(struct fg_chip *chip)
+{
+ union power_supply_propval pval = {0, };
+ int rc;
+
+ if (!chip->batt_psy)
+ chip->batt_psy = power_supply_get_by_name("battery");
+
+ if (!chip->batt_psy)
+ return false;
+
+ rc = power_supply_get_property(chip->batt_psy,
+ POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &pval);
+ if (rc < 0)
+ return false;
+
+ return pval.intval != 0;
+}
+
#define EXPONENT_SHIFT 11
#define EXPONENT_OFFSET -9
#define MANTISSA_SIGN_BIT 10
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 75e79bb..e5a3a07 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -904,6 +904,7 @@
return ret;
}
+ vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, true, 0);
return rc;
}
@@ -1103,6 +1104,25 @@
fg_dbg(chip, FG_STATUS, "Notified charger on float voltage and FCC\n");
}
+static int fg_batt_miss_irq_en_cb(struct votable *votable, void *data,
+ int enable, const char *client)
+{
+ struct fg_chip *chip = data;
+
+ if (!chip->irqs[BATT_MISSING_IRQ].irq)
+ return 0;
+
+ if (enable) {
+ enable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
+ enable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
+ } else {
+ disable_irq_wake(chip->irqs[BATT_MISSING_IRQ].irq);
+ disable_irq(chip->irqs[BATT_MISSING_IRQ].irq);
+ }
+
+ return 0;
+}
+
static int fg_delta_bsoc_irq_en_cb(struct votable *votable, void *data,
int enable, const char *client)
{
@@ -1402,6 +1422,7 @@
static void fg_cap_learning_update(struct fg_chip *chip)
{
int rc, batt_soc, batt_soc_msb;
+ bool input_present = is_input_present(chip);
mutex_lock(&chip->cl.lock);
@@ -1442,11 +1463,29 @@
chip->cl.init_cc_uah = 0;
}
+ if (chip->charge_status == POWER_SUPPLY_STATUS_DISCHARGING) {
+ if (!input_present) {
+ fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
+ batt_soc_msb);
+ chip->cl.active = false;
+ chip->cl.init_cc_uah = 0;
+ }
+ }
+
if (chip->charge_status == POWER_SUPPLY_STATUS_NOT_CHARGING) {
- fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
- batt_soc_msb);
- chip->cl.active = false;
- chip->cl.init_cc_uah = 0;
+ if (is_qnovo_en(chip) && input_present) {
+ /*
+ * Don't abort the capacity learning when qnovo
+ * is enabled and input is present where the
+ * charging status can go to "not charging"
+ * intermittently.
+ */
+ } else {
+ fg_dbg(chip, FG_CAP_LEARN, "Capacity learning aborted @ battery SOC %d\n",
+ batt_soc_msb);
+ chip->cl.active = false;
+ chip->cl.init_cc_uah = 0;
+ }
}
}
@@ -1981,7 +2020,7 @@
{
union power_supply_propval prop = {0, };
int rc;
- bool parallel_en = false, qnovo_en = false;
+ bool parallel_en = false, qnovo_en;
if (is_parallel_charger_available(chip)) {
rc = power_supply_get_property(chip->parallel_psy,
@@ -1994,10 +2033,7 @@
parallel_en = prop.intval;
}
- rc = power_supply_get_property(chip->batt_psy,
- POWER_SUPPLY_PROP_CHARGE_QNOVO_ENABLE, &prop);
- if (!rc)
- qnovo_en = prop.intval;
+ qnovo_en = is_qnovo_en(chip);
fg_dbg(chip, FG_POWER_SUPPLY, "chg_sts: %d par_en: %d qnov_en: %d esr_fcc_ctrl_en: %d\n",
chip->charge_status, parallel_en, qnovo_en,
@@ -2498,6 +2534,23 @@
int rc;
vote(chip->awake_votable, PROFILE_LOAD, true, 0);
+
+ rc = fg_get_batt_id(chip);
+ if (rc < 0) {
+ pr_err("Error in getting battery id, rc:%d\n", rc);
+ goto out;
+ }
+
+ rc = fg_get_batt_profile(chip);
+ if (rc < 0) {
+ pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
+ chip->batt_id_ohms / 1000, rc);
+ goto out;
+ }
+
+ if (!chip->profile_available)
+ goto out;
+
if (!is_profile_load_required(chip))
goto done;
@@ -2562,9 +2615,9 @@
batt_psy_initialized(chip);
fg_notify_charger(chip);
chip->profile_loaded = true;
- chip->soc_reporting_ready = true;
fg_dbg(chip, FG_STATUS, "profile loaded successfully");
out:
+ chip->soc_reporting_ready = true;
vote(chip->awake_votable, PROFILE_LOAD, false, 0);
}
@@ -3550,20 +3603,6 @@
return IRQ_HANDLED;
}
- rc = fg_get_batt_id(chip);
- if (rc < 0) {
- chip->soc_reporting_ready = true;
- pr_err("Error in getting battery id, rc:%d\n", rc);
- return IRQ_HANDLED;
- }
-
- rc = fg_get_batt_profile(chip);
- if (rc < 0) {
- chip->soc_reporting_ready = true;
- pr_err("Error in getting battery profile, rc:%d\n", rc);
- return IRQ_HANDLED;
- }
-
clear_battery_profile(chip);
schedule_delayed_work(&chip->profile_load_work, 0);
@@ -4330,6 +4369,9 @@
if (chip->delta_bsoc_irq_en_votable)
destroy_votable(chip->delta_bsoc_irq_en_votable);
+ if (chip->batt_miss_irq_en_votable)
+ destroy_votable(chip->batt_miss_irq_en_votable);
+
if (chip->batt_id_chan)
iio_channel_release(chip->batt_id_chan);
@@ -4387,6 +4429,7 @@
chip);
if (IS_ERR(chip->awake_votable)) {
rc = PTR_ERR(chip->awake_votable);
+ chip->awake_votable = NULL;
goto exit;
}
@@ -4395,6 +4438,16 @@
fg_delta_bsoc_irq_en_cb, chip);
if (IS_ERR(chip->delta_bsoc_irq_en_votable)) {
rc = PTR_ERR(chip->delta_bsoc_irq_en_votable);
+ chip->delta_bsoc_irq_en_votable = NULL;
+ goto exit;
+ }
+
+ chip->batt_miss_irq_en_votable = create_votable("FG_BATT_MISS_IRQ",
+ VOTE_SET_ANY,
+ fg_batt_miss_irq_en_cb, chip);
+ if (IS_ERR(chip->batt_miss_irq_en_votable)) {
+ rc = PTR_ERR(chip->batt_miss_irq_en_votable);
+ chip->batt_miss_irq_en_votable = NULL;
goto exit;
}
@@ -4419,19 +4472,6 @@
INIT_DELAYED_WORK(&chip->batt_avg_work, batt_avg_work);
INIT_DELAYED_WORK(&chip->sram_dump_work, sram_dump_work);
- rc = fg_get_batt_id(chip);
- if (rc < 0) {
- pr_err("Error in getting battery id, rc:%d\n", rc);
- goto exit;
- }
-
- rc = fg_get_batt_profile(chip);
- if (rc < 0) {
- chip->soc_reporting_ready = true;
- pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
- chip->batt_id_ohms / 1000, rc);
- }
-
rc = fg_memif_init(chip);
if (rc < 0) {
dev_err(chip->dev, "Error in initializing FG_MEMIF, rc:%d\n",
@@ -4475,12 +4515,15 @@
goto exit;
}
- /* Keep SOC_UPDATE irq disabled until we require it */
+ /* Keep SOC_UPDATE_IRQ disabled until we require it */
if (fg_irqs[SOC_UPDATE_IRQ].irq)
disable_irq_nosync(fg_irqs[SOC_UPDATE_IRQ].irq);
- /* Keep BSOC_DELTA_IRQ irq disabled until we require it */
- rerun_election(chip->delta_bsoc_irq_en_votable);
+ /* Keep BSOC_DELTA_IRQ disabled until we require it */
+ vote(chip->delta_bsoc_irq_en_votable, DELTA_BSOC_IRQ_VOTER, false, 0);
+
+ /* Keep BATT_MISSING_IRQ disabled until we require it */
+ vote(chip->batt_miss_irq_en_votable, BATT_MISS_IRQ_VOTER, false, 0);
rc = fg_debugfs_create(chip);
if (rc < 0) {
@@ -4505,8 +4548,7 @@
}
device_init_wakeup(chip->dev, true);
- if (chip->profile_available)
- schedule_delayed_work(&chip->profile_load_work, 0);
+ schedule_delayed_work(&chip->profile_load_work, 0);
pr_debug("FG GEN3 driver probed successfully\n");
return 0;
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index becce31..e94873c 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -266,6 +266,10 @@
debug_mask, __debug_mask, int, 0600
);
+static int __weak_chg_icl_ua = 500000;
+module_param_named(
+ weak_chg_icl_ua, __weak_chg_icl_ua, int, 0600);
+
#define MICRO_1P5A 1500000
#define MICRO_P1A 100000
#define OTG_DEFAULT_DEGLITCH_TIME_MS 50
@@ -461,6 +465,8 @@
val->intval = 0;
else
val->intval = 1;
+ if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
+ val->intval = 0;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
val->intval = chg->voltage_min_uv;
@@ -1466,15 +1472,6 @@
return rc;
}
- /* configure power role for dual-role */
- rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
- TYPEC_POWER_ROLE_CMD_MASK, 0);
- if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't configure power role for DRP rc=%d\n", rc);
- return rc;
- }
-
/*
* disable Type-C factory mode and stay in Attached.SRC state when VCONN
* over-current happens
@@ -1852,6 +1849,16 @@
static int smb2_post_init(struct smb2 *chip)
{
struct smb_charger *chg = &chip->chg;
+ int rc;
+
+ /* configure power role for dual-role */
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ TYPEC_POWER_ROLE_CMD_MASK, 0);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure power role for DRP rc=%d\n", rc);
+ return rc;
+ }
rerun_election(chg->usb_irq_enable_votable);
@@ -2113,7 +2120,7 @@
[SWITCH_POWER_OK_IRQ] = {
.name = "switcher-power-ok",
.handler = smblib_handle_switcher_power_ok,
- .storm_data = {true, 1000, 3},
+ .storm_data = {true, 1000, 8},
},
};
@@ -2307,6 +2314,7 @@
chg->dev = &pdev->dev;
chg->param = v1_params;
chg->debug_mask = &__debug_mask;
+ chg->weak_chg_icl_ua = &__weak_chg_icl_ua;
chg->mode = PARALLEL_MASTER;
chg->irq_info = smb2_irqs;
chg->name = "PMI";
@@ -2418,7 +2426,11 @@
goto cleanup;
}
- smb2_post_init(chip);
+ rc = smb2_post_init(chip);
+ if (rc < 0) {
+ pr_err("Failed in post init rc=%d\n", rc);
+ goto cleanup;
+ }
smb2_create_debugfs(chip);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 6ead522..ae44f01 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -260,7 +260,7 @@
[FLOAT] = {
.name = "FLOAT",
.bit = FLOAT_CHARGER_BIT,
- .pst = POWER_SUPPLY_TYPE_USB_DCP
+ .pst = POWER_SUPPLY_TYPE_USB_FLOAT
},
[HVDCP2] = {
.name = "HVDCP2",
@@ -629,8 +629,29 @@
static void smblib_uusb_removal(struct smb_charger *chg)
{
int rc;
+ struct smb_irq_data *data;
+ struct storm_watch *wdata;
cancel_delayed_work_sync(&chg->pl_enable_work);
+
+ if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
+ smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
+ rc = regulator_disable(chg->dpdm_reg);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
+ rc);
+ }
+
+ if (chg->wa_flags & BOOST_BACK_WA) {
+ data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
+ if (data) {
+ wdata = &data->storm_data;
+ update_storm_count(wdata, WEAK_CHG_STORM_COUNT);
+ vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
+ vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
+ false, 0);
+ }
+ }
vote(chg->pl_disable_votable, PL_DELAY_VOTER, true, 0);
vote(chg->awake_votable, PL_DELAY_VOTER, false, 0);
@@ -736,7 +757,7 @@
return 0;
}
-static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count)
+static int smblib_get_hw_pulse_cnt(struct smb_charger *chg, int *count)
{
int rc;
u8 val[2];
@@ -770,6 +791,24 @@
return 0;
}
+static int smblib_get_pulse_cnt(struct smb_charger *chg, int *count)
+{
+ int rc;
+
+ /* Use software based pulse count if HW INOV is disabled */
+ if (get_effective_result(chg->hvdcp_hw_inov_dis_votable) > 0) {
+ *count = chg->pulse_cnt;
+ return 0;
+ }
+
+ /* Use h/w pulse count if autonomous mode is enabled */
+ rc = smblib_get_hw_pulse_cnt(chg, count);
+ if (rc < 0)
+ smblib_err(chg, "failed to read h/w pulse count rc=%d\n", rc);
+
+ return rc;
+}
+
#define USBIN_25MA 25000
#define USBIN_100MA 100000
#define USBIN_150MA 150000
@@ -1126,7 +1165,7 @@
* the pulse count register get zeroed when autonomous mode is
* disabled. Track that in variables before disabling
*/
- rc = smblib_get_pulse_cnt(chg, &chg->pulse_cnt);
+ rc = smblib_get_hw_pulse_cnt(chg, &chg->pulse_cnt);
if (rc < 0) {
pr_err("failed to read QC_PULSE_COUNT_STATUS_REG rc=%d\n",
rc);
@@ -2309,7 +2348,6 @@
{
const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
int rc, pulses;
- u8 stat;
val->intval = MICRO_5V;
if (apsd_result == NULL) {
@@ -2319,13 +2357,12 @@
switch (apsd_result->pst) {
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
- rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
+ rc = smblib_get_pulse_cnt(chg, &pulses);
if (rc < 0) {
smblib_err(chg,
"Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
return 0;
}
- pulses = (stat & QC_PULSE_COUNT_MASK);
val->intval = MICRO_5V + HVDCP3_STEP_UV * pulses;
break;
default:
@@ -2830,13 +2867,13 @@
* USB MAIN PSY SETTERS *
************************/
-#define SDP_CURRENT_MA 500000
-#define CDP_CURRENT_MA 1500000
-#define DCP_CURRENT_MA 1500000
-#define HVDCP_CURRENT_MA 3000000
-#define TYPEC_DEFAULT_CURRENT_MA 900000
-#define TYPEC_MEDIUM_CURRENT_MA 1500000
-#define TYPEC_HIGH_CURRENT_MA 3000000
+#define SDP_CURRENT_UA 500000
+#define CDP_CURRENT_UA 1500000
+#define DCP_CURRENT_UA 1500000
+#define HVDCP_CURRENT_UA 3000000
+#define TYPEC_DEFAULT_CURRENT_UA 900000
+#define TYPEC_MEDIUM_CURRENT_UA 1500000
+#define TYPEC_HIGH_CURRENT_UA 3000000
int smblib_get_charge_current(struct smb_charger *chg,
int *total_current_ua)
{
@@ -2870,19 +2907,19 @@
/* QC 2.0/3.0 adapter */
if (apsd_result->bit & (QC_3P0_BIT | QC_2P0_BIT)) {
- *total_current_ua = HVDCP_CURRENT_MA;
+ *total_current_ua = HVDCP_CURRENT_UA;
return 0;
}
if (non_compliant) {
switch (apsd_result->bit) {
case CDP_CHARGER_BIT:
- current_ua = CDP_CURRENT_MA;
+ current_ua = CDP_CURRENT_UA;
break;
case DCP_CHARGER_BIT:
case OCP_CHARGER_BIT:
case FLOAT_CHARGER_BIT:
- current_ua = DCP_CURRENT_MA;
+ current_ua = DCP_CURRENT_UA;
break;
default:
current_ua = 0;
@@ -2897,7 +2934,7 @@
case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
switch (apsd_result->bit) {
case CDP_CHARGER_BIT:
- current_ua = CDP_CURRENT_MA;
+ current_ua = CDP_CURRENT_UA;
break;
case DCP_CHARGER_BIT:
case OCP_CHARGER_BIT:
@@ -2910,10 +2947,10 @@
}
break;
case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
- current_ua = TYPEC_MEDIUM_CURRENT_MA;
+ current_ua = TYPEC_MEDIUM_CURRENT_UA;
break;
case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
- current_ua = TYPEC_HIGH_CURRENT_MA;
+ current_ua = TYPEC_HIGH_CURRENT_UA;
break;
case POWER_SUPPLY_TYPEC_NON_COMPLIANT:
case POWER_SUPPLY_TYPEC_NONE:
@@ -3117,6 +3154,8 @@
int rc;
u8 stat;
bool vbus_rising;
+ struct smb_irq_data *data;
+ struct storm_watch *wdata;
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
@@ -3126,10 +3165,23 @@
vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
- if (vbus_rising)
+ if (vbus_rising) {
smblib_cc2_sink_removal_exit(chg);
- else
+ } else {
smblib_cc2_sink_removal_enter(chg);
+ if (chg->wa_flags & BOOST_BACK_WA) {
+ data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
+ if (data) {
+ wdata = &data->storm_data;
+ update_storm_count(wdata,
+ WEAK_CHG_STORM_COUNT);
+ vote(chg->usb_icl_votable, BOOST_BACK_VOTER,
+ false, 0);
+ vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
+ false, 0);
+ }
+ }
+ }
power_supply_changed(chg->usb_psy);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
@@ -3142,6 +3194,8 @@
int rc;
u8 stat;
bool vbus_rising;
+ struct smb_irq_data *data;
+ struct storm_watch *wdata;
rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
if (rc < 0) {
@@ -3178,8 +3232,18 @@
schedule_delayed_work(&chg->pl_enable_work,
msecs_to_jiffies(PL_DELAY_MS));
} else {
- if (chg->wa_flags & BOOST_BACK_WA)
- vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
+ if (chg->wa_flags & BOOST_BACK_WA) {
+ data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
+ if (data) {
+ wdata = &data->storm_data;
+ update_storm_count(wdata,
+ WEAK_CHG_STORM_COUNT);
+ vote(chg->usb_icl_votable, BOOST_BACK_VOTER,
+ false, 0);
+ vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
+ false, 0);
+ }
+ }
if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
@@ -3302,13 +3366,12 @@
}
if (chg->real_charger_type == POWER_SUPPLY_TYPE_USB_HVDCP_3) {
- rc = smblib_read(chg, QC_PULSE_COUNT_STATUS_REG, &stat);
+ rc = smblib_get_pulse_cnt(chg, &pulses);
if (rc < 0) {
smblib_err(chg,
"Couldn't read QC_PULSE_COUNT rc=%d\n", rc);
return;
}
- pulses = (stat & QC_PULSE_COUNT_MASK);
if (pulses < QC3_PULSES_FOR_6V)
smblib_set_opt_freq_buck(chg,
@@ -3409,8 +3472,29 @@
rising ? "rising" : "falling");
}
+static int get_rp_based_dcp_current(struct smb_charger *chg, int typec_mode)
+{
+ int rp_ua;
+
+ switch (typec_mode) {
+ case POWER_SUPPLY_TYPEC_SOURCE_HIGH:
+ rp_ua = TYPEC_HIGH_CURRENT_UA;
+ break;
+ case POWER_SUPPLY_TYPEC_SOURCE_MEDIUM:
+ case POWER_SUPPLY_TYPEC_SOURCE_DEFAULT:
+ /* fall through */
+ default:
+ rp_ua = DCP_CURRENT_UA;
+ }
+
+ return rp_ua;
+}
+
static void smblib_force_legacy_icl(struct smb_charger *chg, int pst)
{
+ int typec_mode;
+ int rp_ua;
+
/* while PD is active it should have complete ICL control */
if (chg->pd_active)
return;
@@ -3431,7 +3515,10 @@
vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
break;
case POWER_SUPPLY_TYPE_USB_DCP:
- vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, 1500000);
+ case POWER_SUPPLY_TYPE_USB_FLOAT:
+ typec_mode = smblib_get_prop_typec_mode(chg);
+ rp_ua = get_rp_based_dcp_current(chg, typec_mode);
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
break;
case POWER_SUPPLY_TYPE_USB_HVDCP:
case POWER_SUPPLY_TYPE_USB_HVDCP_3:
@@ -3563,9 +3650,30 @@
static void smblib_handle_typec_removal(struct smb_charger *chg)
{
int rc;
+ struct smb_irq_data *data;
+ struct storm_watch *wdata;
chg->cc2_detach_wa_active = false;
+ if (chg->dpdm_reg && regulator_is_enabled(chg->dpdm_reg)) {
+ smblib_dbg(chg, PR_MISC, "disabling DPDM regulator\n");
+ rc = regulator_disable(chg->dpdm_reg);
+ if (rc < 0)
+ smblib_err(chg, "Couldn't disable dpdm regulator rc=%d\n",
+ rc);
+ }
+
+ if (chg->wa_flags & BOOST_BACK_WA) {
+ data = chg->irq_info[SWITCH_POWER_OK_IRQ].irq_data;
+ if (data) {
+ wdata = &data->storm_data;
+ update_storm_count(wdata, WEAK_CHG_STORM_COUNT);
+ vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
+ vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
+ false, 0);
+ }
+ }
+
/* reset APSD voters */
vote(chg->apsd_disable_votable, PD_HARD_RESET_VOTER, false, 0);
vote(chg->apsd_disable_votable, PD_VOTER, false, 0);
@@ -3580,6 +3688,7 @@
vote(chg->usb_icl_votable, DCP_VOTER, false, 0);
vote(chg->usb_icl_votable, PL_USBIN_USBIN_VOTER, false, 0);
vote(chg->usb_icl_votable, SW_QC3_VOTER, false, 0);
+ vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
/* reset hvdcp voters */
vote(chg->hvdcp_disable_votable_indirect, VBUS_CC_SHORT_VOTER, true, 0);
@@ -3695,12 +3804,40 @@
typec_sink_removal(chg);
}
+static void smblib_handle_rp_change(struct smb_charger *chg, int typec_mode)
+{
+ int rp_ua;
+ const struct apsd_result *apsd = smblib_get_apsd_result(chg);
+
+ if ((apsd->pst != POWER_SUPPLY_TYPE_USB_DCP)
+ && (apsd->pst != POWER_SUPPLY_TYPE_USB_FLOAT))
+ return;
+
+ /*
+ * handle Rp change for DCP/FLOAT/OCP.
+ * Update the current only if the Rp is different from
+ * the last Rp value.
+ */
+ smblib_dbg(chg, PR_MISC, "CC change old_mode=%d new_mode=%d\n",
+ chg->typec_mode, typec_mode);
+
+ rp_ua = get_rp_based_dcp_current(chg, typec_mode);
+ vote(chg->usb_icl_votable, LEGACY_UNKNOWN_VOTER, true, rp_ua);
+}
+
static void smblib_handle_typec_cc_state_change(struct smb_charger *chg)
{
+ int typec_mode;
+
if (chg->pr_swap_in_progress)
return;
- chg->typec_mode = smblib_get_prop_typec_mode(chg);
+ typec_mode = smblib_get_prop_typec_mode(chg);
+ if (chg->typec_present && (typec_mode != chg->typec_mode))
+ smblib_handle_rp_change(chg, typec_mode);
+
+ chg->typec_mode = typec_mode;
+
if (!chg->typec_present && chg->typec_mode != POWER_SUPPLY_TYPEC_NONE) {
chg->typec_present = true;
smblib_dbg(chg, PR_MISC, "TypeC %s insertion\n",
@@ -3713,6 +3850,12 @@
smblib_handle_typec_removal(chg);
}
+ /* suspend usb if sink */
+ if (chg->typec_status[3] & UFP_DFP_MODE_STATUS_BIT)
+ vote(chg->usb_icl_votable, OTG_VOTER, true, 0);
+ else
+ vote(chg->usb_icl_votable, OTG_VOTER, false, 0);
+
smblib_dbg(chg, PR_INTERRUPT, "IRQ: cc-state-change; Type-C %s detected\n",
smblib_typec_mode_name[chg->typec_mode]);
}
@@ -3760,6 +3903,12 @@
return IRQ_HANDLED;
}
+ if (chg->pr_swap_in_progress) {
+ smblib_dbg(chg, PR_INTERRUPT,
+ "Ignoring since pr_swap_in_progress\n");
+ return IRQ_HANDLED;
+ }
+
mutex_lock(&chg->lock);
smblib_usb_typec_change(chg);
mutex_unlock(&chg->lock);
@@ -3786,10 +3935,23 @@
return IRQ_HANDLED;
}
+static void smblib_bb_removal_work(struct work_struct *work)
+{
+ struct smb_charger *chg = container_of(work, struct smb_charger,
+ bb_removal_work.work);
+
+ vote(chg->usb_icl_votable, BOOST_BACK_VOTER, false, 0);
+ vote(chg->awake_votable, BOOST_BACK_VOTER, false, 0);
+}
+
+#define BOOST_BACK_UNVOTE_DELAY_MS 750
+#define BOOST_BACK_STORM_COUNT 3
+#define WEAK_CHG_STORM_COUNT 8
irqreturn_t smblib_handle_switcher_power_ok(int irq, void *data)
{
struct smb_irq_data *irq_data = data;
struct smb_charger *chg = irq_data->parent_data;
+ struct storm_watch *wdata = &irq_data->storm_data;
int rc, usb_icl;
u8 stat;
@@ -3811,8 +3973,32 @@
return IRQ_HANDLED;
if (is_storming(&irq_data->storm_data)) {
- smblib_err(chg, "Reverse boost detected: voting 0mA to suspend input\n");
- vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0);
+ /* This could be a weak charger reduce ICL */
+ if (!is_client_vote_enabled(chg->usb_icl_votable,
+ WEAK_CHARGER_VOTER)) {
+ smblib_err(chg,
+ "Weak charger detected: voting %dmA ICL\n",
+ *chg->weak_chg_icl_ua / 1000);
+ vote(chg->usb_icl_votable, WEAK_CHARGER_VOTER,
+ true, *chg->weak_chg_icl_ua);
+ /*
+ * reset storm data and set the storm threshold
+ * to 3 for reverse boost detection.
+ */
+ update_storm_count(wdata, BOOST_BACK_STORM_COUNT);
+ } else {
+ smblib_err(chg,
+ "Reverse boost detected: voting 0mA to suspend input\n");
+ vote(chg->usb_icl_votable, BOOST_BACK_VOTER, true, 0);
+ vote(chg->awake_votable, BOOST_BACK_VOTER, true, 0);
+ /*
+ * Remove the boost-back vote after a delay, to avoid
+ * permanently suspending the input if the boost-back
+ * condition is unintentionally hit.
+ */
+ schedule_delayed_work(&chg->bb_removal_work,
+ msecs_to_jiffies(BOOST_BACK_UNVOTE_DELAY_MS));
+ }
}
return IRQ_HANDLED;
@@ -4467,6 +4653,7 @@
INIT_DELAYED_WORK(&chg->pl_enable_work, smblib_pl_enable_work);
INIT_WORK(&chg->legacy_detection_work, smblib_legacy_detection_work);
INIT_DELAYED_WORK(&chg->uusb_otg_work, smblib_uusb_otg_work);
+ INIT_DELAYED_WORK(&chg->bb_removal_work, smblib_bb_removal_work);
chg->fake_capacity = -EINVAL;
chg->fake_input_current_limited = -EINVAL;
@@ -4522,6 +4709,7 @@
cancel_delayed_work_sync(&chg->pl_enable_work);
cancel_work_sync(&chg->legacy_detection_work);
cancel_delayed_work_sync(&chg->uusb_otg_work);
+ cancel_delayed_work_sync(&chg->bb_removal_work);
power_supply_unreg_notifier(&chg->nb);
smblib_destroy_votables(chg);
qcom_batt_deinit();
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index f39f2c9..5c7819e 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -64,9 +64,13 @@
#define BATT_PROFILE_VOTER "BATT_PROFILE_VOTER"
#define OTG_DELAY_VOTER "OTG_DELAY_VOTER"
#define USBIN_I_VOTER "USBIN_I_VOTER"
+#define WEAK_CHARGER_VOTER "WEAK_CHARGER_VOTER"
+#define OTG_VOTER "OTG_VOTER"
#define VCONN_MAX_ATTEMPTS 3
#define OTG_MAX_ATTEMPTS 3
+#define BOOST_BACK_STORM_COUNT 3
+#define WEAK_CHG_STORM_COUNT 8
enum smb_mode {
PARALLEL_MASTER = 0,
@@ -230,6 +234,7 @@
struct smb_chg_freq chg_freq;
int smb_version;
int otg_delay_ms;
+ int *weak_chg_icl_ua;
/* locks */
struct mutex lock;
@@ -292,6 +297,7 @@
struct delayed_work pl_enable_work;
struct work_struct legacy_detection_work;
struct delayed_work uusb_otg_work;
+ struct delayed_work bb_removal_work;
/* cached status */
int voltage_min_uv;
diff --git a/drivers/power/supply/qcom/storm-watch.c b/drivers/power/supply/qcom/storm-watch.c
index 5275079..21ac669 100644
--- a/drivers/power/supply/qcom/storm-watch.c
+++ b/drivers/power/supply/qcom/storm-watch.c
@@ -64,3 +64,13 @@
data->storm_count = 0;
mutex_unlock(&data->storm_lock);
}
+
+void update_storm_count(struct storm_watch *data, int max_count)
+{
+ if (!data)
+ return;
+
+ mutex_lock(&data->storm_lock);
+ data->max_storm_count = max_count;
+ mutex_unlock(&data->storm_lock);
+}
diff --git a/drivers/power/supply/qcom/storm-watch.h b/drivers/power/supply/qcom/storm-watch.h
index ff05c4a..5275d73 100644
--- a/drivers/power/supply/qcom/storm-watch.h
+++ b/drivers/power/supply/qcom/storm-watch.h
@@ -37,4 +37,5 @@
bool is_storming(struct storm_watch *data);
void reset_storm_count(struct storm_watch *data);
+void update_storm_count(struct storm_watch *data, int max_count);
#endif
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 7ad650e..d75f157 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2408,6 +2408,14 @@
count = rdev->deferred_disables;
rdev->deferred_disables = 0;
+ /*
+ * Workqueue functions queue the new work instance while the previous
+ * work instance is being processed. Cancel the queued work instance
+ * as the work instance under processing does the job of the queued
+ * work instance.
+ */
+ cancel_delayed_work(&rdev->disable_work);
+
for (i = 0; i < count; i++) {
ret = _regulator_disable(rdev);
if (ret != 0)
@@ -2451,10 +2459,10 @@
mutex_lock(&rdev->mutex);
rdev->deferred_disables++;
+ mod_delayed_work(system_power_efficient_wq, &rdev->disable_work,
+ msecs_to_jiffies(ms));
mutex_unlock(&rdev->mutex);
- queue_delayed_work(system_power_efficient_wq, &rdev->disable_work,
- msecs_to_jiffies(ms));
return 0;
}
EXPORT_SYMBOL_GPL(regulator_disable_deferred);
diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c
index caf174f..6dbf3cf 100644
--- a/drivers/regulator/tps65086-regulator.c
+++ b/drivers/regulator/tps65086-regulator.c
@@ -156,19 +156,19 @@
VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0),
tps65086_ldoa23_ranges, 0, 0),
TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)),
- TPS65086_SWITCH("SWB1", "swa2", SWB1, TPS65086_SWVTT_EN, BIT(6)),
- TPS65086_SWITCH("SWB2", "swa3", SWB2, TPS65086_SWVTT_EN, BIT(7)),
+ TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)),
+ TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_SWVTT_EN, BIT(7)),
TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)),
};
-static int tps65086_of_parse_cb(struct device_node *dev,
+static int tps65086_of_parse_cb(struct device_node *node,
const struct regulator_desc *desc,
struct regulator_config *config)
{
int ret;
/* Check for 25mV step mode */
- if (of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) {
+ if (of_property_read_bool(node, "ti,regulator-step-size-25mv")) {
switch (desc->id) {
case BUCK1:
case BUCK2:
@@ -192,7 +192,7 @@
}
/* Check for decay mode */
- if (desc->id <= BUCK6 && of_property_read_bool(config->of_node, "ti,regulator-decay")) {
+ if (desc->id <= BUCK6 && of_property_read_bool(node, "ti,regulator-decay")) {
ret = regmap_write_bits(config->regmap,
regulators[desc->id].decay_reg,
regulators[desc->id].decay_mask,
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index b7d54bf..7b696d1 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3590,12 +3590,14 @@
} else {
buf_ptr1 = (struct lpfc_dmabuf *) elsiocb->context2;
lpfc_els_free_data(phba, buf_ptr1);
+ elsiocb->context2 = NULL;
}
}
if (elsiocb->context3) {
buf_ptr = (struct lpfc_dmabuf *) elsiocb->context3;
lpfc_els_free_bpl(phba, buf_ptr);
+ elsiocb->context3 = NULL;
}
lpfc_sli_release_iocbq(phba, elsiocb);
return 0;
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 49b4c79..2d4f4b5 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -5951,18 +5951,25 @@
free_vfi_bmask:
kfree(phba->sli4_hba.vfi_bmask);
+ phba->sli4_hba.vfi_bmask = NULL;
free_xri_ids:
kfree(phba->sli4_hba.xri_ids);
+ phba->sli4_hba.xri_ids = NULL;
free_xri_bmask:
kfree(phba->sli4_hba.xri_bmask);
+ phba->sli4_hba.xri_bmask = NULL;
free_vpi_ids:
kfree(phba->vpi_ids);
+ phba->vpi_ids = NULL;
free_vpi_bmask:
kfree(phba->vpi_bmask);
+ phba->vpi_bmask = NULL;
free_rpi_ids:
kfree(phba->sli4_hba.rpi_ids);
+ phba->sli4_hba.rpi_ids = NULL;
free_rpi_bmask:
kfree(phba->sli4_hba.rpi_bmask);
+ phba->sli4_hba.rpi_bmask = NULL;
err_exit:
return rc;
}
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 8e63a7b..91ec068 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -1555,7 +1555,8 @@
struct atio {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
- uint8_t data[58];
+ __le16 attr_n_length;
+ uint8_t data[56];
uint32_t signature;
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
};
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index 068c4e4..bddaabb 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -2487,6 +2487,10 @@
if (pkt->entry_status & RF_BUSY)
res = DID_BUS_BUSY << 16;
+ if (pkt->entry_type == NOTIFY_ACK_TYPE &&
+ pkt->handle == QLA_TGT_SKIP_HANDLE)
+ return;
+
sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
if (sp) {
sp->done(ha, sp, res);
diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c
index feab7ea..91f5f55 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -3067,7 +3067,7 @@
pkt->entry_type = NOTIFY_ACK_TYPE;
pkt->entry_count = 1;
- pkt->handle = QLA_TGT_SKIP_HANDLE | CTIO_COMPLETION_HANDLE_MARK;
+ pkt->handle = QLA_TGT_SKIP_HANDLE;
nack = (struct nack_to_isp *)pkt;
nack->ox_id = ntfy->ox_id;
@@ -6463,12 +6463,29 @@
if (!vha->flags.online)
return;
- while (ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) {
+ while ((ha->tgt.atio_ring_ptr->signature != ATIO_PROCESSED) ||
+ fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr)) {
pkt = (struct atio_from_isp *)ha->tgt.atio_ring_ptr;
cnt = pkt->u.raw.entry_count;
- qlt_24xx_atio_pkt_all_vps(vha, (struct atio_from_isp *)pkt,
- ha_locked);
+ if (unlikely(fcpcmd_is_corrupted(ha->tgt.atio_ring_ptr))) {
+ /*
+ * This packet is corrupted. The header + payload
+ * can not be trusted. There is no point in passing
+ * it further up.
+ */
+ ql_log(ql_log_warn, vha, 0xffff,
+ "corrupted fcp frame SID[%3phN] OXID[%04x] EXCG[%x] %64phN\n",
+ pkt->u.isp24.fcp_hdr.s_id,
+ be16_to_cpu(pkt->u.isp24.fcp_hdr.ox_id),
+ le32_to_cpu(pkt->u.isp24.exchange_addr), pkt);
+
+ adjust_corrupted_atio(pkt);
+ qlt_send_term_exchange(vha, NULL, pkt, ha_locked, 0);
+ } else {
+ qlt_24xx_atio_pkt_all_vps(vha,
+ (struct atio_from_isp *)pkt, ha_locked);
+ }
for (i = 0; i < cnt; i++) {
ha->tgt.atio_ring_index++;
diff --git a/drivers/scsi/qla2xxx/qla_target.h b/drivers/scsi/qla2xxx/qla_target.h
index f26c5f6..0824a81 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -427,13 +427,33 @@
struct {
uint8_t entry_type; /* Entry type. */
uint8_t entry_count; /* Entry count. */
- uint8_t data[58];
+ __le16 attr_n_length;
+#define FCP_CMD_LENGTH_MASK 0x0fff
+#define FCP_CMD_LENGTH_MIN 0x38
+ uint8_t data[56];
uint32_t signature;
#define ATIO_PROCESSED 0xDEADDEAD /* Signature */
} raw;
} u;
} __packed;
+static inline int fcpcmd_is_corrupted(struct atio *atio)
+{
+ if (atio->entry_type == ATIO_TYPE7 &&
+ (le16_to_cpu(atio->attr_n_length & FCP_CMD_LENGTH_MASK) <
+ FCP_CMD_LENGTH_MIN))
+ return 1;
+ else
+ return 0;
+}
+
+/* adjust corrupted atio so we won't trip over the same entry again. */
+static inline void adjust_corrupted_atio(struct atio_from_isp *atio)
+{
+ atio->u.raw.attr_n_length = cpu_to_le16(FCP_CMD_LENGTH_MIN);
+ atio->u.isp24.fcp_cmnd.add_cdb_len = 0;
+}
+
#define CTIO_TYPE7 0x12 /* Continue target I/O entry (for 24xx) */
/*
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 967bb0d..b9290e7 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2484,7 +2484,8 @@
if (sdp->broken_fua) {
sd_first_printk(KERN_NOTICE, sdkp, "Disabling FUA\n");
sdkp->DPOFUA = 0;
- } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw) {
+ } else if (sdkp->DPOFUA && !sdkp->device->use_10_for_rw &&
+ !sdkp->device->use_16_for_rw) {
sd_first_printk(KERN_NOTICE, sdkp,
"Uses READ/WRITE(6), disabling FUA\n");
sdkp->DPOFUA = 0;
diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index ec91bd0..c680d76 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -534,7 +534,9 @@
{
struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev);
struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc);
+ unsigned long flags;
int req_size;
+ int ret;
BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize);
@@ -562,8 +564,15 @@
req_size = sizeof(cmd->req.cmd);
}
- if (virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)) != 0)
+ ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd));
+ if (ret == -EIO) {
+ cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
+ spin_lock_irqsave(&req_vq->vq_lock, flags);
+ virtscsi_complete_cmd(vscsi, cmd);
+ spin_unlock_irqrestore(&req_vq->vq_lock, flags);
+ } else if (ret != 0) {
return SCSI_MLQUEUE_HOST_BUSY;
+ }
return 0;
}
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index d8c5ea8..01779f9 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -182,6 +182,9 @@
if (!ctrl_dev->iommu_desc.cb_dev)
return 0;
+ if (!IS_ERR_OR_NULL(ctrl_dev->iommu_desc.iommu_map))
+ return 0;
+
dev = ctrl_dev->iommu_desc.cb_dev;
iommu_map = arm_iommu_create_mapping(&platform_bus_type,
va_start, va_size);
@@ -1299,6 +1302,13 @@
if (dev->pipes[i].connected)
msm_slim_disconn_pipe_port(dev, i);
}
+
+ if (!IS_ERR_OR_NULL(dev->iommu_desc.iommu_map)) {
+ arm_iommu_detach_device(dev->iommu_desc.cb_dev);
+ arm_iommu_release_mapping(dev->iommu_desc.iommu_map);
+ dev->iommu_desc.iommu_map = NULL;
+ }
+
if (dereg) {
for (i = 0; i < dev->port_nums; i++) {
if (dev->pipes[i].connected)
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 28f89bf..cded512 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -13,6 +13,7 @@
#define pr_fmt(fmt) "icnss: " fmt
#include <asm/dma-iommu.h>
+#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/iommu.h>
#include <linux/export.h>
@@ -4160,6 +4161,9 @@
int i;
struct device *dev = &pdev->dev;
struct icnss_priv *priv;
+ const __be32 *addrp;
+ u64 prop_size = 0;
+ struct device_node *np;
if (penv) {
icnss_pr_err("Driver is already initialized\n");
@@ -4231,24 +4235,53 @@
}
}
- ret = of_property_read_u32(dev->of_node, "qcom,wlan-msa-memory",
- &priv->msa_mem_size);
+ np = of_parse_phandle(dev->of_node,
+ "qcom,wlan-msa-fixed-region", 0);
+ if (np) {
+ addrp = of_get_address(np, 0, &prop_size, NULL);
+ if (!addrp) {
+ icnss_pr_err("Failed to get assigned-addresses or property\n");
+ ret = -EINVAL;
+ goto out;
+ }
- if (ret || priv->msa_mem_size == 0) {
- icnss_pr_err("Fail to get MSA Memory Size: %u, ret: %d\n",
- priv->msa_mem_size, ret);
- goto out;
+ priv->msa_pa = of_translate_address(np, addrp);
+ if (priv->msa_pa == OF_BAD_ADDR) {
+ icnss_pr_err("Failed to translate MSA PA from device-tree\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ priv->msa_va = memremap(priv->msa_pa,
+ (unsigned long)prop_size, MEMREMAP_WT);
+ if (!priv->msa_va) {
+ icnss_pr_err("MSA PA ioremap failed: phy addr: %pa\n",
+ &priv->msa_pa);
+ ret = -EINVAL;
+ goto out;
+ }
+ priv->msa_mem_size = prop_size;
+ } else {
+ ret = of_property_read_u32(dev->of_node, "qcom,wlan-msa-memory",
+ &priv->msa_mem_size);
+ if (ret || priv->msa_mem_size == 0) {
+ icnss_pr_err("Fail to get MSA Memory Size: %u ret: %d\n",
+ priv->msa_mem_size, ret);
+ goto out;
+ }
+
+ priv->msa_va = dmam_alloc_coherent(&pdev->dev,
+ priv->msa_mem_size, &priv->msa_pa, GFP_KERNEL);
+
+ if (!priv->msa_va) {
+ icnss_pr_err("DMA alloc failed for MSA\n");
+ ret = -ENOMEM;
+ goto out;
+ }
}
- priv->msa_va = dmam_alloc_coherent(&pdev->dev, priv->msa_mem_size,
- &priv->msa_pa, GFP_KERNEL);
- if (!priv->msa_va) {
- icnss_pr_err("DMA alloc failed for MSA\n");
- ret = -ENOMEM;
- goto out;
- }
- icnss_pr_dbg("MSA pa: %pa, MSA va: 0x%p\n", &priv->msa_pa,
- priv->msa_va);
+ icnss_pr_dbg("MSA pa: %pa, MSA va: 0x%p MSA Memory Size: 0x%x\n",
+ &priv->msa_pa, (void *)priv->msa_va, priv->msa_mem_size);
res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"smmu_iova_base");
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index 7298f30..e58fa2e 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -495,6 +495,7 @@
struct mem_alloc_generic_resp_msg_v01 *alloc_resp;
int rc, resp = 0;
int client_id;
+ uint32_t size = 0;
mutex_lock(&memsh_drv->mem_share);
alloc_req = (struct mem_alloc_generic_req_msg_v01 *)req;
@@ -521,12 +522,12 @@
return -EINVAL;
}
- memblock[client_id].free_memory += 1;
- pr_debug("memshare: %s, free memory count for client id: %d = %d",
- __func__, memblock[client_id].client_id,
- memblock[client_id].free_memory);
if (!memblock[client_id].allotted) {
- rc = memshare_alloc(memsh_drv->dev, alloc_req->num_bytes,
+ if (alloc_req->client_id == 1 && alloc_req->num_bytes > 0)
+ size = alloc_req->num_bytes + MEMSHARE_GUARD_BYTES;
+ else
+ size = alloc_req->num_bytes;
+ rc = memshare_alloc(memsh_drv->dev, size,
&memblock[client_id]);
if (rc) {
pr_err("memshare: %s,Unable to allocate memory for requested client\n",
@@ -534,11 +535,16 @@
resp = 1;
}
if (!resp) {
+ memblock[client_id].free_memory += 1;
memblock[client_id].allotted = 1;
memblock[client_id].size = alloc_req->num_bytes;
memblock[client_id].peripheral = alloc_req->proc_id;
}
}
+ pr_debug("memshare: In %s, free memory count for client id: %d = %d",
+ __func__, memblock[client_id].client_id,
+ memblock[client_id].free_memory);
+
memblock[client_id].sequence_id = alloc_req->sequence_id;
fill_alloc_response(alloc_resp, client_id, &resp);
@@ -941,9 +947,11 @@
/*
* Memshare allocation for guaranteed clients
*/
- if (memblock[num_clients].guarantee) {
+ if (memblock[num_clients].guarantee && size > 0) {
+ if (client_id == 1)
+ size += MEMSHARE_GUARD_BYTES;
rc = memshare_alloc(memsh_child->dev,
- memblock[num_clients].size,
+ size,
&memblock[num_clients]);
if (rc) {
pr_err("memshare: %s, Unable to allocate memory for guaranteed clients, rc: %d\n",
@@ -951,6 +959,7 @@
return rc;
}
memblock[num_clients].allotted = 1;
+ shared_hyp_mapping(num_clients);
}
/*
diff --git a/drivers/soc/qcom/memshare/msm_memshare.h b/drivers/soc/qcom/memshare/msm_memshare.h
index f3b594a..ca11137 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.h
+++ b/drivers/soc/qcom/memshare/msm_memshare.h
@@ -24,6 +24,7 @@
#define GPS 0
#define CHECK 0
#define FREE 1
+#define MEMSHARE_GUARD_BYTES (4*1024)
struct mem_blocks {
/* Client Id information */
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
index e38c53e..e90012d 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
@@ -854,10 +854,15 @@
INIT_LIST_HEAD(&commit_list);
}
-int commit_late_init_data(void)
+int commit_late_init_data(bool lock)
{
int rc;
- rt_mutex_lock(&msm_bus_adhoc_lock);
+
+ if (lock) {
+ rt_mutex_lock(&msm_bus_adhoc_lock);
+ return 0;
+ }
+
rc = bus_for_each_dev(&msm_bus_type, NULL, NULL,
bcm_remove_handoff_req);
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
index b331e74..36c0154 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c
@@ -386,6 +386,10 @@
tcs_cmd_gen(cur_bcm, &cmdlist_wake[k],
cur_bcm->node_vec[ACTIVE_CTX].vec_a,
cur_bcm->node_vec[ACTIVE_CTX].vec_b, commit);
+
+ if (cur_rsc->rscdev->req_state == RPMH_AWAKE_STATE)
+ commit = false;
+
tcs_cmd_gen(cur_bcm, &cmdlist_sleep[k],
cur_bcm->node_vec[DUAL_CTX].vec_a,
cur_bcm->node_vec[DUAL_CTX].vec_b, commit);
@@ -555,6 +559,8 @@
int cnt_sleep = 0;
int i = 0;
+ if (!clist)
+ return ret;
list_for_each_entry_safe(node, node_tmp, clist, link) {
if (unlikely(node->node_info->defer_qos))
@@ -1807,9 +1813,10 @@
int __init msm_bus_device_late_init(void)
{
+ commit_late_init_data(true);
MSM_BUS_ERR("msm_bus_late_init: Remove handoff bw requests\n");
init_time = false;
- return commit_late_init_data();
+ return commit_late_init_data(false);
}
subsys_initcall(msm_bus_device_init_driver);
late_initcall_sync(msm_bus_device_late_init);
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
index 17657e5..ad04fef 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
+++ b/drivers/soc/qcom/msm_bus/msm_bus_rpmh.h
@@ -224,7 +224,7 @@
int throttle_en, uint64_t lim_bw);
int msm_bus_commit_data(struct list_head *clist);
int bcm_remove_handoff_req(struct device *dev, void *data);
-int commit_late_init_data(void);
+int commit_late_init_data(bool lock);
int msm_bus_query_gen(struct list_head *qlist,
struct msm_bus_tcs_usecase *tcs_usecase);
void *msm_bus_realloc_devmem(struct device *dev, void *p, size_t old_size,
diff --git a/drivers/soc/qcom/secure_buffer.c b/drivers/soc/qcom/secure_buffer.c
index f1e7347..63cce5c 100644
--- a/drivers/soc/qcom/secure_buffer.c
+++ b/drivers/soc/qcom/secure_buffer.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2011 Google, Inc
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, 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
@@ -412,6 +412,10 @@
return "VMID_WLAN_CE";
case VMID_CP_CAMERA_PREVIEW:
return "VMID_CP_CAMERA_PREVIEW";
+ case VMID_CP_SPSS_SP:
+ return "VMID_CP_SPSS_SP";
+ case VMID_CP_SPSS_SP_SHARED:
+ return "VMID_CP_SPSS_SP_SHARED";
case VMID_INVAL:
return "VMID_INVAL";
default:
diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c
index d36c11b..02fb967 100644
--- a/drivers/spi/spi-davinci.c
+++ b/drivers/spi/spi-davinci.c
@@ -646,7 +646,7 @@
buf = t->rx_buf;
t->rx_dma = dma_map_single(&spi->dev, buf,
t->len, DMA_FROM_DEVICE);
- if (!t->rx_dma) {
+ if (dma_mapping_error(&spi->dev, !t->rx_dma)) {
ret = -EFAULT;
goto err_rx_map;
}
@@ -660,7 +660,7 @@
buf = (void *)t->tx_buf;
t->tx_dma = dma_map_single(&spi->dev, buf,
t->len, DMA_TO_DEVICE);
- if (!t->tx_dma) {
+ if (dma_mapping_error(&spi->dev, t->tx_dma)) {
ret = -EFAULT;
goto err_tx_map;
}
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 24d4492..6db8063 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -621,8 +621,10 @@
if (!spi)
return;
- if (spi->dev.of_node)
+ if (spi->dev.of_node) {
of_node_clear_flag(spi->dev.of_node, OF_POPULATED);
+ of_node_put(spi->dev.of_node);
+ }
if (ACPI_COMPANION(&spi->dev))
acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev));
device_unregister(&spi->dev);
@@ -797,12 +799,12 @@
if (master->dma_tx)
tx_dev = master->dma_tx->device->dev;
else
- tx_dev = &master->dev;
+ tx_dev = master->dev.parent;
if (master->dma_rx)
rx_dev = master->dma_rx->device->dev;
else
- rx_dev = &master->dev;
+ rx_dev = master->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer))
@@ -844,12 +846,12 @@
if (master->dma_tx)
tx_dev = master->dma_tx->device->dev;
else
- tx_dev = &master->dev;
+ tx_dev = master->dev.parent;
if (master->dma_rx)
rx_dev = master->dma_rx->device->dev;
else
- rx_dev = &master->dev;
+ rx_dev = master->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer))
@@ -1589,11 +1591,13 @@
if (rc) {
dev_err(&master->dev, "spi_device register error %s\n",
nc->full_name);
- goto err_out;
+ goto err_of_node_put;
}
return spi;
+err_of_node_put:
+ of_node_put(nc);
err_out:
spi_dev_put(spi);
return ERR_PTR(rc);
diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c
index 9ea4a9f..4082a7d 100644
--- a/drivers/staging/android/ion/ion.c
+++ b/drivers/staging/android/ion/ion.c
@@ -3,7 +3,7 @@
* drivers/staging/android/ion/ion.c
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -76,7 +76,7 @@
* @dev: backpointer to ion device
* @handles: an rb tree of all the handles in this client
* @idr: an idr space for allocating handle ids
- * @lock: lock protecting the tree of handles
+ * @lock: lock protecting the tree of handles and idr
* @name: used for debugging
* @display_name: used for debugging (unique version of @name)
* @display_serial: used for debugging (to make display_name unique)
@@ -91,7 +91,6 @@
struct ion_device *dev;
struct rb_root handles;
struct idr idr;
- /* Protects idr */
struct mutex lock;
char *name;
char *display_name;
@@ -671,8 +670,8 @@
mutex_unlock(&client->lock);
return -ENODEV;
}
- mutex_unlock(&client->lock);
ret = buffer->heap->ops->phys(buffer->heap, buffer, addr, len);
+ mutex_unlock(&client->lock);
return ret;
}
EXPORT_SYMBOL(ion_phys);
@@ -777,33 +776,7 @@
}
EXPORT_SYMBOL(ion_unmap_kernel);
-static struct mutex debugfs_mutex;
static struct rb_root *ion_root_client;
-static int is_client_alive(struct ion_client *client)
-{
- struct rb_node *node;
- struct ion_client *tmp;
- struct ion_device *dev;
-
- node = ion_root_client->rb_node;
- dev = container_of(ion_root_client, struct ion_device, clients);
-
- down_read(&dev->lock);
- while (node) {
- tmp = rb_entry(node, struct ion_client, node);
- if (client < tmp) {
- node = node->rb_left;
- } else if (client > tmp) {
- node = node->rb_right;
- } else {
- up_read(&dev->lock);
- return 1;
- }
- }
-
- up_read(&dev->lock);
- return 0;
-}
static int ion_debug_client_show(struct seq_file *s, void *unused)
{
@@ -814,14 +787,6 @@
"heap_name", "size_in_bytes", "handle refcount",
"buffer");
- mutex_lock(&debugfs_mutex);
- if (!is_client_alive(client)) {
- seq_printf(s, "ion_client 0x%p dead, can't dump its buffers\n",
- client);
- mutex_unlock(&debugfs_mutex);
- return 0;
- }
-
mutex_lock(&client->lock);
for (n = rb_first(&client->handles); n; n = rb_next(n)) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
@@ -836,7 +801,6 @@
seq_puts(s, "\n");
}
mutex_unlock(&client->lock);
- mutex_unlock(&debugfs_mutex);
return 0;
}
@@ -967,27 +931,27 @@
struct rb_node *n;
pr_debug("%s: %d\n", __func__, __LINE__);
- mutex_lock(&debugfs_mutex);
+ down_write(&dev->lock);
+ rb_erase(&client->node, &dev->clients);
+ up_write(&dev->lock);
+
+ /* After this completes, there are no more references to client */
+ debugfs_remove_recursive(client->debug_root);
+
+ mutex_lock(&client->lock);
while ((n = rb_first(&client->handles))) {
struct ion_handle *handle = rb_entry(n, struct ion_handle,
node);
ion_handle_destroy(&handle->ref);
}
+ mutex_unlock(&client->lock);
idr_destroy(&client->idr);
-
- down_write(&dev->lock);
if (client->task)
put_task_struct(client->task);
- rb_erase(&client->node, &dev->clients);
- debugfs_remove_recursive(client->debug_root);
-
- up_write(&dev->lock);
-
kfree(client->display_name);
kfree(client->name);
kfree(client);
- mutex_unlock(&debugfs_mutex);
}
EXPORT_SYMBOL(ion_client_destroy);
@@ -1794,7 +1758,7 @@
seq_printf(s, "%16s %16s %16s\n", "client", "pid", "size");
seq_puts(s, "----------------------------------------------------\n");
- mutex_lock(&debugfs_mutex);
+ down_read(&dev->lock);
for (n = rb_first(&dev->clients); n; n = rb_next(n)) {
struct ion_client *client = rb_entry(n, struct ion_client,
node);
@@ -1813,7 +1777,7 @@
client->pid, size);
}
}
- mutex_unlock(&debugfs_mutex);
+ up_read(&dev->lock);
seq_puts(s, "----------------------------------------------------\n");
seq_puts(s, "orphaned allocations (info is from last known client):\n");
@@ -2048,7 +2012,6 @@
plist_head_init(&idev->heaps);
idev->clients = RB_ROOT;
ion_root_client = &idev->clients;
- mutex_init(&debugfs_mutex);
return idev;
}
EXPORT_SYMBOL(ion_device_create);
diff --git a/drivers/staging/android/ion/ion_cma_heap.c b/drivers/staging/android/ion/ion_cma_heap.c
index 323bb0c..ff6436f 100644
--- a/drivers/staging/android/ion/ion_cma_heap.c
+++ b/drivers/staging/android/ion/ion_cma_heap.c
@@ -4,7 +4,7 @@
* Copyright (C) Linaro 2012
* Author: <benjamin.gaignard@linaro.org> for ST-Ericsson.
*
- * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -242,28 +242,37 @@
static void ion_secure_cma_free(struct ion_buffer *buffer)
{
int ret = 0;
- u32 source_vm;
+ int *source_vm_list;
+ int source_nelems;
int dest_vmid;
int dest_perms;
struct ion_cma_buffer_info *info = buffer->priv_virt;
- source_vm = get_secure_vmid(buffer->flags);
- if (source_vm < 0) {
- pr_err("%s: Failed to get secure vmid\n", __func__);
+ source_nelems = count_set_bits(buffer->flags & ION_FLAGS_CP_MASK);
+ source_vm_list = kcalloc(source_nelems, sizeof(*source_vm_list),
+ GFP_KERNEL);
+ if (!source_vm_list)
return;
+ ret = populate_vm_list(buffer->flags, source_vm_list, source_nelems);
+ if (ret) {
+ pr_err("%s: Failed to get secure vmids\n", __func__);
+ goto out_free_source;
}
+
dest_vmid = VMID_HLOS;
dest_perms = PERM_READ | PERM_WRITE | PERM_EXEC;
- ret = hyp_assign_table(info->table, &source_vm, 1,
+ ret = hyp_assign_table(info->table, source_vm_list, source_nelems,
&dest_vmid, &dest_perms, 1);
if (ret) {
pr_err("%s: Not freeing memory since assign failed\n",
__func__);
- return;
+ goto out_free_source;
}
ion_cma_free(buffer);
+out_free_source:
+ kfree(source_vm_list);
}
static int ion_secure_cma_allocate(
@@ -272,41 +281,64 @@
unsigned long align, unsigned long flags)
{
int ret = 0;
+ int count;
int source_vm;
- int dest_vm;
- int dest_perms;
+ int *dest_vm_list = NULL;
+ int *dest_perms = NULL;
+ int dest_nelems;
struct ion_cma_buffer_info *info;
source_vm = VMID_HLOS;
- dest_vm = get_secure_vmid(flags);
- if (dest_vm < 0) {
- pr_err("%s: Failed to get secure vmid\n", __func__);
- return -EINVAL;
+ dest_nelems = count_set_bits(flags & ION_FLAGS_CP_MASK);
+ dest_vm_list = kcalloc(dest_nelems, sizeof(*dest_vm_list), GFP_KERNEL);
+ if (!dest_vm_list) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ dest_perms = kcalloc(dest_nelems, sizeof(*dest_perms), GFP_KERNEL);
+ if (!dest_perms) {
+ ret = -ENOMEM;
+ goto out_free_dest_vm;
+ }
+ ret = populate_vm_list(flags, dest_vm_list, dest_nelems);
+ if (ret) {
+ pr_err("%s: Failed to get secure vmid(s)\n", __func__);
+ goto out_free_dest;
}
- if (dest_vm == VMID_CP_SEC_DISPLAY)
- dest_perms = PERM_READ;
- else
- dest_perms = PERM_READ | PERM_WRITE;
+ for (count = 0; count < dest_nelems; count++) {
+ if (dest_vm_list[count] == VMID_CP_SEC_DISPLAY)
+ dest_perms[count] = PERM_READ;
+ else
+ dest_perms[count] = PERM_READ | PERM_WRITE;
+ }
ret = ion_cma_allocate(heap, buffer, len, align, flags);
if (ret) {
dev_err(heap->priv, "Unable to allocate cma buffer");
- return ret;
+ goto out_free_dest;
}
info = buffer->priv_virt;
ret = hyp_assign_table(info->table, &source_vm, 1,
- &dest_vm, &dest_perms, 1);
+ dest_vm_list, dest_perms, dest_nelems);
if (ret) {
pr_err("%s: Assign call failed\n", __func__);
goto err;
}
+
+ kfree(dest_vm_list);
+ kfree(dest_perms);
return ret;
err:
ion_secure_cma_free(buffer);
+out_free_dest:
+ kfree(dest_perms);
+out_free_dest_vm:
+ kfree(dest_vm_list);
+out:
return ret;
}
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 49d947e..ba92ed9 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -2,7 +2,7 @@
* drivers/staging/android/ion/ion_priv.h
*
* Copyright (C) 2011 Google, Inc.
- * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -294,6 +294,8 @@
int ion_heap_is_system_secure_heap_type(enum ion_heap_type type);
int get_secure_vmid(unsigned long flags);
bool is_secure_vmid_valid(int vmid);
+unsigned int count_set_bits(unsigned long val);
+int populate_vm_list(unsigned long flags, unsigned int *vm_list, int nelems);
/**
* Functions to help assign/unassign sg_table for System Secure Heap
diff --git a/drivers/staging/android/ion/msm/msm_ion.c b/drivers/staging/android/ion/msm/msm_ion.c
index ae9bf5f..52926f0 100644
--- a/drivers/staging/android/ion/msm/msm_ion.c
+++ b/drivers/staging/android/ion/msm/msm_ion.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2017, 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
@@ -31,6 +31,7 @@
#include <linux/highmem.h>
#include <linux/cma.h>
#include <linux/module.h>
+#include <linux/bitops.h>
#include <linux/show_mem_notifier.h>
#include <asm/cacheflush.h>
#include "../ion_priv.h"
@@ -618,7 +619,32 @@
vmid == VMID_CP_CAMERA ||
vmid == VMID_CP_SEC_DISPLAY ||
vmid == VMID_CP_APP ||
- vmid == VMID_CP_CAMERA_PREVIEW);
+ vmid == VMID_CP_CAMERA_PREVIEW ||
+ vmid == VMID_CP_SPSS_SP ||
+ vmid == VMID_CP_SPSS_SP_SHARED);
+}
+
+unsigned int count_set_bits(unsigned long val)
+{
+ return ((unsigned int)bitmap_weight(&val, BITS_PER_LONG));
+}
+
+int populate_vm_list(unsigned long flags, unsigned int *vm_list,
+ int nelems)
+{
+ unsigned int itr = 0;
+ int vmid;
+
+ flags = flags & ION_FLAGS_CP_MASK;
+ for_each_set_bit(itr, &flags, BITS_PER_LONG) {
+ vmid = get_secure_vmid(0x1UL << itr);
+ if (vmid < 0 || !nelems)
+ return -EINVAL;
+
+ vm_list[nelems - 1] = vmid;
+ nelems--;
+ }
+ return 0;
}
int get_secure_vmid(unsigned long flags)
@@ -639,6 +665,10 @@
return VMID_CP_APP;
if (flags & ION_FLAG_CP_CAMERA_PREVIEW)
return VMID_CP_CAMERA_PREVIEW;
+ if (flags & ION_FLAG_CP_SPSS_SP)
+ return VMID_CP_SPSS_SP;
+ if (flags & ION_FLAG_CP_SPSS_SP_SHARED)
+ return VMID_CP_SPSS_SP_SHARED;
return -EINVAL;
}
/* fix up the cases where the ioctl direction bits are incorrect */
diff --git a/drivers/staging/android/ion/msm/msm_ion.h b/drivers/staging/android/ion/msm/msm_ion.h
index 55b02b6..741d017 100644
--- a/drivers/staging/android/ion/msm/msm_ion.h
+++ b/drivers/staging/android/ion/msm/msm_ion.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2017, 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
@@ -22,6 +22,8 @@
IPT_TYPE_MDP_WRITEBACK = 2,
};
+#define ION_FLAGS_CP_MASK 0x7FFF0000
+
/*
* This flag allows clients when mapping into the IOMMU to specify to
* defer un-mapping from the IOMMU until the buffer memory is freed.
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index cc77674..7381ee9 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -84,6 +84,8 @@
#define ION_FLAG_CP_NON_PIXEL ION_BIT(20)
#define ION_FLAG_CP_CAMERA ION_BIT(21)
#define ION_FLAG_CP_HLOS ION_BIT(22)
+#define ION_FLAG_CP_SPSS_SP ION_BIT(23)
+#define ION_FLAG_CP_SPSS_SP_SHARED ION_BIT(24)
#define ION_FLAG_CP_SEC_DISPLAY ION_BIT(25)
#define ION_FLAG_CP_APP ION_BIT(26)
#define ION_FLAG_CP_CAMERA_PREVIEW ION_BIT(27)
diff --git a/drivers/thermal/step_wise.c b/drivers/thermal/step_wise.c
index 6b05b7b..f6f30a0 100644
--- a/drivers/thermal/step_wise.c
+++ b/drivers/thermal/step_wise.c
@@ -102,7 +102,8 @@
if (!throttle)
next_target = THERMAL_NO_TARGET;
} else {
- next_target = cur_state - 1;
+ if (!throttle)
+ next_target = cur_state - 1;
if (next_target > instance->upper)
next_target = instance->upper;
}
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 68d9feb..95ef027 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -897,6 +897,60 @@
}
static ssize_t
+polling_delay_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", tz->polling_delay);
+}
+
+static ssize_t
+polling_delay_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int delay;
+
+ if (kstrtoint(buf, 10, &delay))
+ return -EINVAL;
+
+ mutex_lock(&tz->lock);
+ tz->polling_delay = delay;
+ mutex_unlock(&tz->lock);
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
+passive_delay_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", tz->passive_delay);
+}
+
+static ssize_t
+passive_delay_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ int delay;
+
+ if (kstrtoint(buf, 10, &delay))
+ return -EINVAL;
+
+ mutex_lock(&tz->lock);
+ tz->passive_delay = delay;
+ mutex_unlock(&tz->lock);
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
policy_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
@@ -1167,6 +1221,10 @@
static DEVICE_ATTR(passive, S_IRUGO | S_IWUSR, passive_show, passive_store);
static DEVICE_ATTR(policy, S_IRUGO | S_IWUSR, policy_show, policy_store);
static DEVICE_ATTR(available_policies, S_IRUGO, available_policies_show, NULL);
+static DEVICE_ATTR(passive_delay, 0644, passive_delay_show,
+ passive_delay_store);
+static DEVICE_ATTR(polling_delay, 0644, polling_delay_show,
+ polling_delay_store);
/* sys I/F for cooling device */
#define to_cooling_device(_dev) \
@@ -1324,6 +1382,54 @@
return sprintf(buf, "%d\n", instance->trip);
}
+static ssize_t
+thermal_cooling_device_upper_limit_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ struct thermal_instance *instance;
+ int ret, upper_limit;
+
+ instance =
+ container_of(attr, struct thermal_instance, upper_attr);
+
+ ret = kstrtoint(buf, 0, &upper_limit);
+ if (ret)
+ return ret;
+ if (upper_limit < instance->lower)
+ return -EINVAL;
+
+ instance->upper = upper_limit;
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
+static ssize_t
+thermal_cooling_device_lower_limit_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct thermal_zone_device *tz = to_thermal_zone(dev);
+ struct thermal_instance *instance;
+ int ret, lower_limit;
+
+ instance =
+ container_of(attr, struct thermal_instance, lower_attr);
+
+ ret = kstrtoint(buf, 0, &lower_limit);
+ if (ret)
+ return ret;
+ if (lower_limit > instance->upper)
+ return -EINVAL;
+
+ instance->lower = lower_limit;
+ thermal_zone_device_update(tz, THERMAL_EVENT_UNSPECIFIED);
+
+ return count;
+}
+
static struct attribute *cooling_device_attrs[] = {
&dev_attr_cdev_type.attr,
&dev_attr_max_state.attr,
@@ -1484,8 +1590,9 @@
"cdev%d_upper_limit", dev->id);
sysfs_attr_init(&dev->upper_attr.attr);
dev->upper_attr.attr.name = dev->upper_attr_name;
- dev->upper_attr.attr.mode = 0444;
+ dev->upper_attr.attr.mode = 0644;
dev->upper_attr.show = thermal_cooling_device_upper_limit_show;
+ dev->upper_attr.store = thermal_cooling_device_upper_limit_store;
result = device_create_file(&tz->device, &dev->upper_attr);
if (result)
goto remove_trip_file;
@@ -1494,8 +1601,9 @@
"cdev%d_lower_limit", dev->id);
sysfs_attr_init(&dev->lower_attr.attr);
dev->lower_attr.attr.name = dev->lower_attr_name;
- dev->lower_attr.attr.mode = 0444;
+ dev->lower_attr.attr.mode = 0644;
dev->lower_attr.show = thermal_cooling_device_lower_limit_show;
+ dev->lower_attr.store = thermal_cooling_device_lower_limit_store;
result = device_create_file(&tz->device, &dev->lower_attr);
if (result)
goto remove_upper_file;
@@ -2084,6 +2192,13 @@
if (result)
goto unregister;
}
+ result = device_create_file(&tz->device, &dev_attr_passive_delay);
+ if (result)
+ goto unregister;
+
+ result = device_create_file(&tz->device, &dev_attr_polling_delay);
+ if (result)
+ goto unregister;
if (IS_ENABLED(CONFIG_THERMAL_EMULATION)) {
result = device_create_file(&tz->device, &dev_attr_emul_temp);
@@ -2207,6 +2322,8 @@
device_remove_file(&tz->device, &dev_attr_mode);
device_remove_file(&tz->device, &dev_attr_policy);
device_remove_file(&tz->device, &dev_attr_available_policies);
+ device_remove_file(&tz->device, &dev_attr_passive_delay);
+ device_remove_file(&tz->device, &dev_attr_polling_delay);
remove_trip_attrs(tz);
thermal_set_governor(tz, NULL);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 24fbebc..cfdd5c3 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2532,7 +2532,7 @@
/* keep other bits untouched (so e.g. forced modes are not lost) */
usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
- GUSBCFG_HNPCAP);
+ GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
/* set the PLL on, remove the HNP/SRP and set the PHY */
val = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
@@ -3403,7 +3403,7 @@
/* keep other bits untouched (so e.g. forced modes are not lost) */
usbcfg = dwc2_readl(hsotg->regs + GUSBCFG);
usbcfg &= ~(GUSBCFG_TOUTCAL_MASK | GUSBCFG_PHYIF16 | GUSBCFG_SRPCAP |
- GUSBCFG_HNPCAP);
+ GUSBCFG_HNPCAP | GUSBCFG_USBTRDTIM_MASK);
/* set the PLL on, remove the HNP/SRP and set the PHY */
trdtim = (hsotg->phyif == GUSBCFG_PHYIF8) ? 9 : 5;
diff --git a/drivers/usb/dwc3/dbm.c b/drivers/usb/dwc3/dbm.c
index 285cd5a..3860a1a 100644
--- a/drivers/usb/dwc3/dbm.c
+++ b/drivers/usb/dwc3/dbm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2015, 2017 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
@@ -129,7 +129,7 @@
enum dbm_reg reg, int ep,
const u32 mask, u32 val)
{
- u32 shift = find_first_bit((void *)&mask, 32);
+ u32 shift = __ffs(mask);
u32 offset = dbm->reg_table[reg].offset +
(dbm->reg_table[reg].ep_mult * ep);
u32 tmp = ioread32(dbm->base + offset);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a496468..81f3384 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -319,7 +319,7 @@
u32 offset,
const u32 mask)
{
- u32 shift = ffs(mask);
+ u32 shift = __ffs(mask);
u32 val = ioread32(base + offset);
val &= mask; /* clear other bits */
@@ -353,7 +353,7 @@
static inline void dwc3_msm_write_reg_field(void __iomem *base, u32 offset,
const u32 mask, u32 val)
{
- u32 shift = find_first_bit((void *)&mask, 32);
+ u32 shift = __ffs(mask);
u32 tmp = ioread32(base + offset);
tmp &= ~mask; /* clear written bits */
diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c
index 920c08a..5804840 100644
--- a/drivers/usb/gadget/function/f_cdev.c
+++ b/drivers/usb/gadget/function/f_cdev.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, 2013-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011, 2013-2017, The Linux Foundation. All rights reserved.
* Linux Foundation chooses to take subject only to the GPLv2 license terms,
* and distributes only under these terms.
*
@@ -826,8 +826,10 @@
opts = container_of(fi, struct f_cdev_opts, func_inst);
- device_destroy(fcdev_classp, MKDEV(major, opts->port->minor));
- cdev_del(&opts->port->fcdev_cdev);
+ if (opts->port) {
+ device_destroy(fcdev_classp, MKDEV(major, opts->port->minor));
+ cdev_del(&opts->port->fcdev_cdev);
+ }
usb_cser_chardev_deinit();
kfree(opts->func_name);
kfree(opts->port);
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index 1210188e..675e50e 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -27,29 +27,23 @@
#include <linux/usb/phy.h>
#include <linux/reset.h>
-#define QUSB2PHY_PWR_CTRL1 0x210
+/* QUSB2PHY_PWR_CTRL1 register related bits */
#define PWR_CTRL1_POWR_DOWN BIT(0)
-#define QUSB2PHY_PLL_COMMON_STATUS_ONE 0x1A0
+/* QUSB2PHY_PLL_COMMON_STATUS_ONE register related bits */
#define CORE_READY_STATUS BIT(0)
/* Get TUNE value from efuse bit-mask */
#define TUNE_VAL_MASK(val, pos, mask) ((val >> pos) & mask)
-#define QUSB2PHY_INTR_CTRL 0x22C
+/* QUSB2PHY_INTR_CTRL register related bits */
#define DMSE_INTR_HIGH_SEL BIT(4)
#define DPSE_INTR_HIGH_SEL BIT(3)
#define CHG_DET_INTR_EN BIT(2)
#define DMSE_INTR_EN BIT(1)
#define DPSE_INTR_EN BIT(0)
-#define QUSB2PHY_INTR_STAT 0x230
-#define DMSE_INTERRUPT BIT(1)
-#define DPSE_INTERRUPT BIT(0)
-
-#define QUSB2PHY_PORT_TUNE1 0x23c
-
-#define QUSB2PHY_PLL_CORE_INPUT_OVERRIDE 0x0a8
+/* QUSB2PHY_PLL_CORE_INPUT_OVERRIDE register related bits */
#define CORE_PLL_RATE BIT(0)
#define CORE_PLL_RATE_MUX BIT(1)
#define CORE_PLL_EN BIT(2)
@@ -73,6 +67,16 @@
module_param(phy_tune1, uint, 0644);
MODULE_PARM_DESC(phy_tune1, "QUSB PHY v2 TUNE1");
+enum qusb_phy_reg {
+ PORT_TUNE1,
+ PLL_COMMON_STATUS_ONE,
+ PWR_CTRL1,
+ INTR_CTRL,
+ PLL_CORE_INPUT_OVERRIDE,
+ TEST1,
+ USB2_PHY_REG_MAX,
+};
+
struct qusb_phy {
struct usb_phy phy;
void __iomem *base;
@@ -92,8 +96,10 @@
int host_init_seq_len;
int *qusb_phy_host_init_seq;
+ unsigned int *phy_reg;
+ int qusb_phy_reg_offset_cnt;
+
u32 tune_val;
- u32 phy_auto_resume_offset;
int efuse_bit_pos;
int efuse_num_of_bits;
@@ -316,7 +322,7 @@
qphy->tune_val = TUNE_VAL_MASK(qphy->tune_val,
qphy->efuse_bit_pos, bit_mask);
- reg = readb_relaxed(qphy->base + QUSB2PHY_PORT_TUNE1);
+ reg = readb_relaxed(qphy->base + qphy->phy_reg[PORT_TUNE1]);
if (qphy->tune_val) {
reg = reg & 0x0f;
reg |= (qphy->tune_val << 4);
@@ -372,7 +378,7 @@
/* Require to get phy pll lock successfully */
usleep_range(150, 160);
- reg = readb_relaxed(qphy->base + QUSB2PHY_PLL_COMMON_STATUS_ONE);
+ reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
if (!(reg & CORE_READY_STATUS)) {
dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
@@ -421,9 +427,9 @@
}
/* Disable the PHY */
- writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) |
+ writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
PWR_CTRL1_POWR_DOWN,
- qphy->base + QUSB2PHY_PWR_CTRL1);
+ qphy->base + qphy->phy_reg[PWR_CTRL1]);
if (qphy->qusb_phy_init_seq)
qusb_phy_write_seq(qphy->base, qphy->qusb_phy_init_seq,
@@ -435,7 +441,7 @@
pr_debug("%s(): Programming TUNE1 parameter as:%x\n", __func__,
qphy->tune_val);
writel_relaxed(qphy->tune_val,
- qphy->base + QUSB2PHY_PORT_TUNE1);
+ qphy->base + qphy->phy_reg[PORT_TUNE1]);
}
/* If phy_tune1 modparam set, override tune1 value */
@@ -443,16 +449,16 @@
pr_debug("%s(): (modparam) TUNE1 val:0x%02x\n",
__func__, phy_tune1);
writel_relaxed(phy_tune1,
- qphy->base + QUSB2PHY_PORT_TUNE1);
+ qphy->base + qphy->phy_reg[PORT_TUNE1]);
}
/* ensure above writes are completed before re-enabling PHY */
wmb();
/* Enable the PHY */
- writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) &
+ writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) &
~PWR_CTRL1_POWR_DOWN,
- qphy->base + QUSB2PHY_PWR_CTRL1);
+ qphy->base + qphy->phy_reg[PWR_CTRL1]);
/* Ensure above write is completed before turning ON ref clk */
wmb();
@@ -460,7 +466,7 @@
/* Require to get phy pll lock successfully */
usleep_range(150, 160);
- reg = readb_relaxed(qphy->base + QUSB2PHY_PLL_COMMON_STATUS_ONE);
+ reg = readb_relaxed(qphy->base + qphy->phy_reg[PLL_COMMON_STATUS_ONE]);
dev_dbg(phy->dev, "QUSB2PHY_PLL_COMMON_STATUS_ONE:%x\n", reg);
if (!(reg & CORE_READY_STATUS)) {
dev_err(phy->dev, "QUSB PHY PLL LOCK fails:%x\n", reg);
@@ -478,9 +484,9 @@
qusb_phy_enable_clocks(qphy, true);
/* Disable the PHY */
- writel_relaxed(readl_relaxed(qphy->base + QUSB2PHY_PWR_CTRL1) |
+ writel_relaxed(readl_relaxed(qphy->base + qphy->phy_reg[PWR_CTRL1]) |
PWR_CTRL1_POWR_DOWN,
- qphy->base + QUSB2PHY_PWR_CTRL1);
+ qphy->base + qphy->phy_reg[PWR_CTRL1]);
/* Makes sure that above write goes through */
wmb();
@@ -525,7 +531,7 @@
(qphy->phy.flags & PHY_HOST_MODE)) {
/* Disable all interrupts */
writel_relaxed(0x00,
- qphy->base + QUSB2PHY_INTR_CTRL);
+ qphy->base + qphy->phy_reg[INTR_CTRL]);
linestate = qusb_phy_get_linestate(qphy);
/*
@@ -537,29 +543,27 @@
* e.g. if currently D+ high, D- low (HS 'J'/Suspend),
* configure the mask to trigger on D+ low OR D- high
*/
- intr_mask = DMSE_INTERRUPT | DPSE_INTERRUPT;
+ intr_mask = DPSE_INTR_EN | DMSE_INTR_EN;
if (!(linestate & LINESTATE_DP)) /* D+ low */
intr_mask |= DPSE_INTR_HIGH_SEL;
if (!(linestate & LINESTATE_DM)) /* D- low */
intr_mask |= DMSE_INTR_HIGH_SEL;
writel_relaxed(intr_mask,
- qphy->base + QUSB2PHY_INTR_CTRL);
+ qphy->base + qphy->phy_reg[INTR_CTRL]);
/* hold core PLL into reset */
writel_relaxed(CORE_PLL_EN_FROM_RESET |
CORE_RESET | CORE_RESET_MUX,
- qphy->base + QUSB2PHY_PLL_CORE_INPUT_OVERRIDE);
+ qphy->base +
+ qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
- if (qphy->phy_auto_resume_offset) {
- /* enable phy auto-resume */
- writel_relaxed(0x91,
- qphy->base + qphy->phy_auto_resume_offset);
- /* flush the previous write before next write */
- wmb();
- writel_relaxed(0x90,
- qphy->base + qphy->phy_auto_resume_offset);
- }
+ /* enable phy auto-resume */
+ writel_relaxed(0x91, qphy->base + qphy->phy_reg[TEST1]);
+ /* flush the previous write before next write */
+ wmb();
+ writel_relaxed(0x90, qphy->base + qphy->phy_reg[TEST1]);
+
dev_dbg(phy->dev, "%s: intr_mask = %x\n",
__func__, intr_mask);
@@ -569,7 +573,7 @@
} else { /* Cable disconnect case */
/* Disable all interrupts */
writel_relaxed(0x00,
- qphy->base + QUSB2PHY_INTR_CTRL);
+ qphy->base + qphy->phy_reg[INTR_CTRL]);
qusb_phy_reset(qphy);
qusb_phy_enable_clocks(qphy, false);
qusb_phy_enable_power(qphy, false, true);
@@ -582,11 +586,11 @@
qusb_phy_enable_clocks(qphy, true);
/* Clear all interrupts on resume */
writel_relaxed(0x00,
- qphy->base + QUSB2PHY_INTR_CTRL);
+ qphy->base + qphy->phy_reg[INTR_CTRL]);
/* bring core PLL out of reset */
- writel_relaxed(CORE_PLL_EN_FROM_RESET,
- qphy->base + QUSB2PHY_PLL_CORE_INPUT_OVERRIDE);
+ writel_relaxed(CORE_PLL_EN_FROM_RESET, qphy->base +
+ qphy->phy_reg[PLL_CORE_INPUT_OVERRIDE]);
/* Makes sure that above write goes through */
wmb();
@@ -870,6 +874,31 @@
}
size = 0;
+ of_get_property(dev->of_node, "qcom,qusb-phy-reg-offset", &size);
+ if (size) {
+ qphy->phy_reg = devm_kzalloc(dev, size, GFP_KERNEL);
+ if (qphy->phy_reg) {
+ qphy->qusb_phy_reg_offset_cnt =
+ size / sizeof(*qphy->phy_reg);
+ if (qphy->qusb_phy_reg_offset_cnt > USB2_PHY_REG_MAX) {
+ dev_err(dev, "invalid reg offset count\n");
+ return -EINVAL;
+ }
+
+ of_property_read_u32_array(dev->of_node,
+ "qcom,qusb-phy-reg-offset",
+ qphy->phy_reg,
+ qphy->qusb_phy_reg_offset_cnt);
+ } else {
+ dev_err(dev, "err mem alloc for qusb_phy_reg_offset\n");
+ return -ENOMEM;
+ }
+ } else {
+ dev_err(dev, "err provide qcom,qmp-phy-reg-offset\n");
+ return -EINVAL;
+ }
+
+ size = 0;
of_get_property(dev->of_node, "qcom,qusb-phy-init-seq", &size);
if (size) {
qphy->qusb_phy_init_seq = devm_kzalloc(dev,
@@ -917,12 +946,6 @@
return ret;
}
- ret = of_property_read_u32(dev->of_node, "qcom,phy-auto-resume-offset",
- &qphy->phy_auto_resume_offset);
- if (ret)
- dev_dbg(dev, "error reading qcom,phy-auto-resume-offset %d\n",
- ret);
-
qphy->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(qphy->vdd)) {
dev_err(dev, "unable to get vdd supply\n");
diff --git a/drivers/vfio/vfio_iommu_spapr_tce.c b/drivers/vfio/vfio_iommu_spapr_tce.c
index 79ddcb0..85d3e64 100644
--- a/drivers/vfio/vfio_iommu_spapr_tce.c
+++ b/drivers/vfio/vfio_iommu_spapr_tce.c
@@ -1292,6 +1292,10 @@
/* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n",
iommu_group_id(iommu_group), iommu_group); */
table_group = iommu_group_get_iommudata(iommu_group);
+ if (!table_group) {
+ ret = -ENODEV;
+ goto unlock_exit;
+ }
if (tce_groups_attached(container) && (!table_group->ops ||
!table_group->ops->take_ownership ||
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index e0c9842..11a72bc 100644
--- a/drivers/watchdog/bcm_kona_wdt.c
+++ b/drivers/watchdog/bcm_kona_wdt.c
@@ -304,6 +304,8 @@
if (!wdt)
return -ENOMEM;
+ spin_lock_init(&wdt->lock);
+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
wdt->base = devm_ioremap_resource(dev, res);
if (IS_ERR(wdt->base))
@@ -316,7 +318,6 @@
return ret;
}
- spin_lock_init(&wdt->lock);
platform_set_drvdata(pdev, wdt);
watchdog_set_drvdata(&bcm_kona_wdt_wdd, wdt);
bcm_kona_wdt_wdd.parent = &pdev->dev;
diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index 8e7a3d6..679f79f 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -409,9 +409,9 @@
if (map == SWIOTLB_MAP_ERROR)
return DMA_ERROR_CODE;
+ dev_addr = xen_phys_to_bus(map);
xen_dma_map_page(dev, pfn_to_page(map >> PAGE_SHIFT),
dev_addr, map & ~PAGE_MASK, size, dir, attrs);
- dev_addr = xen_phys_to_bus(map);
/*
* Ensure that the address returned is DMA'ble
@@ -567,13 +567,14 @@
sg_dma_len(sgl) = 0;
return 0;
}
+ dev_addr = xen_phys_to_bus(map);
xen_dma_map_page(hwdev, pfn_to_page(map >> PAGE_SHIFT),
dev_addr,
map & ~PAGE_MASK,
sg->length,
dir,
attrs);
- sg->dma_address = xen_phys_to_bus(map);
+ sg->dma_address = dev_addr;
} else {
/* we are not interested in the dma_addr returned by
* xen_dma_map_page, only in the potential cache flushes executed
diff --git a/fs/aio.c b/fs/aio.c
index 428484f..0fcb49a 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1085,7 +1085,8 @@
* Tell lockdep we inherited freeze protection from submission
* thread.
*/
- __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+ if (S_ISREG(file_inode(file)->i_mode))
+ __sb_writers_acquired(file_inode(file)->i_sb, SB_FREEZE_WRITE);
file_end_write(file);
}
@@ -1492,7 +1493,8 @@
* by telling it the lock got released so that it doesn't
* complain about held lock when we return to userspace.
*/
- __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
+ if (S_ISREG(file_inode(file)->i_mode))
+ __sb_writers_release(file_inode(file)->i_sb, SB_FREEZE_WRITE);
}
kfree(iovec);
return ret;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 2472af2..cfd724f 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -2296,6 +2296,7 @@
goto end_coredump;
}
}
+ dump_truncate(cprm);
if (!elf_core_write_extra_data(cprm))
goto end_coredump;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index bddbae7..a2a014b 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -4480,8 +4480,19 @@
if (found_type > min_type) {
del_item = 1;
} else {
- if (item_end < new_size)
+ if (item_end < new_size) {
+ /*
+ * With NO_HOLES mode, for the following mapping
+ *
+ * [0-4k][hole][8k-12k]
+ *
+ * if truncating isize down to 6k, it ends up
+ * isize being 8k.
+ */
+ if (btrfs_fs_incompat(root->fs_info, NO_HOLES))
+ last_size = new_size;
break;
+ }
if (found_key.offset >= new_size)
del_item = 1;
else
@@ -7235,7 +7246,6 @@
struct extent_map *em = NULL;
int ret;
- down_read(&BTRFS_I(inode)->dio_sem);
if (type != BTRFS_ORDERED_NOCOW) {
em = create_pinned_em(inode, start, len, orig_start,
block_start, block_len, orig_block_len,
@@ -7254,7 +7264,6 @@
em = ERR_PTR(ret);
}
out:
- up_read(&BTRFS_I(inode)->dio_sem);
return em;
}
@@ -8707,6 +8716,7 @@
dio_data.unsubmitted_oe_range_start = (u64)offset;
dio_data.unsubmitted_oe_range_end = (u64)offset;
current->journal_info = &dio_data;
+ down_read(&BTRFS_I(inode)->dio_sem);
} else if (test_bit(BTRFS_INODE_READDIO_NEED_LOCK,
&BTRFS_I(inode)->runtime_flags)) {
inode_dio_end(inode);
@@ -8719,6 +8729,7 @@
iter, btrfs_get_blocks_direct, NULL,
btrfs_submit_direct, flags);
if (iov_iter_rw(iter) == WRITE) {
+ up_read(&BTRFS_I(inode)->dio_sem);
current->journal_info = NULL;
if (ret < 0 && ret != -EIOCBQUEUED) {
if (dio_data.reserve)
diff --git a/fs/coredump.c b/fs/coredump.c
index 8bdda8e..00a900a 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -833,3 +833,21 @@
return mod ? dump_skip(cprm, align - mod) : 1;
}
EXPORT_SYMBOL(dump_align);
+
+/*
+ * Ensures that file size is big enough to contain the current file
+ * postion. This prevents gdb from complaining about a truncated file
+ * if the last "write" to the file was dump_skip.
+ */
+void dump_truncate(struct coredump_params *cprm)
+{
+ struct file *file = cprm->file;
+ loff_t offset;
+
+ if (file->f_op->llseek && file->f_op->llseek != no_llseek) {
+ offset = file->f_op->llseek(file, 0, SEEK_CUR);
+ if (i_size_read(file->f_mapping->host) < offset)
+ do_truncate(file->f_path.dentry, offset, 0, file);
+ }
+}
+EXPORT_SYMBOL(dump_truncate);
diff --git a/fs/nfs/callback.c b/fs/nfs/callback.c
index 484bebc..0a21150 100644
--- a/fs/nfs/callback.c
+++ b/fs/nfs/callback.c
@@ -279,7 +279,7 @@
printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
cb_info->users);
- serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
+ serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
if (!serv) {
printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
return ERR_PTR(-ENOMEM);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fc9b049..401ea6e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2343,8 +2343,6 @@
if ((mask & ~cache.mask & (MAY_READ | MAY_EXEC)) == 0)
return 0;
- /* even though OPEN succeeded, access is denied. Close the file */
- nfs4_close_state(state, fmode);
return -EACCES;
}
@@ -8431,6 +8429,7 @@
size_t max_pages = max_response_pages(server);
dprintk("--> %s\n", __func__);
+ nfs4_sequence_free_slot(&lgp->res.seq_res);
nfs4_free_pages(lgp->args.layout.pages, max_pages);
pnfs_put_layout_hdr(NFS_I(inode)->layout);
put_nfs_open_context(lgp->args.ctx);
@@ -8505,7 +8504,6 @@
/* if layoutp->len is 0, nfs4_layoutget_prepare called rpc_exit */
if (status == 0 && lgp->res.layoutp->len)
lseg = pnfs_layout_process(lgp);
- nfs4_sequence_free_slot(&lgp->res.seq_res);
rpc_put_task(task);
dprintk("<-- %s status=%d\n", __func__, status);
if (status)
diff --git a/fs/ocfs2/cluster/heartbeat.c b/fs/ocfs2/cluster/heartbeat.c
index 636abcb..5e8709a 100644
--- a/fs/ocfs2/cluster/heartbeat.c
+++ b/fs/ocfs2/cluster/heartbeat.c
@@ -2242,13 +2242,13 @@
spin_unlock(&o2hb_live_lock);
}
-static ssize_t o2hb_heartbeat_group_threshold_show(struct config_item *item,
+static ssize_t o2hb_heartbeat_group_dead_threshold_show(struct config_item *item,
char *page)
{
return sprintf(page, "%u\n", o2hb_dead_threshold);
}
-static ssize_t o2hb_heartbeat_group_threshold_store(struct config_item *item,
+static ssize_t o2hb_heartbeat_group_dead_threshold_store(struct config_item *item,
const char *page, size_t count)
{
unsigned long tmp;
@@ -2297,11 +2297,11 @@
}
-CONFIGFS_ATTR(o2hb_heartbeat_group_, threshold);
+CONFIGFS_ATTR(o2hb_heartbeat_group_, dead_threshold);
CONFIGFS_ATTR(o2hb_heartbeat_group_, mode);
static struct configfs_attribute *o2hb_heartbeat_group_attrs[] = {
- &o2hb_heartbeat_group_attr_threshold,
+ &o2hb_heartbeat_group_attr_dead_threshold,
&o2hb_heartbeat_group_attr_mode,
NULL,
};
diff --git a/include/dt-bindings/msm/msm-bus-ids.h b/include/dt-bindings/msm/msm-bus-ids.h
index 8bd30d4..bc87beb 100644
--- a/include/dt-bindings/msm/msm-bus-ids.h
+++ b/include/dt-bindings/msm/msm-bus-ids.h
@@ -250,7 +250,8 @@
#define MSM_BUS_MASTER_CAMNOC_HF0_UNCOMP 146
#define MSM_BUS_MASTER_CAMNOC_HF1_UNCOMP 147
#define MSM_BUS_MASTER_CAMNOC_SF_UNCOMP 148
-#define MSM_BUS_MASTER_MASTER_LAST 149
+#define MSM_BUS_MASTER_GIC 149
+#define MSM_BUS_MASTER_MASTER_LAST 150
#define MSM_BUS_MASTER_LLCC_DISPLAY 20000
#define MSM_BUS_MASTER_MNOC_HF_MEM_NOC_DISPLAY 20001
@@ -330,7 +331,8 @@
#define MSM_BUS_A2NOC_SNOC_SLV 10065
#define MSM_BUS_SNOC_INT_2 10066
#define MSM_BUS_A0NOC_QDSS_INT 10067
-#define MSM_BUS_INT_LAST 10068
+#define MSM_BUS_SLAVE_ANOC_PCIE_A1NOC_SNOC 10068
+#define MSM_BUS_INT_LAST 10069
#define MSM_BUS_INT_TEST_ID 20000
#define MSM_BUS_INT_TEST_LAST 20050
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index c201017..97498be 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -243,6 +243,8 @@
void bpf_map_put_with_uref(struct bpf_map *map);
void bpf_map_put(struct bpf_map *map);
int bpf_map_precharge_memlock(u32 pages);
+void *bpf_map_area_alloc(size_t size);
+void bpf_map_area_free(void *base);
extern int sysctl_unprivileged_bpf_disabled;
diff --git a/include/linux/coredump.h b/include/linux/coredump.h
index d016a12..28ffa94 100644
--- a/include/linux/coredump.h
+++ b/include/linux/coredump.h
@@ -14,6 +14,7 @@
extern int dump_skip(struct coredump_params *cprm, size_t nr);
extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
extern int dump_align(struct coredump_params *cprm, int align);
+extern void dump_truncate(struct coredump_params *cprm);
#ifdef CONFIG_COREDUMP
extern void do_coredump(const siginfo_t *siginfo);
#else
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 0668534..6e664f6 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -40,6 +40,14 @@
};
/**
+* enum ipa_ipv6ct_en_type - IPv6CT setting type in IPA end-point
+*/
+enum ipa_ipv6ct_en_type {
+ IPA_BYPASS_IPV6CT,
+ IPA_ENABLE_IPV6CT,
+};
+
+/**
* enum ipa_mode_type - mode setting type in IPA end-point
* @BASIC: basic mode
* @ENABLE_FRAMING_HDLC: not currently supported
@@ -119,6 +127,19 @@
};
/**
+ * struct ipa_ep_cfg_conn_track - IPv6 Connection tracking configuration in
+ * IPA end-point
+ * @conn_track_en: Defines speculative conn_track action, means if specific
+ * pipe needs to have UL/DL IPv6 Connection Tracking or Bybass
+ * IPv6 Connection Tracking. 0: Bypass IPv6 Connection Tracking
+ * 1: IPv6 UL/DL Connection Tracking.
+ * Valid for Input Pipes only (IPA consumer)
+ */
+struct ipa_ep_cfg_conn_track {
+ enum ipa_ipv6ct_en_type conn_track_en;
+};
+
+/**
* struct ipa_ep_cfg_hdr - header configuration in IPA end-point
*
* @hdr_len:Header length in bytes to be added/removed. Assuming
@@ -387,6 +408,7 @@
/**
* struct ipa_ep_cfg - configuration of IPA end-point
* @nat: NAT parmeters
+ * @conn_track: IPv6CT parmeters
* @hdr: Header parameters
* @hdr_ext: Extended header parameters
* @mode: Mode parameters
@@ -400,6 +422,7 @@
*/
struct ipa_ep_cfg {
struct ipa_ep_cfg_nat nat;
+ struct ipa_ep_cfg_conn_track conn_track;
struct ipa_ep_cfg_hdr hdr;
struct ipa_ep_cfg_hdr_ext hdr_ext;
struct ipa_ep_cfg_mode mode;
@@ -1172,6 +1195,9 @@
int ipa_cfg_ep_nat(u32 clnt_hdl, const struct ipa_ep_cfg_nat *ipa_ep_cfg);
+int ipa_cfg_ep_conn_track(u32 clnt_hdl,
+ const struct ipa_ep_cfg_conn_track *ep_conn_track);
+
int ipa_cfg_ep_hdr(u32 clnt_hdl, const struct ipa_ep_cfg_hdr *ipa_ep_cfg);
int ipa_cfg_ep_hdr_ext(u32 clnt_hdl,
@@ -1558,6 +1584,12 @@
return -EPERM;
}
+static inline int ipa_cfg_ep_conn_track(u32 clnt_hdl,
+ const struct ipa_ep_cfg_conn_track *ep_conn_track)
+{
+ return -EPERM
+}
+
static inline int ipa_cfg_ep_hdr(u32 clnt_hdl,
const struct ipa_ep_cfg_hdr *ipa_ep_cfg)
{
diff --git a/include/linux/phy.h b/include/linux/phy.h
index bd22670..6c9b1e0 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -401,6 +401,9 @@
u32 advertising;
u32 lp_advertising;
+ /* Energy efficient ethernet modes which should be prohibited */
+ u32 eee_broken_modes;
+
int autoneg;
int link_timeout;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 4381570..8e7a431 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -271,6 +271,7 @@
POWER_SUPPLY_TYPE_USB_HVDCP_3, /* Efficient High Voltage DCP */
POWER_SUPPLY_TYPE_USB_PD, /* Power Delivery */
POWER_SUPPLY_TYPE_WIRELESS, /* Accessory Charger Adapters */
+ POWER_SUPPLY_TYPE_USB_FLOAT, /* Floating charger */
POWER_SUPPLY_TYPE_BMS, /* Battery Monitor System */
POWER_SUPPLY_TYPE_PARALLEL, /* Parallel Path */
POWER_SUPPLY_TYPE_MAIN, /* Main Path */
diff --git a/include/linux/restart_block.h b/include/linux/restart_block.h
new file mode 100644
index 0000000..0d905d8
--- /dev/null
+++ b/include/linux/restart_block.h
@@ -0,0 +1,51 @@
+/*
+ * Common syscall restarting data
+ */
+#ifndef __LINUX_RESTART_BLOCK_H
+#define __LINUX_RESTART_BLOCK_H
+
+#include <linux/compiler.h>
+#include <linux/types.h>
+
+struct timespec;
+struct compat_timespec;
+struct pollfd;
+
+/*
+ * System call restart block.
+ */
+struct restart_block {
+ long (*fn)(struct restart_block *);
+ union {
+ /* For futex_wait and futex_wait_requeue_pi */
+ struct {
+ u32 __user *uaddr;
+ u32 val;
+ u32 flags;
+ u32 bitset;
+ u64 time;
+ u32 __user *uaddr2;
+ } futex;
+ /* For nanosleep */
+ struct {
+ clockid_t clockid;
+ struct timespec __user *rmtp;
+#ifdef CONFIG_COMPAT
+ struct compat_timespec __user *compat_rmtp;
+#endif
+ u64 expires;
+ } nanosleep;
+ /* For poll */
+ struct {
+ struct pollfd __user *ufds;
+ int nfds;
+ int has_timeout;
+ unsigned long tv_sec;
+ unsigned long tv_nsec;
+ } poll;
+ };
+};
+
+extern long do_no_restart_syscall(struct restart_block *parm);
+
+#endif /* __LINUX_RESTART_BLOCK_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 864c7d7..ff65b44 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1499,6 +1499,7 @@
*/
u64 mark_start;
u32 sum, demand;
+ u32 coloc_demand;
u32 sum_history[RAVG_HIST_SIZE_MAX];
u32 *curr_window_cpu, *prev_window_cpu;
u32 curr_window, prev_window;
diff --git a/include/linux/seemp_instrumentation.h b/include/linux/seemp_instrumentation.h
index 21bc436..ff09bd2 100644
--- a/include/linux/seemp_instrumentation.h
+++ b/include/linux/seemp_instrumentation.h
@@ -15,6 +15,8 @@
#ifdef CONFIG_SEEMP_CORE
#include <linux/kernel.h>
+#include <linux/seemp_api.h>
+#include <linux/socket.h>
#define MAX_BUF_SIZE 188
@@ -66,11 +68,33 @@
seemp_logk_kernel_end(blck);
}
+
+static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
+ __u8 asset_category, __u8 response)
+{
+ char *buf = NULL;
+ void *blck = NULL;
+
+ blck = seemp_setup_buf(&buf);
+ if (!blck)
+ return;
+
+ SEEMP_LOGK_RECORD(SEEMP_API_kernel__rtic,
+ "app_pid=%llu,rtic_type=%u,asset_id=%s,asset_category=%u,response=%u",
+ actor, type, asset_id, asset_category, response);
+
+ seemp_logk_kernel_end(blck);
+}
#else
static inline void seemp_logk_sendto(int fd, void __user *buff,
size_t len, unsigned int flags, struct sockaddr __user *addr,
int addr_len)
{
}
+
+static inline void seemp_logk_rtic(__u8 type, __u64 actor, __u8 asset_id[0x20],
+ __u8 asset_category, __u8 response)
+{
+}
#endif
#endif
diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h
index 2873baf..5837387 100644
--- a/include/linux/thread_info.h
+++ b/include/linux/thread_info.h
@@ -9,51 +9,18 @@
#include <linux/types.h>
#include <linux/bug.h>
-
-struct timespec;
-struct compat_timespec;
+#include <linux/restart_block.h>
#ifdef CONFIG_THREAD_INFO_IN_TASK
+/*
+ * For CONFIG_THREAD_INFO_IN_TASK kernels we need <asm/current.h> for the
+ * definition of current, but for !CONFIG_THREAD_INFO_IN_TASK kernels,
+ * including <asm/current.h> can cause a circular dependency on some platforms.
+ */
+#include <asm/current.h>
#define current_thread_info() ((struct thread_info *)current)
#endif
-/*
- * System call restart block.
- */
-struct restart_block {
- long (*fn)(struct restart_block *);
- union {
- /* For futex_wait and futex_wait_requeue_pi */
- struct {
- u32 __user *uaddr;
- u32 val;
- u32 flags;
- u32 bitset;
- u64 time;
- u32 __user *uaddr2;
- } futex;
- /* For nanosleep */
- struct {
- clockid_t clockid;
- struct timespec __user *rmtp;
-#ifdef CONFIG_COMPAT
- struct compat_timespec __user *compat_rmtp;
-#endif
- u64 expires;
- } nanosleep;
- /* For poll */
- struct {
- struct pollfd __user *ufds;
- int nfds;
- int has_timeout;
- unsigned long tv_sec;
- unsigned long tv_nsec;
- } poll;
- };
-};
-
-extern long do_no_restart_syscall(struct restart_block *parm);
-
#include <linux/bitops.h>
#include <asm/thread_info.h>
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 31947b9..835c30e 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -944,10 +944,6 @@
struct flow_cache_object flo;
struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX];
int num_pols, num_xfrms;
-#ifdef CONFIG_XFRM_SUB_POLICY
- struct flowi *origin;
- struct xfrm_selector *partner;
-#endif
u32 xfrm_genid;
u32 policy_genid;
u32 route_mtu_cached;
@@ -963,12 +959,6 @@
dst_release(xdst->route);
if (likely(xdst->u.dst.xfrm))
xfrm_state_put(xdst->u.dst.xfrm);
-#ifdef CONFIG_XFRM_SUB_POLICY
- kfree(xdst->origin);
- xdst->origin = NULL;
- kfree(xdst->partner);
- xdst->partner = NULL;
-#endif
}
#endif
diff --git a/include/soc/qcom/secure_buffer.h b/include/soc/qcom/secure_buffer.h
index f0f81a9..a08cfe1 100644
--- a/include/soc/qcom/secure_buffer.h
+++ b/include/soc/qcom/secure_buffer.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2017, 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
@@ -37,7 +37,9 @@
VMID_CP_APP = 0x12,
VMID_WLAN = 0x18,
VMID_WLAN_CE = 0x19,
+ VMID_CP_SPSS_SP = 0x1A,
VMID_CP_CAMERA_PREVIEW = 0x1D,
+ VMID_CP_SPSS_SP_SHARED = 0x22,
VMID_LAST,
VMID_INVAL = -1
};
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index bf8f149..e94a82b 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -236,6 +236,7 @@
__field( int, samples )
__field(enum task_event, evt )
__field(unsigned int, demand )
+ __field(unsigned int, coloc_demand )
__field(unsigned int, pred_demand )
__array( u32, hist, RAVG_HIST_SIZE_MAX)
__field(unsigned int, nr_big_tasks )
@@ -249,6 +250,7 @@
__entry->samples = samples;
__entry->evt = evt;
__entry->demand = p->ravg.demand;
+ __entry->coloc_demand = p->ravg.coloc_demand;
__entry->pred_demand = p->ravg.pred_demand;
memcpy(__entry->hist, p->ravg.sum_history,
RAVG_HIST_SIZE_MAX * sizeof(u32));
@@ -256,12 +258,12 @@
__entry->cpu = rq->cpu;
),
- TP_printk("%d (%s): runtime %u samples %d event %s demand %u pred_demand %u"
+ TP_printk("%d (%s): runtime %u samples %d event %s demand %u coloc_demand %u pred_demand %u"
" (hist: %u %u %u %u %u) cpu %d nr_big %u",
__entry->pid, __entry->comm,
__entry->runtime, __entry->samples,
task_event_names[__entry->evt],
- __entry->demand, __entry->pred_demand,
+ __entry->demand, __entry->coloc_demand, __entry->pred_demand,
__entry->hist[0], __entry->hist[1],
__entry->hist[2], __entry->hist[3],
__entry->hist[4], __entry->cpu, __entry->nr_big_tasks)
@@ -317,6 +319,7 @@
__field( u64, irqtime )
__field(enum task_event, evt )
__field(unsigned int, demand )
+ __field(unsigned int, coloc_demand )
__field(unsigned int, sum )
__field( int, cpu )
__field(unsigned int, pred_demand )
@@ -350,6 +353,7 @@
__entry->mark_start = p->ravg.mark_start;
__entry->delta_m = (wallclock - p->ravg.mark_start);
__entry->demand = p->ravg.demand;
+ __entry->coloc_demand = p->ravg.coloc_demand;
__entry->sum = p->ravg.sum;
__entry->irqtime = irqtime;
__entry->pred_demand = p->ravg.pred_demand;
@@ -370,12 +374,12 @@
__entry->prev_top = rq->prev_top;
),
- TP_printk("wc %llu ws %llu delta %llu event %s cpu %d cur_freq %u cur_pid %d task %d (%s) ms %llu delta %llu demand %u sum %u irqtime %llu pred_demand %u rq_cs %llu rq_ps %llu cur_window %u (%s) prev_window %u (%s) nt_cs %llu nt_ps %llu active_wins %u grp_cs %lld grp_ps %lld, grp_nt_cs %llu, grp_nt_ps: %llu curr_top %u prev_top %u",
+ TP_printk("wc %llu ws %llu delta %llu event %s cpu %d cur_freq %u cur_pid %d task %d (%s) ms %llu delta %llu demand %u coloc_demand: %u sum %u irqtime %llu pred_demand %u rq_cs %llu rq_ps %llu cur_window %u (%s) prev_window %u (%s) nt_cs %llu nt_ps %llu active_wins %u grp_cs %lld grp_ps %lld, grp_nt_cs %llu, grp_nt_ps: %llu curr_top %u prev_top %u",
__entry->wallclock, __entry->win_start, __entry->delta,
task_event_names[__entry->evt], __entry->cpu,
__entry->cur_freq, __entry->cur_pid,
__entry->pid, __entry->comm, __entry->mark_start,
- __entry->delta_m, __entry->demand,
+ __entry->delta_m, __entry->demand, __entry->coloc_demand,
__entry->sum, __entry->irqtime, __entry->pred_demand,
__entry->rq_cs, __entry->rq_ps, __entry->curr_window,
__window_print(p, __get_dynamic_array(curr_sum), nr_cpu_ids),
diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h
index 8e54723..5c22e8c 100644
--- a/include/uapi/linux/ethtool.h
+++ b/include/uapi/linux/ethtool.h
@@ -1368,6 +1368,8 @@
ETHTOOL_LINK_MODE_10000baseLR_Full_BIT = 44,
ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT = 45,
ETHTOOL_LINK_MODE_10000baseER_Full_BIT = 46,
+ ETHTOOL_LINK_MODE_2500baseT_Full_BIT = 47,
+ ETHTOOL_LINK_MODE_5000baseT_Full_BIT = 48,
/* Last allowed bit for __ETHTOOL_LINK_MODE_LEGACY_MASK is bit
@@ -1377,7 +1379,7 @@
*/
__ETHTOOL_LINK_MODE_LAST
- = ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
+ = ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
};
#define __ETHTOOL_LINK_MODE_LEGACY_MASK(base_name) \
diff --git a/include/uapi/linux/seemp_api.h b/include/uapi/linux/seemp_api.h
index 4dfc257..a42ad4b 100644
--- a/include/uapi/linux/seemp_api.h
+++ b/include/uapi/linux/seemp_api.h
@@ -1,6 +1,8 @@
#ifndef _SEEMP_API_H_
#define _SEEMP_API_H_
+#define SEEMP_API_kernel__rtic 100000
+
#define SEEMP_API_kernel__oom_adjust_write 0
#define SEEMP_API_kernel__sendto 1
#define SEEMP_API_kernel__recvfrom 2
diff --git a/include/uapi/linux/seemp_param_id.h b/include/uapi/linux/seemp_param_id.h
index c72c579..d8b9f78 100644
--- a/include/uapi/linux/seemp_param_id.h
+++ b/include/uapi/linux/seemp_param_id.h
@@ -15,7 +15,11 @@
#define PARAM_ID_SENSOR 8
#define PARAM_ID_WINDOW_TYPE 9
#define PARAM_ID_WINDOW_FLAG 10
-#define NUM_PARAM_IDS 11
+#define PARAM_ID_RTIC_TYPE 11
+#define PARAM_ID_RTIC_ASSET_ID 12
+#define PARAM_ID_RTIC_ASSET_CATEGORY 13
+#define PARAM_ID_RTIC_RESPONSE 14
+#define NUM_PARAM_IDS 15
static inline int param_id_index(const char *param, const char *end)
{
@@ -44,6 +48,14 @@
id = 9;
else if ((len == 11) && !memcmp(param, "window_flag", 11))
id = 10;
+ else if ((len == 9) && !memcmp(param, "rtic_type", 9))
+ id = 11;
+ else if ((len == 8) && !memcmp(param, "asset_id", 8))
+ id = 12;
+ else if ((len == 14) && !memcmp(param, "asset_category", 14))
+ id = 13;
+ else if ((len == 8) && !memcmp(param, "response", 8))
+ id = 14;
return id;
}
@@ -86,6 +98,18 @@
case 10:
name = "window_flag";
break;
+ case 11:
+ name = "rtic_type";
+ break;
+ case 12:
+ name = "asset_id";
+ break;
+ case 13:
+ name = "asset_category";
+ break;
+ case 14:
+ name = "response";
+ break;
}
return name;
}
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index a2ac051..f3721e1 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -11,7 +11,6 @@
*/
#include <linux/bpf.h>
#include <linux/err.h>
-#include <linux/vmalloc.h>
#include <linux/slab.h>
#include <linux/mm.h>
#include <linux/filter.h>
@@ -74,14 +73,10 @@
if (array_size >= U32_MAX - PAGE_SIZE)
return ERR_PTR(-ENOMEM);
-
/* allocate all map elements and zero-initialize them */
- array = kzalloc(array_size, GFP_USER | __GFP_NOWARN);
- if (!array) {
- array = vzalloc(array_size);
- if (!array)
- return ERR_PTR(-ENOMEM);
- }
+ array = bpf_map_area_alloc(array_size);
+ if (!array)
+ return ERR_PTR(-ENOMEM);
/* copy mandatory map attributes */
array->map.map_type = attr->map_type;
@@ -97,7 +92,7 @@
if (array_size >= U32_MAX - PAGE_SIZE ||
elem_size > PCPU_MIN_UNIT_SIZE || bpf_array_alloc_percpu(array)) {
- kvfree(array);
+ bpf_map_area_free(array);
return ERR_PTR(-ENOMEM);
}
out:
@@ -262,7 +257,7 @@
if (array->map.map_type == BPF_MAP_TYPE_PERCPU_ARRAY)
bpf_array_free_percpu(array);
- kvfree(array);
+ bpf_map_area_free(array);
}
static const struct bpf_map_ops array_ops = {
@@ -319,7 +314,8 @@
/* make sure it's empty */
for (i = 0; i < array->map.max_entries; i++)
BUG_ON(array->ptrs[i] != NULL);
- kvfree(array);
+
+ bpf_map_area_free(array);
}
static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index ad1bc67..ad2f0ed 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -13,7 +13,6 @@
#include <linux/bpf.h>
#include <linux/jhash.h>
#include <linux/filter.h>
-#include <linux/vmalloc.h>
#include "percpu_freelist.h"
struct bucket {
@@ -84,14 +83,15 @@
free_percpu(pptr);
}
free_elems:
- vfree(htab->elems);
+ bpf_map_area_free(htab->elems);
}
static int prealloc_elems_and_freelist(struct bpf_htab *htab)
{
int err = -ENOMEM, i;
- htab->elems = vzalloc(htab->elem_size * htab->map.max_entries);
+ htab->elems = bpf_map_area_alloc(htab->elem_size *
+ htab->map.max_entries);
if (!htab->elems)
return -ENOMEM;
@@ -227,14 +227,10 @@
goto free_htab;
err = -ENOMEM;
- htab->buckets = kmalloc_array(htab->n_buckets, sizeof(struct bucket),
- GFP_USER | __GFP_NOWARN);
-
- if (!htab->buckets) {
- htab->buckets = vmalloc(htab->n_buckets * sizeof(struct bucket));
- if (!htab->buckets)
- goto free_htab;
- }
+ htab->buckets = bpf_map_area_alloc(htab->n_buckets *
+ sizeof(struct bucket));
+ if (!htab->buckets)
+ goto free_htab;
for (i = 0; i < htab->n_buckets; i++) {
INIT_HLIST_HEAD(&htab->buckets[i].head);
@@ -258,7 +254,7 @@
free_extra_elems:
free_percpu(htab->extra_elems);
free_buckets:
- kvfree(htab->buckets);
+ bpf_map_area_free(htab->buckets);
free_htab:
kfree(htab);
return ERR_PTR(err);
@@ -715,7 +711,7 @@
pcpu_freelist_destroy(&htab->freelist);
}
free_percpu(htab->extra_elems);
- kvfree(htab->buckets);
+ bpf_map_area_free(htab->buckets);
kfree(htab);
}
diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
index 732ae16..be85191 100644
--- a/kernel/bpf/stackmap.c
+++ b/kernel/bpf/stackmap.c
@@ -7,7 +7,6 @@
#include <linux/bpf.h>
#include <linux/jhash.h>
#include <linux/filter.h>
-#include <linux/vmalloc.h>
#include <linux/stacktrace.h>
#include <linux/perf_event.h>
#include "percpu_freelist.h"
@@ -32,7 +31,7 @@
u32 elem_size = sizeof(struct stack_map_bucket) + smap->map.value_size;
int err;
- smap->elems = vzalloc(elem_size * smap->map.max_entries);
+ smap->elems = bpf_map_area_alloc(elem_size * smap->map.max_entries);
if (!smap->elems)
return -ENOMEM;
@@ -45,7 +44,7 @@
return 0;
free_elems:
- vfree(smap->elems);
+ bpf_map_area_free(smap->elems);
return err;
}
@@ -76,12 +75,9 @@
if (cost >= U32_MAX - PAGE_SIZE)
return ERR_PTR(-E2BIG);
- smap = kzalloc(cost, GFP_USER | __GFP_NOWARN);
- if (!smap) {
- smap = vzalloc(cost);
- if (!smap)
- return ERR_PTR(-ENOMEM);
- }
+ smap = bpf_map_area_alloc(cost);
+ if (!smap)
+ return ERR_PTR(-ENOMEM);
err = -E2BIG;
cost += n_buckets * (value_size + sizeof(struct stack_map_bucket));
@@ -112,7 +108,7 @@
put_buffers:
put_callchain_buffers();
free_smap:
- kvfree(smap);
+ bpf_map_area_free(smap);
return ERR_PTR(err);
}
@@ -262,9 +258,9 @@
/* wait for bpf programs to complete before freeing stack map */
synchronize_rcu();
- vfree(smap->elems);
+ bpf_map_area_free(smap->elems);
pcpu_freelist_destroy(&smap->freelist);
- kvfree(smap);
+ bpf_map_area_free(smap);
put_callchain_buffers();
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 5e668da..cd62aea 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -12,6 +12,8 @@
#include <linux/bpf.h>
#include <linux/syscalls.h>
#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/mmzone.h>
#include <linux/anon_inodes.h>
#include <linux/file.h>
#include <linux/license.h>
@@ -48,6 +50,30 @@
list_add(&tl->list_node, &bpf_map_types);
}
+void *bpf_map_area_alloc(size_t size)
+{
+ /* We definitely need __GFP_NORETRY, so OOM killer doesn't
+ * trigger under memory pressure as we really just want to
+ * fail instead.
+ */
+ const gfp_t flags = __GFP_NOWARN | __GFP_NORETRY | __GFP_ZERO;
+ void *area;
+
+ if (size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) {
+ area = kmalloc(size, GFP_USER | flags);
+ if (area != NULL)
+ return area;
+ }
+
+ return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
+ PAGE_KERNEL);
+}
+
+void bpf_map_area_free(void *area)
+{
+ kvfree(area);
+}
+
int bpf_map_precharge_memlock(u32 pages)
{
struct user_struct *user = get_current_user();
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 3577ec6a..7e3dfa6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -409,12 +409,25 @@
cpu_notify(CPU_ONLINE, cpu);
return 0;
}
+static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st);
static int bringup_wait_for_ap(unsigned int cpu)
{
struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu);
+ /* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */
wait_for_completion(&st->done);
+ BUG_ON(!cpu_online(cpu));
+
+ /* Unpark the stopper thread and the hotplug thread of the target cpu */
+ stop_machine_unpark(cpu);
+ kthread_unpark(st->thread);
+
+ /* Should we go further up ? */
+ if (st->target > CPUHP_AP_ONLINE_IDLE) {
+ __cpuhp_kick_ap_work(st);
+ wait_for_completion(&st->done);
+ }
return st->result;
}
@@ -437,9 +450,7 @@
cpu_notify(CPU_UP_CANCELED, cpu);
return ret;
}
- ret = bringup_wait_for_ap(cpu);
- BUG_ON(!cpu_online(cpu));
- return ret;
+ return bringup_wait_for_ap(cpu);
}
/*
@@ -979,31 +990,20 @@
}
/*
- * Called from the idle task. We need to set active here, so we can kick off
- * the stopper thread and unpark the smpboot threads. If the target state is
- * beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the
- * cpu further.
+ * Called from the idle task. Wake up the controlling task which brings the
+ * stopper and the hotplug thread of the upcoming CPU up and then delegates
+ * the rest of the online bringup to the hotplug thread.
*/
void cpuhp_online_idle(enum cpuhp_state state)
{
struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state);
- unsigned int cpu = smp_processor_id();
/* Happens for the boot cpu */
if (state != CPUHP_AP_ONLINE_IDLE)
return;
st->state = CPUHP_AP_ONLINE_IDLE;
-
- /* Unpark the stopper thread and the hotplug thread of this cpu */
- stop_machine_unpark(cpu);
- kthread_unpark(st->thread);
-
- /* Should we go further up ? */
- if (st->target > CPUHP_AP_ONLINE_IDLE)
- __cpuhp_kick_ap_work(st);
- else
- complete(&st->done);
+ complete(&st->done);
}
/* Requires cpu_add_remove_lock to be held */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d877aba..e2ac135 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -2279,7 +2279,7 @@
struct perf_event_context *ctx = event->ctx;
struct perf_cpu_context *cpuctx = __get_cpu_context(ctx);
struct perf_event_context *task_ctx = cpuctx->task_ctx;
- bool activate = true;
+ bool reprogram = true;
int ret = 0;
raw_spin_lock(&cpuctx->ctx.lock);
@@ -2287,27 +2287,26 @@
raw_spin_lock(&ctx->lock);
task_ctx = ctx;
- /* If we're on the wrong CPU, try again */
- if (task_cpu(ctx->task) != smp_processor_id()) {
+ reprogram = (ctx->task == current);
+
+ /*
+ * If the task is running, it must be running on this CPU,
+ * otherwise we cannot reprogram things.
+ *
+ * If its not running, we don't care, ctx->lock will
+ * serialize against it becoming runnable.
+ */
+ if (task_curr(ctx->task) && !reprogram) {
ret = -ESRCH;
goto unlock;
}
- /*
- * If we're on the right CPU, see if the task we target is
- * current, if not we don't have to activate the ctx, a future
- * context switch will do that for us.
- */
- if (ctx->task != current)
- activate = false;
- else
- WARN_ON_ONCE(cpuctx->task_ctx && cpuctx->task_ctx != ctx);
-
+ WARN_ON_ONCE(reprogram && cpuctx->task_ctx && cpuctx->task_ctx != ctx);
} else if (task_ctx) {
raw_spin_lock(&task_ctx->lock);
}
- if (activate) {
+ if (reprogram) {
ctx_sched_out(ctx, cpuctx, EVENT_TIME);
add_event_to_ctx(event, ctx);
ctx_resched(cpuctx, task_ctx);
@@ -2358,13 +2357,36 @@
/*
* Installing events is tricky because we cannot rely on ctx->is_active
* to be set in case this is the nr_events 0 -> 1 transition.
+ *
+ * Instead we use task_curr(), which tells us if the task is running.
+ * However, since we use task_curr() outside of rq::lock, we can race
+ * against the actual state. This means the result can be wrong.
+ *
+ * If we get a false positive, we retry, this is harmless.
+ *
+ * If we get a false negative, things are complicated. If we are after
+ * perf_event_context_sched_in() ctx::lock will serialize us, and the
+ * value must be correct. If we're before, it doesn't matter since
+ * perf_event_context_sched_in() will program the counter.
+ *
+ * However, this hinges on the remote context switch having observed
+ * our task->perf_event_ctxp[] store, such that it will in fact take
+ * ctx::lock in perf_event_context_sched_in().
+ *
+ * We do this by task_function_call(), if the IPI fails to hit the task
+ * we know any future context switch of task must see the
+ * perf_event_ctpx[] store.
*/
-again:
+
/*
- * Cannot use task_function_call() because we need to run on the task's
- * CPU regardless of whether its current or not.
+ * This smp_mb() orders the task->perf_event_ctxp[] store with the
+ * task_cpu() load, such that if the IPI then does not find the task
+ * running, a future context switch of that task must observe the
+ * store.
*/
- if (!cpu_function_call(task_cpu(task), __perf_install_in_context, event))
+ smp_mb();
+again:
+ if (!task_function_call(task, __perf_install_in_context, event))
return;
raw_spin_lock_irq(&ctx->lock);
@@ -2378,12 +2400,16 @@
raw_spin_unlock_irq(&ctx->lock);
return;
}
- raw_spin_unlock_irq(&ctx->lock);
/*
- * Since !ctx->is_active doesn't mean anything, we must IPI
- * unconditionally.
+ * If the task is not running, ctx->lock will avoid it becoming so,
+ * thus we can safely install the event.
*/
- goto again;
+ if (task_curr(task)) {
+ raw_spin_unlock_irq(&ctx->lock);
+ goto again;
+ }
+ add_event_to_ctx(event, ctx);
+ raw_spin_unlock_irq(&ctx->lock);
}
/*
diff --git a/kernel/kthread.c b/kernel/kthread.c
index 80bf7ba..b65854c 100644
--- a/kernel/kthread.c
+++ b/kernel/kthread.c
@@ -160,11 +160,9 @@
{
__set_current_state(TASK_PARKED);
while (test_bit(KTHREAD_SHOULD_PARK, &self->flags)) {
- preempt_disable();
if (!test_and_set_bit(KTHREAD_IS_PARKED, &self->flags))
complete(&self->parked);
- schedule_preempt_disabled();
- preempt_enable();
+ schedule();
__set_current_state(TASK_PARKED);
}
clear_bit(KTHREAD_IS_PARKED, &self->flags);
diff --git a/kernel/panic.c b/kernel/panic.c
index e6480e2..dbec387 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -249,7 +249,7 @@
* Delay timeout seconds before rebooting the machine.
* We can't use the "normal" timers since we just panicked.
*/
- pr_emerg("Rebooting in %d seconds..", panic_timeout);
+ pr_emerg("Rebooting in %d seconds..\n", panic_timeout);
for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {
touch_nmi_watchdog();
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index e756b83..b6a639b 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -752,6 +752,11 @@
sg_cpu->cpu = cpu;
sg_cpu->flags = SCHED_CPUFREQ_RT;
sg_cpu->iowait_boost_max = policy->cpuinfo.max_freq;
+ }
+
+ for_each_cpu(cpu, policy->cpus) {
+ struct sugov_cpu *sg_cpu = &per_cpu(sugov_cpu, cpu);
+
cpufreq_add_update_util_hook(cpu, &sg_cpu->update_util,
policy_is_shared(policy) ?
sugov_update_shared :
diff --git a/kernel/sched/loadavg.c b/kernel/sched/loadavg.c
index a2d6eb7..ec91fcc 100644
--- a/kernel/sched/loadavg.c
+++ b/kernel/sched/loadavg.c
@@ -201,8 +201,9 @@
struct rq *this_rq = this_rq();
/*
- * If we're still before the sample window, we're done.
+ * If we're still before the pending sample window, we're done.
*/
+ this_rq->calc_load_update = calc_load_update;
if (time_before(jiffies, this_rq->calc_load_update))
return;
@@ -211,7 +212,6 @@
* accounted through the nohz accounting, so skip the entire deal and
* sync up for the next window.
*/
- this_rq->calc_load_update = calc_load_update;
if (time_before(jiffies, this_rq->calc_load_update + 10))
this_rq->calc_load_update += LOAD_FREQ;
}
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index ae45283..69bbce2 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -1704,6 +1704,7 @@
pred_demand);
p->ravg.demand = demand;
+ p->ravg.coloc_demand = div64_u64(sum, sched_ravg_hist_size);
p->ravg.pred_demand = pred_demand;
if (__task_in_cum_window_demand(rq, p))
@@ -1982,6 +1983,7 @@
(u64)sched_ravg_window, 100);
p->ravg.demand = init_load_windows;
+ p->ravg.coloc_demand = init_load_windows;
p->ravg.pred_demand = 0;
for (i = 0; i < RAVG_HIST_SIZE_MAX; ++i)
p->ravg.sum_history[i] = init_load_windows;
@@ -2505,7 +2507,7 @@
(sched_ravg_window * sched_ravg_hist_size))
continue;
- combined_demand += p->ravg.demand;
+ combined_demand += p->ravg.coloc_demand;
}
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index ad1d296..b7812df 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -456,11 +456,11 @@
: 1UL << (BITS_PER_LONG - IO_TLB_SHIFT);
/*
- * For mappings greater than a page, we limit the stride (and
- * hence alignment) to a page size.
+ * For mappings greater than or equal to a page, we limit the stride
+ * (and hence alignment) to a page size.
*/
nslots = ALIGN(size, 1 << IO_TLB_SHIFT) >> IO_TLB_SHIFT;
- if (size > PAGE_SIZE)
+ if (size >= PAGE_SIZE)
stride = (1 << (PAGE_SHIFT - IO_TLB_SHIFT));
else
stride = 1;
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index d5b2b75..e7d5db9 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1227,8 +1227,11 @@
*/
if (unlikely(pmd_trans_migrating(*fe->pmd))) {
page = pmd_page(*fe->pmd);
+ if (!get_page_unless_zero(page))
+ goto out_unlock;
spin_unlock(fe->ptl);
wait_on_page_locked(page);
+ put_page(page);
goto out;
}
@@ -1260,8 +1263,11 @@
/* Migration could have started since the pmd_trans_migrating check */
if (!page_locked) {
+ if (!get_page_unless_zero(page))
+ goto out_unlock;
spin_unlock(fe->ptl);
wait_on_page_locked(page);
+ put_page(page);
page_nid = -1;
goto out;
}
diff --git a/mm/swap_cgroup.c b/mm/swap_cgroup.c
index 454d6d7..3405b4e 100644
--- a/mm/swap_cgroup.c
+++ b/mm/swap_cgroup.c
@@ -204,6 +204,8 @@
struct page *page = map[i];
if (page)
__free_page(page);
+ if (!(i % SWAP_CLUSTER_MAX))
+ cond_resched();
}
vfree(map);
}
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index f2481cb..195de42 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -244,11 +244,21 @@
*/
VIRTUAL_BUG_ON(!is_vmalloc_or_module_addr(vmalloc_addr));
+ /*
+ * Don't dereference bad PUD or PMD (below) entries. This will also
+ * identify huge mappings, which we may encounter on architectures
+ * that define CONFIG_HAVE_ARCH_HUGE_VMAP=y. Such regions will be
+ * identified as vmalloc addresses by is_vmalloc_addr(), but are
+ * not [unambiguously] associated with a struct page, so there is
+ * no correct value to return for them.
+ */
if (!pgd_none(*pgd)) {
pud_t *pud = pud_offset(pgd, addr);
- if (!pud_none(*pud)) {
+ WARN_ON_ONCE(pud_bad(*pud));
+ if (!pud_none(*pud) && !pud_bad(*pud)) {
pmd_t *pmd = pmd_offset(pud, addr);
- if (!pmd_none(*pmd)) {
+ WARN_ON_ONCE(pmd_bad(*pmd));
+ if (!pmd_none(*pmd) && !pmd_bad(*pmd)) {
pte_t *ptep, pte;
ptep = pte_offset_map(pmd, addr);
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index f2531ad..8d213f9 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -277,7 +277,8 @@
return 0;
out_free_newdev:
- free_netdev(new_dev);
+ if (new_dev->reg_state == NETREG_UNINITIALIZED)
+ free_netdev(new_dev);
return err;
}
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c
index 59ce1fc..71b6ab2 100644
--- a/net/caif/cfpkt_skbuff.c
+++ b/net/caif/cfpkt_skbuff.c
@@ -81,11 +81,7 @@
{
struct sk_buff *skb;
- if (likely(in_interrupt()))
- skb = alloc_skb(len + pfx, GFP_ATOMIC);
- else
- skb = alloc_skb(len + pfx, GFP_KERNEL);
-
+ skb = alloc_skb(len + pfx, GFP_ATOMIC);
if (unlikely(skb == NULL))
return NULL;
diff --git a/net/core/dev.c b/net/core/dev.c
index a143dbd..8c1860a 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1252,8 +1252,9 @@
if (!new_ifalias)
return -ENOMEM;
dev->ifalias = new_ifalias;
+ memcpy(dev->ifalias, alias, len);
+ dev->ifalias[len] = 0;
- strlcpy(dev->ifalias, alias, len+1);
return len;
}
diff --git a/net/core/dst.c b/net/core/dst.c
index 656b70d..39cc119 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -470,6 +470,20 @@
spin_lock_bh(&dst_garbage.lock);
dst = dst_garbage.list;
dst_garbage.list = NULL;
+ /* The code in dst_ifdown places a hold on the loopback device.
+ * If the gc entry processing is set to expire after a lengthy
+ * interval, this hold can cause netdev_wait_allrefs() to hang
+ * out and wait for a long time -- until the the loopback
+ * interface is released. If we're really unlucky, it'll emit
+ * pr_emerg messages to console too. Reset the interval here,
+ * so dst cleanups occur in a more timely fashion.
+ */
+ if (dst_garbage.timer_inc > DST_GC_INC) {
+ dst_garbage.timer_inc = DST_GC_INC;
+ dst_garbage.timer_expires = DST_GC_MIN;
+ mod_delayed_work(system_wq, &dst_gc_work,
+ dst_garbage.timer_expires);
+ }
spin_unlock_bh(&dst_garbage.lock);
if (last)
diff --git a/net/core/ethtool.c b/net/core/ethtool.c
index 072c1f4..e9989b8 100644
--- a/net/core/ethtool.c
+++ b/net/core/ethtool.c
@@ -1704,7 +1704,7 @@
static noinline_for_stack int ethtool_set_channels(struct net_device *dev,
void __user *useraddr)
{
- struct ethtool_channels channels, max;
+ struct ethtool_channels channels, max = { .cmd = ETHTOOL_GCHANNELS };
u32 max_rx_in_use = 0;
if (!dev->ethtool_ops->set_channels || !dev->ethtool_ops->get_channels)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 1d91607..9c6fd7f 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -937,6 +937,7 @@
+ nla_total_size(1) /* IFLA_LINKMODE */
+ nla_total_size(4) /* IFLA_CARRIER_CHANGES */
+ nla_total_size(4) /* IFLA_LINK_NETNSID */
+ + nla_total_size(4) /* IFLA_GROUP */
+ nla_total_size(ext_filter_mask
& RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */
+ rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */
@@ -1130,6 +1131,8 @@
struct ifla_vf_mac vf_mac;
struct ifla_vf_info ivi;
+ memset(&ivi, 0, sizeof(ivi));
+
/* Not all SR-IOV capable drivers support the
* spoofcheck and "RSS query enable" query. Preset to
* -1 so the user space tool can detect that the driver
@@ -1138,7 +1141,6 @@
ivi.spoofchk = -1;
ivi.rss_query_en = -1;
ivi.trusted = -1;
- memset(ivi.mac, 0, sizeof(ivi.mac));
/* The default value for VF link state is "auto"
* IFLA_VF_LINK_STATE_AUTO which equals zero
*/
@@ -1464,6 +1466,7 @@
[IFLA_LINK_NETNSID] = { .type = NLA_S32 },
[IFLA_PROTO_DOWN] = { .type = NLA_U8 },
[IFLA_XDP] = { .type = NLA_NESTED },
+ [IFLA_GROUP] = { .type = NLA_U32 },
};
static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = {
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c
index b1dc096..403593b 100644
--- a/net/decnet/dn_route.c
+++ b/net/decnet/dn_route.c
@@ -188,12 +188,6 @@
call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
}
-static inline void dnrt_drop(struct dn_route *rt)
-{
- dst_release(&rt->dst);
- call_rcu_bh(&rt->dst.rcu_head, dst_rcu_free);
-}
-
static void dn_dst_check_expire(unsigned long dummy)
{
int i;
@@ -248,7 +242,7 @@
}
*rtp = rt->dst.dn_next;
rt->dst.dn_next = NULL;
- dnrt_drop(rt);
+ dnrt_free(rt);
break;
}
spin_unlock_bh(&dn_rt_hash_table[i].lock);
@@ -350,7 +344,7 @@
dst_use(&rth->dst, now);
spin_unlock_bh(&dn_rt_hash_table[hash].lock);
- dnrt_drop(rt);
+ dst_free(&rt->dst);
*rp = rth;
return 0;
}
@@ -380,7 +374,7 @@
for(; rt; rt = next) {
next = rcu_dereference_raw(rt->dst.dn_next);
RCU_INIT_POINTER(rt->dst.dn_next, NULL);
- dst_free((struct dst_entry *)rt);
+ dnrt_free(rt);
}
nothing_to_declare:
@@ -1187,7 +1181,7 @@
if (dev_out->flags & IFF_LOOPBACK)
flags |= RTCF_LOCAL;
- rt = dst_alloc(&dn_dst_ops, dev_out, 1, DST_OBSOLETE_NONE, DST_HOST);
+ rt = dst_alloc(&dn_dst_ops, dev_out, 0, DST_OBSOLETE_NONE, DST_HOST);
if (rt == NULL)
goto e_nobufs;
diff --git a/net/decnet/netfilter/dn_rtmsg.c b/net/decnet/netfilter/dn_rtmsg.c
index 85f2fdc..29246bc 100644
--- a/net/decnet/netfilter/dn_rtmsg.c
+++ b/net/decnet/netfilter/dn_rtmsg.c
@@ -102,7 +102,9 @@
{
struct nlmsghdr *nlh = nlmsg_hdr(skb);
- if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
+ if (skb->len < sizeof(*nlh) ||
+ nlh->nlmsg_len < sizeof(*nlh) ||
+ skb->len < nlh->nlmsg_len)
return;
if (!netlink_capable(skb, CAP_NET_ADMIN))
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 3ff9d97..079d76b 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1103,10 +1103,8 @@
/* Use already configured phy mode */
if (p->phy_interface == PHY_INTERFACE_MODE_NA)
p->phy_interface = p->phy->interface;
- phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
- p->phy_interface);
-
- return 0;
+ return phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
+ p->phy_interface);
}
static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 1bc623d..19930da 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -1112,6 +1112,7 @@
pmc = kzalloc(sizeof(*pmc), GFP_KERNEL);
if (!pmc)
return;
+ spin_lock_init(&pmc->lock);
spin_lock_bh(&im->lock);
pmc->interface = im->interface;
in_dev_hold(in_dev);
@@ -2071,21 +2072,26 @@
static void ip_mc_clear_src(struct ip_mc_list *pmc)
{
- struct ip_sf_list *psf, *nextpsf;
+ struct ip_sf_list *psf, *nextpsf, *tomb, *sources;
- for (psf = pmc->tomb; psf; psf = nextpsf) {
- nextpsf = psf->sf_next;
- kfree(psf);
- }
+ spin_lock_bh(&pmc->lock);
+ tomb = pmc->tomb;
pmc->tomb = NULL;
- for (psf = pmc->sources; psf; psf = nextpsf) {
- nextpsf = psf->sf_next;
- kfree(psf);
- }
+ sources = pmc->sources;
pmc->sources = NULL;
pmc->sfmode = MCAST_EXCLUDE;
pmc->sfcount[MCAST_INCLUDE] = 0;
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);
+ }
}
/* Join a multicast group
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index b3cc133..c0cc6aa 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -23,7 +23,8 @@
struct rtable *rt;
struct flowi4 fl4 = {};
__be32 saddr = iph->saddr;
- __u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
+ const struct sock *sk = skb_to_full_sk(skb);
+ __u8 flags = sk ? inet_sk_flowi_flags(sk) : 0;
struct net_device *dev = skb_dst(skb)->dev;
unsigned int hh_len;
@@ -40,7 +41,7 @@
fl4.daddr = iph->daddr;
fl4.saddr = saddr;
fl4.flowi4_tos = RT_TOS(iph->tos);
- fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+ fl4.flowi4_oif = sk ? sk->sk_bound_dev_if : 0;
if (!fl4.flowi4_oif)
fl4.flowi4_oif = l3mdev_master_ifindex(dev);
fl4.flowi4_mark = skb->mark;
@@ -61,7 +62,7 @@
xfrm_decode_session(skb, flowi4_to_flowi(&fl4), AF_INET) == 0) {
struct dst_entry *dst = skb_dst(skb);
skb_dst_set(skb, NULL);
- dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0);
+ dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), sk, 0);
if (IS_ERR(dst))
return PTR_ERR(dst);
skb_dst_set(skb, dst);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index d600735..f24b9f4 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -319,9 +319,9 @@
static void addrconf_mod_dad_work(struct inet6_ifaddr *ifp,
unsigned long delay)
{
- if (!delayed_work_pending(&ifp->dad_work))
- in6_ifa_hold(ifp);
- mod_delayed_work(addrconf_wq, &ifp->dad_work, delay);
+ in6_ifa_hold(ifp);
+ if (mod_delayed_work(addrconf_wq, &ifp->dad_work, delay))
+ in6_ifa_put(ifp);
}
static int snmp6_alloc_dev(struct inet6_dev *idev)
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index eea23b5..ec849d8 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -32,7 +32,6 @@
struct dst_entry *fib6_rule_lookup(struct net *net, struct flowi6 *fl6,
int flags, pol_lookup_t lookup)
{
- struct rt6_info *rt;
struct fib_lookup_arg arg = {
.lookup_ptr = lookup,
.flags = FIB_LOOKUP_NOREF,
@@ -44,21 +43,11 @@
fib_rules_lookup(net->ipv6.fib6_rules_ops,
flowi6_to_flowi(fl6), flags, &arg);
- rt = arg.result;
+ if (arg.result)
+ return arg.result;
- if (!rt) {
- dst_hold(&net->ipv6.ip6_null_entry->dst);
- return &net->ipv6.ip6_null_entry->dst;
- }
-
- if (rt->rt6i_flags & RTF_REJECT &&
- rt->dst.error == -EAGAIN) {
- ip6_rt_put(rt);
- rt = net->ipv6.ip6_null_entry;
- dst_hold(&rt->dst);
- }
-
- return &rt->dst;
+ dst_hold(&net->ipv6.ip6_null_entry->dst);
+ return &net->ipv6.ip6_null_entry->dst;
}
static int fib6_rule_action(struct fib_rule *rule, struct flowi *flp,
@@ -121,7 +110,8 @@
flp6->saddr = saddr;
}
err = rt->dst.error;
- goto out;
+ if (err != -EAGAIN)
+ goto out;
}
again:
ip6_rt_put(rt);
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 8c88a37..636d4d8 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -289,8 +289,7 @@
struct rt6_info *rt;
rt = lookup(net, net->ipv6.fib6_main_tbl, fl6, flags);
- if (rt->rt6i_flags & RTF_REJECT &&
- rt->dst.error == -EAGAIN) {
+ if (rt->dst.error == -EAGAIN) {
ip6_rt_put(rt);
rt = net->ipv6.ip6_null_entry;
dst_hold(&rt->dst);
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c
index ffc83d4..c329a15 100644
--- a/net/ipv6/ip6_gre.c
+++ b/net/ipv6/ip6_gre.c
@@ -542,11 +542,10 @@
memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
- dsfield = ipv4_get_dsfield(iph);
-
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
- & IPV6_TCLASS_MASK;
+ dsfield = ipv4_get_dsfield(iph);
+ else
+ dsfield = ip6_tclass(t->parms.flowinfo);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
fl6.flowi6_mark = skb->mark;
@@ -584,6 +583,9 @@
return -1;
offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+ /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+ ipv6h = ipv6_hdr(skb);
+
if (offset > 0) {
struct ipv6_tlv_tnl_enc_lim *tel;
tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset];
@@ -598,9 +600,11 @@
memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6));
- dsfield = ipv6_get_dsfield(ipv6h);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK);
+ dsfield = ipv6_get_dsfield(ipv6h);
+ else
+ dsfield = ip6_tclass(t->parms.flowinfo);
+
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
fl6.flowlabel |= ip6_flowlabel(ipv6h);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index fafad39..3e42221 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1028,8 +1028,10 @@
}
#endif
if (ipv6_addr_v4mapped(&fl6->saddr) &&
- !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr)))
- return -EAFNOSUPPORT;
+ !(ipv6_addr_v4mapped(&fl6->daddr) || ipv6_addr_any(&fl6->daddr))) {
+ err = -EAFNOSUPPORT;
+ goto out_err_release;
+ }
return 0;
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c
index 97e89a2..b44e9f5 100644
--- a/net/ipv6/ip6_tunnel.c
+++ b/net/ipv6/ip6_tunnel.c
@@ -1196,7 +1196,7 @@
skb_push(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
ipv6h = ipv6_hdr(skb);
- ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield),
+ ip6_flow_hdr(ipv6h, dsfield,
ip6_make_flowlabel(net, skb, fl6->flowlabel, true, fl6));
ipv6h->hop_limit = hop_limit;
ipv6h->nexthdr = proto;
@@ -1231,8 +1231,6 @@
if (tproto != IPPROTO_IPIP && tproto != 0)
return -1;
- dsfield = ipv4_get_dsfield(iph);
-
if (t->parms.collect_md) {
struct ip_tunnel_info *tun_info;
const struct ip_tunnel_key *key;
@@ -1246,6 +1244,7 @@
fl6.flowi6_proto = IPPROTO_IPIP;
fl6.daddr = key->u.ipv6.dst;
fl6.flowlabel = key->label;
+ dsfield = ip6_tclass(key->label);
} else {
if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT))
encap_limit = t->parms.encap_limit;
@@ -1254,8 +1253,9 @@
fl6.flowi6_proto = IPPROTO_IPIP;
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT)
- & IPV6_TCLASS_MASK;
+ dsfield = ipv4_get_dsfield(iph);
+ else
+ dsfield = ip6_tclass(t->parms.flowinfo);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
fl6.flowi6_mark = skb->mark;
}
@@ -1265,6 +1265,8 @@
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
+ dsfield = INET_ECN_encapsulate(dsfield, ipv4_get_dsfield(iph));
+
skb_set_inner_ipproto(skb, IPPROTO_IPIP);
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
@@ -1298,8 +1300,6 @@
ip6_tnl_addr_conflict(t, ipv6h))
return -1;
- dsfield = ipv6_get_dsfield(ipv6h);
-
if (t->parms.collect_md) {
struct ip_tunnel_info *tun_info;
const struct ip_tunnel_key *key;
@@ -1313,8 +1313,11 @@
fl6.flowi6_proto = IPPROTO_IPV6;
fl6.daddr = key->u.ipv6.dst;
fl6.flowlabel = key->label;
+ dsfield = ip6_tclass(key->label);
} else {
offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb));
+ /* ip6_tnl_parse_tlv_enc_lim() might have reallocated skb->head */
+ ipv6h = ipv6_hdr(skb);
if (offset > 0) {
struct ipv6_tlv_tnl_enc_lim *tel;
@@ -1333,7 +1336,9 @@
fl6.flowi6_proto = IPPROTO_IPV6;
if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)
- fl6.flowlabel |= (*(__be32 *)ipv6h & IPV6_TCLASS_MASK);
+ dsfield = ipv6_get_dsfield(ipv6h);
+ else
+ dsfield = ip6_tclass(t->parms.flowinfo);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)
fl6.flowlabel |= ip6_flowlabel(ipv6h);
if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK)
@@ -1345,6 +1350,8 @@
if (iptunnel_handle_offloads(skb, SKB_GSO_IPXIP6))
return -1;
+ dsfield = INET_ECN_encapsulate(dsfield, ipv6_get_dsfield(ipv6h));
+
skb_set_inner_ipproto(skb, IPPROTO_IPV6);
err = ip6_tnl_xmit(skb, dev, dsfield, &fl6, encap_limit, &mtu,
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c
index cc8e3ae..e88bcb8 100644
--- a/net/ipv6/proc.c
+++ b/net/ipv6/proc.c
@@ -219,7 +219,7 @@
u64 buff64[SNMP_MIB_MAX];
int i;
- memset(buff64, 0, sizeof(unsigned long) * SNMP_MIB_MAX);
+ memset(buff64, 0, sizeof(u64) * SNMP_MIB_MAX);
snmp_get_cpu_field64_batch(buff64, itemlist, mib, syncpoff);
for (i = 0; itemlist[i].name; i++)
diff --git a/net/key/af_key.c b/net/key/af_key.c
index f9c9ecb..e67c28e 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -1135,6 +1135,7 @@
goto out;
}
+ err = -ENOBUFS;
key = ext_hdrs[SADB_EXT_KEY_AUTH - 1];
if (sa->sadb_sa_auth) {
int keysize = 0;
@@ -1146,8 +1147,10 @@
if (key)
keysize = (key->sadb_key_bits + 7) / 8;
x->aalg = kmalloc(sizeof(*x->aalg) + keysize, GFP_KERNEL);
- if (!x->aalg)
+ if (!x->aalg) {
+ err = -ENOMEM;
goto out;
+ }
strcpy(x->aalg->alg_name, a->name);
x->aalg->alg_key_len = 0;
if (key) {
@@ -1166,8 +1169,10 @@
goto out;
}
x->calg = kmalloc(sizeof(*x->calg), GFP_KERNEL);
- if (!x->calg)
+ if (!x->calg) {
+ err = -ENOMEM;
goto out;
+ }
strcpy(x->calg->alg_name, a->name);
x->props.calgo = sa->sadb_sa_encrypt;
} else {
@@ -1181,8 +1186,10 @@
if (key)
keysize = (key->sadb_key_bits + 7) / 8;
x->ealg = kmalloc(sizeof(*x->ealg) + keysize, GFP_KERNEL);
- if (!x->ealg)
+ if (!x->ealg) {
+ err = -ENOMEM;
goto out;
+ }
strcpy(x->ealg->alg_name, a->name);
x->ealg->alg_key_len = 0;
if (key) {
@@ -1227,8 +1234,10 @@
struct xfrm_encap_tmpl *natt;
x->encap = kmalloc(sizeof(*x->encap), GFP_KERNEL);
- if (!x->encap)
+ if (!x->encap) {
+ err = -ENOMEM;
goto out;
+ }
natt = x->encap;
n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c
index e702cb95..3bce651 100644
--- a/net/l2tp/l2tp_core.c
+++ b/net/l2tp/l2tp_core.c
@@ -278,6 +278,55 @@
}
EXPORT_SYMBOL_GPL(l2tp_session_find);
+/* Like l2tp_session_find() but takes a reference on the returned session.
+ * Optionally calls session->ref() too if do_ref is true.
+ */
+struct l2tp_session *l2tp_session_get(struct net *net,
+ struct l2tp_tunnel *tunnel,
+ u32 session_id, bool do_ref)
+{
+ struct hlist_head *session_list;
+ struct l2tp_session *session;
+
+ if (!tunnel) {
+ struct l2tp_net *pn = l2tp_pernet(net);
+
+ session_list = l2tp_session_id_hash_2(pn, session_id);
+
+ rcu_read_lock_bh();
+ hlist_for_each_entry_rcu(session, session_list, global_hlist) {
+ if (session->session_id == session_id) {
+ l2tp_session_inc_refcount(session);
+ if (do_ref && session->ref)
+ session->ref(session);
+ rcu_read_unlock_bh();
+
+ return session;
+ }
+ }
+ rcu_read_unlock_bh();
+
+ return NULL;
+ }
+
+ session_list = l2tp_session_id_hash(tunnel, session_id);
+ read_lock_bh(&tunnel->hlist_lock);
+ hlist_for_each_entry(session, session_list, hlist) {
+ if (session->session_id == session_id) {
+ l2tp_session_inc_refcount(session);
+ if (do_ref && session->ref)
+ session->ref(session);
+ read_unlock_bh(&tunnel->hlist_lock);
+
+ return session;
+ }
+ }
+ read_unlock_bh(&tunnel->hlist_lock);
+
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(l2tp_session_get);
+
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
bool do_ref)
{
@@ -307,7 +356,8 @@
/* Lookup a session by interface name.
* This is very inefficient but is only used by management interfaces.
*/
-struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname)
+struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname,
+ bool do_ref)
{
struct l2tp_net *pn = l2tp_pernet(net);
int hash;
@@ -317,7 +367,11 @@
for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) {
hlist_for_each_entry_rcu(session, &pn->l2tp_session_hlist[hash], global_hlist) {
if (!strcmp(session->ifname, ifname)) {
+ l2tp_session_inc_refcount(session);
+ if (do_ref && session->ref)
+ session->ref(session);
rcu_read_unlock_bh();
+
return session;
}
}
@@ -327,7 +381,49 @@
return NULL;
}
-EXPORT_SYMBOL_GPL(l2tp_session_find_by_ifname);
+EXPORT_SYMBOL_GPL(l2tp_session_get_by_ifname);
+
+static int l2tp_session_add_to_tunnel(struct l2tp_tunnel *tunnel,
+ struct l2tp_session *session)
+{
+ struct l2tp_session *session_walk;
+ struct hlist_head *g_head;
+ struct hlist_head *head;
+ struct l2tp_net *pn;
+
+ head = l2tp_session_id_hash(tunnel, session->session_id);
+
+ write_lock_bh(&tunnel->hlist_lock);
+ hlist_for_each_entry(session_walk, head, hlist)
+ if (session_walk->session_id == session->session_id)
+ goto exist;
+
+ if (tunnel->version == L2TP_HDR_VER_3) {
+ pn = l2tp_pernet(tunnel->l2tp_net);
+ g_head = l2tp_session_id_hash_2(l2tp_pernet(tunnel->l2tp_net),
+ session->session_id);
+
+ spin_lock_bh(&pn->l2tp_session_hlist_lock);
+ hlist_for_each_entry(session_walk, g_head, global_hlist)
+ if (session_walk->session_id == session->session_id)
+ goto exist_glob;
+
+ hlist_add_head_rcu(&session->global_hlist, g_head);
+ spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+ }
+
+ hlist_add_head(&session->hlist, head);
+ write_unlock_bh(&tunnel->hlist_lock);
+
+ return 0;
+
+exist_glob:
+ spin_unlock_bh(&pn->l2tp_session_hlist_lock);
+exist:
+ write_unlock_bh(&tunnel->hlist_lock);
+
+ return -EEXIST;
+}
/* Lookup a tunnel by id
*/
@@ -637,6 +733,9 @@
* a data (not control) frame before coming here. Fields up to the
* session-id have already been parsed and ptr points to the data
* after the session-id.
+ *
+ * session->ref() must have been called prior to l2tp_recv_common().
+ * session->deref() will be called automatically after skb is processed.
*/
void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
unsigned char *ptr, unsigned char *optr, u16 hdrflags,
@@ -646,14 +745,6 @@
int offset;
u32 ns, nr;
- /* The ref count is increased since we now hold a pointer to
- * the session. Take care to decrement the refcnt when exiting
- * this function from now on...
- */
- l2tp_session_inc_refcount(session);
- if (session->ref)
- (*session->ref)(session);
-
/* Parse and check optional cookie */
if (session->peer_cookie_len > 0) {
if (memcmp(ptr, &session->peer_cookie[0], session->peer_cookie_len)) {
@@ -806,8 +897,6 @@
/* Try to dequeue as many skbs from reorder_q as we can. */
l2tp_recv_dequeue(session);
- l2tp_session_dec_refcount(session);
-
return;
discard:
@@ -816,8 +905,6 @@
if (session->deref)
(*session->deref)(session);
-
- l2tp_session_dec_refcount(session);
}
EXPORT_SYMBOL(l2tp_recv_common);
@@ -924,8 +1011,14 @@
}
/* Find the session context */
- session = l2tp_session_find(tunnel->l2tp_net, tunnel, session_id);
+ session = l2tp_session_get(tunnel->l2tp_net, tunnel, session_id, true);
if (!session || !session->recv_skb) {
+ if (session) {
+ if (session->deref)
+ session->deref(session);
+ l2tp_session_dec_refcount(session);
+ }
+
/* Not found? Pass to userspace to deal with */
l2tp_info(tunnel, L2TP_MSG_DATA,
"%s: no session found (%u/%u). Passing up.\n",
@@ -934,6 +1027,7 @@
}
l2tp_recv_common(session, skb, ptr, optr, hdrflags, length, payload_hook);
+ l2tp_session_dec_refcount(session);
return 0;
@@ -1740,6 +1834,7 @@
struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg)
{
struct l2tp_session *session;
+ int err;
session = kzalloc(sizeof(struct l2tp_session) + priv_size, GFP_KERNEL);
if (session != NULL) {
@@ -1795,6 +1890,13 @@
l2tp_session_set_header_len(session, tunnel->version);
+ err = l2tp_session_add_to_tunnel(tunnel, session);
+ if (err) {
+ kfree(session);
+
+ return ERR_PTR(err);
+ }
+
/* Bump the reference count. The session context is deleted
* only when this drops to zero.
*/
@@ -1804,28 +1906,14 @@
/* Ensure tunnel socket isn't deleted */
sock_hold(tunnel->sock);
- /* Add session to the tunnel's hash list */
- write_lock_bh(&tunnel->hlist_lock);
- hlist_add_head(&session->hlist,
- l2tp_session_id_hash(tunnel, session_id));
- write_unlock_bh(&tunnel->hlist_lock);
-
- /* And to the global session list if L2TPv3 */
- if (tunnel->version != L2TP_HDR_VER_2) {
- struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
-
- spin_lock_bh(&pn->l2tp_session_hlist_lock);
- hlist_add_head_rcu(&session->global_hlist,
- l2tp_session_id_hash_2(pn, session_id));
- spin_unlock_bh(&pn->l2tp_session_hlist_lock);
- }
-
/* Ignore management session in session count value */
if (session->session_id != 0)
atomic_inc(&l2tp_session_count);
+
+ return session;
}
- return session;
+ return ERR_PTR(-ENOMEM);
}
EXPORT_SYMBOL_GPL(l2tp_session_create);
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h
index e7233ba..0095012 100644
--- a/net/l2tp/l2tp_core.h
+++ b/net/l2tp/l2tp_core.h
@@ -240,12 +240,16 @@
return tunnel;
}
+struct l2tp_session *l2tp_session_get(struct net *net,
+ struct l2tp_tunnel *tunnel,
+ u32 session_id, bool do_ref);
struct l2tp_session *l2tp_session_find(struct net *net,
struct l2tp_tunnel *tunnel,
u32 session_id);
struct l2tp_session *l2tp_session_get_nth(struct l2tp_tunnel *tunnel, int nth,
bool do_ref);
-struct l2tp_session *l2tp_session_find_by_ifname(struct net *net, char *ifname);
+struct l2tp_session *l2tp_session_get_by_ifname(struct net *net, char *ifname,
+ bool do_ref);
struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index 965f7e3..eecc64e 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -223,12 +223,6 @@
goto out;
}
- session = l2tp_session_find(net, tunnel, session_id);
- if (session) {
- rc = -EEXIST;
- goto out;
- }
-
if (cfg->ifname) {
dev = dev_get_by_name(net, cfg->ifname);
if (dev) {
@@ -242,8 +236,8 @@
session = l2tp_session_create(sizeof(*spriv), tunnel, session_id,
peer_session_id, cfg);
- if (!session) {
- rc = -ENOMEM;
+ if (IS_ERR(session)) {
+ rc = PTR_ERR(session);
goto out;
}
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 2066953..3468d56 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -143,19 +143,19 @@
}
/* Ok, this is a data packet. Lookup the session. */
- session = l2tp_session_find(net, NULL, session_id);
- if (session == NULL)
+ session = l2tp_session_get(net, NULL, session_id, true);
+ if (!session)
goto discard;
tunnel = session->tunnel;
- if (tunnel == NULL)
- goto discard;
+ if (!tunnel)
+ goto discard_sess;
/* Trace packet contents, if enabled */
if (tunnel->debug & L2TP_MSG_DATA) {
length = min(32u, skb->len);
if (!pskb_may_pull(skb, length))
- goto discard;
+ goto discard_sess;
/* Point to L2TP header */
optr = ptr = skb->data;
@@ -165,6 +165,7 @@
}
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len, tunnel->recv_payload_hook);
+ l2tp_session_dec_refcount(session);
return 0;
@@ -203,6 +204,12 @@
return sk_receive_skb(sk, skb, 1);
+discard_sess:
+ if (session->deref)
+ session->deref(session);
+ l2tp_session_dec_refcount(session);
+ goto discard;
+
discard_put:
sock_put(sk);
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c
index 26cf4dc..74d0d33 100644
--- a/net/l2tp/l2tp_ip6.c
+++ b/net/l2tp/l2tp_ip6.c
@@ -156,19 +156,19 @@
}
/* Ok, this is a data packet. Lookup the session. */
- session = l2tp_session_find(net, NULL, session_id);
- if (session == NULL)
+ session = l2tp_session_get(net, NULL, session_id, true);
+ if (!session)
goto discard;
tunnel = session->tunnel;
- if (tunnel == NULL)
- goto discard;
+ if (!tunnel)
+ goto discard_sess;
/* Trace packet contents, if enabled */
if (tunnel->debug & L2TP_MSG_DATA) {
length = min(32u, skb->len);
if (!pskb_may_pull(skb, length))
- goto discard;
+ goto discard_sess;
/* Point to L2TP header */
optr = ptr = skb->data;
@@ -179,6 +179,8 @@
l2tp_recv_common(session, skb, ptr, optr, 0, skb->len,
tunnel->recv_payload_hook);
+ l2tp_session_dec_refcount(session);
+
return 0;
pass_up:
@@ -216,6 +218,12 @@
return sk_receive_skb(sk, skb, 1);
+discard_sess:
+ if (session->deref)
+ session->deref(session);
+ l2tp_session_dec_refcount(session);
+ goto discard;
+
discard_put:
sock_put(sk);
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c
index 9f66272..1ccd310 100644
--- a/net/l2tp/l2tp_netlink.c
+++ b/net/l2tp/l2tp_netlink.c
@@ -55,7 +55,8 @@
/* Accessed under genl lock */
static const struct l2tp_nl_cmd_ops *l2tp_nl_cmd_ops[__L2TP_PWTYPE_MAX];
-static struct l2tp_session *l2tp_nl_session_find(struct genl_info *info)
+static struct l2tp_session *l2tp_nl_session_get(struct genl_info *info,
+ bool do_ref)
{
u32 tunnel_id;
u32 session_id;
@@ -66,14 +67,15 @@
if (info->attrs[L2TP_ATTR_IFNAME]) {
ifname = nla_data(info->attrs[L2TP_ATTR_IFNAME]);
- session = l2tp_session_find_by_ifname(net, ifname);
+ session = l2tp_session_get_by_ifname(net, ifname, do_ref);
} else if ((info->attrs[L2TP_ATTR_SESSION_ID]) &&
(info->attrs[L2TP_ATTR_CONN_ID])) {
tunnel_id = nla_get_u32(info->attrs[L2TP_ATTR_CONN_ID]);
session_id = nla_get_u32(info->attrs[L2TP_ATTR_SESSION_ID]);
tunnel = l2tp_tunnel_find(net, tunnel_id);
if (tunnel)
- session = l2tp_session_find(net, tunnel, session_id);
+ session = l2tp_session_get(net, tunnel, session_id,
+ do_ref);
}
return session;
@@ -634,10 +636,12 @@
session_id, peer_session_id, &cfg);
if (ret >= 0) {
- session = l2tp_session_find(net, tunnel, session_id);
- if (session)
+ session = l2tp_session_get(net, tunnel, session_id, false);
+ if (session) {
ret = l2tp_session_notify(&l2tp_nl_family, info, session,
L2TP_CMD_SESSION_CREATE);
+ l2tp_session_dec_refcount(session);
+ }
}
out:
@@ -650,7 +654,7 @@
struct l2tp_session *session;
u16 pw_type;
- session = l2tp_nl_session_find(info);
+ session = l2tp_nl_session_get(info, true);
if (session == NULL) {
ret = -ENODEV;
goto out;
@@ -664,6 +668,10 @@
if (l2tp_nl_cmd_ops[pw_type] && l2tp_nl_cmd_ops[pw_type]->session_delete)
ret = (*l2tp_nl_cmd_ops[pw_type]->session_delete)(session);
+ if (session->deref)
+ session->deref(session);
+ l2tp_session_dec_refcount(session);
+
out:
return ret;
}
@@ -673,7 +681,7 @@
int ret = 0;
struct l2tp_session *session;
- session = l2tp_nl_session_find(info);
+ session = l2tp_nl_session_get(info, false);
if (session == NULL) {
ret = -ENODEV;
goto out;
@@ -708,6 +716,8 @@
ret = l2tp_session_notify(&l2tp_nl_family, info,
session, L2TP_CMD_SESSION_MODIFY);
+ l2tp_session_dec_refcount(session);
+
out:
return ret;
}
@@ -803,29 +813,34 @@
struct sk_buff *msg;
int ret;
- session = l2tp_nl_session_find(info);
+ session = l2tp_nl_session_get(info, false);
if (session == NULL) {
ret = -ENODEV;
- goto out;
+ goto err;
}
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) {
ret = -ENOMEM;
- goto out;
+ goto err_ref;
}
ret = l2tp_nl_session_send(msg, info->snd_portid, info->snd_seq,
0, session, L2TP_CMD_SESSION_GET);
if (ret < 0)
- goto err_out;
+ goto err_ref_msg;
- return genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
+ ret = genlmsg_unicast(genl_info_net(info), msg, info->snd_portid);
-err_out:
+ l2tp_session_dec_refcount(session);
+
+ return ret;
+
+err_ref_msg:
nlmsg_free(msg);
-
-out:
+err_ref:
+ l2tp_session_dec_refcount(session);
+err:
return ret;
}
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c
index 1387f54..1696f1f 100644
--- a/net/l2tp/l2tp_ppp.c
+++ b/net/l2tp/l2tp_ppp.c
@@ -583,6 +583,7 @@
int error = 0;
u32 tunnel_id, peer_tunnel_id;
u32 session_id, peer_session_id;
+ bool drop_refcnt = false;
int ver = 2;
int fd;
@@ -684,36 +685,36 @@
if (tunnel->peer_tunnel_id == 0)
tunnel->peer_tunnel_id = peer_tunnel_id;
- /* Create session if it doesn't already exist. We handle the
- * case where a session was previously created by the netlink
- * interface by checking that the session doesn't already have
- * a socket and its tunnel socket are what we expect. If any
- * of those checks fail, return EEXIST to the caller.
- */
- session = l2tp_session_find(sock_net(sk), tunnel, session_id);
- if (session == NULL) {
- /* Default MTU must allow space for UDP/L2TP/PPP
- * headers.
- */
- cfg.mtu = cfg.mru = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+ session = l2tp_session_get(sock_net(sk), tunnel, session_id, false);
+ if (session) {
+ drop_refcnt = true;
+ ps = l2tp_session_priv(session);
- /* Allocate and initialize a new session context. */
- session = l2tp_session_create(sizeof(struct pppol2tp_session),
- tunnel, session_id,
- peer_session_id, &cfg);
- if (session == NULL) {
- error = -ENOMEM;
+ /* Using a pre-existing session is fine as long as it hasn't
+ * been connected yet.
+ */
+ if (ps->sock) {
+ error = -EEXIST;
+ goto end;
+ }
+
+ /* consistency checks */
+ if (ps->tunnel_sock != tunnel->sock) {
+ error = -EEXIST;
goto end;
}
} else {
- ps = l2tp_session_priv(session);
- error = -EEXIST;
- if (ps->sock != NULL)
- goto end;
+ /* Default MTU must allow space for UDP/L2TP/PPP headers */
+ cfg.mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
+ cfg.mru = cfg.mtu;
- /* consistency checks */
- if (ps->tunnel_sock != tunnel->sock)
+ session = l2tp_session_create(sizeof(struct pppol2tp_session),
+ tunnel, session_id,
+ peer_session_id, &cfg);
+ if (IS_ERR(session)) {
+ error = PTR_ERR(session);
goto end;
+ }
}
/* Associate session with its PPPoL2TP socket */
@@ -778,6 +779,8 @@
session->name);
end:
+ if (drop_refcnt)
+ l2tp_session_dec_refcount(session);
release_sock(sk);
return error;
@@ -805,12 +808,6 @@
if (tunnel->sock == NULL)
goto out;
- /* Check that this session doesn't already exist */
- error = -EEXIST;
- session = l2tp_session_find(net, tunnel, session_id);
- if (session != NULL)
- goto out;
-
/* Default MTU values. */
if (cfg->mtu == 0)
cfg->mtu = 1500 - PPPOL2TP_HEADER_OVERHEAD;
@@ -818,12 +815,13 @@
cfg->mru = cfg->mtu;
/* Allocate and initialize a new session context. */
- error = -ENOMEM;
session = l2tp_session_create(sizeof(struct pppol2tp_session),
tunnel, session_id,
peer_session_id, cfg);
- if (session == NULL)
+ if (IS_ERR(session)) {
+ error = PTR_ERR(session);
goto out;
+ }
ps = l2tp_session_priv(session);
ps->tunnel_sock = tunnel->sock;
@@ -1141,11 +1139,18 @@
if (stats.session_id != 0) {
/* resend to session ioctl handler */
struct l2tp_session *session =
- l2tp_session_find(sock_net(sk), tunnel, stats.session_id);
- if (session != NULL)
- err = pppol2tp_session_ioctl(session, cmd, arg);
- else
+ l2tp_session_get(sock_net(sk), tunnel,
+ stats.session_id, true);
+
+ if (session) {
+ err = pppol2tp_session_ioctl(session, cmd,
+ arg);
+ if (session->deref)
+ session->deref(session);
+ l2tp_session_dec_refcount(session);
+ } else {
err = -EBADR;
+ }
break;
}
#ifdef CONFIG_XFRM
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 8d7747e..37bec0f 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -6,6 +6,7 @@
* Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
* Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (c) 2016 Intel Deutschland GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -1307,6 +1308,26 @@
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_VHT) {
switch (mgmt->u.action.u.vht_group_notif.action_code) {
+ case WLAN_VHT_ACTION_OPMODE_NOTIF: {
+ struct ieee80211_rx_status *status;
+ enum nl80211_band band;
+ u8 opmode;
+
+ status = IEEE80211_SKB_RXCB(skb);
+ band = status->band;
+ opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
+
+ mutex_lock(&local->sta_mtx);
+ sta = sta_info_get_bss(sdata, mgmt->sa);
+
+ if (sta)
+ ieee80211_vht_handle_opmode(sdata, sta,
+ opmode,
+ band);
+
+ mutex_unlock(&local->sta_mtx);
+ break;
+ }
case WLAN_VHT_ACTION_GROUPID_MGMT:
ieee80211_process_mu_groups(sdata, mgmt);
break;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 1075ac2..2bb6899 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -908,12 +908,17 @@
supp_ht = supp_ht || sband->ht_cap.ht_supported;
supp_vht = supp_vht || sband->vht_cap.vht_supported;
- if (sband->ht_cap.ht_supported)
- local->rx_chains =
- max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
- local->rx_chains);
+ if (!sband->ht_cap.ht_supported)
+ continue;
/* TODO: consider VHT for RX chains, hopefully it's the same */
+ local->rx_chains =
+ max(ieee80211_mcs_to_chains(&sband->ht_cap.mcs),
+ local->rx_chains);
+
+ /* no need to mask, SM_PS_DISABLED has all bits set */
+ sband->ht_cap.cap |= WLAN_HT_CAP_SM_PS_DISABLED <<
+ IEEE80211_HT_CAP_SM_PS_SHIFT;
}
/* if low-level driver supports AP, we also support VLAN */
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index c45a0fc..439e597 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2923,17 +2923,10 @@
switch (mgmt->u.action.u.vht_opmode_notif.action_code) {
case WLAN_VHT_ACTION_OPMODE_NOTIF: {
- u8 opmode;
-
/* verify opmode is present */
if (len < IEEE80211_MIN_ACTION_SIZE + 2)
goto invalid;
-
- opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
-
- ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
- opmode, status->band);
- goto handled;
+ goto queue;
}
case WLAN_VHT_ACTION_GROUPID_MGMT: {
if (len < IEEE80211_MIN_ACTION_SIZE + 25)
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index 6832bf6..43e45bb 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -527,8 +527,10 @@
u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, band);
- if (changed > 0)
+ if (changed > 0) {
+ ieee80211_recalc_min_chandef(sdata);
rate_control_rate_update(local, sband, sta, changed);
+ }
}
void ieee80211_get_vht_mask_from_cap(__le16 vht_cap,
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 2754045..04111c1 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -45,6 +45,8 @@
#include <net/netfilter/nf_conntrack_zones.h>
#include <net/netfilter/nf_conntrack_timestamp.h>
#include <net/netfilter/nf_conntrack_labels.h>
+#include <net/netfilter/nf_conntrack_seqadj.h>
+#include <net/netfilter/nf_conntrack_synproxy.h>
#ifdef CONFIG_NF_NAT_NEEDED
#include <net/netfilter/nf_nat_core.h>
#include <net/netfilter/nf_nat_l4proto.h>
@@ -1800,6 +1802,8 @@
nf_ct_tstamp_ext_add(ct, GFP_ATOMIC);
nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
nf_ct_labels_ext_add(ct);
+ nfct_seqadj_ext_add(ct);
+ nfct_synproxy_ext_add(ct);
/* we must add conntrack extensions before confirmation. */
ct->status |= IPS_CONFIRMED;
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
index 04a1b97..14e3d85 100644
--- a/net/netfilter/xt_IDLETIMER.c
+++ b/net/netfilter/xt_IDLETIMER.c
@@ -76,6 +76,7 @@
bool send_nl_msg;
bool active;
uid_t uid;
+ bool suspend_time_valid;
};
static LIST_HEAD(idletimer_tg_list);
@@ -245,8 +246,13 @@
switch (pm_event) {
case PM_SUSPEND_PREPARE:
get_monotonic_boottime(&timer->last_suspend_time);
+ timer->suspend_time_valid = true;
break;
case PM_POST_SUSPEND:
+ if (!timer->suspend_time_valid)
+ break;
+ timer->suspend_time_valid = false;
+
spin_lock_bh(×tamp_lock);
if (!timer->active) {
spin_unlock_bh(×tamp_lock);
@@ -281,7 +287,7 @@
{
int ret;
- info->timer = kmalloc(sizeof(*info->timer), GFP_KERNEL);
+ info->timer = kzalloc(sizeof(*info->timer), GFP_KERNEL);
if (!info->timer) {
ret = -ENOMEM;
goto out;
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index 872db2d..119e51f 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -104,7 +104,7 @@
tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
tcp_hdrlen = tcph->doff * 4;
- if (len < tcp_hdrlen)
+ if (len < tcp_hdrlen || tcp_hdrlen < sizeof(struct tcphdr))
return -1;
if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
@@ -152,6 +152,10 @@
if (len > tcp_hdrlen)
return 0;
+ /* tcph->doff has 4 bits, do not wrap it to 0 */
+ if (tcp_hdrlen >= 15 * 4)
+ return 0;
+
/*
* MSS Option not found ?! add it..
*/
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e1719c6..9647e31 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -239,7 +239,7 @@
union sctp_addr *laddr = (union sctp_addr *)addr;
struct sctp_transport *transport;
- if (sctp_verify_addr(sk, laddr, af->sockaddr_len))
+ if (!af || sctp_verify_addr(sk, laddr, af->sockaddr_len))
return NULL;
addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
@@ -4460,13 +4460,13 @@
for (head = sctp_ep_hashtable; hash < sctp_ep_hashsize;
hash++, head++) {
- read_lock(&head->lock);
+ read_lock_bh(&head->lock);
sctp_for_each_hentry(epb, &head->chain) {
err = cb(sctp_ep(epb), p);
if (err)
break;
}
- read_unlock(&head->lock);
+ read_unlock_bh(&head->lock);
}
return err;
@@ -4506,9 +4506,8 @@
if (err)
return err;
- sctp_transport_get_idx(net, &hti, pos);
- obj = sctp_transport_get_next(net, &hti);
- for (; obj && !IS_ERR(obj); obj = sctp_transport_get_next(net, &hti)) {
+ obj = sctp_transport_get_idx(net, &hti, pos + 1);
+ for (; !IS_ERR_OR_NULL(obj); obj = sctp_transport_get_next(net, &hti)) {
struct sctp_transport *transport = obj;
if (!sctp_transport_hold(transport))
diff --git a/net/tipc/discover.c b/net/tipc/discover.c
index 6b109a8..02462d6 100644
--- a/net/tipc/discover.c
+++ b/net/tipc/discover.c
@@ -169,7 +169,7 @@
/* Send response, if necessary */
if (respond && (mtyp == DSC_REQ_MSG)) {
- rskb = tipc_buf_acquire(MAX_H_SIZE);
+ rskb = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC);
if (!rskb)
return;
tipc_disc_init_msg(net, rskb, DSC_RESP_MSG, bearer);
@@ -278,7 +278,7 @@
req = kmalloc(sizeof(*req), GFP_ATOMIC);
if (!req)
return -ENOMEM;
- req->buf = tipc_buf_acquire(MAX_H_SIZE);
+ req->buf = tipc_buf_acquire(MAX_H_SIZE, GFP_ATOMIC);
if (!req->buf) {
kfree(req);
return -ENOMEM;
diff --git a/net/tipc/link.c b/net/tipc/link.c
index bda89bf..4e8647a 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -1395,7 +1395,7 @@
msg_set_seqno(hdr, seqno++);
pktlen = msg_size(hdr);
msg_set_size(&tnlhdr, pktlen + INT_H_SIZE);
- tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE);
+ tnlskb = tipc_buf_acquire(pktlen + INT_H_SIZE, GFP_ATOMIC);
if (!tnlskb) {
pr_warn("%sunable to send packet\n", link_co_err);
return;
diff --git a/net/tipc/msg.c b/net/tipc/msg.c
index 17201aa..56ea0ad 100644
--- a/net/tipc/msg.c
+++ b/net/tipc/msg.c
@@ -58,12 +58,12 @@
* NOTE: Headroom is reserved to allow prepending of a data link header.
* There may also be unrequested tailroom present at the buffer's end.
*/
-struct sk_buff *tipc_buf_acquire(u32 size)
+struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp)
{
struct sk_buff *skb;
unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u;
- skb = alloc_skb_fclone(buf_size, GFP_ATOMIC);
+ skb = alloc_skb_fclone(buf_size, gfp);
if (skb) {
skb_reserve(skb, BUF_HEADROOM);
skb_put(skb, size);
@@ -95,7 +95,7 @@
struct tipc_msg *msg;
struct sk_buff *buf;
- buf = tipc_buf_acquire(hdr_sz + data_sz);
+ buf = tipc_buf_acquire(hdr_sz + data_sz, GFP_ATOMIC);
if (unlikely(!buf))
return NULL;
@@ -261,7 +261,7 @@
/* No fragmentation needed? */
if (likely(msz <= pktmax)) {
- skb = tipc_buf_acquire(msz);
+ skb = tipc_buf_acquire(msz, GFP_KERNEL);
if (unlikely(!skb))
return -ENOMEM;
skb_orphan(skb);
@@ -282,7 +282,7 @@
msg_set_importance(&pkthdr, msg_importance(mhdr));
/* Prepare first fragment */
- skb = tipc_buf_acquire(pktmax);
+ skb = tipc_buf_acquire(pktmax, GFP_KERNEL);
if (!skb)
return -ENOMEM;
skb_orphan(skb);
@@ -313,7 +313,7 @@
pktsz = drem + INT_H_SIZE;
else
pktsz = pktmax;
- skb = tipc_buf_acquire(pktsz);
+ skb = tipc_buf_acquire(pktsz, GFP_KERNEL);
if (!skb) {
rc = -ENOMEM;
goto error;
@@ -448,7 +448,7 @@
if (msz > (max / 2))
return false;
- _skb = tipc_buf_acquire(max);
+ _skb = tipc_buf_acquire(max, GFP_ATOMIC);
if (!_skb)
return false;
@@ -496,7 +496,7 @@
/* Never return SHORT header; expand by replacing buffer if necessary */
if (msg_short(hdr)) {
- *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen);
+ *skb = tipc_buf_acquire(BASIC_H_SIZE + dlen, GFP_ATOMIC);
if (!*skb)
goto exit;
memcpy((*skb)->data + BASIC_H_SIZE, msg_data(hdr), dlen);
@@ -508,7 +508,7 @@
}
if (skb_cloned(_skb) &&
- pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_KERNEL))
+ pskb_expand_head(_skb, BUF_HEADROOM, BUF_TAILROOM, GFP_ATOMIC))
goto exit;
/* Now reverse the concerned fields */
diff --git a/net/tipc/msg.h b/net/tipc/msg.h
index 50a7398..6c0455c 100644
--- a/net/tipc/msg.h
+++ b/net/tipc/msg.h
@@ -820,7 +820,7 @@
return (msg_user(hdr) == LINK_PROTOCOL) && (msg_type(hdr) == RESET_MSG);
}
-struct sk_buff *tipc_buf_acquire(u32 size);
+struct sk_buff *tipc_buf_acquire(u32 size, gfp_t gfp);
bool tipc_msg_validate(struct sk_buff *skb);
bool tipc_msg_reverse(u32 own_addr, struct sk_buff **skb, int err);
void tipc_msg_init(u32 own_addr, struct tipc_msg *m, u32 user, u32 type,
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index c1cfd92..23f8899 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -69,7 +69,7 @@
u32 dest)
{
struct tipc_net *tn = net_generic(net, tipc_net_id);
- struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size);
+ struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE + size, GFP_ATOMIC);
struct tipc_msg *msg;
if (buf != NULL) {
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 459577e..a3df5e1 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -998,7 +998,8 @@
struct path path = { NULL, NULL };
err = -EINVAL;
- if (sunaddr->sun_family != AF_UNIX)
+ if (addr_len < offsetofend(struct sockaddr_un, sun_family) ||
+ sunaddr->sun_family != AF_UNIX)
goto out;
if (addr_len == sizeof(short)) {
@@ -1109,6 +1110,10 @@
unsigned int hash;
int err;
+ err = -EINVAL;
+ if (alen < offsetofend(struct sockaddr, sa_family))
+ goto out;
+
if (addr->sa_family != AF_UNSPEC) {
err = unix_mkname(sunaddr, alen, &hash);
if (err < 0)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e0437a7..8da67f7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1808,43 +1808,6 @@
goto out;
}
-#ifdef CONFIG_XFRM_SUB_POLICY
-static int xfrm_dst_alloc_copy(void **target, const void *src, int size)
-{
- if (!*target) {
- *target = kmalloc(size, GFP_ATOMIC);
- if (!*target)
- return -ENOMEM;
- }
-
- memcpy(*target, src, size);
- return 0;
-}
-#endif
-
-static int xfrm_dst_update_parent(struct dst_entry *dst,
- const struct xfrm_selector *sel)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
- struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
- return xfrm_dst_alloc_copy((void **)&(xdst->partner),
- sel, sizeof(*sel));
-#else
- return 0;
-#endif
-}
-
-static int xfrm_dst_update_origin(struct dst_entry *dst,
- const struct flowi *fl)
-{
-#ifdef CONFIG_XFRM_SUB_POLICY
- struct xfrm_dst *xdst = (struct xfrm_dst *)dst;
- return xfrm_dst_alloc_copy((void **)&(xdst->origin), fl, sizeof(*fl));
-#else
- return 0;
-#endif
-}
-
static int xfrm_expand_policies(const struct flowi *fl, u16 family,
struct xfrm_policy **pols,
int *num_pols, int *num_xfrms)
@@ -1916,16 +1879,6 @@
xdst = (struct xfrm_dst *)dst;
xdst->num_xfrms = err;
- if (num_pols > 1)
- err = xfrm_dst_update_parent(dst, &pols[1]->selector);
- else
- err = xfrm_dst_update_origin(dst, fl);
- if (unlikely(err)) {
- dst_free(dst);
- XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTBUNDLECHECKERROR);
- return ERR_PTR(err);
- }
-
xdst->num_pols = num_pols;
memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
xdst->policy_genid = atomic_read(&pols[0]->genid);
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 8b918f8..20b2e7d 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -814,6 +814,7 @@
sbsec->flags |= SE_SBPROC | SE_SBGENFS;
if (!strcmp(sb->s_type->name, "debugfs") ||
+ !strcmp(sb->s_type->name, "tracefs") ||
!strcmp(sb->s_type->name, "sysfs") ||
!strcmp(sb->s_type->name, "pstore"))
sbsec->flags |= SE_SBGENFS;
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 373fcad..776dffa 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -294,6 +294,8 @@
#define list_for_each_codec(c, bus) \
list_for_each_entry(c, &(bus)->core.codec_list, core.list)
+#define list_for_each_codec_safe(c, n, bus) \
+ list_for_each_entry_safe(c, n, &(bus)->core.codec_list, core.list)
/* snd_hda_codec_read/write optional flags */
#define HDA_RW_NO_RESPONSE_FALLBACK (1 << 0)
diff --git a/sound/pci/hda/hda_controller.c b/sound/pci/hda/hda_controller.c
index 5008785..0af1132 100644
--- a/sound/pci/hda/hda_controller.c
+++ b/sound/pci/hda/hda_controller.c
@@ -1333,8 +1333,12 @@
/* configure each codec instance */
int azx_codec_configure(struct azx *chip)
{
- struct hda_codec *codec;
- list_for_each_codec(codec, &chip->bus) {
+ struct hda_codec *codec, *next;
+
+ /* use _safe version here since snd_hda_codec_configure() deregisters
+ * the device upon error and deletes itself from the bus list.
+ */
+ list_for_each_codec_safe(codec, next, &chip->bus) {
snd_hda_codec_configure(codec);
}
return 0;
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index e7c8f4f..b0bd290 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3169,6 +3169,7 @@
spec->input_paths[i][nums]);
spec->input_paths[i][nums] =
spec->input_paths[i][n];
+ spec->input_paths[i][n] = 0;
}
}
nums++;
diff --git a/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c b/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c
index 15d62c3..cfe42e0 100644
--- a/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c
+++ b/sound/soc/codecs/msm_sdw/msm_sdw_cdc.c
@@ -1384,7 +1384,7 @@
msm_sdw = snd_soc_codec_get_drvdata(codec);
card = codec->component.card;
- msm_sdw->entry = snd_register_module_info(codec_root->module,
+ msm_sdw->entry = snd_info_create_subdir(codec_root->module,
"152c1000.msm-sdw-codec",
codec_root);
if (!msm_sdw->entry) {
@@ -1762,13 +1762,15 @@
static struct snd_soc_codec_driver soc_codec_dev_msm_sdw = {
.probe = msm_sdw_codec_probe,
.remove = msm_sdw_codec_remove,
- .controls = msm_sdw_snd_controls,
- .num_controls = ARRAY_SIZE(msm_sdw_snd_controls),
- .dapm_widgets = msm_sdw_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(msm_sdw_dapm_widgets),
- .dapm_routes = audio_map,
- .num_dapm_routes = ARRAY_SIZE(audio_map),
.get_regmap = msm_sdw_get_regmap,
+ .component_driver = {
+ .controls = msm_sdw_snd_controls,
+ .num_controls = ARRAY_SIZE(msm_sdw_snd_controls),
+ .dapm_widgets = msm_sdw_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(msm_sdw_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ },
};
static void msm_sdw_add_child_devices(struct work_struct *work)
diff --git a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
index a8fcd34..7892f61 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-analog-cdc.c
@@ -4052,7 +4052,7 @@
sdm660_cdc_priv = snd_soc_codec_get_drvdata(codec);
card = codec->component.card;
- sdm660_cdc_priv->entry = snd_register_module_info(codec_root->module,
+ sdm660_cdc_priv->entry = snd_info_create_subdir(codec_root->module,
"spmi0-03",
codec_root);
if (!sdm660_cdc_priv->entry) {
@@ -4320,13 +4320,15 @@
.suspend = msm_anlg_cdc_suspend,
.resume = msm_anlg_cdc_resume,
.reg_word_size = 1,
- .controls = msm_anlg_cdc_snd_controls,
- .num_controls = ARRAY_SIZE(msm_anlg_cdc_snd_controls),
- .dapm_widgets = msm_anlg_cdc_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(msm_anlg_cdc_dapm_widgets),
- .dapm_routes = audio_map,
- .num_dapm_routes = ARRAY_SIZE(audio_map),
.get_regmap = msm_anlg_get_regmap,
+ .component_driver = {
+ .controls = msm_anlg_cdc_snd_controls,
+ .num_controls = ARRAY_SIZE(msm_anlg_cdc_snd_controls),
+ .dapm_widgets = msm_anlg_cdc_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(msm_anlg_cdc_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ },
};
static int msm_anlg_cdc_init_supplies(struct sdm660_cdc_priv *sdm660_cdc,
diff --git a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
index 3f9c0b4..68a1d8d 100644
--- a/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
+++ b/sound/soc/codecs/sdm660_cdc/msm-digital-cdc.c
@@ -1157,7 +1157,7 @@
msm_dig = snd_soc_codec_get_drvdata(codec);
card = codec->component.card;
- msm_dig->entry = snd_register_module_info(codec_root->module,
+ msm_dig->entry = snd_info_create_subdir(codec_root->module,
"msm_digital_codec",
codec_root);
if (!msm_dig->entry) {
@@ -2037,13 +2037,15 @@
.remove = msm_dig_cdc_soc_remove,
.suspend = msm_dig_cdc_suspend,
.resume = msm_dig_cdc_resume,
- .controls = msm_dig_snd_controls,
- .num_controls = ARRAY_SIZE(msm_dig_snd_controls),
- .dapm_widgets = msm_dig_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(msm_dig_dapm_widgets),
- .dapm_routes = audio_dig_map,
- .num_dapm_routes = ARRAY_SIZE(audio_dig_map),
.get_regmap = msm_digital_get_regmap,
+ .component_driver = {
+ .controls = msm_dig_snd_controls,
+ .num_controls = ARRAY_SIZE(msm_dig_snd_controls),
+ .dapm_widgets = msm_dig_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(msm_dig_dapm_widgets),
+ .dapm_routes = audio_dig_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_dig_map),
+ },
};
const struct regmap_config msm_digital_regmap_config = {
diff --git a/sound/soc/codecs/wcd-dsp-mgr.c b/sound/soc/codecs/wcd-dsp-mgr.c
index 661db2b..a6d46ae 100644
--- a/sound/soc/codecs/wcd-dsp-mgr.c
+++ b/sound/soc/codecs/wcd-dsp-mgr.c
@@ -26,7 +26,8 @@
static char *wdsp_get_cmpnt_type_string(enum wdsp_cmpnt_type);
/* Component related macros */
-#define WDSP_GET_COMPONENT(wdsp, x) (&(wdsp->cmpnts[x]))
+#define WDSP_GET_COMPONENT(wdsp, x) ((x >= WDSP_CMPNT_TYPE_MAX || x < 0) ? \
+ NULL : (&(wdsp->cmpnts[x])))
#define WDSP_GET_CMPNT_TYPE_STR(x) wdsp_get_cmpnt_type_string(x)
/*
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index 329aa7a..f8cd9e2 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -348,7 +348,6 @@
AUDIO_NOMINAL,
CPE_NOMINAL,
HPH_PA_DELAY,
- SB_CLK_GEAR,
ANC_MIC_AMIC1,
ANC_MIC_AMIC2,
ANC_MIC_AMIC3,
@@ -818,7 +817,10 @@
int rx_8_count;
bool clk_mode;
bool clk_internal;
-
+ /* Lock to prevent multiple functions voting at same time */
+ struct mutex sb_clk_gear_lock;
+ /* Count for functions voting or un-voting */
+ u32 ref_count;
/* Lock to protect mclk enablement */
struct mutex mclk_lock;
};
@@ -2948,10 +2950,7 @@
&dai->grph);
break;
case SND_SOC_DAPM_PRE_PMD:
- if (!test_bit(SB_CLK_GEAR, &tasha_p->status_mask)) {
- tasha_codec_vote_max_bw(codec, true);
- set_bit(SB_CLK_GEAR, &tasha_p->status_mask);
- }
+ tasha_codec_vote_max_bw(codec, true);
break;
case SND_SOC_DAPM_POST_PMD:
ret = wcd9xxx_disconnect_port(core, &dai->wcd9xxx_ch_list,
@@ -5263,10 +5262,7 @@
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- if (!test_bit(SB_CLK_GEAR, &tasha->status_mask)) {
- tasha_codec_vote_max_bw(codec, true);
- set_bit(SB_CLK_GEAR, &tasha->status_mask);
- }
+ tasha_codec_vote_max_bw(codec, true);
/* Reset if needed */
tasha_codec_enable_prim_interpolator(codec, reg, event);
break;
@@ -11127,11 +11123,8 @@
if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
return;
- if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
- test_bit(SB_CLK_GEAR, &tasha->status_mask)) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tasha_codec_vote_max_bw(dai->codec, false);
- clear_bit(SB_CLK_GEAR, &tasha->status_mask);
- }
}
static int tasha_set_decimator_rate(struct snd_soc_dai *dai,
@@ -11366,15 +11359,11 @@
static int tasha_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct tasha_priv *tasha = snd_soc_codec_get_drvdata(dai->codec);
-
pr_debug("%s(): substream = %s stream = %d\n", __func__,
substream->name, substream->stream);
- if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) &&
- test_bit(SB_CLK_GEAR, &tasha->status_mask)) {
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
tasha_codec_vote_max_bw(dai->codec, false);
- clear_bit(SB_CLK_GEAR, &tasha->status_mask);
- }
return 0;
}
@@ -13082,13 +13071,29 @@
if (tasha->intf_type == WCD9XXX_INTERFACE_TYPE_I2C)
return 0;
- if (vote)
- bw_ops = SLIM_BW_CLK_GEAR_9;
- else
- bw_ops = SLIM_BW_UNVOTE;
+ mutex_lock(&tasha->sb_clk_gear_lock);
+ if (vote) {
+ tasha->ref_count++;
+ if (tasha->ref_count == 1) {
+ bw_ops = SLIM_BW_CLK_GEAR_9;
+ tasha_codec_slim_reserve_bw(codec,
+ bw_ops, true);
+ }
+ } else if (!vote && tasha->ref_count > 0) {
+ tasha->ref_count--;
+ if (tasha->ref_count == 0) {
+ bw_ops = SLIM_BW_UNVOTE;
+ tasha_codec_slim_reserve_bw(codec,
+ bw_ops, true);
+ }
+ };
- return tasha_codec_slim_reserve_bw(codec,
- bw_ops, true);
+ dev_dbg(codec->dev, "%s Value of counter after vote or un-vote is %d\n",
+ __func__, tasha->ref_count);
+
+ mutex_unlock(&tasha->sb_clk_gear_lock);
+
+ return 0;
}
static int tasha_cpe_err_irq_control(struct snd_soc_codec *codec,
@@ -13271,6 +13276,8 @@
if (ret < 0)
dev_err(codec->dev, "%s: invalid pdata\n", __func__);
+ /* Reset reference counter for voting for max bw */
+ tasha->ref_count = 0;
/* MBHC Init */
wcd_mbhc_deinit(&tasha->mbhc);
tasha->mbhc_started = false;
@@ -14053,6 +14060,7 @@
mutex_init(&tasha->swr_read_lock);
mutex_init(&tasha->swr_write_lock);
mutex_init(&tasha->swr_clk_lock);
+ mutex_init(&tasha->sb_clk_gear_lock);
mutex_init(&tasha->mclk_lock);
cdc_pwr = devm_kzalloc(&pdev->dev, sizeof(struct wcd9xxx_power_region),
@@ -14157,6 +14165,7 @@
mutex_destroy(&tasha->mclk_lock);
devm_kfree(&pdev->dev, tasha);
snd_soc_unregister_codec(&pdev->dev);
+ mutex_destroy(&tasha->sb_clk_gear_lock);
return 0;
}
diff --git a/sound/soc/codecs/wcd934x/wcd934x-routing.h b/sound/soc/codecs/wcd934x/wcd934x-routing.h
index afd93b2..93a1ad3 100644
--- a/sound/soc/codecs/wcd934x/wcd934x-routing.h
+++ b/sound/soc/codecs/wcd934x/wcd934x-routing.h
@@ -117,6 +117,70 @@
const struct snd_soc_dapm_route tavil_audio_map[] = {
+ /* WDMA3 */
+ {"WDMA3 PORT0 MUX", "DEC0", "ADC MUX0"},
+ {"WDMA3 PORT0 MUX", "RX_MIX_TX0", "RX MIX TX0 MUX"},
+ {"WDMA3 PORT1 MUX", "DEC1", "ADC MUX1"},
+ {"WDMA3 PORT1 MUX", "RX_MIX_TX1", "RX MIX TX1 MUX"},
+ {"WDMA3 PORT2 MUX", "DEC2", "ADC MUX2"},
+ {"WDMA3 PORT2 MUX", "RX_MIX_TX2", "RX MIX TX2 MUX"},
+ {"WDMA3 PORT3 MUX", "DEC3", "ADC MUX3"},
+ {"WDMA3 PORT3 MUX", "RX_MIX_TX3", "RX MIX TX3 MUX"},
+ {"WDMA3 PORT4 MUX", "DEC4", "ADC MUX4"},
+ {"WDMA3 PORT4 MUX", "RX_MIX_TX4", "RX MIX TX4 MUX"},
+ {"WDMA3 PORT5 MUX", "DEC5", "ADC MUX5"},
+ {"WDMA3 PORT5 MUX", "RX_MIX_TX5", "RX MIX TX5 MUX"},
+ {"WDMA3 PORT6 MUX", "DEC6", "ADC MUX6"},
+ {"WDMA3 PORT6 MUX", "RX_MIX_TX6", "RX MIX TX6 MUX"},
+
+ {"WDMA3 CH0 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+ {"WDMA3 CH0 MUX", "PORT_7", "ADC MUX7"},
+ {"WDMA3 CH0 MUX", "PORT_8", "ADC MUX8"},
+
+ {"WDMA3 CH1 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+ {"WDMA3 CH1 MUX", "PORT_7", "ADC MUX7"},
+ {"WDMA3 CH1 MUX", "PORT_8", "ADC MUX8"},
+
+ {"WDMA3 CH2 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+ {"WDMA3 CH2 MUX", "PORT_7", "ADC MUX7"},
+ {"WDMA3 CH2 MUX", "PORT_8", "ADC MUX8"},
+
+ {"WDMA3 CH3 MUX", "PORT_0", "WDMA3 PORT0 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_1", "WDMA3 PORT1 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_2", "WDMA3 PORT2 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_3", "WDMA3 PORT3 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_4", "WDMA3 PORT4 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_5", "WDMA3 PORT5 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_6", "WDMA3 PORT6 MUX"},
+ {"WDMA3 CH3 MUX", "PORT_7", "ADC MUX7"},
+ {"WDMA3 CH3 MUX", "PORT_8", "ADC MUX8"},
+
+ {"WDMA3_CH_MIXER", NULL, "WDMA3 CH0 MUX"},
+ {"WDMA3_CH_MIXER", NULL, "WDMA3 CH1 MUX"},
+ {"WDMA3_CH_MIXER", NULL, "WDMA3 CH2 MUX"},
+ {"WDMA3_CH_MIXER", NULL, "WDMA3 CH3 MUX"},
+
+ {"WDMA3_ON_OFF", "Switch", "WDMA3_CH_MIXER"},
+ {"WDMA3_OUT", NULL, "WDMA3_ON_OFF"},
+
/* MAD */
{"MAD_SEL MUX", "SPE", "MAD_CPE_INPUT"},
{"MAD_SEL MUX", "MSM", "MADINPUT"},
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index ca16ed8..3079cca 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -180,6 +180,8 @@
ANC_MIC_AMIC2,
ANC_MIC_AMIC3,
ANC_MIC_AMIC4,
+ CLK_INTERNAL,
+ CLK_MODE,
};
enum {
@@ -1071,6 +1073,40 @@
return ret;
}
+static int tavil_get_clkmode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
+
+ if (test_bit(CLK_MODE, &tavil_p->status_mask))
+ ucontrol->value.enumerated.item[0] = 1;
+ else
+ ucontrol->value.enumerated.item[0] = 0;
+
+ dev_dbg(codec->dev, "%s: is_low_power_clock: %s\n", __func__,
+ test_bit(CLK_MODE, &tavil_p->status_mask) ? "true" : "false");
+
+ return 0;
+}
+
+static int tavil_put_clkmode(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
+ struct tavil_priv *tavil_p = snd_soc_codec_get_drvdata(codec);
+
+ if (ucontrol->value.enumerated.item[0])
+ set_bit(CLK_MODE, &tavil_p->status_mask);
+ else
+ clear_bit(CLK_MODE, &tavil_p->status_mask);
+
+ dev_dbg(codec->dev, "%s: is_low_power_clock: %s\n", __func__,
+ test_bit(CLK_MODE, &tavil_p->status_mask) ? "true" : "false");
+
+ return 0;
+}
+
static int tavil_vi_feed_mixer_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2809,6 +2845,35 @@
return asrc_mode;
}
+static int tavil_codec_wdma3_ctl(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ /* Fix to 16KHz */
+ snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+ 0xF0, 0x10);
+ /* Select mclk_1 */
+ snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+ 0x02, 0x00);
+ /* Enable DMA */
+ snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+ 0x01, 0x01);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ /* Disable DMA */
+ snd_soc_update_bits(codec, WCD934X_DMA_WDMA_CTL_3,
+ 0x01, 0x00);
+ break;
+
+ };
+
+ return 0;
+}
+
static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
int asrc_in, int event)
{
@@ -5547,6 +5612,9 @@
static const struct soc_enum tavil_anc_func_enum =
SOC_ENUM_SINGLE_EXT(2, tavil_anc_func_text);
+static const char *const tavil_clkmode_text[] = {"EXTERNAL", "INTERNAL"};
+static SOC_ENUM_SINGLE_EXT_DECL(tavil_clkmode_enum, tavil_clkmode_text);
+
/* Cutoff frequency for high pass filter */
static const char * const cf_text[] = {
"CF_NEG_3DB_4HZ", "CF_NEG_3DB_75HZ", "CF_NEG_3DB_150HZ"
@@ -5726,6 +5794,9 @@
SOC_ENUM_EXT("ANC Function", tavil_anc_func_enum, tavil_get_anc_func,
tavil_put_anc_func),
+ SOC_ENUM_EXT("CLK MODE", tavil_clkmode_enum, tavil_get_clkmode,
+ tavil_put_clkmode),
+
SOC_ENUM("TX0 HPF cut off", cf_dec0_enum),
SOC_ENUM("TX1 HPF cut off", cf_dec1_enum),
SOC_ENUM("TX2 HPF cut off", cf_dec2_enum),
@@ -6165,6 +6236,39 @@
"OFF", "ON",
};
+static const char *const wdma3_port0_text[] = {
+ "RX_MIX_TX0", "DEC0"
+};
+
+static const char *const wdma3_port1_text[] = {
+ "RX_MIX_TX1", "DEC1"
+};
+
+static const char *const wdma3_port2_text[] = {
+ "RX_MIX_TX2", "DEC2"
+};
+
+static const char *const wdma3_port3_text[] = {
+ "RX_MIX_TX3", "DEC3"
+};
+
+static const char *const wdma3_port4_text[] = {
+ "RX_MIX_TX4", "DEC4"
+};
+
+static const char *const wdma3_port5_text[] = {
+ "RX_MIX_TX5", "DEC5"
+};
+
+static const char *const wdma3_port6_text[] = {
+ "RX_MIX_TX6", "DEC6"
+};
+
+static const char *const wdma3_ch_text[] = {
+ "PORT_0", "PORT_1", "PORT_2", "PORT_3", "PORT_4",
+ "PORT_5", "PORT_6", "PORT_7", "PORT_8",
+};
+
static const struct snd_kcontrol_new aif4_vi_mixer[] = {
SOC_SINGLE_EXT("SPKR_VI_1", SND_SOC_NOPM, WCD934X_TX14, 1, 0,
tavil_vi_feed_mixer_get, tavil_vi_feed_mixer_put),
@@ -6570,6 +6674,20 @@
WCD_DAPM_ENUM(anc0_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 0, anc0_fb_mux_text);
WCD_DAPM_ENUM(anc1_fb, WCD934X_CDC_RX_INP_MUX_ANC_CFG0, 3, anc1_fb_mux_text);
+
+WCD_DAPM_ENUM(wdma3_port0, WCD934X_DMA_WDMA3_PRT_CFG, 0, wdma3_port0_text);
+WCD_DAPM_ENUM(wdma3_port1, WCD934X_DMA_WDMA3_PRT_CFG, 1, wdma3_port1_text);
+WCD_DAPM_ENUM(wdma3_port2, WCD934X_DMA_WDMA3_PRT_CFG, 2, wdma3_port2_text);
+WCD_DAPM_ENUM(wdma3_port3, WCD934X_DMA_WDMA3_PRT_CFG, 3, wdma3_port3_text);
+WCD_DAPM_ENUM(wdma3_port4, WCD934X_DMA_WDMA3_PRT_CFG, 4, wdma3_port4_text);
+WCD_DAPM_ENUM(wdma3_port5, WCD934X_DMA_WDMA3_PRT_CFG, 5, wdma3_port5_text);
+WCD_DAPM_ENUM(wdma3_port6, WCD934X_DMA_WDMA3_PRT_CFG, 6, wdma3_port6_text);
+
+WCD_DAPM_ENUM(wdma3_ch0, WCD934X_DMA_CH_0_1_CFG_WDMA_3, 0, wdma3_ch_text);
+WCD_DAPM_ENUM(wdma3_ch1, WCD934X_DMA_CH_0_1_CFG_WDMA_3, 4, wdma3_ch_text);
+WCD_DAPM_ENUM(wdma3_ch2, WCD934X_DMA_CH_2_3_CFG_WDMA_3, 0, wdma3_ch_text);
+WCD_DAPM_ENUM(wdma3_ch3, WCD934X_DMA_CH_2_3_CFG_WDMA_3, 4, wdma3_ch_text);
+
static const struct snd_kcontrol_new anc_ear_switch =
SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
@@ -6637,6 +6755,9 @@
SOC_DAPM_SINGLE("LO2 Switch", SND_SOC_NOPM, 0, 1, 0),
};
+static const struct snd_kcontrol_new wdma3_onoff_switch =
+ SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 0);
+
static int tavil_dsd_mixer_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -7319,6 +7440,28 @@
SND_SOC_DAPM_MUX_E("ASRC3 MUX", SND_SOC_NOPM, ASRC3, 0,
&asrc3_mux, tavil_codec_enable_asrc_resampler,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* WDMA3 widgets */
+ WCD_DAPM_MUX("WDMA3 PORT0 MUX", 0, wdma3_port0),
+ WCD_DAPM_MUX("WDMA3 PORT1 MUX", 1, wdma3_port1),
+ WCD_DAPM_MUX("WDMA3 PORT2 MUX", 2, wdma3_port2),
+ WCD_DAPM_MUX("WDMA3 PORT3 MUX", 3, wdma3_port3),
+ WCD_DAPM_MUX("WDMA3 PORT4 MUX", 4, wdma3_port4),
+ WCD_DAPM_MUX("WDMA3 PORT5 MUX", 5, wdma3_port5),
+ WCD_DAPM_MUX("WDMA3 PORT6 MUX", 6, wdma3_port6),
+
+ WCD_DAPM_MUX("WDMA3 CH0 MUX", 0, wdma3_ch0),
+ WCD_DAPM_MUX("WDMA3 CH1 MUX", 4, wdma3_ch1),
+ WCD_DAPM_MUX("WDMA3 CH2 MUX", 0, wdma3_ch2),
+ WCD_DAPM_MUX("WDMA3 CH3 MUX", 4, wdma3_ch3),
+
+ SND_SOC_DAPM_MIXER("WDMA3_CH_MIXER", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SWITCH_E("WDMA3_ON_OFF", SND_SOC_NOPM, 0, 0,
+ &wdma3_onoff_switch, tavil_codec_wdma3_ctl,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_OUTPUT("WDMA3_OUT"),
};
static int tavil_get_channel_map(struct snd_soc_dai *dai,
@@ -8316,6 +8459,50 @@
return ret;
}
+/*
+ * tavil_cdc_mclk_tx_enable: Enable/Disable codec's clock for TX path
+ * @codec: Handle to codec
+ * @enable: Indicates whether clock should be enabled or disabled
+ */
+int tavil_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable)
+{
+ struct tavil_priv *tavil_p;
+ int ret = 0;
+ bool clk_mode;
+ bool clk_internal;
+
+ if (!codec)
+ return -EINVAL;
+
+ tavil_p = snd_soc_codec_get_drvdata(codec);
+ clk_mode = test_bit(CLK_MODE, &tavil_p->status_mask);
+ clk_internal = test_bit(CLK_INTERNAL, &tavil_p->status_mask);
+
+ dev_dbg(codec->dev, "%s: clkmode: %d, enable: %d, clk_internal: %d\n",
+ __func__, clk_mode, enable, clk_internal);
+
+ if (clk_mode || clk_internal) {
+ if (enable) {
+ wcd_resmgr_enable_master_bias(tavil_p->resmgr);
+ tavil_dig_core_power_collapse(tavil_p, POWER_RESUME);
+ tavil_vote_svs(tavil_p, true);
+ ret = tavil_codec_internal_rco_ctrl(codec, enable);
+ set_bit(CLK_INTERNAL, &tavil_p->status_mask);
+ } else {
+ clear_bit(CLK_INTERNAL, &tavil_p->status_mask);
+ tavil_codec_internal_rco_ctrl(codec, enable);
+ tavil_vote_svs(tavil_p, false);
+ tavil_dig_core_power_collapse(tavil_p, POWER_COLLAPSE);
+ wcd_resmgr_disable_master_bias(tavil_p->resmgr);
+ }
+ } else {
+ ret = __tavil_cdc_mclk_enable(tavil_p, enable);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(tavil_cdc_mclk_tx_enable);
+
static const struct wcd_resmgr_cb tavil_resmgr_cb = {
.cdc_rco_ctrl = __tavil_codec_internal_rco_ctrl,
};
diff --git a/sound/soc/codecs/wcd934x/wcd934x.h b/sound/soc/codecs/wcd934x/wcd934x.h
index c3bf50a..27c21f1 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.h
+++ b/sound/soc/codecs/wcd934x/wcd934x.h
@@ -137,6 +137,7 @@
extern void *tavil_get_afe_config(struct snd_soc_codec *codec,
enum afe_config_type config_type);
extern int tavil_cdc_mclk_enable(struct snd_soc_codec *codec, bool enable);
+extern int tavil_cdc_mclk_tx_enable(struct snd_soc_codec *codec, bool enable);
extern int tavil_set_spkr_mode(struct snd_soc_codec *codec, int mode);
extern int tavil_set_spkr_gain_offset(struct snd_soc_codec *codec, int offset);
extern struct wcd_dsp_cntl *tavil_get_wcd_dsp_cntl(struct device *dev);
diff --git a/sound/soc/codecs/wcd_cpe_services.c b/sound/soc/codecs/wcd_cpe_services.c
index 0028ebc..ad8962b 100644
--- a/sound/soc/codecs/wcd_cpe_services.c
+++ b/sound/soc/codecs/wcd_cpe_services.c
@@ -20,7 +20,6 @@
#include <linux/mfd/wcd9xxx/core.h>
#include <sound/cpe_cmi.h>
#include <sound/soc.h>
-#include <linux/mfd/wcd9xxx/wcd9330_registers.h>
#include <linux/mfd/wcd9335/registers.h>
#include "wcd_cpe_services.h"
#include "wcd_cmi_api.h"
@@ -46,9 +45,6 @@
#define LISTEN_CTL_SPE_VAL 0x0
#define LISTEN_CTL_MSM_VAL 0x1
-#define TOMTOM_A_SVASS_SPE_INBOX(N) (TOMTOM_A_SVASS_SPE_INBOX_0 + (N))
-#define TOMTOM_A_SVASS_SPE_OUTBOX(N) (TOMTOM_A_SVASS_SPE_OUTBOX_0 + (N))
-
#define WCD9335_CPE_SS_SPE_DRAM_OFFSET 0x48000
#define WCD9335_CPE_SS_SPE_DRAM_SIZE 0x34000
#define WCD9335_CPE_SS_SPE_IRAM_OFFSET 0x80000
@@ -316,8 +312,7 @@
{
int ret = 0;
- if (reg != TOMTOM_A_SVASS_MEM_BANK &&
- reg != WCD9335_CPE_SS_MEM_BANK_0)
+ if (reg != WCD9335_CPE_SS_MEM_BANK_0)
pr_debug("%s: reg = 0x%x, value = 0x%x\n",
__func__, reg, val);
@@ -2149,73 +2144,27 @@
static enum cpe_svc_result cpe_tgt_tomtom_boot(int debug_mode)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
-
- if (!debug_mode)
- rc = cpe_update_bits(TOMTOM_A_SVASS_CPAR_WDOG_CFG,
- 0x3F, 0x31);
- else
- pr_info("%s: CPE in debug mode, WDOG disabled\n",
- __func__);
-
- rc = cpe_update_bits(TOMTOM_A_SVASS_CLKRST_CTL,
- 0x02, 0x00);
- rc = cpe_update_bits(TOMTOM_A_SVASS_CLKRST_CTL,
- 0x0C, 0x04);
- rc = cpe_update_bits(TOMTOM_A_SVASS_CPAR_CFG,
- 0x01, 0x01);
-
- return rc;
+ return CPE_SVC_SUCCESS;
}
static u32 cpe_tgt_tomtom_is_cpar_init_done(void)
{
- u8 status = 0;
-
- cpe_register_read(TOMTOM_A_SVASS_STATUS, &status);
- return status & 0x01;
+ return 0;
}
static u32 cpe_tgt_tomtom_is_active(void)
{
- u8 status = 0;
-
- cpe_register_read(TOMTOM_A_SVASS_STATUS, &status);
- return status & 0x04;
+ return 0;
}
static enum cpe_svc_result cpe_tgt_tomtom_reset(void)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
-
- rc = cpe_update_bits(TOMTOM_A_SVASS_CPAR_WDOG_CFG,
- 0x30, 0x00);
-
- rc = cpe_update_bits(TOMTOM_A_SVASS_CPAR_CFG,
- 0x01, 0x00);
- rc = cpe_update_bits(TOMTOM_A_MEM_LEAKAGE_CTL,
- 0x07, 0x03);
- rc = cpe_update_bits(TOMTOM_A_SVASS_CLKRST_CTL,
- 0x08, 0x08);
- rc = cpe_update_bits(TOMTOM_A_SVASS_CLKRST_CTL,
- 0x02, 0x02);
- return rc;
+ return CPE_SVC_SUCCESS;
}
enum cpe_svc_result cpe_tgt_tomtom_voicetx(bool enable)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u8 val = 0;
-
- if (enable)
- val = 0x02;
- else
- val = 0x00;
- rc = cpe_update_bits(TOMTOM_A_SVASS_CFG,
- 0x02, val);
- val = 0;
- cpe_register_read(TOMTOM_A_SVASS_CFG, &val);
- return rc;
+ return CPE_SVC_SUCCESS;
}
enum cpe_svc_result cpe_svc_toggle_lab(void *cpe_handle, bool enable)
@@ -2235,251 +2184,37 @@
static enum cpe_svc_result cpe_tgt_tomtom_read_mailbox(u8 *buffer,
size_t size)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u32 cnt = 0;
-
- if (size >= TOMTOM_A_SVASS_SPE_OUTBOX_SIZE)
- size = TOMTOM_A_SVASS_SPE_OUTBOX_SIZE - 1;
- for (cnt = 0; (cnt < size) && (rc == CPE_SVC_SUCCESS); cnt++) {
- rc = cpe_register_read(TOMTOM_A_SVASS_SPE_OUTBOX(cnt),
- &(buffer[cnt]));
- }
- return rc;
+ return CPE_SVC_SUCCESS;
}
static enum cpe_svc_result cpe_tgt_tomtom_write_mailbox(u8 *buffer,
size_t size)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u32 cnt = 0;
-
- if (size >= TOMTOM_A_SVASS_SPE_INBOX_SIZE)
- size = TOMTOM_A_SVASS_SPE_INBOX_SIZE - 1;
- for (cnt = 0; (cnt < size) && (rc == CPE_SVC_SUCCESS); cnt++) {
- rc = cpe_register_write(TOMTOM_A_SVASS_SPE_INBOX(cnt),
- buffer[cnt]);
- }
-
- if (rc == CPE_SVC_SUCCESS)
- rc = cpe_register_write(TOMTOM_A_SVASS_SPE_INBOX_TRG, 1);
-
- return rc;
-}
-
-static enum cpe_svc_result cpe_get_mem_addr(struct cpe_info *t_info,
- const struct cpe_svc_mem_segment *mem_seg,
- u32 *addr, u8 *mem)
-{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u32 offset, mem_sz, address;
- u8 mem_type;
-
- switch (mem_seg->type) {
-
- case CPE_SVC_DATA_MEM:
- mem_type = MEM_ACCESS_DRAM_VAL;
- offset = TOMTOM_A_SVASS_SPE_DRAM_OFFSET;
- mem_sz = TOMTOM_A_SVASS_SPE_DRAM_SIZE;
- break;
-
- case CPE_SVC_INSTRUCTION_MEM:
- mem_type = MEM_ACCESS_IRAM_VAL;
- offset = TOMTOM_A_SVASS_SPE_IRAM_OFFSET;
- mem_sz = TOMTOM_A_SVASS_SPE_IRAM_SIZE;
- break;
-
- default:
- pr_err("%s: Invalid mem type = %u\n",
- __func__, mem_seg->type);
- return CPE_SVC_INVALID_HANDLE;
- }
-
- if (mem_seg->cpe_addr < offset) {
- pr_err("%s: Invalid addr %x for mem type %u\n",
- __func__, mem_seg->cpe_addr, mem_type);
- return CPE_SVC_INVALID_HANDLE;
- }
-
- address = mem_seg->cpe_addr - offset;
- if (address + mem_seg->size > mem_sz) {
- pr_err("%s: wrong size %zu, start address %x, mem_type %u\n",
- __func__, mem_seg->size, address, mem_type);
- return CPE_SVC_INVALID_HANDLE;
- }
-
- (*addr) = address;
- (*mem) = mem_type;
-
- return rc;
+ return CPE_SVC_SUCCESS;
}
static enum cpe_svc_result cpe_tgt_tomtom_read_RAM(struct cpe_info *t_info,
struct cpe_svc_mem_segment *mem_seg)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u8 mem_reg_val = 0;
- u32 cnt = 0;
- bool autoinc;
- u8 mem = MEM_ACCESS_NONE_VAL;
- u32 addr = 0;
- u32 ptr_update = true;
-
- if (!mem_seg) {
- pr_err("%s: Invalid mem segment\n",
- __func__);
- return CPE_SVC_INVALID_HANDLE;
- }
-
- rc = cpe_get_mem_addr(t_info, mem_seg, &addr, &mem);
-
- if (rc != CPE_SVC_SUCCESS) {
- pr_err("%s: Cannot obtain address, mem_type %u\n",
- __func__, mem_seg->type);
- return rc;
- }
-
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_CTL, 0);
- autoinc = cpe_register_read_autoinc_supported();
- if (autoinc)
- mem_reg_val |= 0x04;
-
- mem_reg_val |= 0x08;
- mem_reg_val |= mem;
-
- do {
- if (!autoinc || ptr_update) {
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_PTR0,
- (addr & 0xFF));
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_PTR1,
- ((addr >> 8) & 0xFF));
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_PTR2,
- ((addr >> 16) & 0xFF));
-
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_CTL,
- mem_reg_val);
-
- ptr_update = false;
- }
- rc = cpe_register_read(TOMTOM_A_SVASS_MEM_BANK,
- &mem_seg->data[cnt]);
-
- if (!autoinc)
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_CTL, 0);
- } while (++cnt < mem_seg->size);
-
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_CTL, 0);
-
- return rc;
+ return CPE_SVC_SUCCESS;
}
static enum cpe_svc_result cpe_tgt_tomtom_write_RAM(struct cpe_info *t_info,
const struct cpe_svc_mem_segment *mem_seg)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u8 mem_reg_val = 0;
- u8 mem = MEM_ACCESS_NONE_VAL;
- u32 addr = 0;
- u8 *temp_ptr = NULL;
- u32 temp_size = 0;
- bool autoinc;
-
- if (!mem_seg) {
- pr_err("%s: Invalid mem segment\n",
- __func__);
- return CPE_SVC_INVALID_HANDLE;
- }
-
- rc = cpe_get_mem_addr(t_info, mem_seg, &addr, &mem);
-
- if (rc != CPE_SVC_SUCCESS) {
- pr_err("%s: Cannot obtain address, mem_type %u\n",
- __func__, mem_seg->type);
- return rc;
- }
-
- autoinc = cpe_register_read_autoinc_supported();
- if (autoinc)
- mem_reg_val |= 0x04;
- mem_reg_val |= mem;
-
- rc = cpe_update_bits(TOMTOM_A_SVASS_MEM_CTL,
- 0x0F, mem_reg_val);
-
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_PTR0,
- (addr & 0xFF));
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_PTR1,
- ((addr >> 8) & 0xFF));
-
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_PTR2,
- ((addr >> 16) & 0xFF));
-
- temp_size = 0;
- temp_ptr = mem_seg->data;
-
- while (temp_size <= mem_seg->size) {
- u32 to_write = (mem_seg->size >= temp_size+CHUNK_SIZE)
- ? CHUNK_SIZE : (mem_seg->size-temp_size);
-
- if (t_info->state == CPE_STATE_OFFLINE) {
- pr_err("%s: CPE is offline\n", __func__);
- return CPE_SVC_FAILED;
- }
-
- cpe_register_write_repeat(TOMTOM_A_SVASS_MEM_BANK,
- temp_ptr, to_write);
- temp_size += CHUNK_SIZE;
- temp_ptr += CHUNK_SIZE;
- }
-
- rc = cpe_register_write(TOMTOM_A_SVASS_MEM_CTL, 0);
- return rc;
+ return CPE_SVC_SUCCESS;
}
static enum cpe_svc_result cpe_tgt_tomtom_route_notification(
enum cpe_svc_module module,
enum cpe_svc_route_dest dest)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u8 ctl_reg_val = 0;
-
- switch (module) {
- case CPE_SVC_LISTEN_PROC:
- switch (dest) {
- case CPE_SVC_EXTERNAL:
- ctl_reg_val = LISTEN_CTL_MSM_VAL;
- break;
- case CPE_SVC_INTERNAL:
- ctl_reg_val = LISTEN_CTL_SPE_VAL;
- break;
- default:
- pr_err("%s: Invalid dest %d\n",
- __func__, dest);
- return CPE_SVC_FAILED;
- }
-
- rc = cpe_update_bits(TOMTOM_A_SVASS_CFG,
- 0x01, ctl_reg_val);
- break;
- default:
- pr_err("%s: Invalid module %d\n",
- __func__, module);
- rc = CPE_SVC_FAILED;
- break;
- }
-
- return rc;
+ return CPE_SVC_SUCCESS;
}
static enum cpe_svc_result cpe_tgt_tomtom_set_debug_mode(u32 enable)
{
- enum cpe_svc_result rc = CPE_SVC_SUCCESS;
- u8 dbg_reg_val = 0x00;
-
- if (enable)
- dbg_reg_val = 0x08;
- rc = cpe_update_bits(TOMTOM_A_SVASS_DEBUG,
- 0x08, dbg_reg_val);
- return rc;
+ return CPE_SVC_SUCCESS;
}
static const struct cpe_svc_hw_cfg *cpe_tgt_tomtom_get_cpe_info(void)
diff --git a/sound/soc/msm/Kconfig b/sound/soc/msm/Kconfig
index c557ae0..abadd08 100644
--- a/sound/soc/msm/Kconfig
+++ b/sound/soc/msm/Kconfig
@@ -112,14 +112,12 @@
select MSM_CDC_PINCTRL
select SND_SOC_MSM_SDW
select SND_SOC_SDM660_CDC
- select SND_SOC_MSM_HDMI_CODEC_RX
select QTI_PP
select DTS_SRS_TM
select DOLBY_LICENSE
select SND_HWDEP
select MSM_ULTRASOUND
select DTS_EAGLE
- select SND_SOC_SDM660_COMMON
select SND_SOC_COMPRESS
select PINCTRL_LPI
help
@@ -144,7 +142,6 @@
select SND_SOC_WCD9335
select SND_SOC_WCD934X
select SND_SOC_WSA881X
- select SND_SOC_MSM_HDMI_CODEC_RX
select MFD_CORE
select QTI_PP
select DTS_SRS_TM
@@ -154,7 +151,6 @@
select SND_HWDEP
select MSM_ULTRASOUND
select DTS_EAGLE
- select SND_SOC_SDM660_COMMON
select SND_SOC_COMPRESS
select PINCTRL_LPI
help
@@ -233,12 +229,12 @@
DAI-links
config SND_SOC_660
- tristate "SoC Machine driver for SDM660 boards"
- depends on ARCH_SDM660
+ tristate "SoC Machine driver for SDM660/670 boards"
+ depends on ARCH_SDM660 || ARCH_SDM670
select SND_SOC_INT_CODEC
select SND_SOC_EXT_CODEC
help
- To add support for SoC audio on SDM660.
+ To add support for SoC audio on SDM660/670.
This will enable sound soc drivers which
interfaces with DSP, also it will enable
the machine driver and the corresponding
diff --git a/sound/soc/msm/qdsp6v2/audio_calibration.c b/sound/soc/msm/qdsp6v2/audio_calibration.c
index 808a0e4..d709b09 100644
--- a/sound/soc/msm/qdsp6v2/audio_calibration.c
+++ b/sound/soc/msm/qdsp6v2/audio_calibration.c
@@ -460,6 +460,12 @@
data->cal_type.cal_hdr.buffer_number);
ret = -EINVAL;
goto done;
+ } else if ((data->hdr.cal_type_size + sizeof(data->hdr)) > size) {
+ pr_err("%s: cal type hdr size %zd + cal type size %d is greater than user buffer size %d\n",
+ __func__, sizeof(data->hdr), data->hdr.cal_type_size,
+ size);
+ ret = -EFAULT;
+ goto done;
}
@@ -497,13 +503,7 @@
goto unlock;
if (data == NULL)
goto unlock;
- if ((sizeof(data->hdr) + data->hdr.cal_type_size) > size) {
- pr_err("%s: header size %zd plus cal type size %d are greater than data buffer size %d\n",
- __func__, sizeof(data->hdr),
- data->hdr.cal_type_size, size);
- ret = -EFAULT;
- goto unlock;
- } else if (copy_to_user((void *)arg, data,
+ if (copy_to_user(arg, data,
sizeof(data->hdr) + data->hdr.cal_type_size)) {
pr_err("%s: Could not copy cal type to user\n",
__func__);
diff --git a/sound/soc/msm/sdm660-common.c b/sound/soc/msm/sdm660-common.c
index eddcb45..b34b04b 100644
--- a/sound/soc/msm/sdm660-common.c
+++ b/sound/soc/msm/sdm660-common.c
@@ -12,6 +12,9 @@
#include <linux/input.h>
#include <linux/of_gpio.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <linux/mfd/msm-cdc-pinctrl.h>
#include <sound/pcm_params.h>
#include <sound/q6afe-v2.h>
@@ -190,7 +193,7 @@
static struct snd_soc_aux_dev *msm_aux_dev;
static struct snd_soc_codec_conf *msm_codec_conf;
-static bool msm_swap_gnd_mic(struct snd_soc_codec *codec);
+static bool msm_swap_gnd_mic(struct snd_soc_codec *codec, bool active);
static struct wcd_mbhc_config mbhc_cfg = {
.read_fw_bin = false,
@@ -2038,16 +2041,16 @@
}
}
-static int msm_ext_disp_get_idx_from_beid(int32_t be_id)
+static int msm_ext_disp_get_idx_from_beid(int32_t id)
{
int idx;
- switch (be_id) {
+ switch (id) {
case MSM_BACKEND_DAI_DISPLAY_PORT_RX:
idx = DP_RX_IDX;
break;
default:
- pr_err("%s: Incorrect ext_disp be_id %d\n", __func__, be_id);
+ pr_err("%s: Incorrect ext_disp id %d\n", __func__, id);
idx = -EINVAL;
break;
}
@@ -2077,7 +2080,7 @@
pr_debug("%s: format = %d, rate = %d\n",
__func__, params_format(params), params_rate(params));
- switch (dai_link->be_id) {
+ switch (dai_link->id) {
case MSM_BACKEND_DAI_USB_RX:
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
usb_rx_cfg.bit_format);
@@ -2093,8 +2096,8 @@
break;
case MSM_BACKEND_DAI_DISPLAY_PORT_RX:
- idx = msm_ext_disp_get_idx_from_beid(dai_link->be_id);
- if (IS_ERR_VALUE(idx)) {
+ idx = msm_ext_disp_get_idx_from_beid(dai_link->id);
+ if (idx < 0) {
pr_err("%s: Incorrect ext disp idx %d\n",
__func__, idx);
rc = idx;
@@ -2341,11 +2344,11 @@
}
EXPORT_SYMBOL(msm_aux_pcm_snd_shutdown);
-static int msm_get_port_id(int be_id)
+static int msm_get_port_id(int id)
{
int afe_port_id;
- switch (be_id) {
+ switch (id) {
case MSM_BACKEND_DAI_PRI_MI2S_RX:
afe_port_id = AFE_PORT_ID_PRIMARY_MI2S_RX;
break;
@@ -2371,7 +2374,7 @@
afe_port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX;
break;
default:
- pr_err("%s: Invalid be_id: %d\n", __func__, be_id);
+ pr_err("%s: Invalid id: %d\n", __func__, id);
afe_port_id = -EINVAL;
}
@@ -2422,7 +2425,7 @@
int port_id = 0;
int index = cpu_dai->id;
- port_id = msm_get_port_id(rtd->dai_link->be_id);
+ port_id = msm_get_port_id(rtd->dai_link->id);
if (port_id < 0) {
dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
ret = port_id;
@@ -2461,7 +2464,7 @@
int ret = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int port_id = msm_get_port_id(rtd->dai_link->be_id);
+ int port_id = msm_get_port_id(rtd->dai_link->id);
int index = cpu_dai->id;
unsigned int fmt = SND_SOC_DAIFMT_CBS_CFS;
@@ -2539,7 +2542,7 @@
{
int ret;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- int port_id = msm_get_port_id(rtd->dai_link->be_id);
+ int port_id = msm_get_port_id(rtd->dai_link->id);
int index = rtd->cpu_dai->id;
pr_debug("%s(): substream = %s stream = %d\n", __func__,
@@ -2594,7 +2597,7 @@
return ret;
}
-static bool msm_swap_gnd_mic(struct snd_soc_codec *codec)
+static bool msm_swap_gnd_mic(struct snd_soc_codec *codec, bool active)
{
struct snd_soc_card *card = codec->component.card;
struct msm_asoc_mach_data *pdata =
@@ -2699,13 +2702,13 @@
dai_link[i].codec_name = NULL;
}
if (pdata->snd_card_val == INT_SND_CARD) {
- if ((dai_link[i].be_id ==
+ if ((dai_link[i].id ==
MSM_BACKEND_DAI_INT0_MI2S_RX) ||
- (dai_link[i].be_id ==
+ (dai_link[i].id ==
MSM_BACKEND_DAI_INT1_MI2S_RX) ||
- (dai_link[i].be_id ==
+ (dai_link[i].id ==
MSM_BACKEND_DAI_INT2_MI2S_TX) ||
- (dai_link[i].be_id ==
+ (dai_link[i].id ==
MSM_BACKEND_DAI_INT3_MI2S_TX)) {
index = of_property_match_string(cdev->of_node,
"asoc-codec-names",
diff --git a/sound/soc/msm/sdm660-ext-dai-links.c b/sound/soc/msm/sdm660-ext-dai-links.c
index 1c03d8c..77d3875 100644
--- a/sound/soc/msm/sdm660-ext-dai-links.c
+++ b/sound/soc/msm/sdm660-ext-dai-links.c
@@ -86,8 +86,8 @@
goto exit;
}
- dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) be_id %d\n",
- __func__, tx_ch_cnt, dai_link->be_id);
+ dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) id %d\n",
+ __func__, tx_ch_cnt, dai_link->id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
@@ -279,7 +279,7 @@
.platform_name = "msm-pcm-hostless",
.codec_name = "tasha_codec",
.codec_dai_name = "tasha_vifeedback",
- .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
@@ -368,7 +368,7 @@
.platform_name = "msm-pcm-hostless",
.codec_name = "tavil_codec",
.codec_dai_name = "tavil_vifeedback",
- .be_id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_4_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
@@ -411,7 +411,7 @@
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
.init = &msm_audrx_init,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
/* this dainlink has playback support */
@@ -428,7 +428,7 @@
.codec_dai_name = "tasha_tx1",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
.ops = &msm_ext_slimbus_be_ops,
@@ -442,7 +442,7 @@
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -458,7 +458,7 @@
.codec_dai_name = "tasha_tx3",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_suspend = 1,
@@ -472,7 +472,7 @@
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -489,7 +489,7 @@
.no_pcm = 1,
.dpcm_capture = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_suspend = 1,
@@ -503,7 +503,7 @@
.codec_dai_name = "tasha_mix_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -519,7 +519,7 @@
.codec_dai_name = "tasha_rx3",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -536,7 +536,7 @@
.codec_dai_name = "tasha_mad1",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_suspend = 1,
@@ -550,7 +550,7 @@
.codec_dai_name = "tasha_rx4",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -569,7 +569,7 @@
.codec_dai_name = "tavil_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_0_RX,
.init = &msm_audrx_init,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
/* this dainlink has playback support */
@@ -586,7 +586,7 @@
.codec_dai_name = "tavil_tx1",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_0_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
.ops = &msm_ext_slimbus_be_ops,
@@ -600,7 +600,7 @@
.codec_dai_name = "tavil_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_1_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -616,7 +616,7 @@
.codec_dai_name = "tavil_tx3",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_1_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_suspend = 1,
@@ -630,7 +630,7 @@
.codec_dai_name = "tavil_rx2",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_2_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_2_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_pmdown_time = 1,
@@ -645,7 +645,7 @@
.codec_dai_name = "tavil_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_3_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -661,7 +661,7 @@
.codec_dai_name = "tavil_tx1",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_3_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_suspend = 1,
@@ -675,7 +675,7 @@
.codec_dai_name = "tavil_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_4_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -691,7 +691,7 @@
.codec_dai_name = "tavil_rx3",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_5_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -708,7 +708,7 @@
.codec_dai_name = "tavil_mad1",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_5_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
.ignore_suspend = 1,
@@ -722,7 +722,7 @@
.codec_dai_name = "tavil_rx4",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_6_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_ext_slimbus_be_ops,
/* dai link has playback support */
@@ -748,7 +748,7 @@
.dpcm_capture = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA1
},
{/* hw:x,1 */
.name = MSM_DAILINK_NAME(Media2),
@@ -765,7 +765,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
},
{/* hw:x,2 */
.name = "VoiceMMode1",
@@ -782,7 +782,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_VOICEMMODE1,
+ .id = MSM_FRONTEND_DAI_VOICEMMODE1,
},
{/* hw:x,3 */
.name = "MSM VoIP",
@@ -799,7 +799,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_VOIP,
+ .id = MSM_FRONTEND_DAI_VOIP,
},
{/* hw:x,4 */
.name = MSM_DAILINK_NAME(ULL),
@@ -815,7 +815,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA3,
},
/* Hostless PCM purpose */
{/* hw:x,5 */
@@ -871,7 +871,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA4,
},
{/* hw:x,9*/
.name = "AUXPCM Hostless",
@@ -953,7 +953,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA5,
},
/* LSM FE */
{/* hw:x,14 */
@@ -970,7 +970,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM1,
+ .id = MSM_FRONTEND_DAI_LSM1,
},
{/* hw:x,15 */
.name = MSM_DAILINK_NAME(Compress2),
@@ -987,7 +987,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA7,
},
{/* hw:x,16 */
.name = MSM_DAILINK_NAME(Compress3),
@@ -1004,7 +1004,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA10,
},
{/* hw:x,17 */
.name = MSM_DAILINK_NAME(ULL_NOIRQ),
@@ -1021,7 +1021,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA8,
},
{/* hw:x,18 */
.name = "HDMI_RX_HOSTLESS",
@@ -1053,7 +1053,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_VOICEMMODE2,
+ .id = MSM_FRONTEND_DAI_VOICEMMODE2,
},
{/* hw:x,20 */
.name = "Listen 2 Audio Service",
@@ -1069,7 +1069,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM2,
+ .id = MSM_FRONTEND_DAI_LSM2,
},
{/* hw:x,21 */
.name = "Listen 3 Audio Service",
@@ -1085,7 +1085,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM3,
+ .id = MSM_FRONTEND_DAI_LSM3,
},
{/* hw:x,22 */
.name = "Listen 4 Audio Service",
@@ -1101,7 +1101,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM4,
+ .id = MSM_FRONTEND_DAI_LSM4,
},
{/* hw:x,23 */
.name = "Listen 5 Audio Service",
@@ -1117,7 +1117,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM5,
+ .id = MSM_FRONTEND_DAI_LSM5,
},
{/* hw:x,24 */
.name = "Listen 6 Audio Service",
@@ -1133,7 +1133,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM6
+ .id = MSM_FRONTEND_DAI_LSM6
},
{/* hw:x,25 */
.name = "Listen 7 Audio Service",
@@ -1149,7 +1149,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM7,
+ .id = MSM_FRONTEND_DAI_LSM7,
},
{/* hw:x,26 */
.name = "Listen 8 Audio Service",
@@ -1165,7 +1165,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM8,
+ .id = MSM_FRONTEND_DAI_LSM8,
},
{/* hw:x,27 */
.name = MSM_DAILINK_NAME(Media9),
@@ -1182,7 +1182,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA9,
},
{/* hw:x,28 */
.name = MSM_DAILINK_NAME(Compress4),
@@ -1199,7 +1199,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA11,
},
{/* hw:x,29 */
.name = MSM_DAILINK_NAME(Compress5),
@@ -1216,7 +1216,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA12,
},
{/* hw:x,30 */
.name = MSM_DAILINK_NAME(Compress6),
@@ -1233,7 +1233,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA13,
},
{/* hw:x,31 */
.name = MSM_DAILINK_NAME(Compress7),
@@ -1250,7 +1250,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA14,
},
{/* hw:x,32 */
.name = MSM_DAILINK_NAME(Compress8),
@@ -1267,7 +1267,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA15,
},
{/* hw:x,33 */
.name = MSM_DAILINK_NAME(Compress9),
@@ -1284,7 +1284,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA16,
},
{/* hw:x,34 */
.name = "SLIMBUS_8 Hostless",
@@ -1332,7 +1332,7 @@
.ignore_suspend = 1,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
},
};
@@ -1346,7 +1346,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .id = MSM_BACKEND_DAI_AFE_PCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
@@ -1361,7 +1361,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .id = MSM_BACKEND_DAI_AFE_PCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -1375,7 +1375,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ .id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -1389,7 +1389,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ .id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -1403,7 +1403,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+ .id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -1417,7 +1417,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+ .id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -1430,7 +1430,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_USB_RX,
+ .id = MSM_BACKEND_DAI_USB_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1444,7 +1444,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_USB_TX,
+ .id = MSM_BACKEND_DAI_USB_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -1457,7 +1457,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1471,7 +1471,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1485,7 +1485,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1499,7 +1499,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1513,7 +1513,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1527,7 +1527,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1541,7 +1541,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1555,7 +1555,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -1572,7 +1572,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_PRI_MI2S_RX,
+ .id = MSM_BACKEND_DAI_PRI_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1587,7 +1587,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
+ .id = MSM_BACKEND_DAI_PRI_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1601,7 +1601,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ .id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1616,7 +1616,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+ .id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1630,7 +1630,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ .id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1645,7 +1645,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
+ .id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1659,7 +1659,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+ .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1674,7 +1674,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
+ .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -1692,7 +1692,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1707,7 +1707,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1723,7 +1723,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1738,7 +1738,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
@@ -1754,7 +1754,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_TERT_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1769,7 +1769,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_TERT_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
@@ -1785,7 +1785,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -1800,7 +1800,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
@@ -1822,7 +1822,7 @@
.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_wcn_ops,
/* dai link has playback support */
@@ -1838,7 +1838,7 @@
.codec_dai_name = "btfm_bt_sco_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.ops = &msm_wcn_ops,
.ignore_suspend = 1,
@@ -1852,7 +1852,7 @@
.codec_dai_name = "btfm_fm_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
.be_hw_params_fixup = msm_ext_be_hw_params_fixup,
.init = &msm_wcn_init,
.ops = &msm_wcn_ops,
@@ -1871,7 +1871,7 @@
.codec_dai_name = "msm_dp_audio_codec_rx_dai",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_DISPLAY_PORT_RX,
+ .id = MSM_BACKEND_DAI_DISPLAY_PORT_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
diff --git a/sound/soc/msm/sdm660-external.c b/sound/soc/msm/sdm660-external.c
index 2c3d7fc..84d1c2e 100644
--- a/sound/soc/msm/sdm660-external.c
+++ b/sound/soc/msm/sdm660-external.c
@@ -747,11 +747,11 @@
msm_bt_sample_rate_put),
};
-static int msm_slim_get_ch_from_beid(int32_t be_id)
+static int msm_slim_get_ch_from_beid(int32_t id)
{
int ch_id = 0;
- switch (be_id) {
+ switch (id) {
case MSM_BACKEND_DAI_SLIMBUS_0_RX:
ch_id = SLIM_RX_0;
break;
@@ -821,14 +821,14 @@
pr_debug("%s: format = %d, rate = %d\n",
__func__, params_format(params), params_rate(params));
- switch (dai_link->be_id) {
+ switch (dai_link->id) {
case MSM_BACKEND_DAI_SLIMBUS_0_RX:
case MSM_BACKEND_DAI_SLIMBUS_1_RX:
case MSM_BACKEND_DAI_SLIMBUS_2_RX:
case MSM_BACKEND_DAI_SLIMBUS_3_RX:
case MSM_BACKEND_DAI_SLIMBUS_4_RX:
case MSM_BACKEND_DAI_SLIMBUS_6_RX:
- idx = msm_slim_get_ch_from_beid(dai_link->be_id);
+ idx = msm_slim_get_ch_from_beid(dai_link->id);
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
slim_rx_cfg[idx].bit_format);
rate->min = rate->max = slim_rx_cfg[idx].sample_rate;
@@ -837,7 +837,7 @@
case MSM_BACKEND_DAI_SLIMBUS_0_TX:
case MSM_BACKEND_DAI_SLIMBUS_3_TX:
- idx = msm_slim_get_ch_from_beid(dai_link->be_id);
+ idx = msm_slim_get_ch_from_beid(dai_link->id);
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
slim_tx_cfg[idx].bit_format);
rate->min = rate->max = slim_tx_cfg[idx].sample_rate;
@@ -938,15 +938,15 @@
__func__, ret);
goto err_ch_map;
}
- if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
+ if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_5_RX) {
pr_debug("%s: rx_5_ch=%d\n", __func__,
slim_rx_cfg[5].channels);
rx_ch_count = slim_rx_cfg[5].channels;
- } else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_2_RX) {
+ } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_2_RX) {
pr_debug("%s: rx_2_ch=%d\n", __func__,
slim_rx_cfg[2].channels);
rx_ch_count = slim_rx_cfg[2].channels;
- } else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
+ } else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_6_RX) {
pr_debug("%s: rx_6_ch=%d\n", __func__,
slim_rx_cfg[6].channels);
rx_ch_count = slim_rx_cfg[6].channels;
@@ -973,19 +973,19 @@
goto err_ch_map;
}
/* For <codec>_tx1 case */
- if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
+ if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_0_TX)
user_set_tx_ch = slim_tx_cfg[0].channels;
/* For <codec>_tx3 case */
- else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
+ else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_1_TX)
user_set_tx_ch = slim_tx_cfg[1].channels;
- else if (dai_link->be_id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
+ else if (dai_link->id == MSM_BACKEND_DAI_SLIMBUS_4_TX)
user_set_tx_ch = msm_vi_feed_tx_ch;
else
user_set_tx_ch = tx_ch_cnt;
- pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), be_id (%d)\n",
+ pr_debug("%s: msm_slim_0_tx_ch(%d) user_set_tx_ch(%d) tx_ch_cnt(%d), id (%d)\n",
__func__, slim_tx_cfg[0].channels, user_set_tx_ch,
- tx_ch_cnt, dai_link->be_id);
+ tx_ch_cnt, dai_link->id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
user_set_tx_ch, tx_ch, 0, 0);
@@ -1097,8 +1097,8 @@
goto end;
}
- pr_debug("%s: tx_ch_cnt(%d) be_id %d\n",
- __func__, tx_ch_cnt, dai_link->be_id);
+ pr_debug("%s: tx_ch_cnt(%d) id %d\n",
+ __func__, tx_ch_cnt, dai_link->id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
tx_ch_cnt, tx_ch, 0, 0);
@@ -1495,7 +1495,7 @@
snd_soc_codec_get_dapm(codec);
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux;
+ struct snd_soc_component *aux_comp;
struct snd_card *card;
struct snd_info_entry *entry;
struct msm_asoc_mach_data *pdata =
@@ -1678,13 +1678,20 @@
* Send speaker configuration only for WSA8810.
* Defalut configuration is for WSA8815.
*/
+ pr_debug("%s: Number of aux devices: %d\n",
+ __func__, rtd->card->num_aux_devs);
+
if (!strcmp(dev_name(codec_dai->dev), "tavil_codec")) {
- if (rtd_aux && rtd_aux->component)
- if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
- !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ if (rtd->card->num_aux_devs &&
+ !list_empty(&rtd->card->aux_comp_list)) {
+ aux_comp = list_first_entry(&rtd->card->aux_comp_list,
+ struct snd_soc_component, list_aux);
+ if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
+ !strcmp(aux_comp->name, WSA8810_NAME_2)) {
tavil_set_spkr_mode(rtd->codec, SPKR_MODE_1);
tavil_set_spkr_gain_offset(rtd->codec,
RX_GAIN_OFFSET_M1P5_DB);
+ }
}
card = rtd->card->snd_card;
entry = snd_info_create_subdir(card->module, "codecs",
@@ -1698,12 +1705,16 @@
pdata->codec_root = entry;
tavil_codec_info_create_codec_entry(pdata->codec_root, codec);
} else {
- if (rtd_aux && rtd_aux->component)
- if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
- !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ if (rtd->card->num_aux_devs &&
+ !list_empty(&rtd->card->aux_comp_list)) {
+ aux_comp = list_first_entry(&rtd->card->aux_comp_list,
+ struct snd_soc_component, list_aux);
+ if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
+ !strcmp(aux_comp->name, WSA8810_NAME_2)) {
tasha_set_spkr_mode(rtd->codec, SPKR_MODE_1);
tasha_set_spkr_gain_offset(rtd->codec,
RX_GAIN_OFFSET_M1P5_DB);
+ }
}
card = rtd->card->snd_card;
entry = snd_info_create_subdir(card->module, "codecs",
diff --git a/sound/soc/msm/sdm660-internal.c b/sound/soc/msm/sdm660-internal.c
index 802137b..a57d6f6 100644
--- a/sound/soc/msm/sdm660-internal.c
+++ b/sound/soc/msm/sdm660-internal.c
@@ -539,11 +539,11 @@
return 0;
}
-static int int_mi2s_get_idx_from_beid(int32_t be_id)
+static int int_mi2s_get_idx_from_beid(int32_t id)
{
int idx = 0;
- switch (be_id) {
+ switch (id) {
case MSM_BACKEND_DAI_INT0_MI2S_RX:
idx = INT0_MI2S;
break;
@@ -596,13 +596,13 @@
pr_debug("%s: format = %d, rate = %d\n",
__func__, params_format(params), params_rate(params));
- switch (dai_link->be_id) {
+ switch (dai_link->id) {
case MSM_BACKEND_DAI_INT0_MI2S_RX:
case MSM_BACKEND_DAI_INT2_MI2S_TX:
case MSM_BACKEND_DAI_INT3_MI2S_TX:
case MSM_BACKEND_DAI_INT4_MI2S_RX:
case MSM_BACKEND_DAI_INT5_MI2S_TX:
- idx = int_mi2s_get_idx_from_beid(dai_link->be_id);
+ idx = int_mi2s_get_idx_from_beid(dai_link->id);
rate->min = rate->max = int_mi2s_cfg[idx].sample_rate;
channels->min = channels->max =
int_mi2s_cfg[idx].channels;
@@ -625,7 +625,7 @@
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
- switch (dai_link->be_id) {
+ switch (dai_link->id) {
case MSM_BACKEND_DAI_SLIMBUS_7_RX:
case MSM_BACKEND_DAI_SLIMBUS_7_TX:
param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
@@ -982,11 +982,11 @@
return 0;
}
-static int int_mi2s_get_port_id(int be_id)
+static int int_mi2s_get_port_id(int id)
{
int afe_port_id;
- switch (be_id) {
+ switch (id) {
case MSM_BACKEND_DAI_INT0_MI2S_RX:
afe_port_id = AFE_PORT_ID_INT0_MI2S_RX;
break;
@@ -1003,7 +1003,7 @@
afe_port_id = AFE_PORT_ID_INT5_MI2S_TX;
break;
default:
- pr_err("%s: Invalid be_id: %d\n", __func__, be_id);
+ pr_err("%s: Invalid id: %d\n", __func__, id);
afe_port_id = -EINVAL;
}
@@ -1073,7 +1073,7 @@
int port_id = 0;
int index;
- port_id = int_mi2s_get_port_id(rtd->dai_link->be_id);
+ port_id = int_mi2s_get_port_id(rtd->dai_link->id);
if (port_id < 0) {
dev_err(rtd->card->dev, "%s: Invalid port_id\n", __func__);
ret = port_id;
@@ -1303,7 +1303,7 @@
card = rtd->card->snd_card;
if (!codec_root)
- codec_root = snd_register_module_info(card->module, "codecs",
+ codec_root = snd_info_create_subdir(card->module, "codecs",
card->proc_root);
if (!codec_root) {
pr_debug("%s: Cannot create codecs module entry\n",
@@ -1323,7 +1323,7 @@
struct snd_soc_dapm_context *dapm =
snd_soc_codec_get_dapm(codec);
struct msm_asoc_mach_data *pdata = snd_soc_card_get_drvdata(rtd->card);
- struct snd_soc_pcm_runtime *rtd_aux = rtd->card->rtd_aux;
+ struct snd_soc_component *aux_comp;
struct snd_card *card;
snd_soc_add_codec_controls(codec, msm_sdw_controls,
@@ -1342,16 +1342,22 @@
* Send speaker configuration only for WSA8810.
* Default configuration is for WSA8815.
*/
- if (rtd_aux && rtd_aux->component)
- if (!strcmp(rtd_aux->component->name, WSA8810_NAME_1) ||
- !strcmp(rtd_aux->component->name, WSA8810_NAME_2)) {
+ pr_debug("%s: Number of aux devices: %d\n",
+ __func__, rtd->card->num_aux_devs);
+ if (rtd->card->num_aux_devs &&
+ !list_empty(&rtd->card->aux_comp_list)) {
+ aux_comp = list_first_entry(&rtd->card->aux_comp_list,
+ struct snd_soc_component, list_aux);
+ if (!strcmp(aux_comp->name, WSA8810_NAME_1) ||
+ !strcmp(aux_comp->name, WSA8810_NAME_2)) {
msm_sdw_set_spkr_mode(rtd->codec, SPKR_MODE_1);
msm_sdw_set_spkr_gain_offset(rtd->codec,
RX_GAIN_OFFSET_M1P5_DB);
+ }
}
card = rtd->card->snd_card;
if (!codec_root)
- codec_root = snd_register_module_info(card->module, "codecs",
+ codec_root = snd_info_create_subdir(card->module, "codecs",
card->proc_root);
if (!codec_root) {
pr_debug("%s: Cannot create codecs module entry\n",
@@ -1396,8 +1402,8 @@
goto exit;
}
- dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) be_id %d\n",
- __func__, tx_ch_cnt, dai_link->be_id);
+ dev_dbg(rtd->dev, "%s: tx_ch_cnt(%d) id %d\n",
+ __func__, tx_ch_cnt, dai_link->id);
ret = snd_soc_dai_set_channel_map(cpu_dai,
tx_ch_cnt, tx_ch, rx_ch_cnt, rx_ch);
@@ -1669,7 +1675,7 @@
.dpcm_capture = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA1
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA1
},
{/* hw:x,1 */
.name = MSM_DAILINK_NAME(Media2),
@@ -1686,7 +1692,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA2,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA2,
},
{/* hw:x,2 */
.name = "VoiceMMode1",
@@ -1703,7 +1709,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_VOICEMMODE1,
+ .id = MSM_FRONTEND_DAI_VOICEMMODE1,
},
{/* hw:x,3 */
.name = "MSM VoIP",
@@ -1720,7 +1726,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_VOIP,
+ .id = MSM_FRONTEND_DAI_VOIP,
},
{/* hw:x,4 */
.name = MSM_DAILINK_NAME(ULL),
@@ -1736,7 +1742,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA3,
},
/* Hostless PCM purpose */
{/* hw:x,5 */
@@ -1792,7 +1798,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA4,
},
{/* hw:x,9*/
.name = "AUXPCM Hostless",
@@ -1873,7 +1879,7 @@
.ignore_suspend = 1,
/* this dai link has playback support */
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA5,
},
/* LSM FE */
{/* hw:x,14 */
@@ -1890,7 +1896,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM1,
+ .id = MSM_FRONTEND_DAI_LSM1,
},
{/* hw:x,15 */
.name = MSM_DAILINK_NAME(Compress2),
@@ -1905,7 +1911,7 @@
.trigger = {SND_SOC_DPCM_TRIGGER_POST,
SND_SOC_DPCM_TRIGGER_POST},
.ignore_suspend = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA7,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA7,
},
{/* hw:x,16 */
.name = MSM_DAILINK_NAME(Compress3),
@@ -1922,7 +1928,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA10,
},
{/* hw:x,17 */
.name = MSM_DAILINK_NAME(ULL_NOIRQ),
@@ -1939,7 +1945,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA8,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA8,
},
{/* hw:x,18 */
.name = "HDMI_RX_HOSTLESS",
@@ -1971,7 +1977,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_VOICEMMODE2,
+ .id = MSM_FRONTEND_DAI_VOICEMMODE2,
},
{/* hw:x,20 */
.name = "Listen 2 Audio Service",
@@ -1987,7 +1993,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM2,
+ .id = MSM_FRONTEND_DAI_LSM2,
},
{/* hw:x,21 */
.name = "Listen 3 Audio Service",
@@ -2003,7 +2009,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM3,
+ .id = MSM_FRONTEND_DAI_LSM3,
},
{/* hw:x,22 */
.name = "Listen 4 Audio Service",
@@ -2019,7 +2025,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM4,
+ .id = MSM_FRONTEND_DAI_LSM4,
},
{/* hw:x,23 */
.name = "Listen 5 Audio Service",
@@ -2035,7 +2041,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM5,
+ .id = MSM_FRONTEND_DAI_LSM5,
},
{/* hw:x,24 */
.name = "Listen 6 Audio Service",
@@ -2051,7 +2057,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM6
+ .id = MSM_FRONTEND_DAI_LSM6
},
{/* hw:x,25 */
.name = "Listen 7 Audio Service",
@@ -2067,7 +2073,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM7,
+ .id = MSM_FRONTEND_DAI_LSM7,
},
{/* hw:x,26 */
.name = "Listen 8 Audio Service",
@@ -2083,7 +2089,7 @@
.ignore_pmdown_time = 1,
.codec_dai_name = "snd-soc-dummy-dai",
.codec_name = "snd-soc-dummy",
- .be_id = MSM_FRONTEND_DAI_LSM8,
+ .id = MSM_FRONTEND_DAI_LSM8,
},
{/* hw:x,27 */
.name = MSM_DAILINK_NAME(Media9),
@@ -2100,7 +2106,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA9,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA9,
},
{/* hw:x,28 */
.name = MSM_DAILINK_NAME(Compress4),
@@ -2117,7 +2123,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA11,
},
{/* hw:x,29 */
.name = MSM_DAILINK_NAME(Compress5),
@@ -2134,7 +2140,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA12,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA12,
},
{/* hw:x,30 */
.name = MSM_DAILINK_NAME(Compress6),
@@ -2151,7 +2157,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA13,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA13,
},
{/* hw:x,31 */
.name = MSM_DAILINK_NAME(Compress7),
@@ -2168,7 +2174,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA14,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA14,
},
{/* hw:x,32 */
.name = MSM_DAILINK_NAME(Compress8),
@@ -2185,7 +2191,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA15,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA15,
},
{/* hw:x,33 */
.name = MSM_DAILINK_NAME(Compress9),
@@ -2202,7 +2208,7 @@
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
/* this dai link has playback support */
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA16,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA16,
},
{/* hw:x,34 */
.name = "SLIMBUS_8 Hostless",
@@ -2302,7 +2308,7 @@
.ignore_suspend = 1,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
.ignore_pmdown_time = 1,
- .be_id = MSM_FRONTEND_DAI_MULTIMEDIA6,
+ .id = MSM_FRONTEND_DAI_MULTIMEDIA6,
},
};
@@ -2315,7 +2321,7 @@
.platform_name = "msm-pcm-hostless",
.codec_name = "msm_sdw_codec",
.codec_dai_name = "msm_sdw_vifeedback",
- .be_id = MSM_BACKEND_DAI_INT5_MI2S_TX,
+ .id = MSM_BACKEND_DAI_INT5_MI2S_TX,
.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
.ops = &msm_sdw_mi2s_be_ops,
.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
@@ -2338,7 +2344,7 @@
.dpcm_playback = 1,
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
ASYNC_DPCM_SND_SOC_HW_PARAMS,
- .be_id = MSM_BACKEND_DAI_INT0_MI2S_RX,
+ .id = MSM_BACKEND_DAI_INT0_MI2S_RX,
.init = &msm_audrx_init,
.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
.ops = &msm_int_mi2s_be_ops,
@@ -2355,7 +2361,7 @@
.dpcm_capture = 1,
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
ASYNC_DPCM_SND_SOC_HW_PARAMS,
- .be_id = MSM_BACKEND_DAI_INT3_MI2S_TX,
+ .id = MSM_BACKEND_DAI_INT3_MI2S_TX,
.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
.ops = &msm_int_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2371,7 +2377,7 @@
.dpcm_capture = 1,
.async_ops = ASYNC_DPCM_SND_SOC_PREPARE |
ASYNC_DPCM_SND_SOC_HW_PARAMS,
- .be_id = MSM_BACKEND_DAI_INT2_MI2S_TX,
+ .id = MSM_BACKEND_DAI_INT2_MI2S_TX,
.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
.ops = &msm_int_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2385,7 +2391,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_AFE_PCM_RX,
+ .id = MSM_BACKEND_DAI_AFE_PCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
@@ -2400,7 +2406,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
+ .id = MSM_BACKEND_DAI_AFE_PCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -2414,7 +2420,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
+ .id = MSM_BACKEND_DAI_INCALL_RECORD_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -2428,7 +2434,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
+ .id = MSM_BACKEND_DAI_INCALL_RECORD_RX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -2442,7 +2448,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
+ .id = MSM_BACKEND_DAI_VOICE_PLAYBACK_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -2456,7 +2462,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
+ .id = MSM_BACKEND_DAI_VOICE2_PLAYBACK_TX,
.be_hw_params_fixup = msm_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -2469,7 +2475,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_USB_RX,
+ .id = MSM_BACKEND_DAI_USB_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -2483,7 +2489,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_USB_TX,
+ .id = MSM_BACKEND_DAI_USB_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
},
@@ -2496,7 +2502,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_PRI_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2510,7 +2516,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_PRI_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2524,7 +2530,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_SEC_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2538,7 +2544,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_SEC_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2552,7 +2558,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_TERT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2566,7 +2572,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_TERT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2580,7 +2586,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
+ .id = MSM_BACKEND_DAI_QUAT_TDM_RX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2594,7 +2600,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
+ .id = MSM_BACKEND_DAI_QUAT_TDM_TX_0,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_tdm_be_ops,
.ignore_suspend = 1,
@@ -2611,7 +2617,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_PRI_MI2S_RX,
+ .id = MSM_BACKEND_DAI_PRI_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2626,7 +2632,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_PRI_MI2S_TX,
+ .id = MSM_BACKEND_DAI_PRI_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2640,7 +2646,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
+ .id = MSM_BACKEND_DAI_SECONDARY_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2655,7 +2661,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
+ .id = MSM_BACKEND_DAI_SECONDARY_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2669,7 +2675,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
+ .id = MSM_BACKEND_DAI_TERTIARY_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2684,7 +2690,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
+ .id = MSM_BACKEND_DAI_TERTIARY_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2698,7 +2704,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
+ .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2713,7 +2719,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
+ .id = MSM_BACKEND_DAI_QUATERNARY_MI2S_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ops = &msm_mi2s_be_ops,
.ignore_suspend = 1,
@@ -2731,7 +2737,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -2746,7 +2752,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -2762,7 +2768,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_SEC_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -2777,7 +2783,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_SEC_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
@@ -2793,7 +2799,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_TERT_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -2808,7 +2814,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_TERT_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_TERT_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
@@ -2824,7 +2830,7 @@
.codec_dai_name = "msm-stub-rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
+ .id = MSM_BACKEND_DAI_QUAT_AUXPCM_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
@@ -2839,7 +2845,7 @@
.codec_dai_name = "msm-stub-tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
+ .id = MSM_BACKEND_DAI_QUAT_AUXPCM_TX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_suspend = 1,
.ignore_pmdown_time = 1,
@@ -2862,7 +2868,7 @@
.codec_dai_name = "btfm_bt_sco_a2dp_slim_rx",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_7_RX,
.be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
.ops = &msm_wcn_ops,
/* dai link has playback support */
@@ -2878,7 +2884,7 @@
.codec_dai_name = "btfm_bt_sco_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_7_TX,
.be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
.ops = &msm_wcn_ops,
.ignore_suspend = 1,
@@ -2892,7 +2898,7 @@
.codec_dai_name = "btfm_fm_slim_tx",
.no_pcm = 1,
.dpcm_capture = 1,
- .be_id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
+ .id = MSM_BACKEND_DAI_SLIMBUS_8_TX,
.be_hw_params_fixup = msm_btfm_be_hw_params_fixup,
.init = &msm_wcn_init,
.ops = &msm_wcn_ops,
@@ -2910,7 +2916,7 @@
.codec_dai_name = "msm_sdw_i2s_rx1",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_INT4_MI2S_RX,
+ .id = MSM_BACKEND_DAI_INT4_MI2S_RX,
.init = &msm_sdw_audrx_init,
.be_hw_params_fixup = int_mi2s_be_hw_params_fixup,
.ops = &msm_sdw_mi2s_be_ops,
@@ -2929,7 +2935,7 @@
.codec_dai_name = "msm_dp_audio_codec_rx_dai",
.no_pcm = 1,
.dpcm_playback = 1,
- .be_id = MSM_BACKEND_DAI_DISPLAY_PORT_RX,
+ .id = MSM_BACKEND_DAI_DISPLAY_PORT_RX,
.be_hw_params_fixup = msm_common_be_hw_params_fixup,
.ignore_pmdown_time = 1,
.ignore_suspend = 1,
diff --git a/sound/soc/msm/sdm845.c b/sound/soc/msm/sdm845.c
index d3c4e05..9248766 100644
--- a/sound/soc/msm/sdm845.c
+++ b/sound/soc/msm/sdm845.c
@@ -538,10 +538,10 @@
};
static struct snd_soc_dapm_route wcd_audio_paths[] = {
- {"MIC BIAS1", NULL, "MCLK"},
- {"MIC BIAS2", NULL, "MCLK"},
- {"MIC BIAS3", NULL, "MCLK"},
- {"MIC BIAS4", NULL, "MCLK"},
+ {"MIC BIAS1", NULL, "MCLK TX"},
+ {"MIC BIAS2", NULL, "MCLK TX"},
+ {"MIC BIAS3", NULL, "MCLK TX"},
+ {"MIC BIAS4", NULL, "MCLK TX"},
};
static struct afe_clk_set mi2s_clk[MI2S_MAX] = {
@@ -2784,6 +2784,38 @@
return ret;
}
+static int msm_snd_enable_codec_ext_tx_clk(struct snd_soc_codec *codec,
+ int enable, bool dapm)
+{
+ int ret = 0;
+
+ if (!strcmp(dev_name(codec->dev), "tavil_codec")) {
+ ret = tavil_cdc_mclk_tx_enable(codec, enable);
+ } else {
+ dev_err(codec->dev, "%s: unknown codec to enable TX ext clk\n",
+ __func__);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int msm_mclk_tx_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+
+ pr_debug("%s: event = %d\n", __func__, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ return msm_snd_enable_codec_ext_tx_clk(codec, 1, true);
+ case SND_SOC_DAPM_POST_PMD:
+ return msm_snd_enable_codec_ext_tx_clk(codec, 0, true);
+ }
+ return 0;
+}
+
static int msm_mclk_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2840,7 +2872,7 @@
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("MCLK TX", SND_SOC_NOPM, 0, 0,
- NULL, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ msm_mclk_tx_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SPK("Lineout_1 amp", NULL),
SND_SOC_DAPM_SPK("Lineout_2 amp", NULL),
diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S
index 49e6eba..98dcc11 100644
--- a/tools/arch/x86/lib/memcpy_64.S
+++ b/tools/arch/x86/lib/memcpy_64.S
@@ -286,7 +286,7 @@
_ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
_ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
_ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
- _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
+ _ASM_EXTABLE_FAULT(.L_cache_w2, .L_memcpy_mcsafe_fail)
_ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
_ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
_ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
diff --git a/tools/objtool/arch/x86/decode.c b/tools/objtool/arch/x86/decode.c
index 5e0dea2..039636f 100644
--- a/tools/objtool/arch/x86/decode.c
+++ b/tools/objtool/arch/x86/decode.c
@@ -150,9 +150,9 @@
*type = INSN_RETURN;
break;
- case 0xc5: /* iret */
case 0xca: /* retf */
case 0xcb: /* retf */
+ case 0xcf: /* iret */
*type = INSN_CONTEXT_SWITCH;
break;
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index e8a1f69..b8dadb0 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -757,11 +757,20 @@
insn->jump_dest->offset > orig_insn->offset))
break;
+ /* look for a relocation which references .rodata */
text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
insn->len);
- if (text_rela && text_rela->sym == file->rodata->sym)
- return find_rela_by_dest(file->rodata,
- text_rela->addend);
+ if (!text_rela || text_rela->sym != file->rodata->sym)
+ continue;
+
+ /*
+ * Make sure the .rodata address isn't associated with a
+ * symbol. gcc jump tables are anonymous data.
+ */
+ if (find_symbol_containing(file->rodata, text_rela->addend))
+ continue;
+
+ return find_rela_by_dest(file->rodata, text_rela->addend);
}
return NULL;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 0d7983a..d897702 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -85,6 +85,18 @@
return NULL;
}
+struct symbol *find_symbol_containing(struct section *sec, unsigned long offset)
+{
+ struct symbol *sym;
+
+ list_for_each_entry(sym, &sec->symbol_list, list)
+ if (sym->type != STT_SECTION &&
+ offset >= sym->offset && offset < sym->offset + sym->len)
+ return sym;
+
+ return NULL;
+}
+
struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
unsigned int len)
{
diff --git a/tools/objtool/elf.h b/tools/objtool/elf.h
index aa1ff65..731973e 100644
--- a/tools/objtool/elf.h
+++ b/tools/objtool/elf.h
@@ -79,6 +79,7 @@
struct elf *elf_open(const char *name);
struct section *find_section_by_name(struct elf *elf, const char *name);
struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
+struct symbol *find_symbol_containing(struct section *sec, unsigned long offset);
struct rela *find_rela_by_dest(struct section *sec, unsigned long offset);
struct rela *find_rela_by_dest_range(struct section *sec, unsigned long offset,
unsigned int len);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index d281ae2..1d9c02b 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -645,18 +645,31 @@
return ret;
}
-static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
- int ntevs, const char *module)
+static int
+post_process_module_probe_trace_events(struct probe_trace_event *tevs,
+ int ntevs, const char *module,
+ struct debuginfo *dinfo)
{
+ Dwarf_Addr text_offs = 0;
int i, ret = 0;
char *mod_name = NULL;
+ struct map *map;
if (!module)
return 0;
- mod_name = find_module_name(module);
+ map = get_target_map(module, false);
+ if (!map || debuginfo__get_text_offset(dinfo, &text_offs, true) < 0) {
+ pr_warning("Failed to get ELF symbols for %s\n", module);
+ return -EINVAL;
+ }
+ mod_name = find_module_name(module);
for (i = 0; i < ntevs; i++) {
+ ret = post_process_probe_trace_point(&tevs[i].point,
+ map, (unsigned long)text_offs);
+ if (ret < 0)
+ break;
tevs[i].point.module =
strdup(mod_name ? mod_name : module);
if (!tevs[i].point.module) {
@@ -666,6 +679,8 @@
}
free(mod_name);
+ map__put(map);
+
return ret;
}
@@ -722,7 +737,7 @@
static int post_process_probe_trace_events(struct perf_probe_event *pev,
struct probe_trace_event *tevs,
int ntevs, const char *module,
- bool uprobe)
+ bool uprobe, struct debuginfo *dinfo)
{
int ret;
@@ -730,7 +745,8 @@
ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
else if (module)
/* Currently ref_reloc_sym based probe is not for drivers */
- ret = add_module_to_probe_trace_events(tevs, ntevs, module);
+ ret = post_process_module_probe_trace_events(tevs, ntevs,
+ module, dinfo);
else
ret = post_process_kernel_probe_trace_events(tevs, ntevs);
@@ -774,30 +790,27 @@
}
}
- debuginfo__delete(dinfo);
-
if (ntevs > 0) { /* Succeeded to find trace events */
pr_debug("Found %d probe_trace_events.\n", ntevs);
ret = post_process_probe_trace_events(pev, *tevs, ntevs,
- pev->target, pev->uprobes);
+ pev->target, pev->uprobes, dinfo);
if (ret < 0 || ret == ntevs) {
+ pr_debug("Post processing failed or all events are skipped. (%d)\n", ret);
clear_probe_trace_events(*tevs, ntevs);
zfree(tevs);
+ ntevs = 0;
}
- if (ret != ntevs)
- return ret < 0 ? ret : ntevs;
- ntevs = 0;
- /* Fall through */
}
+ debuginfo__delete(dinfo);
+
if (ntevs == 0) { /* No error but failed to find probe point. */
pr_warning("Probe point '%s' not found.\n",
synthesize_perf_probe_point(&pev->point));
return -ENOENT;
- }
- /* Error path : ntevs < 0 */
- pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
- if (ntevs < 0) {
+ } else if (ntevs < 0) {
+ /* Error path : ntevs < 0 */
+ pr_debug("An error occurred in debuginfo analysis (%d).\n", ntevs);
if (ntevs == -EBADF)
pr_warning("Warning: No dwarf info found in the vmlinux - "
"please rebuild kernel with CONFIG_DEBUG_INFO=y.\n");
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index df4debe..0d9d6e0 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -1501,7 +1501,8 @@
}
/* For the kernel module, we need a special code to get a DIE */
-static int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs)
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+ bool adjust_offset)
{
int n, i;
Elf32_Word shndx;
@@ -1530,6 +1531,8 @@
if (!shdr)
return -ENOENT;
*offs = shdr->sh_addr;
+ if (adjust_offset)
+ *offs -= shdr->sh_offset;
}
}
return 0;
@@ -1543,16 +1546,12 @@
Dwarf_Addr _addr = 0, baseaddr = 0;
const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp;
int baseline = 0, lineno = 0, ret = 0;
- bool reloc = false;
-retry:
+ /* We always need to relocate the address for aranges */
+ if (debuginfo__get_text_offset(dbg, &baseaddr, false) == 0)
+ addr += baseaddr;
/* Find cu die */
if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) {
- if (!reloc && debuginfo__get_text_offset(dbg, &baseaddr) == 0) {
- addr += baseaddr;
- reloc = true;
- goto retry;
- }
pr_warning("Failed to find debug information for address %lx\n",
addr);
ret = -EINVAL;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index f1d8558..2956c51 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -46,6 +46,9 @@
int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr,
struct perf_probe_point *ppt);
+int debuginfo__get_text_offset(struct debuginfo *dbg, Dwarf_Addr *offs,
+ bool adjust_offset);
+
/* Find a line range */
int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr);